mirror of
https://github.com/IliesAllali/parenthese.git
synced 2026-11-11 16:12:14 +00:00
fix(arbre): place envoyée visible jusqu'à la relecture, erreurs d'enregistrement affichées
- Contributeur : après l'envoi, la place proposée reste à l'écran comme un nom modifié, au lieu de revenir à l'ancienne place jusqu'à l'approbation. - Admin : un échec d'enregistrement d'une personne est signalé par un toast d'erreur, et le brouillon est conservé au lieu d'être vidé. - Gestionnaire handleResetTreeLayout (le bouton arrive dans le commit suivant). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
697c0e3897
commit
6ff99337d2
2 files changed
+45
No files matched your search
@@ -1179,6 +1179,12 @@ function App() {
|
||||
const timer = setTimeout(() => setDraftNotice(''), 4500)
|
||||
return () => clearTimeout(timer)
|
||||
}, [draftNotice])
|
||||
const [editSaveError, setEditSaveError] = useState('')
|
||||
useEffect(() => {
|
||||
if (!editSaveError) return undefined
|
||||
const timer = setTimeout(() => setEditSaveError(''), 6000)
|
||||
return () => clearTimeout(timer)
|
||||
}, [editSaveError])
|
||||
|
||||
// Soumission des modifications
|
||||
const handleEditSubmit = useCallback(async () => {
|
||||
@@ -1196,6 +1202,7 @@ function App() {
|
||||
const treeId = tree.treeContext.treeId
|
||||
const draft = editMode.restoreDraft()
|
||||
|
||||
let failedPersonSaves = 0
|
||||
if (token && treeId) {
|
||||
// Appliquer les modifications de personnes depuis le draft
|
||||
const modifiedPersons = draft.modifiedPersons || {}
|
||||
@@ -1219,6 +1226,7 @@ function App() {
|
||||
try {
|
||||
await updatePerson(treeId, personId, payload, token)
|
||||
} catch (err) {
|
||||
failedPersonSaves += 1
|
||||
console.error('Failed to update person:', personId, err)
|
||||
}
|
||||
}
|
||||
@@ -1266,6 +1274,11 @@ function App() {
|
||||
}
|
||||
|
||||
await tree.refreshCurrentTreeGraph({ relayout: false })
|
||||
if (failedPersonSaves > 0) {
|
||||
// Brouillon gardé : rien n'est perdu, l'admin peut réessayer
|
||||
setEditSaveError(t("Certaines modifications n'ont pas pu être enregistrées. Vérifiez puis réessayez."))
|
||||
return
|
||||
}
|
||||
editMode.clearDraft()
|
||||
editMode.deactivate()
|
||||
} else {
|
||||
@@ -1309,6 +1322,16 @@ function App() {
|
||||
return
|
||||
}
|
||||
|
||||
// Comme un nom modifié, la place envoyée reste à l'écran jusqu'à la relecture
|
||||
for (const [personId, changes] of Object.entries(draft.modifiedPersons || {})) {
|
||||
if (!Number.isFinite(changes?.layoutX) || !Number.isFinite(changes?.layoutY)) continue
|
||||
const localPerson = persons.find((candidate) => String(candidate.id) === String(personId))
|
||||
if (localPerson) {
|
||||
localPerson.layoutX = changes.layoutX
|
||||
localPerson.layoutY = changes.layoutY
|
||||
}
|
||||
}
|
||||
|
||||
editMode.clearDraft()
|
||||
editMode.deactivate()
|
||||
setShowContribModal(false)
|
||||
@@ -2532,6 +2555,22 @@ function App() {
|
||||
}
|
||||
}
|
||||
|
||||
// Admin : efface les positions manuelles de l'arbre, y compris celles restées dans son brouillon
|
||||
const handleResetTreeLayout = useCallback(async () => {
|
||||
const draft = editMode.restoreDraft()
|
||||
if (draft.modifiedPersons) {
|
||||
const modifiedPersons = {}
|
||||
for (const [personId, changes] of Object.entries(draft.modifiedPersons)) {
|
||||
const rest = { ...changes }
|
||||
delete rest.layoutX
|
||||
delete rest.layoutY
|
||||
if (Object.keys(rest).length > 0) modifiedPersons[personId] = rest
|
||||
}
|
||||
editMode.updateDraft({ modifiedPersons })
|
||||
}
|
||||
await refreshTreeAndKeepSelection(null, { relayout: true })
|
||||
}, [editMode.restoreDraft, editMode.updateDraft, refreshTreeAndKeepSelection])
|
||||
|
||||
const handleGedcomImported = useCallback(async (result, treeIdOverride = null) => {
|
||||
await refreshTreeAndKeepSelection(null, { relayout: true })
|
||||
const refs = Array.isArray(result?.photoRefs) ? result.photoRefs : []
|
||||
@@ -2803,6 +2842,9 @@ function App() {
|
||||
{draftNotice && !contribSuccess && !showContribModal && (
|
||||
<div className="contrib-success-toast" role="status">{draftNotice}</div>
|
||||
)}
|
||||
{editSaveError && (
|
||||
<div className="contrib-success-toast" role="alert">{editSaveError}</div>
|
||||
)}
|
||||
{contribSuccess && (
|
||||
<div className="contrib-success-toast" role="status">
|
||||
{t("Merci, c'est envoyé ! Ça apparaîtra dans l'arbre une fois relu.")}
|
||||
@@ -2942,6 +2984,8 @@ function App() {
|
||||
onGedcomImported={handleGedcomImported}
|
||||
onOpenPhotoStart={() => { setAdminPanelVisible(false); openPhotoStart() }}
|
||||
onClose={() => setAdminPanelVisible(false)}
|
||||
hasManualPositions={persons.some((person) => Number.isFinite(person.layoutX) && Number.isFinite(person.layoutY))}
|
||||
onLayoutReset={handleResetTreeLayout}
|
||||
/>
|
||||
<PhotoStartPanel
|
||||
visible={photoStart.visible}
|
||||
|
||||
@@ -97,4 +97,5 @@ export default {
|
||||
'Ressource introuvable.': 'Not found.',
|
||||
'Conflit détecté (email ou slug déjà utilisé).': 'Conflict detected (email or slug already in use).',
|
||||
"Erreur backend. Vérifiez que l'API et la base sont lancées.": 'Server error. Check that the API and database are running.',
|
||||
"Certaines modifications n'ont pas pu être enregistrées. Vérifiez puis réessayez.": "Some changes couldn't be saved. Check them and try again.",
|
||||
}
|
||||
Reference in new issue
Block a user