diff --git a/web/modules/custom/figli_compta_ledger/css/home.css b/web/modules/custom/figli_compta_ledger/css/home.css index 8f7f058..1788a34 100644 --- a/web/modules/custom/figli_compta_ledger/css/home.css +++ b/web/modules/custom/figli_compta_ledger/css/home.css @@ -217,6 +217,24 @@ html.gin--dark-mode #figli-home-app { #figli-home-app .type-ouverture { background: #7c3aed1a; color: #9061f0; } #figli-home-app .type-autre { background: #6b72801a; color: var(--figli-text-light); } +/* Click-to-edit type badge -- swaps for a native + // instead of the badge -- only one at a time. + editingTypeId: null, + typeUpdateError: null, // Fenêtre glissante. windowStart: null, windowEnd: null, @@ -396,6 +417,36 @@ toggleEntreeFilter(id) { this.filterEntreeId = this.filterEntreeId === id ? null : id; }, + startEditType(item) { + this.typeUpdateError = null; + this.editingTypeId = item.id; + }, + // Optimistically patches the row in `rows` (not the transient + // `item` from groupedRows -- that object is rebuilt from scratch on + // every computed re-evaluation, so mutating it wouldn't stick) for + // instant feedback, then reconciles with the server in the + // background via reloadWindow() (picks up anything else the save + // touched, e.g. a cleared field_entree_liee). + async saveType(item, event) { + const newType = event.target.value; + this.editingTypeId = null; + if (newType === item.type) return; + try { + const result = await updateLigneType(item.nid, newType); + const row = this.rows.find((r) => r.id === item.id); + if (row) { + row.type = newType; + row.linkable = LINKABLE_TYPES.includes(newType); + if (result.entree_liee_cleared) { + row.entreeLieeId = null; + row.entreeLieeLabel = null; + } + } + this.reloadWindow(); + } catch (err) { + this.typeUpdateError = err.message; + } + }, onCellHover(evt) { const cell = evt.target.closest('td, th'); if (!cell) return; diff --git a/web/modules/custom/figli_compta_ledger/src/Controller/LedgerActionsController.php b/web/modules/custom/figli_compta_ledger/src/Controller/LedgerActionsController.php new file mode 100644 index 0000000..52ead26 --- /dev/null +++ b/web/modules/custom/figli_compta_ledger/src/Controller/LedgerActionsController.php @@ -0,0 +1,83 @@ +bundle() !== 'ligne_comptable') { + return new JsonResponse(['error' => 'Type de contenu invalide.'], 404); + } + + // Scoped to CsrfRequestHeaderAccessCheck::TOKEN_KEY -- the same value + // core's own /session/token controller generates against, which is + // what the frontend fetches this token from. + $csrfToken = $request->headers->get('X-CSRF-Token', ''); + if (!\Drupal::csrfToken()->validate($csrfToken, CsrfRequestHeaderAccessCheck::TOKEN_KEY)) { + return new JsonResponse(['error' => 'Jeton de sécurité invalide, rechargez la page.'], 403); + } + + $data = json_decode($request->getContent(), TRUE); + $type = is_array($data) ? ($data['type'] ?? NULL) : NULL; + if (!in_array($type, self::ALLOWED_TYPES, TRUE)) { + return new JsonResponse(['error' => 'Type de ligne invalide.'], 400); + } + + $node->set('field_type_ligne', $type); + + // A type that's no longer linkable shouldn't keep a stale + // field_entree_liee reference around (mirrors the form's #states: + // charge/autre/ouverture/entree don't expose that field at all). + if (!in_array($type, self::LINKABLE_TYPES, TRUE) + && $node->hasField('field_entree_liee') + && !$node->get('field_entree_liee')->isEmpty()) { + $node->set('field_entree_liee', NULL); + } + + try { + $node->save(); + } + catch (EntityStorageException $e) { + return new JsonResponse(['error' => $e->getMessage()], 422); + } + + return new JsonResponse([ + 'success' => TRUE, + 'type' => $type, + 'entree_liee_cleared' => !in_array($type, self::LINKABLE_TYPES, TRUE), + ]); + } + +} diff --git a/web/modules/custom/figli_compta_ledger/templates/figli-compta-home.html.twig b/web/modules/custom/figli_compta_ledger/templates/figli-compta-home.html.twig index 96ed064..93ce752 100644 --- a/web/modules/custom/figli_compta_ledger/templates/figli-compta-home.html.twig +++ b/web/modules/custom/figli_compta_ledger/templates/figli-compta-home.html.twig @@ -67,6 +67,8 @@ {{ filteredRows.length }} / {{ rows.length }} lignes chargées{{ errorCount ? ' — ' + errorCount + ' avec écart' : '' }} +

Erreur : {{ typeUpdateError }}

+

Chargement des données…

Erreur de chargement : {{ error }}

@@ -120,7 +122,24 @@ {{ formatDate(item.date) }} {{ item.client || '—' }} - {{ typeLabel(item.type) }} + + + {{ typeLabel(item.type) }} + {{ item.libelle }}