mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-25 03:00:54 +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