2024-11-28 07:55:51 +04:00
|
|
|
import {forwardRef, useRef, useState} from 'react'
|
2024-09-15 18:02:30 +04:00
|
|
|
import PropTypes from 'prop-types'
|
|
|
|
|
import Table from '@mui/material/Table'
|
|
|
|
|
import TableBody from '@mui/material/TableBody'
|
|
|
|
|
import TableCell from '@mui/material/TableCell'
|
|
|
|
|
import TableContainer from '@mui/material/TableContainer'
|
|
|
|
|
import TableHead from '@mui/material/TableHead'
|
|
|
|
|
import TableRow from '@mui/material/TableRow'
|
|
|
|
|
import Paper from '@mui/material/Paper'
|
|
|
|
|
import Button from '@mui/material/Button'
|
2025-07-23 17:41:00 +04:00
|
|
|
import ToggleButton from '@mui/material/ToggleButton'
|
|
|
|
|
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'
|
|
|
|
|
import ViewListIcon from '@mui/icons-material/ViewList'
|
|
|
|
|
import TimelineIcon from '@mui/icons-material/Timeline'
|
2024-09-15 18:02:30 +04:00
|
|
|
import {TableVirtuoso} from 'react-virtuoso'
|
|
|
|
|
import {Box, Typography} from '@mui/material'
|
2025-07-23 08:45:15 +04:00
|
|
|
import SessionExpired from '../session/session-expired.js'
|
2024-11-28 07:55:51 +04:00
|
|
|
import VersionDialog from './version-dialog.js'
|
2025-07-23 17:41:00 +04:00
|
|
|
import VersionTimeline from './version-timeline.js'
|
2025-07-23 18:50:23 +04:00
|
|
|
import VersionSearch from './version-search.js'
|
|
|
|
|
import VersionFilters from './version-filters.js'
|
2024-09-15 18:02:30 +04:00
|
|
|
import {formatDate} from '@/lib/format.js'
|
2024-11-28 07:55:51 +04:00
|
|
|
import {compareVersion} from '@/lib/directus.js'
|
2025-07-23 18:50:23 +04:00
|
|
|
import {filterVersions, getFilterStats} from '@/lib/version-utils.js'
|
2024-09-15 18:02:30 +04:00
|
|
|
|
|
|
|
|
const columns = [
|
|
|
|
|
{
|
|
|
|
|
width: 200,
|
|
|
|
|
label: 'Version',
|
|
|
|
|
dataKey: 'name',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
width: 120,
|
|
|
|
|
label: 'Créée le',
|
|
|
|
|
dataKey: 'date_created',
|
|
|
|
|
numeric: true,
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const VirtuosoTableComponents = {
|
2024-11-28 07:55:51 +04:00
|
|
|
Scroller: forwardRef((props, ref) => (
|
2024-09-15 18:02:30 +04:00
|
|
|
<TableContainer component={Paper} {...props} ref={ref} />
|
|
|
|
|
)),
|
|
|
|
|
Table: props => (
|
|
|
|
|
<Table {...props} sx={{borderCollapse: 'separate', tableLayout: 'fixed'}} />
|
|
|
|
|
),
|
2024-11-28 07:55:51 +04:00
|
|
|
TableHead: forwardRef((props, ref) => <TableHead {...props} ref={ref} />),
|
2024-09-15 18:02:30 +04:00
|
|
|
TableRow,
|
2024-11-28 07:55:51 +04:00
|
|
|
TableBody: forwardRef((props, ref) => <TableBody {...props} ref={ref} />),
|
2024-09-15 18:02:30 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function fixedHeaderContent() {
|
|
|
|
|
return (
|
|
|
|
|
<TableRow>
|
|
|
|
|
{columns.map(column => (
|
|
|
|
|
<TableCell
|
|
|
|
|
key={column.dataKey}
|
|
|
|
|
variant='head'
|
|
|
|
|
align={column.numeric || false ? 'right' : 'left'}
|
|
|
|
|
style={{width: column.width}}
|
|
|
|
|
sx={{backgroundColor: 'background.paper'}}
|
|
|
|
|
>
|
|
|
|
|
{column.label}
|
|
|
|
|
</TableCell>
|
|
|
|
|
))}
|
|
|
|
|
</TableRow>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-28 07:55:51 +04:00
|
|
|
function rowContent({
|
|
|
|
|
row,
|
|
|
|
|
accessToken,
|
|
|
|
|
userId,
|
|
|
|
|
countdownRef,
|
|
|
|
|
setError,
|
|
|
|
|
setIsErrorAlertOpen,
|
|
|
|
|
setIsOpenComparison,
|
2024-12-17 05:45:16 +04:00
|
|
|
setVersionCompare
|
2024-11-28 07:55:51 +04:00
|
|
|
}) {
|
|
|
|
|
const handleButtonClick = async versionId => {
|
|
|
|
|
const version = await compareVersion({
|
|
|
|
|
accessToken,
|
|
|
|
|
userId,
|
|
|
|
|
versionId,
|
|
|
|
|
countdownRef,
|
|
|
|
|
setError,
|
|
|
|
|
setIsErrorAlertOpen
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if (version) {
|
2024-12-17 05:45:16 +04:00
|
|
|
setVersionCompare({...version, versionId})
|
2024-11-28 07:55:51 +04:00
|
|
|
setIsOpenComparison(true)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 18:02:30 +04:00
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
{columns.map(column => (
|
|
|
|
|
<TableCell
|
|
|
|
|
key={column.dataKey}
|
|
|
|
|
align={column.numeric || false ? 'right' : 'left'}
|
|
|
|
|
>
|
2024-11-28 07:55:51 +04:00
|
|
|
{column.dataKey === 'date_created'
|
|
|
|
|
? formatDate(row[column.dataKey], 'Pp')
|
|
|
|
|
: <Button variant='outlined' color='success' onClick={() => handleButtonClick(row.id)}>{row[column.dataKey]}</Button>}
|
2024-09-15 18:02:30 +04:00
|
|
|
</TableCell>
|
|
|
|
|
))}
|
|
|
|
|
</>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-28 07:55:51 +04:00
|
|
|
export default function ListVersions({
|
|
|
|
|
collection,
|
|
|
|
|
data,
|
|
|
|
|
accessToken,
|
|
|
|
|
userId,
|
|
|
|
|
setError,
|
|
|
|
|
setIsErrorAlertOpen
|
|
|
|
|
}) {
|
|
|
|
|
const countdownRef = useRef()
|
2025-07-23 17:41:00 +04:00
|
|
|
const [viewMode, setViewMode] = useState('table')
|
2024-11-28 07:55:51 +04:00
|
|
|
const [isOpenComparison, setIsOpenComparison] = useState(false)
|
2024-12-17 05:45:16 +04:00
|
|
|
const [versionCompare, setVersionCompare] = useState(null)
|
2025-07-23 18:50:23 +04:00
|
|
|
const [searchTerm, setSearchTerm] = useState('')
|
|
|
|
|
const [filters, setFilters] = useState({
|
|
|
|
|
author: '',
|
|
|
|
|
dateFrom: '',
|
|
|
|
|
dateTo: '',
|
|
|
|
|
status: ''
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Filter data based on search and filters
|
|
|
|
|
const filteredData = filterVersions(data, searchTerm, filters)
|
|
|
|
|
const stats = getFilterStats(data, filteredData)
|
2024-12-17 05:45:16 +04:00
|
|
|
|
|
|
|
|
const versionData = data.find(({id}) => id === versionCompare?.versionId)
|
2024-11-28 07:55:51 +04:00
|
|
|
|
2025-07-23 18:50:23 +04:00
|
|
|
const handleSearchChange = newSearchTerm => {
|
|
|
|
|
setSearchTerm(newSearchTerm)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleFiltersChange = newFilters => {
|
|
|
|
|
setFilters(newFilters)
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-23 17:41:00 +04:00
|
|
|
const handleViewModeChange = (event, newViewMode) => {
|
|
|
|
|
if (newViewMode !== null) {
|
|
|
|
|
setViewMode(newViewMode)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-15 18:02:30 +04:00
|
|
|
return (
|
2024-11-28 07:55:51 +04:00
|
|
|
<>
|
|
|
|
|
<Box>
|
2025-07-23 17:41:00 +04:00
|
|
|
<Box sx={{
|
|
|
|
|
display: 'flex',
|
|
|
|
|
justifyContent: 'space-between',
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
mb: 2
|
|
|
|
|
}}
|
|
|
|
|
>
|
2025-07-23 18:50:23 +04:00
|
|
|
<Box>
|
|
|
|
|
<Typography variant='button' sx={{fontWeight: 'bold'}}>
|
|
|
|
|
{collection}
|
|
|
|
|
</Typography>
|
|
|
|
|
{stats.hidden > 0 && (
|
|
|
|
|
<Typography variant='caption' color='text.secondary' sx={{ml: 1}}>
|
|
|
|
|
({stats.filtered}/{stats.total} versions)
|
|
|
|
|
</Typography>
|
|
|
|
|
)}
|
|
|
|
|
</Box>
|
2025-07-23 17:41:00 +04:00
|
|
|
|
|
|
|
|
<ToggleButtonGroup
|
|
|
|
|
exclusive
|
|
|
|
|
color='primary'
|
|
|
|
|
size='small'
|
|
|
|
|
value={viewMode}
|
|
|
|
|
onChange={handleViewModeChange}
|
|
|
|
|
>
|
|
|
|
|
<ToggleButton value='table' aria-label='vue tableau'>
|
|
|
|
|
<ViewListIcon sx={{mr: 1}} />
|
|
|
|
|
Table
|
|
|
|
|
</ToggleButton>
|
|
|
|
|
<ToggleButton value='timeline' aria-label='vue chronologique'>
|
|
|
|
|
<TimelineIcon sx={{mr: 1}} />
|
|
|
|
|
Timeline
|
|
|
|
|
</ToggleButton>
|
|
|
|
|
</ToggleButtonGroup>
|
|
|
|
|
</Box>
|
|
|
|
|
|
2025-07-23 18:50:23 +04:00
|
|
|
<VersionSearch onSearchChange={handleSearchChange} />
|
|
|
|
|
<VersionFilters data={data} onFiltersChange={handleFiltersChange} />
|
|
|
|
|
|
|
|
|
|
{filteredData.length === 0 ? (
|
|
|
|
|
<Box sx={{textAlign: 'center', py: 4}}>
|
|
|
|
|
<Typography variant='body1' color='text.secondary'>
|
|
|
|
|
{searchTerm || Object.values(filters).some(Boolean)
|
|
|
|
|
? 'Aucune version ne correspond aux critères de recherche'
|
|
|
|
|
: 'Aucune version disponible'}
|
|
|
|
|
</Typography>
|
|
|
|
|
</Box>
|
2025-07-23 17:41:00 +04:00
|
|
|
) : (
|
2025-07-23 18:50:23 +04:00
|
|
|
viewMode === 'table' ? (
|
|
|
|
|
<Paper style={{height: 350, width: '100%', marginBlock: 5}}>
|
|
|
|
|
<TableVirtuoso
|
|
|
|
|
data={filteredData}
|
|
|
|
|
components={VirtuosoTableComponents}
|
|
|
|
|
fixedHeaderContent={fixedHeaderContent}
|
|
|
|
|
itemContent={(index, row) => rowContent({
|
|
|
|
|
index, row, accessToken, userId, countdownRef, setError, setIsErrorAlertOpen, setIsOpenComparison, setVersionCompare
|
|
|
|
|
})}
|
|
|
|
|
/>
|
|
|
|
|
</Paper>
|
|
|
|
|
) : (
|
|
|
|
|
<VersionTimeline
|
|
|
|
|
collection={collection}
|
|
|
|
|
data={filteredData}
|
|
|
|
|
accessToken={accessToken}
|
|
|
|
|
userId={userId}
|
|
|
|
|
setError={setError}
|
|
|
|
|
setIsErrorAlertOpen={setIsErrorAlertOpen}
|
|
|
|
|
/>
|
|
|
|
|
)
|
2025-07-23 17:41:00 +04:00
|
|
|
)}
|
2024-11-28 07:55:51 +04:00
|
|
|
</Box>
|
2025-07-23 17:41:00 +04:00
|
|
|
|
2024-11-28 07:55:51 +04:00
|
|
|
{isOpenComparison && (
|
2024-12-17 05:45:16 +04:00
|
|
|
<VersionDialog versionData={versionData} versionCompare={versionCompare} isOpen={isOpenComparison} setIsOpen={setIsOpenComparison} />
|
2024-11-28 07:55:51 +04:00
|
|
|
)}
|
2025-07-23 08:45:15 +04:00
|
|
|
<SessionExpired ref={countdownRef} setError={setError} setIsErrorAlertOpen={setIsErrorAlertOpen} />
|
2024-11-28 07:55:51 +04:00
|
|
|
</>
|
2024-09-15 18:02:30 +04:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ListVersions.propTypes = {
|
|
|
|
|
collection: PropTypes.oneOf(['titres', 'articles']).isRequired,
|
2024-11-28 07:55:51 +04:00
|
|
|
data: PropTypes.array.isRequired,
|
|
|
|
|
accessToken: PropTypes.string.isRequired,
|
|
|
|
|
userId: PropTypes.string.isRequired,
|
|
|
|
|
setError: PropTypes.func.isRequired,
|
|
|
|
|
setIsErrorAlertOpen: PropTypes.func.isRequired
|
2024-09-15 18:02:30 +04:00
|
|
|
}
|