mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-12-16 06:45:48 -07:00
Updated Scheduled Jobs List
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
"description": "Deletes Agent and Engine Logs from C:\\Borealis.",
|
"description": "Deletes Agent and Engine Logs from C:\\Borealis.",
|
||||||
"files": [],
|
"files": [],
|
||||||
"name": "Borealis - Delete Logs [WIN]",
|
"name": "Borealis - Delete Logs [WIN]",
|
||||||
"script": "UmVtb3ZlLUl0ZW0gLUxpdGVyYWxQYXRoICdDOlxCb3JlYWxpc1xBZ2VudFxMb2dzJywnQzpcQm9yZWFsaXNcRW5naW5lXExvZ3MnIC1SZWN1cnNlIC1Gb3JjZSAtRXJyb3JBY3Rpb24gU2lsZW50bHlDb250aW51ZQ==",
|
"script": "UmVtb3ZlLUl0ZW0gLUxpdGVyYWxQYXRoICdDOlxCb3JlYWxpc1xBZ2VudFxMb2dzJywnQzpcQm9yZWFsaXNcRW5naW5lXExvZ3MnIC1SZWN1cnNlIC1Gb3JjZSAtRXJyb3JBY3Rpb24gU2lsZW50bHlDb250aW51ZQpSZW1vdmUtSXRlbSAtTGl0ZXJhbFBhdGggJ0U6XEdpdEh1YlxCb3JlYWxpc1xBZ2VudFxMb2dzJywnRTpcR2l0SHViXEJvcmVhbGlzXEVuZ2luZVxMb2dzJyAtUmVjdXJzZSAtRm9yY2UgLUVycm9yQWN0aW9uIFNpbGVudGx5Q29udGludWU=",
|
||||||
"script_encoding": "base64",
|
"script_encoding": "base64",
|
||||||
"sites": {
|
"sites": {
|
||||||
"mode": "all",
|
"mode": "all",
|
||||||
|
|||||||
Binary file not shown.
@@ -177,13 +177,10 @@ const SAMPLE_ROWS = [
|
|||||||
const selectionCol = {
|
const selectionCol = {
|
||||||
headerName: "",
|
headerName: "",
|
||||||
field: "__select__",
|
field: "__select__",
|
||||||
cellClass: 'ag-selection-centered',
|
|
||||||
cellStyle: { display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 0 },
|
|
||||||
width: 52,
|
width: 52,
|
||||||
maxWidth: 52,
|
maxWidth: 52,
|
||||||
checkboxSelection: true,
|
checkboxSelection: true,
|
||||||
headerCheckboxSelection: true,
|
headerCheckboxSelection: true,
|
||||||
headerCheckboxSelectionFilteredOnly: false,
|
|
||||||
resizable: false,
|
resizable: false,
|
||||||
sortable: false,
|
sortable: false,
|
||||||
suppressMenu: true,
|
suppressMenu: true,
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
////////// PROJECT FILE SEPARATION LINE ////////// CODE AFTER THIS LINE ARE FROM: <ProjectRoot>/Data/WebUI/src/Scheduled_Jobs_List.jsx
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Scheduled_Jobs_List — Borealis MagicUI styling parity with Page Template
|
||||||
|
// - Aurora gradient shell
|
||||||
|
// - Small Material icon LEFT of title
|
||||||
|
// - Subtitle under title
|
||||||
|
// - Top-right utility buttons (Refresh, Create Job, Settings)
|
||||||
|
// - AG Grid Quartz theme + square checkboxes, rounded chrome
|
||||||
|
// - Keeps all original logic + renderers
|
||||||
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
import React, {
|
import React, {
|
||||||
useCallback,
|
useCallback,
|
||||||
@@ -16,34 +24,68 @@ import {
|
|||||||
Dialog,
|
Dialog,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
CircularProgress
|
CircularProgress,
|
||||||
|
IconButton,
|
||||||
|
Stack,
|
||||||
|
Tooltip
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import {
|
||||||
|
Schedule as HeaderIcon,
|
||||||
|
Cached as CachedIcon,
|
||||||
|
Add as AddIcon,
|
||||||
|
Tune as TuneIcon
|
||||||
|
} from "@mui/icons-material";
|
||||||
import { AgGridReact } from "ag-grid-react";
|
import { AgGridReact } from "ag-grid-react";
|
||||||
import { ModuleRegistry, AllCommunityModule, themeQuartz } from "ag-grid-community";
|
import { ModuleRegistry, AllCommunityModule, themeQuartz } from "ag-grid-community";
|
||||||
import { DomainBadge, resolveDomainMeta } from "../Assemblies/Assembly_Badges";
|
import { DomainBadge, resolveDomainMeta } from "../Assemblies/Assembly_Badges";
|
||||||
import { buildAssemblyIndex, resolveAssemblyForComponent } from "../Assemblies/assemblyUtils";
|
import { buildAssemblyIndex, resolveAssemblyForComponent } from "../Assemblies/assemblyUtils";
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Register AG Grid community modules
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
ModuleRegistry.registerModules([AllCommunityModule]);
|
ModuleRegistry.registerModules([AllCommunityModule]);
|
||||||
|
|
||||||
const myTheme = themeQuartz.withParams({
|
// -----------------------------------------------------------------------------
|
||||||
accentColor: "#FFA6FF",
|
// MagicUI x Quartz Theme (parity with Page_Template)
|
||||||
backgroundColor: "#1f2836",
|
// -----------------------------------------------------------------------------
|
||||||
|
const gridTheme = themeQuartz.withParams({
|
||||||
|
accentColor: "#8b5cf6",
|
||||||
|
backgroundColor: "#070b1a",
|
||||||
browserColorScheme: "dark",
|
browserColorScheme: "dark",
|
||||||
chromeBackgroundColor: {
|
fontFamily: { googleFont: "IBM Plex Sans" },
|
||||||
ref: "foregroundColor",
|
foregroundColor: "#f4f7ff",
|
||||||
mix: 0.07,
|
headerFontSize: 13,
|
||||||
onto: "backgroundColor"
|
|
||||||
},
|
|
||||||
fontFamily: {
|
|
||||||
googleFont: "IBM Plex Sans"
|
|
||||||
},
|
|
||||||
foregroundColor: "#FFF",
|
|
||||||
headerFontSize: 14
|
|
||||||
});
|
});
|
||||||
|
const themeClassName = gridTheme.themeName || "ag-theme-quartz";
|
||||||
|
|
||||||
const themeClassName = myTheme.themeName || "ag-theme-quartz";
|
// Typography
|
||||||
const gridFontFamily = '"IBM Plex Sans", "Helvetica Neue", Arial, sans-serif';
|
const gridFontFamily = "'IBM Plex Sans','Helvetica Neue',Arial,sans-serif";
|
||||||
const iconFontFamily = '"Quartz Regular"';
|
const iconFontFamily = "'Quartz Regular'";
|
||||||
|
|
||||||
|
// Aurora gradient shell colors
|
||||||
|
const AURORA_SHELL = {
|
||||||
|
background:
|
||||||
|
"radial-gradient(120% 120% at 0% 0%, rgba(76, 186, 255, 0.16), transparent 55%), " +
|
||||||
|
"radial-gradient(120% 120% at 100% 0%, rgba(214, 130, 255, 0.18), transparent 60%), #040711",
|
||||||
|
text: "#e2e8f0",
|
||||||
|
subtext: "#9ba3b4",
|
||||||
|
accent: "#7dd3fc",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gradient button styling
|
||||||
|
const gradientButtonSx = {
|
||||||
|
backgroundImage: "linear-gradient(135deg,#7dd3fc,#c084fc)",
|
||||||
|
color: "#0b1220",
|
||||||
|
borderRadius: 999,
|
||||||
|
textTransform: "none",
|
||||||
|
boxShadow: "0 10px 26px rgba(124,58,237,0.28)",
|
||||||
|
px: 2.6,
|
||||||
|
minWidth: 116,
|
||||||
|
"&:hover": {
|
||||||
|
backgroundImage: "linear-gradient(135deg,#86e1ff,#d1a6ff)",
|
||||||
|
boxShadow: "0 12px 34px rgba(124,58,237,0.38)",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
function ResultsBar({ counts }) {
|
function ResultsBar({ counts }) {
|
||||||
const total = Math.max(1, Number(counts?.total_targets || 0));
|
const total = Math.max(1, Number(counts?.total_targets || 0));
|
||||||
@@ -67,24 +109,8 @@ function ResultsBar({ counts }) {
|
|||||||
.some((section) => Number(counts?.[section.key] || 0) > 0);
|
.some((section) => Number(counts?.[section.key] || 0) > 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box sx={{ display: "flex", flexDirection: "column", gap: 0.25, lineHeight: 1.7, fontFamily: gridFontFamily }}>
|
||||||
sx={{
|
<Box sx={{ display: "flex", borderRadius: 1, overflow: "hidden", width: 220, height: 6 }}>
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
gap: 0.25,
|
|
||||||
lineHeight: 1.7,
|
|
||||||
fontFamily: gridFontFamily
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
borderRadius: 1,
|
|
||||||
overflow: "hidden",
|
|
||||||
width: 220,
|
|
||||||
height: 6
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{sections.map((section) => {
|
{sections.map((section) => {
|
||||||
const value = Number(counts?.[section.key] || 0);
|
const value = Number(counts?.[section.key] || 0);
|
||||||
if (!value) return null;
|
if (!value) return null;
|
||||||
@@ -116,20 +142,8 @@ function ResultsBar({ counts }) {
|
|||||||
return sections
|
return sections
|
||||||
.filter((section) => Number(counts?.[section.key] || 0) > 0)
|
.filter((section) => Number(counts?.[section.key] || 0) > 0)
|
||||||
.map((section) => (
|
.map((section) => (
|
||||||
<Box
|
<Box key={section.key} component="span" sx={{ display: "inline-flex", alignItems: "center", gap: 0.5 }}>
|
||||||
key={section.key}
|
<Box component="span" sx={{ width: 6, height: 6, borderRadius: 1, backgroundColor: section.color }} />
|
||||||
component="span"
|
|
||||||
sx={{ display: "inline-flex", alignItems: "center", gap: 0.5 }}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
component="span"
|
|
||||||
sx={{
|
|
||||||
width: 6,
|
|
||||||
height: 6,
|
|
||||||
borderRadius: 1,
|
|
||||||
backgroundColor: section.color
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{counts?.[section.key]} {labelFor(section.key)}
|
{counts?.[section.key]} {labelFor(section.key)}
|
||||||
</Box>
|
</Box>
|
||||||
));
|
));
|
||||||
@@ -478,12 +492,8 @@ export default function ScheduledJobsList({ onCreateJob, onEditJob, refreshToken
|
|||||||
onChange={handleToggle}
|
onChange={handleToggle}
|
||||||
onClick={(event) => event.stopPropagation()}
|
onClick={(event) => event.stopPropagation()}
|
||||||
sx={{
|
sx={{
|
||||||
"& .MuiSwitch-switchBase.Mui-checked": {
|
"& .MuiSwitch-switchBase.Mui-checked": { color: "#58a6ff" },
|
||||||
color: "#58a6ff"
|
"& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track": { bgcolor: "#58a6ff" }
|
||||||
},
|
|
||||||
"& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track": {
|
|
||||||
bgcolor: "#58a6ff"
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -491,49 +501,42 @@ export default function ScheduledJobsList({ onCreateJob, onEditJob, refreshToken
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Selection column parity (square, centered, pinned left)
|
||||||
|
const selectionCol = {
|
||||||
|
headerName: "",
|
||||||
|
field: "__select__",
|
||||||
|
width: 52,
|
||||||
|
maxWidth: 52,
|
||||||
|
checkboxSelection: true,
|
||||||
|
headerCheckboxSelection: true,
|
||||||
|
resizable: false,
|
||||||
|
sortable: false,
|
||||||
|
suppressMenu: true,
|
||||||
|
filter: false,
|
||||||
|
pinned: "left",
|
||||||
|
lockPosition: true,
|
||||||
|
};
|
||||||
|
|
||||||
const columnDefs = useMemo(
|
const columnDefs = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
selectionCol,
|
||||||
headerName: "",
|
|
||||||
field: "__checkbox__",
|
|
||||||
checkboxSelection: true,
|
|
||||||
headerCheckboxSelection: true,
|
|
||||||
maxWidth: 60,
|
|
||||||
minWidth: 60,
|
|
||||||
sortable: false,
|
|
||||||
filter: false,
|
|
||||||
resizable: false,
|
|
||||||
suppressMenu: true,
|
|
||||||
pinned: false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
headerName: "Name",
|
headerName: "Name",
|
||||||
field: "name",
|
field: "name",
|
||||||
cellRenderer: nameCellRenderer,
|
cellRenderer: nameCellRenderer,
|
||||||
sort: "asc"
|
sort: "asc",
|
||||||
|
minWidth: 220,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headerName: "Assembly(s)",
|
headerName: "Assembly(s)",
|
||||||
field: "componentsMeta",
|
field: "componentsMeta",
|
||||||
minWidth: 240,
|
minWidth: 260,
|
||||||
cellRenderer: assembliesCellRenderer
|
cellRenderer: assembliesCellRenderer
|
||||||
},
|
},
|
||||||
{
|
{ headerName: "Target", field: "target", minWidth: 140 },
|
||||||
headerName: "Target",
|
{ headerName: "Recurrence", field: "occurrence", minWidth: 160 },
|
||||||
field: "target"
|
{ headerName: "Last Run", field: "lastRun", minWidth: 160 },
|
||||||
},
|
{ headerName: "Next Run", field: "nextRun", minWidth: 160 },
|
||||||
{
|
|
||||||
headerName: "Recurrence",
|
|
||||||
field: "occurrence"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
headerName: "Last Run",
|
|
||||||
field: "lastRun"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
headerName: "Next Run",
|
|
||||||
field: "nextRun"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
headerName: "Results",
|
headerName: "Results",
|
||||||
field: "resultsCounts",
|
field: "resultsCounts",
|
||||||
@@ -562,7 +565,6 @@ export default function ScheduledJobsList({ onCreateJob, onEditJob, refreshToken
|
|||||||
sortable: true,
|
sortable: true,
|
||||||
filter: "agTextColumnFilter",
|
filter: "agTextColumnFilter",
|
||||||
resizable: true,
|
resizable: true,
|
||||||
flex: 1,
|
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
cellStyle: {
|
cellStyle: {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@@ -570,145 +572,181 @@ export default function ScheduledJobsList({ onCreateJob, onEditJob, refreshToken
|
|||||||
color: "#f5f7fa",
|
color: "#f5f7fa",
|
||||||
fontFamily: gridFontFamily,
|
fontFamily: gridFontFamily,
|
||||||
fontSize: "13px"
|
fontSize: "13px"
|
||||||
},
|
}
|
||||||
headerClass: "scheduled-jobs-grid-header"
|
|
||||||
}),
|
}),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleRefreshClick = useCallback(async () => {
|
||||||
|
await loadJobs({ showLoading: true });
|
||||||
|
}, [loadJobs]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<Paper
|
||||||
sx={{
|
sx={{
|
||||||
m: 2,
|
m: 0,
|
||||||
p: 0,
|
p: 0,
|
||||||
bgcolor: "#1e1e1e",
|
background: AURORA_SHELL.background,
|
||||||
color: "#f5f7fa",
|
border: "none",
|
||||||
fontFamily: gridFontFamily,
|
boxShadow: "none",
|
||||||
|
borderRadius: 0,
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
minWidth: 0,
|
minWidth: 0,
|
||||||
minHeight: 420
|
minHeight: 420,
|
||||||
|
height: "100%",
|
||||||
|
color: AURORA_SHELL.text,
|
||||||
|
fontFamily: gridFontFamily,
|
||||||
}}
|
}}
|
||||||
elevation={2}
|
elevation={0}
|
||||||
>
|
>
|
||||||
<Box
|
{/* Page header (keep padding: top 24px, left/right 24px) */}
|
||||||
sx={{
|
<Box sx={{ px: 3, pt: 3, pb: 1 }}>
|
||||||
display: "flex",
|
<Stack direction="row" alignItems="center" spacing={1.25}>
|
||||||
alignItems: "center",
|
<HeaderIcon sx={{ fontSize: 22, color: AURORA_SHELL.accent }} />
|
||||||
justifyContent: "space-between",
|
<Typography variant="h6" sx={{ fontWeight: 700, letterSpacing: 0.5 }}>
|
||||||
p: 2,
|
|
||||||
borderBottom: "1px solid #2a2a2a"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box>
|
|
||||||
<Typography variant="h6" sx={{ color: "#58a6ff", mb: 0.3 }}>
|
|
||||||
Scheduled Jobs
|
Scheduled Jobs
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2" sx={{ color: "#aaa" }}>
|
<Box sx={{ flexGrow: 1 }} />
|
||||||
List of automation jobs with schedules, results, and actions.
|
<Stack direction="row" spacing={1}>
|
||||||
</Typography>
|
<Tooltip title="Refresh">
|
||||||
</Box>
|
<span>
|
||||||
<Box sx={{ display: "flex", gap: 1, alignItems: "center" }}>
|
<IconButton
|
||||||
<Button
|
size="small"
|
||||||
variant="outlined"
|
onClick={handleRefreshClick}
|
||||||
size="small"
|
sx={{ color: "#cbd5e1", borderRadius: 1, "&:hover": { color: "#ffffff" } }}
|
||||||
disabled={!anySelected}
|
>
|
||||||
sx={{
|
<CachedIcon fontSize="small" />
|
||||||
color: anySelected ? "#ff8080" : "#666",
|
</IconButton>
|
||||||
borderColor: anySelected ? "#ff8080" : "#333",
|
</span>
|
||||||
textTransform: "none",
|
</Tooltip>
|
||||||
fontFamily: gridFontFamily,
|
<Tooltip title="Create Job">
|
||||||
"&:hover": {
|
<span>
|
||||||
borderColor: anySelected ? "#ff8080" : "#333"
|
<Button size="small" startIcon={<AddIcon />} sx={gradientButtonSx} onClick={() => onCreateJob && onCreateJob()}>
|
||||||
}
|
Create Job
|
||||||
}}
|
</Button>
|
||||||
onClick={() => setBulkDeleteOpen(true)}
|
</span>
|
||||||
>
|
</Tooltip>
|
||||||
Delete Job
|
<Tooltip title="Settings">
|
||||||
</Button>
|
<span>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
size="small"
|
||||||
size="small"
|
variant="outlined"
|
||||||
sx={{
|
startIcon={<TuneIcon />}
|
||||||
bgcolor: "#58a6ff",
|
sx={{
|
||||||
color: "#0b0f19",
|
borderColor: "rgba(148,163,184,0.35)",
|
||||||
textTransform: "none",
|
color: "#e2e8f0",
|
||||||
fontFamily: gridFontFamily,
|
textTransform: "none",
|
||||||
"&:hover": {
|
borderRadius: 999,
|
||||||
bgcolor: "#7db7ff"
|
px: 1.7,
|
||||||
}
|
minWidth: 86,
|
||||||
}}
|
"&:hover": { borderColor: "rgba(148,163,184,0.55)" },
|
||||||
onClick={() => onCreateJob && onCreateJob()}
|
}}
|
||||||
>
|
>
|
||||||
Create Job
|
Settings
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
{/* Subtitle directly under title (muted color, small size) */}
|
||||||
|
<Typography variant="body2" sx={{ color: AURORA_SHELL.subtext, mt: 0.75 }}>
|
||||||
|
List of automation jobs with schedules, results, and actions.
|
||||||
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{loading && (
|
{/* Content area — a bit more top space below subtitle */}
|
||||||
<Box
|
<Box sx={{ mt: "28px", px: 2, pb: 2, flexGrow: 1, minHeight: 0, display: "flex", flexDirection: "column" }}>
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: 1,
|
|
||||||
color: "#7db7ff",
|
|
||||||
px: 2,
|
|
||||||
py: 1.5,
|
|
||||||
borderBottom: "1px solid #2a2a2a"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CircularProgress size={18} sx={{ color: "#58a6ff" }} />
|
|
||||||
<Typography variant="body2">Loading scheduled jobs…</Typography>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{error && (
|
|
||||||
<Box sx={{ px: 2, py: 1.5, color: "#ff8080", borderBottom: "1px solid #2a2a2a" }}>
|
|
||||||
<Typography variant="body2">{error}</Typography>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
flexGrow: 1,
|
|
||||||
minHeight: 0,
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
mt: "10px",
|
|
||||||
px: 2,
|
|
||||||
pb: 2
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
<Box
|
||||||
className={themeClassName}
|
className={themeClassName}
|
||||||
sx={{
|
sx={{
|
||||||
|
background: "transparent",
|
||||||
|
border: "none",
|
||||||
|
p: 0,
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
|
minHeight: 0,
|
||||||
|
height: "100%",
|
||||||
|
position: "relative",
|
||||||
fontFamily: gridFontFamily,
|
fontFamily: gridFontFamily,
|
||||||
"--ag-font-family": gridFontFamily,
|
"--ag-font-family": gridFontFamily,
|
||||||
"--ag-icon-font-family": iconFontFamily,
|
"--ag-icon-font-family": iconFontFamily,
|
||||||
"--ag-row-border-style": "solid",
|
|
||||||
"--ag-row-border-color": "#2a2a2a",
|
"& .ag-cell": {
|
||||||
"--ag-row-border-width": "1px",
|
display: "flex",
|
||||||
"& .ag-root-wrapper": {
|
alignItems: "center",
|
||||||
borderRadius: 1,
|
paddingTop: "8px",
|
||||||
minHeight: 320
|
paddingBottom: "8px",
|
||||||
},
|
},
|
||||||
"& .ag-root, & .ag-header, & .ag-center-cols-container, & .ag-paging-panel": {
|
|
||||||
fontFamily: gridFontFamily
|
/* Center the selection column (header + body) */
|
||||||
|
"& .ag-header .ag-header-select-all, & .ag-header .ag-checkbox-input-wrapper": {
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
},
|
},
|
||||||
"& .ag-icon": {
|
"& .ag-cell.ag-selection-centered": {
|
||||||
fontFamily: iconFontFamily
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
paddingLeft: 0,
|
||||||
|
paddingRight: 0,
|
||||||
},
|
},
|
||||||
"& .scheduled-jobs-grid-header": {
|
"& .ag-cell.ag-selection-centered .ag-cell-wrapper": {
|
||||||
fontFamily: gridFontFamily,
|
gap: "0 !important",
|
||||||
fontWeight: 600,
|
width: "100%",
|
||||||
color: "#f5f7fa"
|
display: "flex",
|
||||||
}
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
paddingTop: 0,
|
||||||
|
paddingBottom: 0,
|
||||||
|
},
|
||||||
|
"& .ag-cell.ag-selection-centered .ag-selection-checkbox, & .ag-cell.ag-selection-centered .ag-checkbox-input-wrapper": {
|
||||||
|
margin: "0 auto",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
"--ag-background-color": "#070b1a",
|
||||||
|
"--ag-foreground-color": "#f4f7ff",
|
||||||
|
"--ag-header-background-color": "#0f172a",
|
||||||
|
"--ag-header-foreground-color": "#cfe0ff",
|
||||||
|
"--ag-odd-row-background-color": "rgba(255,255,255,0.02)",
|
||||||
|
"--ag-row-hover-color": "rgba(125,183,255,0.08)",
|
||||||
|
"--ag-selected-row-background-color": "rgba(64,164,255,0.18)",
|
||||||
|
"--ag-border-color": "rgba(125,183,255,0.18)",
|
||||||
|
"--ag-row-border-color": "rgba(125,183,255,0.14)",
|
||||||
|
"--ag-border-radius": "8px",
|
||||||
|
"--ag-checkbox-border-radius": "3px",
|
||||||
|
"--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",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{/* Action bar for bulk delete stays above grid when needed */}
|
||||||
|
{anySelected && (
|
||||||
|
<Box sx={{ display: "flex", alignItems: "center", gap: 1, color: "#7db7ff", px: 1.5, py: 1 }}>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
size="small"
|
||||||
|
sx={{
|
||||||
|
color: "#ff8080",
|
||||||
|
borderColor: "rgba(255,128,128,0.5)",
|
||||||
|
textTransform: "none",
|
||||||
|
borderRadius: 999,
|
||||||
|
"&:hover": { borderColor: "#ff8080" },
|
||||||
|
}}
|
||||||
|
onClick={() => setBulkDeleteOpen(true)}
|
||||||
|
>
|
||||||
|
Delete Job
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
<AgGridReact
|
<AgGridReact
|
||||||
rowData={rows}
|
rowData={rows}
|
||||||
columnDefs={columnDefs}
|
columnDefs={columnDefs}
|
||||||
@@ -724,13 +762,8 @@ export default function ScheduledJobsList({ onCreateJob, onEditJob, refreshToken
|
|||||||
overlayNoRowsTemplate="<span class='ag-overlay-no-rows-center'>No scheduled jobs found.</span>"
|
overlayNoRowsTemplate="<span class='ag-overlay-no-rows-center'>No scheduled jobs found.</span>"
|
||||||
onGridReady={handleGridReady}
|
onGridReady={handleGridReady}
|
||||||
onSelectionChanged={handleSelectionChanged}
|
onSelectionChanged={handleSelectionChanged}
|
||||||
theme={myTheme}
|
theme={gridTheme}
|
||||||
style={{
|
style={{ width: "100%", height: "100%", fontFamily: gridFontFamily, "--ag-icon-font-family": iconFontFamily }}
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
fontFamily: gridFontFamily,
|
|
||||||
"--ag-icon-font-family": iconFontFamily
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
Reference in New Issue
Block a user