DataGrid - initial commit
This commit is contained in:
@@ -8,6 +8,8 @@ import FormField from "../../components/FormField";
|
||||
import LoadingFrame from "../../components/LoadingFrame";
|
||||
import PageTitle from "../../components/PageTitle";
|
||||
import StatusBadge from "../../components/StatusBadge";
|
||||
import DismissibleAlert from "../../components/DismissibleAlert";
|
||||
import DataGrid, { type DataGridColumn } from "../../components/table/DataGrid";
|
||||
import { publishCampaignVersion, updateCampaignMetadata, type CampaignVersionListItem } from "../../api/campaigns";
|
||||
import { useCampaignWorkspaceData } from "./hooks/useCampaignWorkspaceData";
|
||||
import { canUnlockValidationVersion, formatDateTime, isFinalLockedVersion, isUserLockedVersion, isVersionReadyForDelivery, summaryValue } from "./utils/campaignView";
|
||||
@@ -94,8 +96,8 @@ export default function CampaignOverviewPage({ settings, campaignId }: { setting
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{error && <div className="alert danger">{error}</div>}
|
||||
{message && <div className="alert success">{message}</div>}
|
||||
{error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>}
|
||||
{message && <DismissibleAlert tone="success" resetKey={message}>{message}</DismissibleAlert>}
|
||||
|
||||
<LoadingFrame loading={loading} label="Loading campaign overview…">
|
||||
<Card title="Campaign identity">
|
||||
@@ -118,48 +120,15 @@ export default function CampaignOverviewPage({ settings, campaignId }: { setting
|
||||
</Card>
|
||||
|
||||
<Card title="Version history">
|
||||
<div className="app-table-wrap">
|
||||
<table className="app-table version-history-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Version</th>
|
||||
<th>State</th>
|
||||
<th>Lock</th>
|
||||
<th>Validation</th>
|
||||
<th>Build</th>
|
||||
<th>Updated</th>
|
||||
<th aria-label="Actions"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{versions.length === 0 && (
|
||||
<tr><td colSpan={7} className="muted">No versions found.</td></tr>
|
||||
)}
|
||||
{versions.map((version) => {
|
||||
const isCurrentVersion = version.id === data.currentVersion?.id;
|
||||
return (
|
||||
<tr key={version.id} className={isCurrentVersion ? "current-version-row" : undefined}>
|
||||
<td>#{version.version_number}</td>
|
||||
<td><StatusBadge status={version.workflow_state ?? "editing"} /></td>
|
||||
<td>{versionLockLabel(version)}</td>
|
||||
<td>{validationLabel(version)}</td>
|
||||
<td>{buildLabel(version)}</td>
|
||||
<td>{formatDateTime(version.updated_at)}</td>
|
||||
<td className="table-action-cell">
|
||||
<div className="button-row compact-actions">
|
||||
<Link to={`review?version=${version.id}`}><Button variant="primary">Open</Button></Link>
|
||||
<Button
|
||||
onClick={() => setLockingVersion(version)}
|
||||
disabled={isUserLockedVersion(version) || isFinalLockedVersion(version) || canUnlockValidationVersion(version)}
|
||||
>Lock</Button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<DataGrid
|
||||
id={`campaign-${campaignId}-versions`}
|
||||
rows={versions}
|
||||
columns={versionColumns(setLockingVersion)}
|
||||
getRowKey={(version) => version.id}
|
||||
emptyText="No versions found."
|
||||
className="version-history-table"
|
||||
rowClassName={(version) => version.id === data.currentVersion?.id ? "current-version-row" : undefined}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
<Card title="Current version state">
|
||||
@@ -186,6 +155,32 @@ export default function CampaignOverviewPage({ settings, campaignId }: { setting
|
||||
);
|
||||
}
|
||||
|
||||
function versionColumns(setLockingVersion: (version: CampaignVersionListItem) => void): DataGridColumn<CampaignVersionListItem>[] {
|
||||
return [
|
||||
{ id: "version", header: "Version", width: 110, sortable: true, filterable: true, sticky: "start", render: (version) => `#${version.version_number}`, value: (version) => version.version_number ?? 0 },
|
||||
{ id: "state", header: "State", width: 140, sortable: true, filterable: true, render: (version) => <StatusBadge status={version.workflow_state ?? "editing"} />, value: (version) => version.workflow_state ?? "editing" },
|
||||
{ id: "lock", header: "Lock", width: 170, sortable: true, filterable: true, render: versionLockLabel, value: versionLockLabel },
|
||||
{ id: "validation", header: "Validation", width: 170, sortable: true, filterable: true, render: validationLabel, value: validationLabel },
|
||||
{ id: "build", header: "Build", width: 140, sortable: true, filterable: true, render: buildLabel, value: buildLabel },
|
||||
{ id: "updated", header: "Updated", width: 190, sortable: true, filterable: true, render: (version) => formatDateTime(version.updated_at), value: (version) => version.updated_at ?? "" },
|
||||
{
|
||||
id: "actions",
|
||||
header: "Actions",
|
||||
width: 190,
|
||||
sticky: "end",
|
||||
render: (version) => (
|
||||
<div className="button-row compact-actions">
|
||||
<Link to={`send?version=${version.id}`}><Button variant="primary">Open</Button></Link>
|
||||
<Button
|
||||
onClick={() => setLockingVersion(version)}
|
||||
disabled={isUserLockedVersion(version) || isFinalLockedVersion(version) || canUnlockValidationVersion(version)}
|
||||
>Lock</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
function versionLockLabel(version: CampaignVersionListItem): string {
|
||||
if (isUserLockedVersion(version)) return "User locked";
|
||||
if (isFinalLockedVersion(version)) return "Final";
|
||||
|
||||
Reference in New Issue
Block a user