Files
Flowise/packages/ui/src/views/credentials/index.jsx
T
2023-11-23 08:31:13 -05:00

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&nbsp;</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