Add table view to tools page (#2870)
This commit is contained in:
parent
877bc20d23
commit
ab76c48111
|
|
@ -0,0 +1,144 @@
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
|
import { styled } from '@mui/material/styles'
|
||||||
|
import { tableCellClasses } from '@mui/material/TableCell'
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Paper,
|
||||||
|
Skeleton,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableContainer,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
Typography,
|
||||||
|
useTheme
|
||||||
|
} from '@mui/material'
|
||||||
|
|
||||||
|
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
||||||
|
borderColor: theme.palette.grey[900] + 25,
|
||||||
|
|
||||||
|
[`&.${tableCellClasses.head}`]: {
|
||||||
|
color: theme.palette.grey[900]
|
||||||
|
},
|
||||||
|
[`&.${tableCellClasses.body}`]: {
|
||||||
|
fontSize: 14,
|
||||||
|
height: 64
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
const StyledTableRow = styled(TableRow)(() => ({
|
||||||
|
// hide last border
|
||||||
|
'&:last-child td, &:last-child th': {
|
||||||
|
border: 0
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
export const ToolsTable = ({ data, isLoading, onSelect }) => {
|
||||||
|
const theme = useTheme()
|
||||||
|
const customization = useSelector((state) => state.customization)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TableContainer sx={{ border: 1, borderColor: theme.palette.grey[900] + 25, borderRadius: 2 }} component={Paper}>
|
||||||
|
<Table sx={{ minWidth: 650 }} size='small' aria-label='a dense table'>
|
||||||
|
<TableHead
|
||||||
|
sx={{
|
||||||
|
backgroundColor: customization.isDarkMode ? theme.palette.common.black : theme.palette.grey[100],
|
||||||
|
height: 56
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TableRow>
|
||||||
|
<StyledTableCell component='th' scope='row' key='0'>
|
||||||
|
Name
|
||||||
|
</StyledTableCell>
|
||||||
|
<StyledTableCell key='1'>Description</StyledTableCell>
|
||||||
|
<StyledTableCell component='th' scope='row' key='3'>
|
||||||
|
|
||||||
|
</StyledTableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{isLoading ? (
|
||||||
|
<>
|
||||||
|
<StyledTableRow>
|
||||||
|
<StyledTableCell>
|
||||||
|
<Skeleton variant='text' />
|
||||||
|
</StyledTableCell>
|
||||||
|
<StyledTableCell>
|
||||||
|
<Skeleton variant='text' />
|
||||||
|
</StyledTableCell>
|
||||||
|
<StyledTableCell>
|
||||||
|
<Skeleton variant='text' />
|
||||||
|
</StyledTableCell>
|
||||||
|
</StyledTableRow>
|
||||||
|
<StyledTableRow>
|
||||||
|
<StyledTableCell>
|
||||||
|
<Skeleton variant='text' />
|
||||||
|
</StyledTableCell>
|
||||||
|
<StyledTableCell>
|
||||||
|
<Skeleton variant='text' />
|
||||||
|
</StyledTableCell>
|
||||||
|
<StyledTableCell>
|
||||||
|
<Skeleton variant='text' />
|
||||||
|
</StyledTableCell>
|
||||||
|
</StyledTableRow>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{data?.map((row, index) => (
|
||||||
|
<StyledTableRow key={index}>
|
||||||
|
<StyledTableCell sx={{ display: 'flex', alignItems: 'center', gap: 1 }} key='0'>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 35,
|
||||||
|
height: 35,
|
||||||
|
display: 'flex',
|
||||||
|
flexShrink: 0,
|
||||||
|
marginRight: 10,
|
||||||
|
borderRadius: '50%',
|
||||||
|
backgroundImage: `url(${row.iconSrc})`,
|
||||||
|
backgroundSize: 'contain',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'center center'
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
display: '-webkit-box',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 500,
|
||||||
|
WebkitLineClamp: 2,
|
||||||
|
WebkitBoxOrient: 'vertical',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
overflow: 'hidden'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button onClick={() => onSelect(row)} sx={{ textAlign: 'left' }}>
|
||||||
|
{row.templateName || row.name}
|
||||||
|
</Button>
|
||||||
|
</Typography>
|
||||||
|
</StyledTableCell>
|
||||||
|
<StyledTableCell key='1'>
|
||||||
|
<Typography sx={{ overflowWrap: 'break-word', whiteSpace: 'pre-line' }}>
|
||||||
|
{row.description || ''}
|
||||||
|
</Typography>
|
||||||
|
</StyledTableCell>
|
||||||
|
<StyledTableCell key='3'></StyledTableCell>
|
||||||
|
</StyledTableRow>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolsTable.propTypes = {
|
||||||
|
data: PropTypes.array,
|
||||||
|
isLoading: PropTypes.bool,
|
||||||
|
onSelect: PropTypes.func
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useEffect, useState, useRef } from 'react'
|
import { useEffect, useState, useRef } from 'react'
|
||||||
|
|
||||||
// material-ui
|
// material-ui
|
||||||
import { Box, Stack, Button, ButtonGroup, Skeleton } from '@mui/material'
|
import { Box, Stack, Button, ButtonGroup, Skeleton, ToggleButtonGroup, ToggleButton } from '@mui/material'
|
||||||
|
|
||||||
// project imports
|
// project imports
|
||||||
import MainCard from '@/ui-component/cards/MainCard'
|
import MainCard from '@/ui-component/cards/MainCard'
|
||||||
|
|
@ -10,6 +10,7 @@ import { gridSpacing } from '@/store/constant'
|
||||||
import ToolEmptySVG from '@/assets/images/tools_empty.svg'
|
import ToolEmptySVG from '@/assets/images/tools_empty.svg'
|
||||||
import { StyledButton } from '@/ui-component/button/StyledButton'
|
import { StyledButton } from '@/ui-component/button/StyledButton'
|
||||||
import ToolDialog from './ToolDialog'
|
import ToolDialog from './ToolDialog'
|
||||||
|
import { ToolsTable } from '@/ui-component/table/ToolsListTable'
|
||||||
|
|
||||||
// API
|
// API
|
||||||
import toolsApi from '@/api/tools'
|
import toolsApi from '@/api/tools'
|
||||||
|
|
@ -18,22 +19,31 @@ import toolsApi from '@/api/tools'
|
||||||
import useApi from '@/hooks/useApi'
|
import useApi from '@/hooks/useApi'
|
||||||
|
|
||||||
// icons
|
// icons
|
||||||
import { IconPlus, IconFileUpload } from '@tabler/icons-react'
|
import { IconPlus, IconFileUpload, IconLayoutGrid, IconList } from '@tabler/icons-react'
|
||||||
import ViewHeader from '@/layout/MainLayout/ViewHeader'
|
import ViewHeader from '@/layout/MainLayout/ViewHeader'
|
||||||
import ErrorBoundary from '@/ErrorBoundary'
|
import ErrorBoundary from '@/ErrorBoundary'
|
||||||
|
import { useTheme } from '@mui/material/styles'
|
||||||
|
|
||||||
// ==============================|| CHATFLOWS ||============================== //
|
// ==============================|| CHATFLOWS ||============================== //
|
||||||
|
|
||||||
const Tools = () => {
|
const Tools = () => {
|
||||||
|
const theme = useTheme()
|
||||||
const getAllToolsApi = useApi(toolsApi.getAllTools)
|
const getAllToolsApi = useApi(toolsApi.getAllTools)
|
||||||
|
|
||||||
const [isLoading, setLoading] = useState(true)
|
const [isLoading, setLoading] = useState(true)
|
||||||
const [error, setError] = useState(null)
|
const [error, setError] = useState(null)
|
||||||
const [showDialog, setShowDialog] = useState(false)
|
const [showDialog, setShowDialog] = useState(false)
|
||||||
const [dialogProps, setDialogProps] = useState({})
|
const [dialogProps, setDialogProps] = useState({})
|
||||||
|
const [view, setView] = useState(localStorage.getItem('toolsDisplayStyle') || 'card')
|
||||||
|
|
||||||
const inputRef = useRef(null)
|
const inputRef = useRef(null)
|
||||||
|
|
||||||
|
const handleChange = (event, nextView) => {
|
||||||
|
if (nextView === null) return
|
||||||
|
localStorage.setItem('toolsDisplayStyle', nextView)
|
||||||
|
setView(nextView)
|
||||||
|
}
|
||||||
|
|
||||||
const onUploadFile = (file) => {
|
const onUploadFile = (file) => {
|
||||||
try {
|
try {
|
||||||
const dialogProp = {
|
const dialogProp = {
|
||||||
|
|
@ -118,6 +128,38 @@ const Tools = () => {
|
||||||
) : (
|
) : (
|
||||||
<Stack flexDirection='column' sx={{ gap: 3 }}>
|
<Stack flexDirection='column' sx={{ gap: 3 }}>
|
||||||
<ViewHeader title='Tools'>
|
<ViewHeader title='Tools'>
|
||||||
|
<ToggleButtonGroup
|
||||||
|
sx={{ borderRadius: 2, maxHeight: 40 }}
|
||||||
|
value={view}
|
||||||
|
color='primary'
|
||||||
|
exclusive
|
||||||
|
onChange={handleChange}
|
||||||
|
>
|
||||||
|
<ToggleButton
|
||||||
|
sx={{
|
||||||
|
borderColor: theme.palette.grey[900] + 25,
|
||||||
|
borderRadius: 2,
|
||||||
|
color: theme?.customization?.isDarkMode ? 'white' : 'inherit'
|
||||||
|
}}
|
||||||
|
variant='contained'
|
||||||
|
value='card'
|
||||||
|
title='Card View'
|
||||||
|
>
|
||||||
|
<IconLayoutGrid />
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton
|
||||||
|
sx={{
|
||||||
|
borderColor: theme.palette.grey[900] + 25,
|
||||||
|
borderRadius: 2,
|
||||||
|
color: theme?.customization?.isDarkMode ? 'white' : 'inherit'
|
||||||
|
}}
|
||||||
|
variant='contained'
|
||||||
|
value='list'
|
||||||
|
title='List View'
|
||||||
|
>
|
||||||
|
<IconList />
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||||
<Button
|
<Button
|
||||||
variant='outlined'
|
variant='outlined'
|
||||||
|
|
@ -147,19 +189,25 @@ const Tools = () => {
|
||||||
</StyledButton>
|
</StyledButton>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</ViewHeader>
|
</ViewHeader>
|
||||||
{isLoading ? (
|
{!view || view === 'card' ? (
|
||||||
<Box display='grid' gridTemplateColumns='repeat(3, 1fr)' gap={gridSpacing}>
|
<>
|
||||||
<Skeleton variant='rounded' height={160} />
|
{isLoading ? (
|
||||||
<Skeleton variant='rounded' height={160} />
|
<Box display='grid' gridTemplateColumns='repeat(3, 1fr)' gap={gridSpacing}>
|
||||||
<Skeleton variant='rounded' height={160} />
|
<Skeleton variant='rounded' height={160} />
|
||||||
</Box>
|
<Skeleton variant='rounded' height={160} />
|
||||||
|
<Skeleton variant='rounded' height={160} />
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Box display='grid' gridTemplateColumns='repeat(3, 1fr)' gap={gridSpacing}>
|
||||||
|
{getAllToolsApi.data &&
|
||||||
|
getAllToolsApi.data.map((data, index) => (
|
||||||
|
<ItemCard data={data} key={index} onClick={() => edit(data)} />
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Box display='grid' gridTemplateColumns='repeat(3, 1fr)' gap={gridSpacing}>
|
<ToolsTable data={getAllToolsApi.data} isLoading={isLoading} onSelect={edit} />
|
||||||
{getAllToolsApi.data &&
|
|
||||||
getAllToolsApi.data.map((data, index) => (
|
|
||||||
<ItemCard data={data} key={index} onClick={() => edit(data)} />
|
|
||||||
))}
|
|
||||||
</Box>
|
|
||||||
)}
|
)}
|
||||||
{!isLoading && (!getAllToolsApi.data || getAllToolsApi.data.length === 0) && (
|
{!isLoading && (!getAllToolsApi.data || getAllToolsApi.data.length === 0) && (
|
||||||
<Stack sx={{ alignItems: 'center', justifyContent: 'center' }} flexDirection='column'>
|
<Stack sx={{ alignItems: 'center', justifyContent: 'center' }} flexDirection='column'>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue