diff --git a/components/versions/list-versions.js b/components/versions/list-versions.js
index 004d827..c51ba3e 100644
--- a/components/versions/list-versions.js
+++ b/components/versions/list-versions.js
@@ -249,8 +249,10 @@ export default function ListVersions({
@@ -271,13 +273,14 @@ export default function ListVersions({
size='small'
value={viewMode}
onChange={handleViewModeChange}
+ sx={{alignSelf: {xs: 'center', sm: 'auto'}}}
>
-
+
Table
-
+
Timeline
@@ -308,7 +311,6 @@ export default function ListVersions({
) : (
@@ -106,31 +107,29 @@ export default function VersionComparison({versionData, versionCompare, voteRefr
@{versionData.user_created?.split('-')[0] || 'Système'}
- {!outdated && (
-
-
- {versionData && (
-
- {formatDate(versionData.date_created)}
-
- )}
-
-
-
+
+ {versionData && (
+
+ {formatDate(versionData.date_created)}
+
+ )}
+
- )}
+
+
diff --git a/components/versions/version-timeline.js b/components/versions/version-timeline.js
index 61a3db6..e0f1d5c 100644
--- a/components/versions/version-timeline.js
+++ b/components/versions/version-timeline.js
@@ -1,118 +1,36 @@
import {useRef, useState, useEffect} from 'react'
-import {useTheme} from '@mui/material/styles'
import PropTypes from 'prop-types'
import Box from '@mui/material/Box'
import Typography from '@mui/material/Typography'
-import Card from '@mui/material/Card'
-import CardContent from '@mui/material/CardContent'
-import CardActions from '@mui/material/CardActions'
-import Button from '@mui/material/Button'
-import Chip from '@mui/material/Chip'
-import Avatar from '@mui/material/Avatar'
-import Divider from '@mui/material/Divider'
-import Timeline from '@mui/lab/Timeline'
-import TimelineItem from '@mui/lab/TimelineItem'
-import TimelineSeparator from '@mui/lab/TimelineSeparator'
-import TimelineConnector from '@mui/lab/TimelineConnector'
-import TimelineContent from '@mui/lab/TimelineContent'
-import TimelineDot from '@mui/lab/TimelineDot'
-import TimelineOppositeContent from '@mui/lab/TimelineOppositeContent'
-import AccessTimeIcon from '@mui/icons-material/AccessTime'
-import CheckCircleIcon from '@mui/icons-material/CheckCircle'
-import ErrorIcon from '@mui/icons-material/Error'
-import EditIcon from '@mui/icons-material/Edit'
+import IconButton from '@mui/material/IconButton'
+import Collapse from '@mui/material/Collapse'
import Snackbar from '@mui/material/Snackbar'
import Alert from '@mui/material/Alert'
+import CompareArrowsIcon from '@mui/icons-material/CompareArrows'
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
+import ExpandLessIcon from '@mui/icons-material/ExpandLess'
import SessionExpired from '../session/session-expired.js'
-import MarkdownRenderer from '../markdown-renderer/index.js'
import VersionDialog from './version-dialog.js'
import VoteButtons from './vote-buttons.js'
import CopyButton from './copy-button.js'
-import ShareButton from './share-button.js'
-import ExportPdfButton from './export-pdf-button.js'
-import PrintButton from './print-button.js'
import {formatDate} from '@/lib/format.js'
import {compareVersion} from '@/lib/directus.js'
-function getVersionStatus(version, index, totalVersions, data) {
- // Logic to determine version status based on position and data
- // Find which version is the "main" (published) by checking if it matches current content
- // This would require the current item content to be passed
- // For now, we assume the most recent is current unless it's been promoted
-
- // Check if this is the initial version
- if (index === totalVersions - 1) {
- return 'initial' // First version
+function getStatusColor(isOutdated, index) {
+ if (isOutdated) {
+ return '#D32F2F'
}
- // If there's a more recent version after this one, this is outdated
- // unless this IS the main version (would need item content to determine)
- if (index > 0) {
- return 'outdated' // Older versions are outdated
+ if (index === 0) {
+ return '#1976D2'
}
- // Most recent version is current (being edited/proposed)
- return 'current'
+ return '#9E9E9E'
}
-function getStatusConfig(status) {
- switch (status) {
- case 'current': {
- return {
- color: '#1976D2',
- bgColor: '#E3F2FD',
- icon: ,
- label: 'En cours',
- chipColor: 'primary'
- }
- }
-
- case 'published': {
- return {
- color: '#2E7D32',
- bgColor: '#E8F5E9',
- icon: ,
- label: 'Publié',
- chipColor: 'success'
- }
- }
-
- case 'archived': {
- return {
- color: '#757575',
- bgColor: '#F5F5F5',
- icon: ,
- label: 'Archivé',
- chipColor: 'default'
- }
- }
-
- case 'outdated': {
- return {
- color: '#D32F2F',
- bgColor: '#F9E8E8',
- icon: ,
- label: 'Obsolète',
- chipColor: 'error'
- }
- }
-
- default: {
- return {
- color: '#757575',
- bgColor: '#F5F5F5',
- icon: ,
- label: 'Archivé',
- chipColor: 'default'
- }
- }
- }
-}
-
-function VersionCard({
+function VersionItem({
version,
index,
- totalVersions,
accessToken,
userId,
countdownRef,
@@ -122,13 +40,11 @@ function VersionCard({
setVersionCompare,
onVoteResult
}) {
- const theme = useTheme()
- const [versionStatus, setVersionStatus] = useState(null)
const [isOutdated, setIsOutdated] = useState(false)
+ const [expanded, setExpanded] = useState(false)
- // Fetch real status from API
useEffect(() => {
- async function fetchVersionStatus() {
+ async function fetchStatus() {
try {
const comparisonData = await compareVersion({
accessToken,
@@ -140,41 +56,23 @@ function VersionCard({
})
if (comparisonData) {
- // Store outdated flag for vote disabling
setIsOutdated(comparisonData.outdated)
-
- // Determine status based on API response
- let status
- if (comparisonData.outdated) {
- status = 'outdated'
- } else if (index === totalVersions - 1) {
- status = 'initial'
- } else {
- status = 'current'
- }
- setVersionStatus(status)
}
- } catch (error) {
- // Fallback to position-based status on error
- setVersionStatus(getVersionStatus(version, index, totalVersions, null))
+ } catch {
+ setIsOutdated(false)
}
}
- fetchVersionStatus()
- }, [version.id, index, totalVersions, accessToken, userId, countdownRef, setError, setIsErrorAlertOpen])
+ fetchStatus()
+ }, [version.id, accessToken, userId, countdownRef, setError, setIsErrorAlertOpen])
- const status = versionStatus || getVersionStatus(version, index, totalVersions, null)
+ const statusColor = getStatusColor(isOutdated, index)
- const statusConfig = getStatusConfig(status)
- const userDisplayName = version.user_created?.split('-')[0] || 'Système'
-
- // Check if voting is disabled (after 3 days OR if outdated)
const createdAt = new Date(version.date_created)
const threeDaysAgo = new Date(Date.now() - (3 * 24 * 60 * 60 * 1000))
- const isExpired = createdAt < threeDaysAgo
- const isVoteDisabled = isExpired || isOutdated
+ const isVoteDisabled = createdAt < threeDaysAgo || isOutdated
- const handleCompareClick = async () => {
+ const handleCompare = async () => {
const comparisonData = await compareVersion({
accessToken,
userId,
@@ -190,162 +88,121 @@ function VersionCard({
}
}
- // Create content preview preserving markdown structure
- const createContentPreview = content => {
- if (!content) {
- return 'Contenu non disponible'
- }
-
- // If content is short enough, return as is
- if (content.length <= 150) {
- return content
- }
-
- // Find a good breaking point (end of sentence, paragraph, or word)
- const preview = content.slice(0, 150)
- const lastSentence = Math.max(preview.lastIndexOf('.'), preview.lastIndexOf('!'), preview.lastIndexOf('?'))
- const lastParagraph = preview.lastIndexOf('\n\n')
- const lastWord = preview.lastIndexOf(' ')
-
- // Choose the best breaking point
- let breakPoint = 150
- if (lastSentence > 100) {
- breakPoint = lastSentence + 1
- } else if (lastParagraph > 80) {
- breakPoint = lastParagraph
- } else if (lastWord > 100) {
- breakPoint = lastWord
- }
-
- return content.slice(0, breakPoint) + (content.length > breakPoint ? '...' : '')
- }
-
- const contentPreview = createContentPreview(version?.delta?.contenu)
-
return (
-
-
-
+
+
+
+
+ {/* Content */}
+
+ {/* Header row */}
+
-
-
- {statusConfig.icon}
-
-
-
- {version.name}
-
-
- par @{userDisplayName}
-
-
+
+
+ {version.name}
+
+
+ {formatDate(version.date_created, 'dd/MM/yy HH:mm')}
+
-
-
- {isExpired && !isOutdated && (
-
- )}
-
-
- div': {fontSize: '0.875rem', fontStyle: 'italic'}}}>
- (
-
- {children}
-
- )}
- />
-
-
-
-
- {formatDate(version.date_created, 'PPpp')}
-
-
-
-
-
-
-
+ {/* Actions */}
+
+
+
+
+ setExpanded(!expanded)}>
+ {expanded ? : }
+
-
-
-
-
-
-
+ {/* Expanded content */}
+
+
+ {/* Preview */}
+ {version.delta?.contenu && (
+
+ {version.delta.contenu}
+
+ )}
+
+ {/* Actions row */}
+
+
+
+
+
+
+
)
}
export default function VersionTimeline({
- collection,
data,
accessToken,
userId,
@@ -367,58 +224,24 @@ export default function VersionTimeline({
})
}
- const handleCloseSnackbar = () => {
- setSnackbar(prev => ({...prev, open: false}))
- }
-
return (
<>
-
-
- Historique des versions - {collection}
-
-
-
- {data.map((version, index) => (
-
-
-
- {formatDate(version.date_created, 'dd/MM/yyyy')}
-
-
-
- {formatDate(version.date_created, 'HH:mm')}
-
-
-
-
-
- {index === 0 ? : }
-
- {index < data.length - 1 && }
-
-
-
-
-
-
- ))}
-
+
+ {data.map((version, index) => (
+
+ ))}
{isOpenComparison && (
@@ -440,9 +263,14 @@ export default function VersionTimeline({
open={snackbar.open}
autoHideDuration={6000}
anchorOrigin={{vertical: 'bottom', horizontal: 'center'}}
- onClose={handleCloseSnackbar}
+ onClose={() => setSnackbar(prev => ({...prev, open: false}))}
>
-
+ setSnackbar(prev => ({...prev, open: false}))}
+ >
{snackbar.message}
@@ -451,7 +279,6 @@ export default function VersionTimeline({
}
VersionTimeline.propTypes = {
- collection: PropTypes.oneOf(['titres', 'articles']).isRequired,
data: PropTypes.array.isRequired,
accessToken: PropTypes.string.isRequired,
userId: PropTypes.string.isRequired,
@@ -459,10 +286,9 @@ VersionTimeline.propTypes = {
setIsErrorAlertOpen: PropTypes.func.isRequired
}
-VersionCard.propTypes = {
+VersionItem.propTypes = {
version: PropTypes.object.isRequired,
index: PropTypes.number.isRequired,
- totalVersions: PropTypes.number.isRequired,
accessToken: PropTypes.string.isRequired,
userId: PropTypes.string.isRequired,
countdownRef: PropTypes.object.isRequired,