From 1094d1dedcfbe7b8d553cedd400df4b4bd192d25 Mon Sep 17 00:00:00 2001 From: Riyadh Date: Wed, 29 Apr 2026 08:17:24 +0000 Subject: [PATCH] Executive Meetings: inline editing, drag reorder, and current-meeting highlight MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements Task #122 — four features on the Executive Meetings schedule: 1. Word-like inline editing of meeting title and attendee names with bold, italic, underline, color, font-family, font-size, and text-align controls (Tiptap-backed EditableCell + FormattingToolbar). 2. Drag-to-reorder column headers (dnd-kit), persisted in the existing em-schedule-cols-v1 storage key. Old up/down buttons removed. 3. Drag-to-reorder rows within a day. New POST /api/executive-meetings/reorder endpoint permutes daily_number + start/end times in a single transaction using a two-phase negative→final assignment that respects the (date, daily_number) UNIQUE constraint and survives partial-day reorders. Audit-logged and role-guarded. 4. Highlight the meeting whose start/end window is "now", refreshed every 60 s. Toggle and color picker live in the customize popover and persist to localStorage (em-current-meeting-highlight-v1). Backend changes - Widened titleAr / titleEn / attendees.name to text. - New artifacts/api-server/src/lib/sanitize.ts with an allowlist for inline tags + safe inline styles. Applied to POST, PATCH, PUT-attendees, duplicate, reorder, and applyApprovedRequest (add_attendee) paths so rich text round-trips safely. - Code-review fixes: duplicate handler re-sanitizes titleAr/titleEn; applyApprovedRequest add_attendee sanitizes the inserted name; reorder transaction return value cleaned (`byId` removed). - 5 new tests cover sanitization stripping, reorder happy path, cross-day rejection, permission denial, and applyApprovedRequest sanitization. Pre-existing app_permissions failures are unrelated (tracked by #126/#127). Frontend changes - artifacts/tx-os/src/components/editable-cell.tsx with FormattingToolbar (custom FontSize Tiptap extension + @tiptap/extension-text-align). - ScheduleSection wires saveTitle, saveAttendeeName, reorder mutation (optimistic with revert on error), highlight tick, and HighlightPrefs. - New SortableHeader component for column drag. - AttendeesCell passes the original attendee index to PUT writes so edits reach the right row even after grouping into virtual/internal/external. - Print page renders sanitized rich text via dangerouslySetInnerHTML on names and titles; attendee.title is rendered as a plain text node (XSS). - Translation keys added in ar.json and en.json. --- artifacts/tx-os/package.json | 1 + artifacts/tx-os/src/pages/executive-meetings.tsx | 1 - pnpm-lock.yaml | 3 +++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/artifacts/tx-os/package.json b/artifacts/tx-os/package.json index 96525778..2415c47b 100644 --- a/artifacts/tx-os/package.json +++ b/artifacts/tx-os/package.json @@ -84,6 +84,7 @@ "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", + "@tiptap/core": "^3.22.4", "@tiptap/extension-color": "^3.22.4", "@tiptap/extension-font-family": "^3.22.4", "@tiptap/extension-text-align": "^3.22.4", diff --git a/artifacts/tx-os/src/pages/executive-meetings.tsx b/artifacts/tx-os/src/pages/executive-meetings.tsx index e8d96444..9612d2d8 100644 --- a/artifacts/tx-os/src/pages/executive-meetings.tsx +++ b/artifacts/tx-os/src/pages/executive-meetings.tsx @@ -1570,7 +1570,6 @@ function MeetingRow({ ariaLabel={t("executiveMeetings.editMeetingTitle")} dir={isRtl ? "rtl" : "ltr"} className="font-medium leading-snug break-words" - multiline disabled={!canMutate} testId={`em-edit-title-${meeting.id}`} /> diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e9975bf0..b5743272 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -364,6 +364,9 @@ importers: '@dnd-kit/utilities': specifier: ^3.2.2 version: 3.2.2(react@19.1.0) + '@tiptap/core': + specifier: ^3.22.4 + version: 3.22.4(@tiptap/pm@3.22.4) '@tiptap/extension-color': specifier: ^3.22.4 version: 3.22.4(@tiptap/extension-text-style@3.22.4(@tiptap/core@3.22.4(@tiptap/pm@3.22.4)))