Commit Graph

127 Commits

Author SHA1 Message Date
riyadhafraa 8810130ef5 Make row borders darker and more prominent
Update border colors and thickness in PDF renderer and UI to ensure visibility and consistency.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 0b5defcb-10cb-452f-a4e7-72763eeb98bc
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/k1UTYfG
Replit-Helium-Checkpoint-Created: true
2026-05-04 11:57:42 +00:00
riyadhafraa 4a3305ba07 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 7629a54c-a648-4057-b56d-1f6617787ef9
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/nFy3UZm
Replit-Helium-Checkpoint-Created: true
2026-05-04 11:12:09 +00:00
riyadhafraa 204f2ec5b0 Improve PDF export to correctly display partial row coloring
Update PDF generation logic to ensure partial row coloring is applied correctly to specific columns.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 63d5ae46-8988-42c4-8fd5-2e6a5696549c
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Zh9QhRk
Replit-Helium-Checkpoint-Created: true
2026-05-04 10:59:48 +00:00
riyadhafraa 328d867975 Improve PDF schedule layout for better readability and alignment
Adjust PDF rendering to ensure all meeting details (number, title, attendees, time) are contained within a single row, improve vertical alignment to the top, and set correct text alignment for RTL content.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 5cba573f-cf8f-4641-b2db-92b5b87be569
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Zh9QhRk
Replit-Helium-Checkpoint-Created: true
2026-05-04 09:59:03 +00:00
riyadhafraa d05b5297f1 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 1441ae22-f1f6-4f78-b140-f28ef6e4048f
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Zh9QhRk
Replit-Helium-Checkpoint-Created: true
2026-05-04 09:40:36 +00:00
riyadhafraa 771cfb5611 Improve PDF generation for meeting tables with better text handling
Update PDF rendering logic to correctly handle bidirectional text, cell merging, and text wrapping for meeting tables.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 36ae937b-a1fc-4edb-8901-b07ed7713220
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Zh9QhRk
Replit-Helium-Checkpoint-Created: true
2026-05-04 09:24:37 +00:00
riyadhafraa 43ae5ff90d Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: c2314a1f-ae0f-47c2-bf5c-1f075822b8d7
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/ylDMZtF
Replit-Helium-Checkpoint-Created: true
2026-05-04 08:22:32 +00:00
riyadhafraa e6a43b85bf Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: c50a00a7-7b14-4d88-b65c-7ca92171a73e
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/bEwHL7p
Replit-Helium-Checkpoint-Created: true
2026-05-04 08:09:03 +00:00
riyadhafraa 57096e69a5 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 6a7f1a74-369f-4e38-9f13-96369912cc6c
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/TFW8qXL
Replit-Helium-Checkpoint-Created: true
2026-05-04 07:50:43 +00:00
riyadhafraa 10679127e6 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 6f5061c3-9885-4173-9988-00e335acadc8
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/HhIDQsV
Replit-Helium-Checkpoint-Created: true
2026-05-04 07:29:50 +00:00
riyadhafraa 17f1771659 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 7d330ba0-531c-4dc4-a3bd-3ac086027533
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/HhIDQsV
Replit-Helium-Checkpoint-Created: true
2026-05-04 07:15:12 +00:00
riyadhafraa acd1199d61 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: f68e6e2d-59e7-427a-8220-1cead24caf3b
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/HhIDQsV
Replit-Helium-Checkpoint-Created: true
2026-05-04 07:03:37 +00:00
riyadhafraa 7473e6f2ea Task #352: Make logo upload always visible for admin users
Previously, the logo upload field in Font Settings was hidden behind two
conditions: canEditGlobal AND scope === "global". Admin users had to
first switch the scope dropdown to "Global" before the logo upload
appeared, making it very hard to discover.

Changes:
- Frontend (executive-meetings.tsx): Removed `scope === "global"`
  condition from logo upload rendering — now shows whenever
  `canEditGlobal` is true (admin/executive_office_manager).
- Frontend: Save function now always sends `logoObjectPath` when
  `canEditGlobal` is true, regardless of selected scope.
- Backend (executive-meetings.ts): When an admin saves with user scope
  and includes logoObjectPath, the logo is written to the global row
  (upsert) in the same transaction. This preserves the global-only
  semantics while allowing admins to update the logo from any scope.
- When no global row exists, new row uses safe defaults (system font,
  14px, regular, start, #000000) instead of copying the user's prefs.
- Removed the 400 rejection for logoObjectPath on user-scope saves.
- Authorization preserved: only EM_ADMIN_ROLES can trigger logo writes.

Tested:
- API: PATCH with scope=user + logoObjectPath correctly updates global row
- E2E: Logo upload field visible for admin in user scope (confirmed)
- Code review: APPROVED (addressed comment about safe defaults)
- Pre-existing test failures unchanged (PDF font assertion, notification tests)
2026-05-04 06:44:02 +00:00
riyadhafraa 6a964ed9d9 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: c6f14bf2-1beb-4d63-b916-cc82cbea11ff
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/hqxYGHc
Replit-Helium-Checkpoint-Created: true
2026-05-04 06:34:58 +00:00
riyadhafraa d308b0a5ac Add custom Arabic font files for PDF generation
Uploads DIN Next LT Arabic font files (Regular and Bold) to the attached assets directory for use in PDF generation, replacing system fallbacks.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 93e41a01-e925-4b9c-8659-8917bbcf8455
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-04 06:13:12 +00:00
riyadhafraa 751d81b1f6 Update image file for font display clarification
Update attached image to illustrate font rendering and fallback mechanisms.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: ff6817a2-f5cf-42bf-b743-cec3bf708ab5
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 19:38:33 +00:00
riyadhafraa 0ef7d91cbe Task #351: Match Executive Meetings PDF to user's reference layout
User compared the rendered PDF against their reference (rrr1) and flagged
three concrete differences. This change addresses all three:

1. Time format — formatTimeRange now joins start/end with U+2011
   NON-BREAKING HYPHEN (no surrounding spaces): "9:40‑9:50" instead of
   "9:40 – 9:50". The non-breaking hyphen looks identical to ASCII "-"
   and prevents PDFKit from wrapping the range across two lines in the
   narrow Time column.

2. Date placement — removed the ISO date that was printed under the
   header title. Added a new bottom-aligned footer block on the leading
   edge (right for AR, left for EN) that prints:
     • "مقيد" / "Recorded by" (bold)
     • Long-form date "3 May 2026" (always Latin, English month name
       even on the AR PDF, mirroring the reference)
   The date row is forced to baseDirection="ltr" so RTL bidi doesn't
   visually reorder the runs into "May 2026 3" on the AR PDF.
   formatLongDate parses the ISO route param in UTC to avoid host-tz
   day drift. The footer is extracted into a drawFooter() helper and
   called in BOTH the empty-day and populated-day code paths so it
   always renders.

3. Title weight — title was already calling drawMixedLine with
   weight:"bold" but added explicit confirmation; column proportions
   tweaked (6/36/39/19) so the wider Time column doesn't force range
   wrapping while keeping enough room for Meeting/Attendees content.

Other touches:
- Added `recordedBy` to PdfLabels type + RenderPdfInput.labels type
  and to ar.json/en.json executiveMeetings.pdf blocks.
- Page-break check reserves footer height so the last row never
  overlaps the bottom footer.

Verified: PDF Arabic shaping regression test passes; live AR/EN PDFs
match the reference; one-page-fit still holds for typical days.
Pre-existing tsc errors in executive-meetings.ts and unrelated test
suite failures are not caused by this work.
2026-05-03 19:27:11 +00:00
riyadhafraa fa9b395be5 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 06c7a404-fec6-4834-9c06-327a20dc608d
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 19:17:44 +00:00
riyadhafraa 26a869c0eb PDF: inline attendees, tighter layout — fit a typical day on one page
Follow-up to the Arabic shaping fix. The downloaded schedule PDF was
spilling onto a second page even for modest days because (a) attendees
were stacked one-per-line and (b) the page header + cell padding +
column proportions reserved more vertical space than necessary.

Changes (artifacts/api-server/src/lib/pdf-renderer.ts):

- Attendees now render as a single inline paragraph per cell (joined
  with two spaces) and wrap naturally — matches the user's reference
  layout where attendees flow as one paragraph.
- Re-balanced column widths from 6/30/44/20 → 6/38/40/16. Meeting
  titles get more room (no more 6-line wraps for typical titles) and
  attendees get less (they're inline now).
- Page margin tightened 36pt → 24pt.
- Title size cap tightened (28 → 22) so the header band doesn't eat a
  table row.
- moveDown gaps trimmed (0.4→0.2 between title and date, 0.8→0.4
  before the table).
- Cell vertical padding trimmed (5pt → 3pt).
- drawWrappingLine now passes lineGap: -1 to pdfkit's text() so wrapped
  paragraphs get tighter inter-line spacing; the row-height probe
  passes the same option so probe and draw stay symmetric.
- Row-height probe now uses heightOfString() output directly
  (Math.max(lineHeight, measured) + 2) instead of rounding up to whole
  lineHeight units, removing the half-line of empty space that was
  visible below short cells.

Verified:
- EN: all 10 meetings on one A4 page.
- AR: 9 of 10 meetings on one A4 page; the 10th row contains
  multi-line internal/external subheadings which legitimately need a
  taller cell — typical days fit on a single page.
- PDF Arabic shaping regression test still passes.
- No row overlaps anywhere.

Logo: handler already loads the brand-settings logo (logoObjectPath)
and embeds it in the header — no code change needed. If the logo isn't
visible, none has been uploaded in brand settings.
2026-05-03 19:11:49 +00:00
riyadhafraa e0824bc6a0 Fix overlapping text and improve Arabic rendering in PDFs
Update PDF rendering logic to use fontkit for Arabic shaping and RTL reordering, eliminating pre-shaping and resolving text overlap issues.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 32b8a89e-ae1f-4a09-ae50-3a53ae3f3477
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 19:01:50 +00:00
riyadhafraa 6cbd5968e5 Ensure Arabic text displays correctly when printing documents
Update font configurations to exclusively use DIN Next LT Arabic, preload necessary font files, and implement eager font loading to prevent display issues during printing.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 814df7a0-9300-4efe-a4b5-b5e474e8c99f
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 18:37:48 +00:00
riyadhafraa a4e58b2263 Improve dialog box alignment and spacing for better user experience
Update `DialogHeader` to use `sm:text-start` for RTL alignment and `DialogFooter` to use `gap-2` instead of `sm:space-x-2` for improved spacing in dialog components.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: f335791d-bd37-4801-bf2e-18c339d6fdc5
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 17:43:07 +00:00
riyadhafraa abaf54f254 Improve Arabic text rendering for printouts by preloading fonts
Preload DIN Next LT Arabic and Tajawal fonts in index.html and adjust the print CSS font stack to ensure correct Arabic character shaping in print mode.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 820da5a0-fe82-4670-9807-63a51f533e44
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 16:02:10 +00:00
riyadhafraa 03e92f9e8c Improve Arabic text display when printing the schedule
Add print-specific CSS to force Arabic web font and enable ligatures for proper shaping in print mode.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 93b31a62-139b-4870-b40e-2ffc4ec05a8d
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 15:55:29 +00:00
riyadhafraa 627a8fe7b1 Fix Arabic text rendering in generated PDFs
Add Arabic text shaping functionality to convert base characters to their contextual presentation forms before bidi reordering and PDF rendering. Includes a new regression test to verify correct shaping by asserting the presence of presentation form codepoints in the PDF's embedded ToUnicode CMap.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 18d38e3a-cfe8-4b69-a02c-380283320b78
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 15:26:38 +00:00
riyadhafraa 64fcbb7a20 Task #349 follow-up: brand-logo embed test + label module + user-scope guard
Original task: Executive Meetings PDF improvements — respect user
font prefs, render saved per-meeting rowColor, drop legacy
isHighlighted baking, brand logo on left of PDF header with title
"قائمة بأسماء حضور الاجتماعات", and a logo upload + font color
picker in the font-settings page.

Prior mark_task_complete was rejected for three issues. This commit
closes all of them:

- Extract bilingual PDF labels into
  artifacts/api-server/src/lib/pdf-labels.ts and import it from the
  PDF route. Mirror the same keys under executiveMeetings.pdf.* in
  the tx-os ar.json / en.json locales so the frontend stays in
  sync.
- Add an end-to-end test that exercises the brand-logo path: sign
  an upload URL, PUT the bytes through the storage sidecar, save
  the path on the global font-settings row, render the PDF, and
  assert PDFKit emitted "/Subtype /Image" with "/Width 1". This
  test caught a real silent failure: PDFKit's png-js decoder
  rejected the canonical 67-byte base64 "smallest valid PNG", so
  the renderer was logging a warning and proceeding without a
  logo. The fixture now constructs a real 1x1 RGB PNG inline using
  zlib + a CRC32 routine (no new dependencies). Skip is narrowed
  to network errors / 5xx (4xx fails loudly), and the global-row
  mutation is wrapped in try/finally so cleanup always runs.
- Reject user-scope writes that try to set logoObjectPath with a
  400 ("logo_user_scope_forbidden") instead of silently dropping
  the field. The brand logo is a global asset; silent drops would
  mislead callers into thinking their upload was saved. Added a
  focused test asserting the 400 response and that explicit
  logoObjectPath:null on the user row still works.

Also removed 12 stray backup/snapshot files at the repo root
(*.old, *-base.{ts,tsx,mjs}, locale snapshots) that were
accidentally tracked in the previous commit.

Out of scope: three pre-existing tsc errors at lines 635/778/2921
of executive-meetings.ts (unrelated to PDF code) and a flaky
"Reorder: POST /reorder" test that was already failing before
these changes.
2026-05-03 15:06:14 +00:00
riyadhafraa 57e8297464 Task #349: Executive Meetings PDF improvements
- Schema: add `font_color` (hex, default #000000) and `logo_object_path`
  to `executive_meeting_font_settings`. Pushed via drizzle-kit.

- PDF renderer:
  - Add `fontColor` to PdfFontPrefs (body cells only; header chrome
    and logo intentionally ignore it to preserve branding).
  - Add `rowColor` to PdfMeeting and a ROW_COLOR_FILL palette kept in
    lockstep with the on-screen swatches; deliberately stop painting
    the legacy `isHighlighted` overlay so the archived PDF reflects
    editorial state instead of the viewer's transient cursor.
  - Add optional `logo: Buffer`. Header now reserves a left-anchored
    logo box and centers the title in the remaining width; bad image
    bytes log + fall back to the no-logo layout instead of crashing.

- API route:
  - Extend fontSettingsSchema with strict #RRGGBB regex and
    /^/objects/<id>$/ regex for logoObjectPath.
  - resolveFontPrefsForUser now returns { font, logoObjectPath }.
  - loadLogoBytes downloads the brand asset via ObjectStorageService.
  - Logo only writable on the global-scope row.
  - PDF labels switched to "قائمة بأسماء حضور الاجتماعات" /
    "Meeting Attendance List" per the user's printed sample.

- Frontend (executive-meetings.tsx):
  - FontPrefs gains fontColor; FontSettingsResponse.global gains
    logoObjectPath; DEFAULT_FONT and effectiveFont updated.
  - buildFontStyle applies fontColor to on-screen rows.
  - FontSettingsSection: native color picker + hex text input;
    logo upload (PNG/JPEG) via @workspace/object-storage-web's
    useUpload, visible only at the global scope for admins.

- Locales: AR/EN keys for fontColor + logo.{label,upload,replace,
  remove,uploading,uploadFailed,globalOnly}.

- Tests: existing font-settings roundtrip extended with fontColor;
  new test rejects malformed fontColor and non-/objects logo paths.

Type-check clean for api-server and tx-os; new font-settings tests
pass. Other test failures in the suite pre-date this change.
2026-05-03 14:34:29 +00:00
riyadhafraa 6de67b0ecb Update audit log table with reorganized columns and localized content
Reorganize audit log table columns for RTL rendering, remove entityId, and update localized keys and enum values.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 37907bed-f6b6-47d9-bffb-5a50bc660b83
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 14:19:06 +00:00
riyadhafraa 0a18cf2abe Task start baseline checkpoint for code review
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: ac46926c-da15-4b39-a44e-d8b743720927
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 13:54:24 +00:00
riyadhafraa 46dee9cf13 Update button order and clean up HTML content
Reorder UI buttons and sanitize HTML content in title and attendee fields.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 7ff9197c-e52a-49a8-b981-b98e20de8d21
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 12:59:13 +00:00
riyadhafraa 4845b00229 Update Arabic meeting alerts to use "next" and "starts after" phrasing
Update Arabic localization strings in `ar.json` and adjust conditional logic in `upcoming-meeting-alert.tsx` to implement the requested text changes for meeting alerts.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 1fa1a054-545f-4815-84a7-7b8664041413
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 12:49:59 +00:00
riyadhafraa 41cf24533e EM upcoming alert: Arabic copy tweaks (#346)
Two small Arabic-only string changes in the Upcoming Meeting alert
popup, requested off a screenshot:

1. Header title: "اجتماع يبدأ قريبًا" → "الاجتماع التالي".
2. Countdown line: replaced "خلال" with "بعد" so the alert reads
   "يبدأ بعد 5 دقائق" instead of "يبدأ خلال 5 دقائق". Applied to all
   plural forms (one/two/few/many/other). minutesAway_zero ("يبدأ
   الآن") and the separate startsNow key were left unchanged.

Files:
- artifacts/tx-os/src/locales/ar.json
  - executiveMeetings.alert.title
  - executiveMeetings.alert.minutesAway_{one,two,few,many,other}

Out of scope (untouched on purpose):
- en.json — user only asked about the Arabic copy.
- upcoming-meeting-alert.tsx — no logic/layout change needed; it
  already reads these keys via i18next.
- All other behavior (blink, drag, buttons, etc.) carried over from
  #344.

Verification:
- ar.json still valid JSON; key set unchanged.
- Pre-existing red workflows (api-server, combined `test`) are
  unrelated upstream failures and not caused by this change.
2026-05-03 12:49:15 +00:00
riyadhafraa d725a63db3 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 75a790b7-ee08-416a-aec5-88fe90a5d590
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 12:48:03 +00:00
riyadhafraa d0038a0bd9 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: c6c7f89f-2076-4655-8246-744d340fea59
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Ow4s0aa
Replit-Helium-Checkpoint-Created: true
2026-05-03 12:39:01 +00:00
riyadhafraa 5a004925d5 Task start baseline checkpoint for code review
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 0117caec-5fc0-49b3-8125-1dc02cfee596
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/vKbTeqB
Replit-Helium-Checkpoint-Created: true
2026-05-03 12:05:55 +00:00
riyadhafraa 854ec177fc Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 070b6956-c3af-4e4e-97b8-4cb932e22e23
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/vKbTeqB
Replit-Helium-Checkpoint-Created: true
2026-05-03 12:05:52 +00:00
riyadhafraa 8d0d749d19 Adjust table column alignment for better readability on smaller screens
Align specific table columns to the start to prevent layout issues with long text.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 3b6aa4c0-6f89-44f5-a192-3827f92b1a5e
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/vKbTeqB
Replit-Helium-Checkpoint-Created: true
2026-05-03 11:53:52 +00:00
riyadhafraa bd38bc5ca4 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: ccad63cc-87f7-4e83-9089-23ffbe308268
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/vKbTeqB
Replit-Helium-Checkpoint-Created: true
2026-05-03 11:49:10 +00:00
riyadhafraa f51eba68ed Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 737237cd-13b1-4c39-83f7-0411eb3069af
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/vKbTeqB
Replit-Helium-Checkpoint-Created: true
2026-05-03 11:33:43 +00:00
riyadhafraa 1923a9ca25 Update screenshot to show correct meeting management tab
Update attached screenshot to reflect the manage meetings tab.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 26502b01-f36d-4ce8-bb8f-64652a15c0ed
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/vKbTeqB
Replit-Helium-Checkpoint-Created: true
2026-05-03 11:19:56 +00:00
riyadhafraa c9ffb09e36 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 9e3c014c-0bfd-4123-86ce-e5601a120326
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/2VzZgdn
Replit-Helium-Checkpoint-Created: true
2026-05-03 10:51:13 +00:00
riyadhafraa d2dda556d6 #324 Make the Add/Edit Meeting dialog fit on a phone screen
After #322 trimmed the dialog, the Save/Cancel footer slid below
the visible 90vh sheet on phones because the whole DialogContent
was a single overflow-y-auto block.

Changes in artifacts/tx-os/src/pages/executive-meetings.tsx:

MeetingFormDialog
- Rebuilt DialogContent as a flex column: shrink-0 header,
  flex-1 min-h-0 overflow-y-auto middle (the only scroller),
  shrink-0 footer. Save/Cancel now stay pinned at the bottom
  even after many attendees are added.
- Reduced mobile padding/gaps (`p-4 sm:p-6`,
  `gap-3 sm:gap-4`, grid `gap-2 sm:gap-3`). Desktop spacing
  unchanged.
- Switched the field grid from `grid-cols-1 sm:grid-cols-2`
  to a flat `grid-cols-2` so the two short fields (التاريخ,
  الرقم اليومي) share a row even on mobile. Title spans both
  columns; time pickers span both on mobile and one each on
  sm+ via the new mobileFull variant.
- Inner scroll wrapper uses negative margins + matching padding
  so scroll content can extend edge-to-edge without losing the
  dialog's gutter.

FormRow helper
- Broadened `full` from `sm:col-span-2` to `col-span-2`
  (works in both 1-col and 2-col grids; only callers using
  `full` are in this file).
- Added `mobileFull` prop → `col-span-2 sm:col-span-1` for
  the time pickers, so AM/PM controls don't get squeezed on
  phones.

Out of scope (untouched): validation, save logic, attendee
model, removed-field defaults from #322, duplicate dialog,
audit, schedule view, translations.
2026-05-03 10:09:29 +00:00
riyadhafraa cfd2a46d39 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 5123ce28-d8a4-40de-88ed-223d3e32ae49
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/2VzZgdn
Replit-Helium-Checkpoint-Created: true
2026-05-03 10:06:28 +00:00
riyadhafraa 5cb1644300 Update meeting form layout and Arabic title label
Refactor executive meetings form layout in `executive-meetings.tsx` to use a responsive grid, ensuring the Arabic title spans full width and other fields stack appropriately on smaller screens. Update Arabic and English locale files (`ar.json`, `en.json`) to change the Arabic title field label from "العنوان (عربي)" to "العنوان".

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 57375b7d-57d9-4fe3-a745-00a2cad59df8
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/2VzZgdn
Replit-Helium-Checkpoint-Created: true
2026-05-03 10:00:45 +00:00
riyadhafraa fd7c3c6498 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 9a1523d5-dc1f-4906-a63a-b530a5b52d4a
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/fHzEBLA
Replit-Helium-Checkpoint-Created: true
2026-05-03 09:47:11 +00:00
riyadhafraa ea89647264 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: ec66417e-470f-4913-a3ff-c38d7c0fc4d5
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/fHzEBLA
Replit-Helium-Checkpoint-Created: true
2026-05-03 09:35:43 +00:00
riyadhafraa 83ee3be884 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 966f071a-6816-4f85-a574-20c5c1ea98f7
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/Q5rwhix
Replit-Helium-Checkpoint-Created: true
2026-05-03 08:01:55 +00:00
riyadhafraa 45f3d88ac5 EM time picker: mobile/iPad-friendly layout + touch targets
Follow-up to task #315. The 3-control picker shipped with desktop-
sized inline controls (~22px tall) and a single-row layout that
pushed the end picker out of view on a 375px iPhone, leaving the
user with no obvious way to fill the second time field.

What changed
- src/components/time-picker-12h.tsx: bumped the "inline" size
  from h<22px text-[10px] to h-8 (32px) text-sm/text-xs across
  hour input, minute input, and AM/PM toggle so a finger tap on
  mobile/iPad lands cleanly. Added `gap-1.5` between the
  [hour:minute] group and the AM/PM toggle so a thumb-tap on the
  toggle doesn't accidentally land on the minute input. Added a
  visible focus ring color and lightened the placeholder so the
  empty fields read as "fill me in" rather than already-active.
- src/pages/executive-meetings.tsx (TimeRangeCell wrapper):
  switched from `inline-flex` (single-row, ellipsis on overflow)
  to `flex flex-wrap items-end gap-x-1.5 gap-y-1`. The end picker
  now drops onto a second line when the cell can't fit both
  side-by-side, which is the iPhone case. The "–" separator is
  hidden on narrow widths (`hidden sm:inline`) since wrapping
  makes it visually wrong.
- Bumped Start/End labels from 10px to 11px font-medium for
  better at-a-glance scanability of which time field is which —
  this was the user-reported clarity issue.
- Save/cancel icon buttons grew to 32x32 hit areas (was tiny
  p-0.5 around a 14px icon ≈ 16px clickable).
- tests/executive-meetings-keyboard-editing.spec.mjs: added a
  new test.describe block "Schedule mobile viewport (iPhone 375)"
  with `test.use({ viewport: { width: 375, height: 667 } })`. The
  test asserts: (a) all 8 picker sub-controls + save button are
  visible on iPhone, (b) each interactive control is at least
  28px tall (regression guard against shrinking touch targets),
  (c) a complete tap-driven hour+minute+AM/PM entry on both
  start and end persists 21:30–22:45 to the DB.

Validation
- Unit tests: 22/22 pass (no logic changes — only CSS + layout).
- E2E: Tab walks (desktop) + compact+PM toggle (desktop) +
  new iPhone-375 mobile test all pass.
- TypeScript: clean.
2026-05-03 06:22:54 +00:00
riyadhafraa 79e03053aa Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 4467bc05-db1e-4d31-b5c0-92f5d9c3aa1c
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/GbTNwz8
Replit-Helium-Checkpoint-Created: true
2026-05-02 10:32:39 +00:00
riyadhafraa f7b93aa4e7 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: d8980aeb-a819-4c14-97a6-7384215c51d1
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/GbTNwz8
Replit-Helium-Checkpoint-Created: true
2026-05-02 09:34:57 +00:00