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'
|
||||
|
||||
// material-ui
|
||||
import { Box, Stack, Button, ButtonGroup, Skeleton } from '@mui/material'
|
||||
import { Box, Stack, Button, ButtonGroup, Skeleton, ToggleButtonGroup, ToggleButton } from '@mui/material'
|
||||
|
||||
// project imports
|
||||
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 { StyledButton } from '@/ui-component/button/StyledButton'
|
||||
import ToolDialog from './ToolDialog'
|
||||
import { ToolsTable } from '@/ui-component/table/ToolsListTable'
|
||||
|
||||
// API
|
||||
import toolsApi from '@/api/tools'
|
||||
|
|
@ -18,22 +19,31 @@ import toolsApi from '@/api/tools'
|
|||
import useApi from '@/hooks/useApi'
|
||||
|
||||
// icons
|
||||
import { IconPlus, IconFileUpload } from '@tabler/icons-react'
|
||||
import { IconPlus, IconFileUpload, IconLayoutGrid, IconList } from '@tabler/icons-react'
|
||||
import ViewHeader from '@/layout/MainLayout/ViewHeader'
|
||||
import ErrorBoundary from '@/ErrorBoundary'
|
||||
import { useTheme } from '@mui/material/styles'
|
||||
|
||||
// ==============================|| CHATFLOWS ||============================== //
|
||||
|
||||
const Tools = () => {
|
||||
const theme = useTheme()
|
||||
const getAllToolsApi = useApi(toolsApi.getAllTools)
|
||||
|
||||
const [isLoading, setLoading] = useState(true)
|
||||
const [error, setError] = useState(null)
|
||||
const [showDialog, setShowDialog] = useState(false)
|
||||
const [dialogProps, setDialogProps] = useState({})
|
||||
const [view, setView] = useState(localStorage.getItem('toolsDisplayStyle') || 'card')
|
||||
|
||||
const inputRef = useRef(null)
|
||||
|
||||
const handleChange = (event, nextView) => {
|
||||
if (nextView === null) return
|
||||
localStorage.setItem('toolsDisplayStyle', nextView)
|
||||
setView(nextView)
|
||||
}
|
||||
|
||||
const onUploadFile = (file) => {
|
||||
try {
|
||||
const dialogProp = {
|
||||
|
|
@ -118,6 +128,38 @@ const Tools = () => {
|
|||
) : (
|
||||
<Stack flexDirection='column' sx={{ gap: 3 }}>
|
||||
<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' }}>
|
||||
<Button
|
||||
variant='outlined'
|
||||
|
|
@ -147,19 +189,25 @@ const Tools = () => {
|
|||
</StyledButton>
|
||||
</ButtonGroup>
|
||||
</ViewHeader>
|
||||
{isLoading ? (
|
||||
<Box display='grid' gridTemplateColumns='repeat(3, 1fr)' gap={gridSpacing}>
|
||||
<Skeleton variant='rounded' height={160} />
|
||||
<Skeleton variant='rounded' height={160} />
|
||||
<Skeleton variant='rounded' height={160} />
|
||||
</Box>
|
||||
{!view || view === 'card' ? (
|
||||
<>
|
||||
{isLoading ? (
|
||||
<Box display='grid' gridTemplateColumns='repeat(3, 1fr)' gap={gridSpacing}>
|
||||
<Skeleton variant='rounded' height={160} />
|
||||
<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}>
|
||||
{getAllToolsApi.data &&
|
||||
getAllToolsApi.data.map((data, index) => (
|
||||
<ItemCard data={data} key={index} onClick={() => edit(data)} />
|
||||
))}
|
||||
</Box>
|
||||
<ToolsTable data={getAllToolsApi.data} isLoading={isLoading} onSelect={edit} />
|
||||
)}
|
||||
{!isLoading && (!getAllToolsApi.data || getAllToolsApi.data.length === 0) && (
|
||||
<Stack sx={{ alignItems: 'center', justifyContent: 'center' }} flexDirection='column'>
|
||||
|
|
|
|||
Loading…
Reference in New Issue