e93ca043f8
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, and font controls (Tiptap-backed EditableCell). 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 swaps daily_number in a single transaction using a two-phase negative→final assignment that respects the (date, daily_number) UNIQUE constraint. 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. Backend changes - Widened titleAr / titleEn / attendees.name to text (applied via direct ALTER TABLE because db:push --force is currently blocked by Task #126). - New artifacts/api-server/src/lib/sanitize.ts with an allowlist for inline tags + safe inline styles. Applied to POST, PATCH, PUT-attendees, duplicate, and reorder paths so rich text round-trips safely. - Code-review fix: duplicate handler now re-sanitizes titleAr/titleEn. - Code-review fix: print page no longer interpolates the unsanitized attendee.title into dangerouslySetInnerHTML. - 4 new tests cover sanitization stripping, reorder happy path, cross-day rejection, and permission denial. Pre-existing app_permissions failures are unrelated and tracked by Task #126. Frontend changes - artifacts/tx-os/src/components/editable-cell.tsx with FormattingToolbar. - ScheduleSection wires saveTitle, saveAttendeeName, reorder mutation (optimistic with revert on error), highlight tick, and HighlightPrefs. - New SortableHeader component for column drag. - AttendeesCell now passes the original attendee index to PUT writes so edits reach the right row even after grouping into virtual/internal/ external sections. - Print page renders sanitized HTML via dangerouslySetInnerHTML on names and titles (titles still rendered as plain text on the print page). - Translation keys added in ar.json and en.json. Drift - Sanitization for attendee.title was identified by the architect review as a defense-in-depth gap and proposed as Task #130 rather than fixing inline; the print-page XSS path that depended on it was fixed directly.
47 lines
1.3 KiB
JSON
47 lines
1.3 KiB
JSON
{
|
|
"name": "@workspace/api-server",
|
|
"version": "0.0.0",
|
|
"private": true,
|
|
"type": "module",
|
|
"scripts": {
|
|
"dev": "export NODE_ENV=development && pnpm run build && pnpm run start",
|
|
"build": "node ./build.mjs",
|
|
"start": "node --enable-source-maps ./dist/index.mjs",
|
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
"test": "node --test 'tests/**/*.test.mjs'"
|
|
},
|
|
"dependencies": {
|
|
"@google-cloud/storage": "^7.19.0",
|
|
"@workspace/api-zod": "workspace:*",
|
|
"@workspace/db": "workspace:*",
|
|
"bcryptjs": "^3.0.3",
|
|
"connect-pg-simple": "^10.0.0",
|
|
"cookie-parser": "^1.4.7",
|
|
"cors": "^2",
|
|
"drizzle-orm": "catalog:",
|
|
"express": "^5",
|
|
"express-session": "^1.19.0",
|
|
"google-auth-library": "^10.6.2",
|
|
"pino": "^9",
|
|
"pino-http": "^10",
|
|
"sanitize-html": "^2.17.3",
|
|
"socket.io": "^4.8.3",
|
|
"zod": "catalog:"
|
|
},
|
|
"devDependencies": {
|
|
"@types/bcryptjs": "^3.0.0",
|
|
"@types/connect-pg-simple": "^7.0.3",
|
|
"@types/cookie-parser": "^1.4.10",
|
|
"@types/cors": "^2.8.19",
|
|
"@types/express": "^5.0.6",
|
|
"@types/express-session": "^1.19.0",
|
|
"@types/node": "catalog:",
|
|
"@types/sanitize-html": "^2.16.1",
|
|
"esbuild": "^0.27.3",
|
|
"esbuild-plugin-pino": "^2.3.3",
|
|
"pg": "^8.20.0",
|
|
"pino-pretty": "^13",
|
|
"thread-stream": "3.1.0"
|
|
}
|
|
}
|