mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-22 07:01:07 +03:00
337 lines
14 KiB
React
337 lines
14 KiB
React
import { useEffect, useState } from 'react'
|
|
import { useDispatch, useSelector } from 'react-redux'
|
|
import { enqueueSnackbar as enqueueSnackbarAction, closeSnackbar as closeSnackbarAction } from 'store/actions'
|
|
import moment from 'moment'
|
|
|
|
// material-ui
|
|
import {
|
|
Button,
|
|
Box,
|
|
Stack,
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableContainer,
|
|
TableHead,
|
|
TableRow,
|
|
Paper,
|
|
IconButton,
|
|
Toolbar,
|
|
TextField,
|
|
InputAdornment,
|
|
ButtonGroup
|
|
} from '@mui/material'
|
|
import { useTheme } from '@mui/material/styles'
|
|
|
|
// project imports
|
|
import MainCard from '@/ui-component/cards/MainCard'
|
|
import { StyledButton } from '@/ui-component/button/StyledButton'
|
|
import CredentialListDialog from './CredentialListDialog'
|
|
import ConfirmDialog from '@/ui-component/dialog/ConfirmDialog'
|
|
import AddEditCredentialDialog from './AddEditCredentialDialog'
|
|
|
|
// API
|
|
import credentialsApi from '@/api/credentials'
|
|
|
|
// Hooks
|
|
import useApi from '@/hooks/useApi'
|
|
import useConfirm from '@/hooks/useConfirm'
|
|
|
|
// utils
|
|
import useNotifier from '@/utils/useNotifier'
|
|
|
|
// Icons
|
|
import { IconTrash, IconEdit, IconX, IconPlus, IconSearch } from '@tabler/icons'
|
|
import CredentialEmptySVG from '@/assets/images/credential_empty.svg'
|
|
|
|
// const
|
|
import { baseURL } from '@/store/constant'
|
|
import { SET_COMPONENT_CREDENTIALS } from '@/store/actions'
|
|
|
|
// ==============================|| Credentials ||============================== //
|
|
|
|
const Credentials = () => {
|
|
const theme = useTheme()
|
|
const customization = useSelector((state) => state.customization)
|
|
|
|
const dispatch = useDispatch()
|
|
useNotifier()
|
|
|
|
const enqueueSnackbar = (...args) => dispatch(enqueueSnackbarAction(...args))
|
|
const closeSnackbar = (...args) => dispatch(closeSnackbarAction(...args))
|
|
|
|
const [showCredentialListDialog, setShowCredentialListDialog] = useState(false)
|
|
const [credentialListDialogProps, setCredentialListDialogProps] = useState({})
|
|
const [showSpecificCredentialDialog, setShowSpecificCredentialDialog] = useState(false)
|
|
const [specificCredentialDialogProps, setSpecificCredentialDialogProps] = useState({})
|
|
const [credentials, setCredentials] = useState([])
|
|
const [componentsCredentials, setComponentsCredentials] = useState([])
|
|
|
|
const { confirm } = useConfirm()
|
|
|
|
const getAllCredentialsApi = useApi(credentialsApi.getAllCredentials)
|
|
const getAllComponentsCredentialsApi = useApi(credentialsApi.getAllComponentsCredentials)
|
|
|
|
const [search, setSearch] = useState('')
|
|
const onSearchChange = (event) => {
|
|
setSearch(event.target.value)
|
|
}
|
|
function filterCredentials(data) {
|
|
return data.credentialName.toLowerCase().indexOf(search.toLowerCase()) > -1
|
|
}
|
|
|
|
const listCredential = () => {
|
|
const dialogProp = {
|
|
title: 'Add New Credential',
|
|
componentsCredentials
|
|
}
|
|
setCredentialListDialogProps(dialogProp)
|
|
setShowCredentialListDialog(true)
|
|
}
|
|
|
|
const addNew = (credentialComponent) => {
|
|
const dialogProp = {
|
|
type: 'ADD',
|
|
cancelButtonName: 'Cancel',
|
|
confirmButtonName: 'Add',
|
|
credentialComponent
|
|
}
|
|
setSpecificCredentialDialogProps(dialogProp)
|
|
setShowSpecificCredentialDialog(true)
|
|
}
|
|
|
|
const edit = (credential) => {
|
|
const dialogProp = {
|
|
type: 'EDIT',
|
|
cancelButtonName: 'Cancel',
|
|
confirmButtonName: 'Save',
|
|
data: credential
|
|
}
|
|
setSpecificCredentialDialogProps(dialogProp)
|
|
setShowSpecificCredentialDialog(true)
|
|
}
|
|
|
|
const deleteCredential = async (credential) => {
|
|
const confirmPayload = {
|
|
title: `Delete`,
|
|
description: `Delete credential ${credential.name}?`,
|
|
confirmButtonName: 'Delete',
|
|
cancelButtonName: 'Cancel'
|
|
}
|
|
const isConfirmed = await confirm(confirmPayload)
|
|
|
|
if (isConfirmed) {
|
|
try {
|
|
const deleteResp = await credentialsApi.deleteCredential(credential.id)
|
|
if (deleteResp.data) {
|
|
enqueueSnackbar({
|
|
message: 'Credential deleted',
|
|
options: {
|
|
key: new Date().getTime() + Math.random(),
|
|
variant: 'success',
|
|
action: (key) => (
|
|
<Button style={{ color: 'white' }} onClick={() => closeSnackbar(key)}>
|
|
<IconX />
|
|
</Button>
|
|
)
|
|
}
|
|
})
|
|
onConfirm()
|
|
}
|
|
} catch (error) {
|
|
const errorData = error.response.data || `${error.response.status}: ${error.response.statusText}`
|
|
enqueueSnackbar({
|
|
message: `Failed to delete Credential: ${errorData}`,
|
|
options: {
|
|
key: new Date().getTime() + Math.random(),
|
|
variant: 'error',
|
|
persist: true,
|
|
action: (key) => (
|
|
<Button style={{ color: 'white' }} onClick={() => closeSnackbar(key)}>
|
|
<IconX />
|
|
</Button>
|
|
)
|
|
}
|
|
})
|
|
onCancel()
|
|
}
|
|
}
|
|
}
|
|
|
|
const onCredentialSelected = (credentialComponent) => {
|
|
setShowCredentialListDialog(false)
|
|
addNew(credentialComponent)
|
|
}
|
|
|
|
const onConfirm = () => {
|
|
setShowCredentialListDialog(false)
|
|
setShowSpecificCredentialDialog(false)
|
|
getAllCredentialsApi.request()
|
|
}
|
|
|
|
useEffect(() => {
|
|
getAllCredentialsApi.request()
|
|
getAllComponentsCredentialsApi.request()
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
if (getAllCredentialsApi.data) {
|
|
setCredentials(getAllCredentialsApi.data)
|
|
}
|
|
}, [getAllCredentialsApi.data])
|
|
|
|
useEffect(() => {
|
|
if (getAllComponentsCredentialsApi.data) {
|
|
setComponentsCredentials(getAllComponentsCredentialsApi.data)
|
|
dispatch({ type: SET_COMPONENT_CREDENTIALS, componentsCredentials: getAllComponentsCredentialsApi.data })
|
|
}
|
|
}, [getAllComponentsCredentialsApi.data, dispatch])
|
|
|
|
return (
|
|
<>
|
|
<MainCard sx={{ background: customization.isDarkMode ? theme.palette.common.black : '' }}>
|
|
<Stack flexDirection='row'>
|
|
<Box sx={{ flexGrow: 1 }}>
|
|
<Toolbar
|
|
disableGutters={true}
|
|
style={{
|
|
margin: 1,
|
|
padding: 1,
|
|
paddingBottom: 10,
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
width: '100%'
|
|
}}
|
|
>
|
|
<h1>Credentials </h1>
|
|
<TextField
|
|
size='small'
|
|
sx={{ display: { xs: 'none', sm: 'block' }, ml: 3 }}
|
|
variant='outlined'
|
|
placeholder='Search credential name'
|
|
onChange={onSearchChange}
|
|
InputProps={{
|
|
startAdornment: (
|
|
<InputAdornment position='start'>
|
|
<IconSearch />
|
|
</InputAdornment>
|
|
)
|
|
}}
|
|
/>
|
|
<Box sx={{ flexGrow: 1 }} />
|
|
<ButtonGroup
|
|
sx={{ maxHeight: 40 }}
|
|
disableElevation
|
|
variant='contained'
|
|
aria-label='outlined primary button group'
|
|
>
|
|
<ButtonGroup disableElevation aria-label='outlined primary button group'>
|
|
<StyledButton
|
|
variant='contained'
|
|
sx={{ color: 'white', mr: 1, height: 37 }}
|
|
onClick={listCredential}
|
|
startIcon={<IconPlus />}
|
|
>
|
|
Add Credential
|
|
</StyledButton>
|
|
</ButtonGroup>
|
|
</ButtonGroup>
|
|
</Toolbar>
|
|
</Box>
|
|
</Stack>
|
|
{credentials.length <= 0 && (
|
|
<Stack sx={{ alignItems: 'center', justifyContent: 'center' }} flexDirection='column'>
|
|
<Box sx={{ p: 2, height: 'auto' }}>
|
|
<img
|
|
style={{ objectFit: 'cover', height: '30vh', width: 'auto' }}
|
|
src={CredentialEmptySVG}
|
|
alt='CredentialEmptySVG'
|
|
/>
|
|
</Box>
|
|
<div>No Credentials Yet</div>
|
|
</Stack>
|
|
)}
|
|
{credentials.length > 0 && (
|
|
<TableContainer component={Paper}>
|
|
<Table sx={{ minWidth: 650 }} aria-label='simple table'>
|
|
<TableHead>
|
|
<TableRow>
|
|
<TableCell>Name</TableCell>
|
|
<TableCell>Last Updated</TableCell>
|
|
<TableCell>Created</TableCell>
|
|
<TableCell> </TableCell>
|
|
<TableCell> </TableCell>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{credentials.filter(filterCredentials).map((credential, index) => (
|
|
<TableRow key={index} sx={{ '&:last-child td, &:last-child th': { border: 0 } }}>
|
|
<TableCell component='th' scope='row'>
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
flexDirection: 'row',
|
|
alignItems: 'center'
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
width: 25,
|
|
height: 25,
|
|
marginRight: 10,
|
|
borderRadius: '50%'
|
|
}}
|
|
>
|
|
<img
|
|
style={{
|
|
width: '100%',
|
|
height: '100%',
|
|
borderRadius: '50%',
|
|
objectFit: 'contain'
|
|
}}
|
|
alt={credential.credentialName}
|
|
src={`${baseURL}/api/v1/components-credentials-icon/${credential.credentialName}`}
|
|
/>
|
|
</div>
|
|
{credential.name}
|
|
</div>
|
|
</TableCell>
|
|
<TableCell>{moment(credential.updatedDate).format('DD-MMM-YY')}</TableCell>
|
|
<TableCell>{moment(credential.createdDate).format('DD-MMM-YY')}</TableCell>
|
|
<TableCell>
|
|
<IconButton title='Edit' color='primary' onClick={() => edit(credential)}>
|
|
<IconEdit />
|
|
</IconButton>
|
|
</TableCell>
|
|
<TableCell>
|
|
<IconButton title='Delete' color='error' onClick={() => deleteCredential(credential)}>
|
|
<IconTrash />
|
|
</IconButton>
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</TableContainer>
|
|
)}
|
|
</MainCard>
|
|
<CredentialListDialog
|
|
show={showCredentialListDialog}
|
|
dialogProps={credentialListDialogProps}
|
|
onCancel={() => setShowCredentialListDialog(false)}
|
|
onCredentialSelected={onCredentialSelected}
|
|
></CredentialListDialog>
|
|
<AddEditCredentialDialog
|
|
show={showSpecificCredentialDialog}
|
|
dialogProps={specificCredentialDialogProps}
|
|
onCancel={() => setShowSpecificCredentialDialog(false)}
|
|
onConfirm={onConfirm}
|
|
></AddEditCredentialDialog>
|
|
<ConfirmDialog />
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default Credentials
|