From 3121d31aa275b725080fa8a15cb1789301691678 Mon Sep 17 00:00:00 2001 From: Nicole Rappe Date: Sat, 22 Nov 2025 00:51:27 -0700 Subject: [PATCH] Additional UI Fixes for Scheduler --- .../src/Scheduling/Create_Job.jsx | 93 ++++++++++++++++--- .../src/Scheduling/Scheduled_Jobs_List.jsx | 47 ++++++++-- Docs/Codex/USER_INTERFACE.md | 26 +++++- 3 files changed, 145 insertions(+), 21 deletions(-) diff --git a/Data/Engine/web-interface/src/Scheduling/Create_Job.jsx b/Data/Engine/web-interface/src/Scheduling/Create_Job.jsx index ecc00bd9..d79785a7 100644 --- a/Data/Engine/web-interface/src/Scheduling/Create_Job.jsx +++ b/Data/Engine/web-interface/src/Scheduling/Create_Job.jsx @@ -87,6 +87,20 @@ const gridTheme = themeQuartz.withParams({ const gridThemeClass = gridTheme.themeName || "ag-theme-quartz"; const gridFontFamily = '"IBM Plex Sans","Helvetica Neue",Arial,sans-serif'; const iconFontFamily = '"Quartz Regular"'; +const LEFT_ALIGN_CELL_STYLE = { + display: "flex", + alignItems: "center", + justifyContent: "flex-start", + textAlign: "left", +}; + +const GRID_STYLE_BASE = { + width: "100%", + height: "100%", + fontFamily: gridFontFamily, + "--ag-icon-font-family": iconFontFamily, + "--ag-cell-horizontal-padding": "18px", +}; const GRID_WRAPPER_SX = { width: "100%", @@ -133,9 +147,53 @@ const GRID_WRAPPER_SX = { "& .ag-checkbox-input-wrapper": { borderRadius: "3px", }, - "& .ag-cell.auto-col-tight": { - paddingLeft: 8, - paddingRight: 6, + "& .ag-center-cols-container .ag-cell, & .ag-pinned-left-cols-container .ag-cell, & .ag-pinned-right-cols-container .ag-cell": { + display: "flex", + alignItems: "center", + justifyContent: "flex-start", + textAlign: "left", + paddingTop: "8px", + paddingBottom: "8px", + paddingLeft: "18px", + paddingRight: "12px", + gap: 0, + }, + "& .ag-center-cols-container .ag-cell .ag-cell-wrapper, & .ag-pinned-left-cols-container .ag-cell .ag-cell-wrapper, & .ag-pinned-right-cols-container .ag-cell .ag-cell-wrapper": { + width: "100%", + display: "flex", + alignItems: "center", + justifyContent: "flex-start", + gap: 0, + paddingTop: 0, + paddingBottom: 0, + }, + "& .ag-center-cols-container .ag-cell .ag-cell-value, & .ag-pinned-left-cols-container .ag-cell .ag-cell-value, & .ag-pinned-right-cols-container .ag-cell .ag-cell-value": { + flexGrow: 1, + display: "flex", + alignItems: "center", + justifyContent: "flex-start", + textAlign: "left", + }, + "& .ag-center-cols-container .ag-cell.auto-col-tight, & .ag-pinned-left-cols-container .ag-cell.auto-col-tight, & .ag-pinned-right-cols-container .ag-cell.auto-col-tight": { + paddingLeft: "12px", + paddingRight: "9px", + justifyContent: "flex-start", + textAlign: "left", + alignItems: "center", + gap: 0, + }, + "& .ag-center-cols-container .ag-cell.auto-col-tight .ag-cell-wrapper, & .ag-pinned-left-cols-container .ag-cell.auto-col-tight .ag-cell-wrapper, & .ag-pinned-right-cols-container .ag-cell.auto-col-tight .ag-cell-wrapper": { + flex: 1, + justifyContent: "flex-start", + alignItems: "center", + gap: 0, + }, + "& .ag-center-cols-container .ag-cell.auto-col-tight .ag-cell-value, & .ag-pinned-left-cols-container .ag-cell.auto-col-tight .ag-cell-value, & .ag-pinned-right-cols-container .ag-cell.auto-col-tight .ag-cell-value": { + width: "100%", + textAlign: "left", + display: "flex", + justifyContent: "flex-start", + alignItems: "center", }, "& .status-pill-cell": { display: "flex", @@ -922,7 +980,8 @@ export default function CreateJob({ onCancel, onCreated, initialJob = null, quic suppressMenu: false, filter: true, floatingFilter: false, - cellClass: "auto-col-tight" + cellClass: "auto-col-tight", + cellStyle: LEFT_ALIGN_CELL_STYLE, }), [] ); @@ -1197,6 +1256,7 @@ export default function CreateJob({ onCancel, onCreated, initialJob = null, quic filter: true, floatingFilter: false, cellClass: "auto-col-tight", + cellStyle: LEFT_ALIGN_CELL_STYLE, }), [] ); @@ -2729,11 +2789,14 @@ const heroTiles = useMemo(() => { suppressCellFocus headerHeight={44} rowHeight={48} + pagination + paginationPageSize={20} + paginationPageSizeSelector={[20, 50, 100]} overlayNoRowsTemplate="No targets selected." getRowId={(params) => params.data?.id || params.rowIndex} onGridReady={handleTargetGridReady} theme={gridTheme} - style={{ width: "100%", height: "100%", fontFamily: gridFontFamily, "--ag-icon-font-family": iconFontFamily }} + style={GRID_STYLE_BASE} /> {targets.length === 0 && ( @@ -2980,16 +3043,14 @@ const heroTiles = useMemo(() => { suppressCellFocus headerHeight={44} rowHeight={50} + pagination + paginationPageSize={20} + paginationPageSizeSelector={[20, 50, 100]} overlayNoRowsTemplate="No targets found for this job." getRowId={(params) => params.data?.id || params.rowIndex} onGridReady={handleJobHistoryGridReady} theme={gridTheme} - style={{ - width: "100%", - height: "100%", - fontFamily: gridFontFamily, - "--ag-icon-font-family": iconFontFamily, - }} + style={GRID_STYLE_BASE} /> { suppressCellFocus headerHeight={44} rowHeight={48} + pagination + paginationPageSize={20} + paginationPageSizeSelector={[20, 50, 100]} overlayNoRowsTemplate="No runs in the last 30 days." getRowId={(params) => params.data?.key || params.rowIndex} onGridReady={handleHistorySummaryGridReady} theme={gridTheme} - style={{ width: "100%", height: "100%", fontFamily: gridFontFamily, "--ag-icon-font-family": iconFontFamily }} + style={GRID_STYLE_BASE} /> @@ -3208,8 +3272,11 @@ const heroTiles = useMemo(() => { rowHeight={48} domLayout="normal" overlayNoRowsTemplate="No assemblies available." + pagination + paginationPageSize={20} + paginationPageSizeSelector={[20, 50, 100]} theme={gridTheme} - style={{ width: "100%", height: "100%", fontFamily: gridFontFamily, "--ag-icon-font-family": iconFontFamily }} + style={GRID_STYLE_BASE} rowSelection="single" animateRows getRowId={(params) => params.data?.id || params.rowIndex} diff --git a/Data/Engine/web-interface/src/Scheduling/Scheduled_Jobs_List.jsx b/Data/Engine/web-interface/src/Scheduling/Scheduled_Jobs_List.jsx index b7b9f273..1495f34a 100644 --- a/Data/Engine/web-interface/src/Scheduling/Scheduled_Jobs_List.jsx +++ b/Data/Engine/web-interface/src/Scheduling/Scheduled_Jobs_List.jsx @@ -678,10 +678,14 @@ export default function ScheduledJobsList({ onCreateJob, onEditJob, refreshToken cellStyle: { display: "flex", alignItems: "center", + justifyContent: "flex-start", color: "#f5f7fa", fontFamily: gridFontFamily, - fontSize: "13px" - } + fontSize: "13px", + textAlign: "left", + paddingLeft: "8px", + paddingRight: "6px", + }, }), [] ); @@ -851,11 +855,32 @@ export default function ScheduledJobsList({ onCreateJob, onEditJob, refreshToken "--ag-font-family": gridFontFamily, "--ag-icon-font-family": iconFontFamily, - "& .ag-cell": { + "& .ag-center-cols-container .ag-cell, & .ag-pinned-left-cols-container .ag-cell, & .ag-pinned-right-cols-container .ag-cell": { display: "flex", alignItems: "center", + justifyContent: "flex-start", + textAlign: "left", paddingTop: "8px", paddingBottom: "8px", + paddingLeft: "18px", + paddingRight: "12px", + gap: 0, + }, + "& .ag-center-cols-container .ag-cell .ag-cell-wrapper, & .ag-pinned-left-cols-container .ag-cell .ag-cell-wrapper, & .ag-pinned-right-cols-container .ag-cell .ag-cell-wrapper": { + width: "100%", + display: "flex", + alignItems: "center", + justifyContent: "flex-start", + gap: 0, + paddingTop: 0, + paddingBottom: 0, + }, + "& .ag-center-cols-container .ag-cell .ag-cell-value, & .ag-pinned-left-cols-container .ag-cell .ag-cell-value, & .ag-pinned-right-cols-container .ag-cell .ag-cell-value": { + width: "100%", + display: "flex", + alignItems: "center", + justifyContent: "flex-start", + textAlign: "left", }, /* Center the selection column (header + body) */ @@ -886,9 +911,18 @@ export default function ScheduledJobsList({ onCreateJob, onEditJob, refreshToken alignItems: "center", justifyContent: "center", }, - "& .ag-cell.auto-col-tight": { - paddingRight: 0, - paddingLeft: 0, + "& .ag-center-cols-container .ag-cell.auto-col-tight, & .ag-pinned-left-cols-container .ag-cell.auto-col-tight, & .ag-pinned-right-cols-container .ag-cell.auto-col-tight": { + paddingLeft: "12px", + paddingRight: "9px", + justifyContent: "flex-start !important", + textAlign: "left !important", + }, + "& .ag-center-cols-container .ag-cell.auto-col-tight .ag-cell-wrapper, & .ag-pinned-left-cols-container .ag-cell.auto-col-tight .ag-cell-wrapper, & .ag-pinned-right-cols-container .ag-cell.auto-col-tight .ag-cell-wrapper": { + justifyContent: "flex-start !important", + }, + "& .ag-center-cols-container .ag-cell.auto-col-tight .ag-cell-value, & .ag-pinned-left-cols-container .ag-cell.auto-col-tight .ag-cell-value, & .ag-pinned-right-cols-container .ag-cell.auto-col-tight .ag-cell-value": { + textAlign: "left !important", + justifyContent: "flex-start !important", }, }} style={{ @@ -906,6 +940,7 @@ export default function ScheduledJobsList({ onCreateJob, onEditJob, refreshToken "--ag-checkbox-background-color": "rgba(255,255,255,0.06)", "--ag-checkbox-border-color": "rgba(180,200,220,0.6)", "--ag-checkbox-checked-color": "#7dd3fc", + "--ag-cell-horizontal-padding": "18px", }} > {/* Action bar for bulk delete stays above grid when needed */} diff --git a/Docs/Codex/USER_INTERFACE.md b/Docs/Codex/USER_INTERFACE.md index 8fa97473..9d831b89 100644 --- a/Docs/Codex/USER_INTERFACE.md +++ b/Docs/Codex/USER_INTERFACE.md @@ -22,7 +22,7 @@ Applies to all Borealis frontends. Use `Data/Engine/web-interface/src/Admin/Page - Buttons & chips: gradient pills for primary CTAs (`linear-gradient(135deg,#34d399,#22d3ee)` success; `#7dd3fc→#c084fc` creation); neutral actions use rounded outlines with `rgba(148,163,184,0.4)` borders and uppercase microcopy. - Rainbow accents: for creation CTAs, use dark-fill pills with rainbow border gradients + teal halo (shared with Quick Job). - AG Grid treatment: Quartz theme with matte navy headers, subtle alternating row opacity, cyan/magenta interaction glows, rounded wrappers, soft borders, inset selection glows. -- Default grid cell padding: leave a small left inset (≈4px) on value cells (including `auto-col-tight`) so text doesn’t hug column edges; keep right padding modest (≈6px) to balance density. +- Default grid cell padding: keep roughly 18px on the left edge and 12px on the right for standard cells (12px/9px for `auto-col-tight`) so text never hugs a column edge. Target the center + pinned containers so both regions stay aligned. - Overlays/menus: `rgba(8,12,24,0.96)` canvas, blurred backdrops, thin steel borders; bright typography; deep blue glass inputs; cyan confirm, mauve destructive accents. ## AG Grid Column Behavior (All Tables) @@ -31,6 +31,28 @@ Applies to all Borealis frontends. Use `Data/Engine/web-interface/src/Admin/Page - Helper: store the grid API in a ref and call `api.autoSizeColumns(AUTO_SIZE_COLUMNS, true)` inside `requestAnimationFrame` (or `setTimeout(...,0)` fallback); swallow errors because it can run before rows render. - Hook the helper into both `onGridReady` and a `useEffect` watching the dataset (e.g., `[filteredRows, loading]`); skip while `loading` or when there are zero rows. - Column defs: apply shared `cellClass: "auto-col-tight"` (or equivalent) to every auto-sized column for consistent padding. Last column keeps the class for styling consistency. -- CSS override: add `& .ag-cell.auto-col-tight { padding-left: 8px; padding-right: 6px; }` (or equivalent) in the theme scope to keep text away from the left edge. +- CSS override: ensure the wrapper targets both center and pinned containers so every cell shares the same flex alignment. Then apply the tighter inset to `auto-col-tight`: + ```jsx + "& .ag-center-cols-container .ag-cell, & .ag-pinned-left-cols-container .ag-cell, & .ag-pinned-right-cols-container .ag-cell": { + display: "flex", + alignItems: "center", + justifyContent: "flex-start", + textAlign: "left", + padding: "8px 12px 8px 18px", + }, + "& .ag-center-cols-container .ag-cell .ag-cell-wrapper, & .ag-pinned-left-cols-container .ag-cell .ag-cell-wrapper, & .ag-pinned-right-cols-container .ag-cell .ag-cell-wrapper": { + width: "100%", + display: "flex", + alignItems: "center", + justifyContent: "flex-start", + padding: 0, + }, + "& .ag-center-cols-container .ag-cell.auto-col-tight, & .ag-pinned-left-cols-container .ag-cell.auto-col-tight, & .ag-pinned-right-cols-container .ag-cell.auto-col-tight": { + paddingLeft: "12px", + paddingRight: "9px", + }, + ``` +- Style helper: reuse a `GRID_STYLE_BASE` (or similar) to set fonts/icons and `--ag-cell-horizontal-padding: "18px"` on every grid, then merge it with per-grid dimensions. - Fill column: last column `{ flex: 1, minWidth: X }` (no width/maxWidth) to stretch when horizontal space remains. +- Pagination baseline: every Quartz grid ships with `pagination`, `paginationPageSize={20}`, and `paginationPageSizeSelector={[20, 50, 100]}`. This matches Device List behavior and prevents infinitely tall tables (Targets, assembly pickers, job histories, etc.). - Example: follow the scaffolding in `Engine/web-interface/src/Scheduling/Scheduled_Jobs_List.jsx` and the structure in `Data/Engine/web-interface/src/Admin/Page_Template.jsx`.