mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 15:00:57 +03:00
Show a dialog to fetch and manage links in web scraper nodes
This commit is contained in:
@@ -0,0 +1,184 @@
|
|||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { createPortal } from 'react-dom'
|
||||||
|
import { useDispatch } from 'react-redux'
|
||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
FormControl,
|
||||||
|
IconButton,
|
||||||
|
OutlinedInput,
|
||||||
|
Stack,
|
||||||
|
Typography
|
||||||
|
} from '@mui/material'
|
||||||
|
import { IconTrash } from '@tabler/icons'
|
||||||
|
import PerfectScrollbar from 'react-perfect-scrollbar'
|
||||||
|
|
||||||
|
import { BackdropLoader } from 'ui-component/loading/BackdropLoader'
|
||||||
|
import { StyledButton } from 'ui-component/button/StyledButton'
|
||||||
|
|
||||||
|
import scraperApi from 'api/scraper'
|
||||||
|
|
||||||
|
import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from 'store/actions'
|
||||||
|
|
||||||
|
const ManageScrapedLinksDialog = ({ show, dialogProps, onCancel, onSave }) => {
|
||||||
|
const portalElement = document.getElementById('portal')
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [selectedLinks, setSelectedLinks] = useState([])
|
||||||
|
const [url, setUrl] = useState('')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (dialogProps.url) setUrl(dialogProps.url)
|
||||||
|
if (dialogProps.selectedLinks) setSelectedLinks(dialogProps.selectedLinks)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
setLoading(false)
|
||||||
|
setSelectedLinks([])
|
||||||
|
setUrl('')
|
||||||
|
}
|
||||||
|
}, [dialogProps])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (show) dispatch({ type: SHOW_CANVAS_DIALOG })
|
||||||
|
else dispatch({ type: HIDE_CANVAS_DIALOG })
|
||||||
|
return () => dispatch({ type: HIDE_CANVAS_DIALOG })
|
||||||
|
}, [show, dispatch])
|
||||||
|
|
||||||
|
const handleFetchLinks = async () => {
|
||||||
|
setLoading(true)
|
||||||
|
const fetchLinksResp = await scraperApi.fetchAllLinks(url, 'webCrawl')
|
||||||
|
if (fetchLinksResp.data) {
|
||||||
|
setSelectedLinks(fetchLinksResp.data.links)
|
||||||
|
}
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeLink = (index, event) => {
|
||||||
|
const { value } = event.target
|
||||||
|
const links = [...selectedLinks]
|
||||||
|
links[index] = value
|
||||||
|
setSelectedLinks(links)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRemoveLink = (index) => {
|
||||||
|
const links = [...selectedLinks]
|
||||||
|
links.splice(index, 1)
|
||||||
|
setSelectedLinks(links)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSaveLinks = () => {
|
||||||
|
onSave(selectedLinks)
|
||||||
|
}
|
||||||
|
|
||||||
|
const component = show ? (
|
||||||
|
<Dialog
|
||||||
|
onClose={onCancel}
|
||||||
|
open={show}
|
||||||
|
fullWidth
|
||||||
|
maxWidth='sm'
|
||||||
|
aria-labelledby='manage-scraped-links-dialog-title'
|
||||||
|
aria-describedby='manage-scraped-links-dialog-description'
|
||||||
|
>
|
||||||
|
<DialogTitle sx={{ fontSize: '1rem' }} id='manage-scraped-links-dialog-title'>
|
||||||
|
{dialogProps.title || `Manage Scraped Links - ${url}`}
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Box sx={{ mb: 4 }}>
|
||||||
|
<Stack flexDirection='row' gap={1} sx={{ width: '100%' }}>
|
||||||
|
<FormControl sx={{ mt: 1, width: '100%', display: 'flex', flexShrink: 1 }} size='small'>
|
||||||
|
<OutlinedInput
|
||||||
|
id='url'
|
||||||
|
size='small'
|
||||||
|
type='text'
|
||||||
|
value={url}
|
||||||
|
name='url'
|
||||||
|
onChange={(e) => {
|
||||||
|
setUrl(e.target.value)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<Button
|
||||||
|
sx={{ borderRadius: '12px', mt: 1, display: 'flex', flexShrink: 0 }}
|
||||||
|
size='small'
|
||||||
|
variant='contained'
|
||||||
|
onClick={handleFetchLinks}
|
||||||
|
>
|
||||||
|
Fetch Links
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
<Typography sx={{ mb: 2, fontWeight: 500 }}>Scraped Links</Typography>
|
||||||
|
{selectedLinks.length > 0 ? (
|
||||||
|
<PerfectScrollbar
|
||||||
|
style={{
|
||||||
|
height: '100%',
|
||||||
|
maxHeight: '320px',
|
||||||
|
overflowX: 'hidden',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: 4
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{selectedLinks.map((link, index) => (
|
||||||
|
<div key={index} style={{ display: 'flex', width: '100%' }}>
|
||||||
|
<Box sx={{ display: 'flex', width: '100%' }}>
|
||||||
|
<OutlinedInput
|
||||||
|
sx={{ width: '100%' }}
|
||||||
|
key={index}
|
||||||
|
type='text'
|
||||||
|
onChange={(e) => handleChangeLink(index, e)}
|
||||||
|
size='small'
|
||||||
|
value={link}
|
||||||
|
name={`link_${index}`}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ width: 'auto', flexGrow: 1 }}>
|
||||||
|
<IconButton
|
||||||
|
sx={{ height: 30, width: 30 }}
|
||||||
|
size='small'
|
||||||
|
color='error'
|
||||||
|
onClick={() => handleRemoveLink(index)}
|
||||||
|
edge='end'
|
||||||
|
>
|
||||||
|
<IconTrash />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</PerfectScrollbar>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{loading && <BackdropLoader open={loading} />}
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||||
|
<Typography sx={{ my: 2 }}>Links scraped from the URL will appear here</Typography>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={onCancel}>Cancel</Button>
|
||||||
|
<StyledButton variant='contained' onClick={handleSaveLinks}>
|
||||||
|
Save
|
||||||
|
</StyledButton>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
) : null
|
||||||
|
|
||||||
|
return createPortal(component, portalElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
ManageScrapedLinksDialog.propTypes = {
|
||||||
|
show: PropTypes.bool,
|
||||||
|
dialogProps: PropTypes.object,
|
||||||
|
onCancel: PropTypes.func,
|
||||||
|
onSave: PropTypes.func
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ManageScrapedLinksDialog
|
||||||
Reference in New Issue
Block a user