Task #152: cell-merge + current-meeting tint on EM schedule
Adds two related features to the executive-meetings schedule: 1. Current-meeting tinting — meeting/attendees/time cells of the row matching the current time get a soft wash of the user's highlight color (~13% alpha), keeping their original text color and the existing colored ring. The # cell stays solid white/red. 2. Cell-merge overlay — editors can merge "meeting+attendees", "meeting+attendees+time", or the whole row into a single free-text cell. Stored in the DB so all viewers see the same overlay; the originals (titleAr/En, attendees, start/endTime) stay untouched and are restored on Unmerge. Implementation notes - DB: 3 nullable columns added to executive_meetings (merge_start_column, merge_end_column, merge_text). Applied via direct ALTER TABLE because pnpm --filter db run push is blocked by the pre-existing app_permissions duplicate (Task #148, surfaced as the new follow-up #156). Schema file kept in sync. - API: meetingPatchSchema accepts an optional `merge` field (`null | {start,end,text}`) with start<=end ordering and server-side sanitizeRichText on the text. Reuses the existing PATCH route. - Frontend: new MergeMenu component + canonical-order range resolution so merges still render when boundary columns are hidden, and gracefully degrade to unmerged rendering (without losing DB state) when column reordering makes the visible span non-contiguous. Unmerge stays available whenever a stored merge exists, even in degraded state, and existing mergeText is preserved on re-merge. - i18n: en + ar keys under executiveMeetings.merge.* Out of scope (deferred to follow-ups #154 / #155, per task brief) - API + e2e test coverage for the merge endpoint and UI flows - Realtime emission for executive-meetings mutations (no existing emit on this surface; covered by #155) Validation - TypeScript compiles cleanly across api-server + tx-os. - API tests: 108/110 pass — the 2 failures are the pre-existing app_permissions-unique cases (Task #148, follow-up #156), unrelated to this change. - Architect code review approved after addressing hidden-column fallback, non-contiguous reorder degradation, and Unmerge-availability edge cases.
This commit is contained in:
@@ -33,6 +33,17 @@ export const executiveMeetingsTable = pgTable(
|
||||
isHighlighted: integer("is_highlighted").notNull().default(0),
|
||||
notes: text("notes"),
|
||||
attachments: jsonb("attachments").default([]),
|
||||
// Optional cell-merge overlay for the schedule grid. When set, the
|
||||
// schedule renders one merged cell spanning columns
|
||||
// [mergeStartColumn..mergeEndColumn] and shows mergeText (sanitized
|
||||
// HTML) instead of the original column values. The original
|
||||
// titleAr/En + attendees + start/endTime stay untouched in the DB,
|
||||
// so clearing the merge restores the original cells exactly.
|
||||
// Allowed values for the column ids match the frontend ColumnId
|
||||
// enum: "number" | "meeting" | "attendees" | "time".
|
||||
mergeStartColumn: varchar("merge_start_column", { length: 32 }),
|
||||
mergeEndColumn: varchar("merge_end_column", { length: 32 }),
|
||||
mergeText: text("merge_text"),
|
||||
createdBy: integer("created_by").references(() => usersTable.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user