quidproquo-web-admin 0.1.27 → 0.1.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,6 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.MaintenanceEditor = MaintenanceEditor;
16
16
  const jsx_runtime_1 = require("react/jsx-runtime");
17
+ const quidproquo_core_1 = require("quidproquo-core");
17
18
  const quidproquo_features_1 = require("quidproquo-features");
18
19
  const quidproquo_web_react_1 = require("quidproquo-web-react");
19
20
  const react_1 = require("react");
@@ -94,11 +95,11 @@ function MaintenanceEditor({ docId, onBack }) {
94
95
  else if (dialog.kind === 'reopen') {
95
96
  const reopened = yield applyEvent(quidproquo_features_1.EventDocEffect.CreateDraft, undefined);
96
97
  if (reopened) {
97
- yield applyEvent(quidproquo_features_1.MaintenanceEffect.AddUpdate, Object.assign({ updateId: crypto.randomUUID() }, values));
98
+ yield applyEvent(quidproquo_features_1.MaintenanceEffect.AddUpdate, Object.assign({ updateId: (0, quidproquo_core_1.generateUuid)() }, values));
98
99
  }
99
100
  }
100
101
  else {
101
- yield applyEvent(quidproquo_features_1.MaintenanceEffect.AddUpdate, Object.assign({ updateId: crypto.randomUUID() }, values));
102
+ yield applyEvent(quidproquo_features_1.MaintenanceEffect.AddUpdate, Object.assign({ updateId: (0, quidproquo_core_1.generateUuid)() }, values));
102
103
  }
103
104
  setDialog({ kind: 'closed' });
104
105
  });
@@ -1 +1 @@
1
- {"version":3,"file":"MaintenanceEditor.js","sourceRoot":"","sources":["../../../src/Maintenance/MaintenanceEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Nullable } from 'quidproquo-core';\nimport {\n EventDocEffect,\n EventDocEvent,\n EventDocStatus,\n isMaintenancePubliclyVisible,\n MaintenanceEffect,\n maintenanceEventDoc,\n MaintenanceLevel,\n MaintenanceType,\n MaintenanceUpdateEntry,\n toMaintenancePublicState,\n} from 'quidproquo-features';\nimport { useAuthAccessToken, useBaseUrlResolvers } from 'quidproquo-web-react';\n\nimport { useEffect, useMemo, useState } from 'react';\nimport AddIcon from '@mui/icons-material/Add';\nimport ArrowBackIcon from '@mui/icons-material/ArrowBack';\nimport DeleteIcon from '@mui/icons-material/Delete';\nimport EditIcon from '@mui/icons-material/Edit';\nimport EngineeringIcon from '@mui/icons-material/Engineering';\nimport {\n Alert,\n Box,\n Button,\n Chip,\n CircularProgress,\n Divider,\n IconButton,\n Paper,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n Typography,\n} from '@mui/material';\n\nimport { appendMaintenanceEvent, fetchMaintenanceEvents } from './logic';\nimport { MaintenanceUserPreview } from './MaintenanceUserPreview';\nimport { MaintenanceUpdateFormPrefill, MaintenanceUpdateFormValues, UpdateDialog } from './UpdateDialog';\n\ntype MaintenanceEditorProps = {\n docId: string;\n onBack: () => void;\n};\n\ntype DialogMode = { kind: 'closed' } | { kind: 'add' } | { kind: 'edit'; update: MaintenanceUpdateEntry } | { kind: 'reopen' };\n\n// One maintenance: a read-only header card with the CURRENT folded state, and\n// the update feed it derives from. The UPDATE is the only mutation — adding one\n// (prefilled from the last, ETA blank against the running clock) moves the whole\n// status; editing/deleting entries re-derives, so deleting the newest rolls the\n// card back. Closing publishes; reopening demands a fresh update (level resets\n// to Low in the prefill) so a maintenance closed at High never reopens locked.\nexport function MaintenanceEditor({ docId, onBack }: MaintenanceEditorProps) {\n const urlResolvers = useBaseUrlResolvers();\n const accessToken = useAuthAccessToken();\n\n const [events, setEvents] = useState<EventDocEvent[] | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n const [dialog, setDialog] = useState<DialogMode>({ kind: 'closed' });\n\n const folded = useMemo(() => (events ? maintenanceEventDoc.views.document.fold(events) : null), [events]);\n const isClosed = folded?.status === EventDocStatus.Published;\n\n useEffect(() => {\n const load = async () => {\n setError(null);\n try {\n setEvents(await fetchMaintenanceEvents(docId, urlResolvers.getApiUrl(), accessToken));\n } catch (loadError) {\n setError(`Failed to load maintenance: ${loadError}`);\n }\n };\n load();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [docId]);\n\n const applyEvent = async (type: string, data: unknown): Promise<boolean> => {\n setBusy(true);\n setError(null);\n try {\n const event = await appendMaintenanceEvent(docId, type, data, urlResolvers.getApiUrl(), accessToken);\n setEvents((prev) => (prev ? [...prev, event] : [event]));\n return true;\n } catch (appendError) {\n setError(`Failed to save change: ${appendError}`);\n return false;\n } finally {\n setBusy(false);\n }\n };\n\n if (!folded) {\n return (\n <Box sx={{ display: 'flex', justifyContent: 'center', p: 6 }}>{error ? <Alert severity=\"error\">{error}</Alert> : <CircularProgress />}</Box>\n );\n }\n\n const updatesNewestFirst = [...folded.updates].reverse();\n const lastUpdate: Nullable<MaintenanceUpdateEntry> = folded.updates[folded.updates.length - 1] ?? null;\n\n const addPrefill: MaintenanceUpdateFormPrefill = {\n bannerText: folded.bannerText,\n reason: folded.reason,\n level: folded.level,\n maintenanceType: folded.maintenanceType,\n affectedServices: folded.affectedServices,\n internalNotes: '',\n };\n\n // Reopen is \"create from inside\": reason/type/services carry over for\n // convenience, but the level RESETS to Low and there is no running clock.\n const reopenPrefill: MaintenanceUpdateFormPrefill = {\n ...addPrefill,\n level: MaintenanceLevel.Low,\n };\n\n const onDialogSave = async (values: MaintenanceUpdateFormValues) => {\n if (dialog.kind === 'edit') {\n await applyEvent(MaintenanceEffect.EditUpdate, { updateId: dialog.update.id, ...values });\n } else if (dialog.kind === 'reopen') {\n const reopened = await applyEvent(EventDocEffect.CreateDraft, undefined);\n if (reopened) {\n await applyEvent(MaintenanceEffect.AddUpdate, { updateId: crypto.randomUUID(), ...values });\n }\n } else {\n await applyEvent(MaintenanceEffect.AddUpdate, { updateId: crypto.randomUUID(), ...values });\n }\n setDialog({ kind: 'closed' });\n };\n\n return (\n <Box sx={{ p: 3, display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>\n <IconButton aria-label=\"Back to maintenance list\" onClick={onBack}>\n <ArrowBackIcon />\n </IconButton>\n <Typography color=\"text.secondary\" variant=\"body2\">\n Maintenance\n </Typography>\n </Box>\n\n {error && <Alert severity=\"error\">{error}</Alert>}\n\n {/* 70/30: the editor on the left, the what-users-see mock on the right. */}\n <Box sx={{ display: 'flex', gap: 3, alignItems: 'flex-start' }}>\n <Box sx={{ flex: '1 1 70%', minWidth: 0, display: 'flex', flexDirection: 'column', gap: 2 }}>\n {/* The current folded state — read-only; it moves only via updates. */}\n <Paper sx={{ p: 3, display: 'flex', flexDirection: 'column', gap: 1.5 }} variant=\"outlined\">\n <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2 }}>\n <EngineeringIcon color={isClosed ? 'disabled' : 'warning'} sx={{ fontSize: 40 }} />\n <Box sx={{ flexGrow: 1 }}>\n <Typography variant=\"h5\">{folded.bannerText || folded.name}</Typography>\n {folded.reason && folded.reason !== folded.bannerText && (\n <Typography color=\"text.secondary\" variant=\"body2\">\n Latest: {folded.reason}\n </Typography>\n )}\n <Box sx={{ display: 'flex', gap: 1, mt: 1, flexWrap: 'wrap' }}>\n {isClosed ? <Chip label=\"Closed\" size=\"small\" /> : <Chip color=\"warning\" label=\"Active\" size=\"small\" />}\n <Chip\n color={\n folded.level === MaintenanceLevel.High && !isClosed ? 'error' : folded.level === MaintenanceLevel.Info ? 'info' : 'default'\n }\n label={\n folded.level === MaintenanceLevel.High\n ? 'High — UI locked'\n : folded.level === MaintenanceLevel.Info\n ? 'Info — banner'\n : folded.level === MaintenanceLevel.Internal\n ? 'Internal — hidden from users'\n : 'Low — banner only'\n }\n size=\"small\"\n variant={folded.level === MaintenanceLevel.High ? 'filled' : 'outlined'}\n />\n <Chip label={folded.maintenanceType === MaintenanceType.Incident ? 'Incident' : 'Deploy'} size=\"small\" variant=\"outlined\" />\n {folded.etaEndsAt && <Chip label={`Ends ~${new Date(folded.etaEndsAt).toLocaleTimeString()}`} size=\"small\" variant=\"outlined\" />}\n <Chip\n label={folded.affectedServices ? `Affected: ${folded.affectedServices.join(', ')}` : 'All services'}\n size=\"small\"\n variant=\"outlined\"\n />\n </Box>\n </Box>\n {isClosed ? (\n <Button disabled={busy} onClick={() => setDialog({ kind: 'reopen' })} variant=\"contained\">\n Reopen maintenance\n </Button>\n ) : (\n <Button\n color=\"success\"\n disabled={busy}\n onClick={() => applyEvent(EventDocEffect.Publish, { effectiveFrom: new Date().toISOString() })}\n variant=\"contained\"\n >\n Close maintenance\n </Button>\n )}\n </Box>\n {lastUpdate?.internalNotes && (\n <Typography color=\"text.secondary\" sx={{ fontStyle: 'italic' }} variant=\"body2\">\n Internal: {lastUpdate.internalNotes}\n </Typography>\n )}\n </Paper>\n\n <Divider />\n\n <Box sx={{ display: 'flex', alignItems: 'center' }}>\n <Typography sx={{ flexGrow: 1 }} variant=\"h6\">\n Updates\n </Typography>\n <Button disabled={isClosed || busy} onClick={() => setDialog({ kind: 'add' })} startIcon={<AddIcon />} variant=\"outlined\">\n Add update\n </Button>\n </Box>\n\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Status</TableCell>\n <TableCell>Level</TableCell>\n <TableCell>ETA</TableCell>\n <TableCell>Internal notes</TableCell>\n <TableCell>Posted</TableCell>\n <TableCell align=\"right\">Actions</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {updatesNewestFirst.map((update) => (\n <TableRow key={update.id} hover>\n <TableCell sx={{ maxWidth: 420 }}>{update.reason}</TableCell>\n <TableCell>\n <Chip\n color={update.level === MaintenanceLevel.High ? 'error' : update.level === MaintenanceLevel.Info ? 'info' : 'default'}\n label={update.level}\n size=\"small\"\n variant={update.level === MaintenanceLevel.High ? 'filled' : 'outlined'}\n />\n </TableCell>\n <TableCell>{update.etaSetAt ? (update.etaDurationMins === null ? 'Cleared' : `${update.etaDurationMins}m`) : '—'}</TableCell>\n <TableCell sx={{ maxWidth: 360 }}>\n {update.internalNotes ? (\n <Typography color=\"text.secondary\" sx={{ fontStyle: 'italic' }} variant=\"body2\">\n {update.internalNotes}\n </Typography>\n ) : (\n '—'\n )}\n </TableCell>\n <TableCell sx={{ whiteSpace: 'nowrap' }}>\n {new Date(update.createdAt).toLocaleString()} — {update.createdByDisplayName}\n {update.updatedAt ? ' (edited)' : ''}\n </TableCell>\n <TableCell align=\"right\" sx={{ whiteSpace: 'nowrap' }}>\n {!isClosed && (\n <>\n <IconButton aria-label=\"Edit update\" disabled={busy} onClick={() => setDialog({ kind: 'edit', update })} size=\"small\">\n <EditIcon fontSize=\"small\" />\n </IconButton>\n <IconButton\n aria-label=\"Delete update\"\n disabled={busy}\n onClick={() => applyEvent(MaintenanceEffect.RemoveUpdate, { updateId: update.id })}\n size=\"small\"\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButton>\n </>\n )}\n </TableCell>\n </TableRow>\n ))}\n {folded.updates.length === 0 && (\n <TableRow>\n <TableCell colSpan={6}>\n <Typography color=\"text.secondary\" sx={{ p: 1 }} variant=\"body2\">\n No updates posted yet.\n </Typography>\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </Box>\n\n <Box sx={{ flex: '0 0 30%', minWidth: 300 }}>\n <MaintenanceUserPreview publicState={toMaintenancePublicState(folded)} visible={isMaintenancePubliclyVisible(folded)} />\n </Box>\n </Box>\n\n <UpdateDialog\n busy={busy}\n confirmLabel={dialog.kind === 'reopen' ? 'Reopen maintenance' : dialog.kind === 'edit' ? 'Save update' : 'Add update'}\n currentEtaEndsAt={dialog.kind === 'reopen' ? null : folded.etaEndsAt}\n initialValues={\n dialog.kind === 'edit'\n ? {\n bannerText: dialog.update.bannerText,\n reason: dialog.update.reason,\n level: dialog.update.level,\n maintenanceType: dialog.update.maintenanceType,\n affectedServices: dialog.update.affectedServices,\n internalNotes: dialog.update.internalNotes,\n }\n : dialog.kind === 'reopen'\n ? reopenPrefill\n : addPrefill\n }\n onCancel={() => setDialog({ kind: 'closed' })}\n onSave={onDialogSave}\n open={dialog.kind !== 'closed'}\n title={dialog.kind === 'reopen' ? 'Reopen maintenance' : dialog.kind === 'edit' ? 'Edit update' : 'Add update'}\n />\n </Box>\n );\n}\n"]}
1
+ {"version":3,"file":"MaintenanceEditor.js","sourceRoot":"","sources":["../../../src/Maintenance/MaintenanceEditor.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;AAuDA,8CAyQC;;AAhUD,qDAAyD;AACzD,6DAW6B;AAC7B,+DAA+E;AAE/E,iCAAqD;AACrD,kEAA8C;AAC9C,8EAA0D;AAC1D,wEAAoD;AACpD,oEAAgD;AAChD,kFAA8D;AAC9D,4CAeuB;AAEvB,mCAAyE;AACzE,qEAAkE;AAClE,iDAAyG;AASzG,8EAA8E;AAC9E,gFAAgF;AAChF,iFAAiF;AACjF,gFAAgF;AAChF,+EAA+E;AAC/E,+EAA+E;AAC/E,SAAgB,iBAAiB,CAAC,EAAE,KAAK,EAAE,MAAM,EAA0B;;IACzE,MAAM,YAAY,GAAG,IAAA,0CAAmB,GAAE,CAAC;IAC3C,MAAM,WAAW,GAAG,IAAA,yCAAkB,GAAE,CAAC;IAEzC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,EAAyB,IAAI,CAAC,CAAC;IACnE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAgB,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,EAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAErE,MAAM,MAAM,GAAG,IAAA,eAAO,EAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,yCAAmB,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1G,MAAM,QAAQ,GAAG,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,MAAK,oCAAc,CAAC,SAAS,CAAC;IAE7D,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,MAAM,IAAI,GAAG,GAAS,EAAE;YACtB,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,IAAI,CAAC;gBACH,SAAS,CAAC,MAAM,IAAA,8BAAsB,EAAC,KAAK,EAAE,YAAY,CAAC,SAAS,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;YACxF,CAAC;YAAC,OAAO,SAAS,EAAE,CAAC;gBACnB,QAAQ,CAAC,+BAA+B,SAAS,EAAE,CAAC,CAAC;YACvD,CAAC;QACH,CAAC,CAAA,CAAC;QACF,IAAI,EAAE,CAAC;QACP,uDAAuD;IACzD,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,MAAM,UAAU,GAAG,CAAO,IAAY,EAAE,IAAa,EAAoB,EAAE;QACzE,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAA,8BAAsB,EAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,SAAS,EAAE,EAAE,WAAW,CAAC,CAAC;YACrG,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACzD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,WAAW,EAAE,CAAC;YACrB,QAAQ,CAAC,0BAA0B,WAAW,EAAE,CAAC,CAAC;YAClD,OAAO,KAAK,CAAC;QACf,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;IACH,CAAC,CAAA,CAAC;IAEF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CACL,uBAAC,cAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,YAAG,KAAK,CAAC,CAAC,CAAC,uBAAC,gBAAK,IAAC,QAAQ,EAAC,OAAO,YAAE,KAAK,GAAS,CAAC,CAAC,CAAC,uBAAC,2BAAgB,KAAG,GAAO,CAC7I,CAAC;IACJ,CAAC;IAED,MAAM,kBAAkB,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;IACzD,MAAM,UAAU,GAAqC,MAAA,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,mCAAI,IAAI,CAAC;IAEvG,MAAM,UAAU,GAAiC;QAC/C,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,aAAa,EAAE,EAAE;KAClB,CAAC;IAEF,sEAAsE;IACtE,0EAA0E;IAC1E,MAAM,aAAa,mCACd,UAAU,KACb,KAAK,EAAE,sCAAgB,CAAC,GAAG,GAC5B,CAAC;IAEF,MAAM,YAAY,GAAG,CAAO,MAAmC,EAAE,EAAE;QACjE,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC3B,MAAM,UAAU,CAAC,uCAAiB,CAAC,UAAU,kBAAI,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,IAAK,MAAM,EAAG,CAAC;QAC5F,CAAC;aAAM,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,oCAAc,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;YACzE,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,UAAU,CAAC,uCAAiB,CAAC,SAAS,kBAAI,QAAQ,EAAE,IAAA,8BAAY,GAAE,IAAK,MAAM,EAAG,CAAC;YACzF,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,CAAC,uCAAiB,CAAC,SAAS,kBAAI,QAAQ,EAAE,IAAA,8BAAY,GAAE,IAAK,MAAM,EAAG,CAAC;QACzF,CAAC;QACD,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAChC,CAAC,CAAA,CAAC;IAEF,OAAO,CACL,wBAAC,cAAG,IAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,aACjE,wBAAC,cAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,aACxD,uBAAC,qBAAU,kBAAY,0BAA0B,EAAC,OAAO,EAAE,MAAM,YAC/D,uBAAC,mBAAa,KAAG,GACN,EACb,uBAAC,qBAAU,IAAC,KAAK,EAAC,gBAAgB,EAAC,OAAO,EAAC,OAAO,4BAErC,IACT,EAEL,KAAK,IAAI,uBAAC,gBAAK,IAAC,QAAQ,EAAC,OAAO,YAAE,KAAK,GAAS,EAGjD,wBAAC,cAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,aAC5D,wBAAC,cAAG,IAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,aAEzF,wBAAC,gBAAK,IAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,OAAO,EAAC,UAAU,aACzF,wBAAC,cAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,EAAE,aAC5D,uBAAC,qBAAe,IAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAI,EACnF,wBAAC,cAAG,IAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,aACtB,uBAAC,qBAAU,IAAC,OAAO,EAAC,IAAI,YAAE,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,GAAc,EACvE,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,UAAU,IAAI,CACvD,wBAAC,qBAAU,IAAC,KAAK,EAAC,gBAAgB,EAAC,OAAO,EAAC,OAAO,yBACvC,MAAM,CAAC,MAAM,IACX,CACd,EACD,wBAAC,cAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,aAC1D,QAAQ,CAAC,CAAC,CAAC,uBAAC,eAAI,IAAC,KAAK,EAAC,QAAQ,EAAC,IAAI,EAAC,OAAO,GAAG,CAAC,CAAC,CAAC,uBAAC,eAAI,IAAC,KAAK,EAAC,SAAS,EAAC,KAAK,EAAC,QAAQ,EAAC,IAAI,EAAC,OAAO,GAAG,EACvG,uBAAC,eAAI,IACH,KAAK,EACH,MAAM,CAAC,KAAK,KAAK,sCAAgB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,sCAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAE7H,KAAK,EACH,MAAM,CAAC,KAAK,KAAK,sCAAgB,CAAC,IAAI;oEACpC,CAAC,CAAC,kBAAkB;oEACpB,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,sCAAgB,CAAC,IAAI;wEACtC,CAAC,CAAC,eAAe;wEACjB,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,sCAAgB,CAAC,QAAQ;4EAC1C,CAAC,CAAC,8BAA8B;4EAChC,CAAC,CAAC,mBAAmB,EAE7B,IAAI,EAAC,OAAO,EACZ,OAAO,EAAE,MAAM,CAAC,KAAK,KAAK,sCAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,GACvE,EACF,uBAAC,eAAI,IAAC,KAAK,EAAE,MAAM,CAAC,eAAe,KAAK,qCAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAC,OAAO,EAAC,OAAO,EAAC,UAAU,GAAG,EAC3H,MAAM,CAAC,SAAS,IAAI,uBAAC,eAAI,IAAC,KAAK,EAAE,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,kBAAkB,EAAE,EAAE,EAAE,IAAI,EAAC,OAAO,EAAC,OAAO,EAAC,UAAU,GAAG,EAChI,uBAAC,eAAI,IACH,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,aAAa,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,EACnG,IAAI,EAAC,OAAO,EACZ,OAAO,EAAC,UAAU,GAClB,IACE,IACF,EACL,QAAQ,CAAC,CAAC,CAAC,CACV,uBAAC,iBAAM,IAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAC,WAAW,mCAEhF,CACV,CAAC,CAAC,CAAC,CACF,uBAAC,iBAAM,IACL,KAAK,EAAC,SAAS,EACf,QAAQ,EAAE,IAAI,EACd,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,oCAAc,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,EAC9F,OAAO,EAAC,WAAW,kCAGZ,CACV,IACG,EACL,CAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,aAAa,KAAI,CAC5B,wBAAC,qBAAU,IAAC,KAAK,EAAC,gBAAgB,EAAC,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAC,OAAO,2BAClE,UAAU,CAAC,aAAa,IACxB,CACd,IACK,EAER,uBAAC,kBAAO,KAAG,EAEX,wBAAC,cAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,aAChD,uBAAC,qBAAU,IAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,OAAO,EAAC,IAAI,wBAEhC,EACb,uBAAC,iBAAM,IAAC,QAAQ,EAAE,QAAQ,IAAI,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,uBAAC,aAAO,KAAG,EAAE,OAAO,EAAC,UAAU,2BAEhH,IACL,EAEN,wBAAC,gBAAK,IAAC,IAAI,EAAC,OAAO,aACjB,uBAAC,oBAAS,cACR,wBAAC,mBAAQ,eACP,uBAAC,oBAAS,yBAAmB,EAC7B,uBAAC,oBAAS,wBAAkB,EAC5B,uBAAC,oBAAS,sBAAgB,EAC1B,uBAAC,oBAAS,iCAA2B,EACrC,uBAAC,oBAAS,yBAAmB,EAC7B,uBAAC,oBAAS,IAAC,KAAK,EAAC,OAAO,wBAAoB,IACnC,GACD,EACZ,wBAAC,oBAAS,eACP,kBAAkB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAClC,wBAAC,mBAAQ,IAAiB,KAAK,mBAC7B,uBAAC,oBAAS,IAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,YAAG,MAAM,CAAC,MAAM,GAAa,EAC7D,uBAAC,oBAAS,cACR,uBAAC,eAAI,IACH,KAAK,EAAE,MAAM,CAAC,KAAK,KAAK,sCAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,sCAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EACrH,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,IAAI,EAAC,OAAO,EACZ,OAAO,EAAE,MAAM,CAAC,KAAK,KAAK,sCAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,GACvE,GACQ,EACZ,uBAAC,oBAAS,cAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAa,EAC7H,uBAAC,oBAAS,IAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,YAC7B,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CACtB,uBAAC,qBAAU,IAAC,KAAK,EAAC,gBAAgB,EAAC,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAC,OAAO,YAC5E,MAAM,CAAC,aAAa,GACV,CACd,CAAC,CAAC,CAAC,CACF,GAAG,CACJ,GACS,EACZ,wBAAC,oBAAS,IAAC,EAAE,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,aACpC,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,cAAK,MAAM,CAAC,oBAAoB,EAC3E,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,IAC1B,EACZ,uBAAC,oBAAS,IAAC,KAAK,EAAC,OAAO,EAAC,EAAE,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,YAClD,CAAC,QAAQ,IAAI,CACZ,6DACE,uBAAC,qBAAU,kBAAY,aAAa,EAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAC,OAAO,YACnH,uBAAC,cAAQ,IAAC,QAAQ,EAAC,OAAO,GAAG,GAClB,EACb,uBAAC,qBAAU,kBACE,eAAe,EAC1B,QAAQ,EAAE,IAAI,EACd,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,uCAAiB,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,EAClF,IAAI,EAAC,OAAO,YAEZ,uBAAC,gBAAU,IAAC,QAAQ,EAAC,OAAO,GAAG,GACpB,IACZ,CACJ,GACS,KAxCC,MAAM,CAAC,EAAE,CAyCb,CACZ,CAAC,EACD,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAC9B,uBAAC,mBAAQ,cACP,uBAAC,oBAAS,IAAC,OAAO,EAAE,CAAC,YACnB,uBAAC,qBAAU,IAAC,KAAK,EAAC,gBAAgB,EAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAC,OAAO,uCAEnD,GACH,GACH,CACZ,IACS,IACN,IACJ,EAEN,uBAAC,cAAG,IAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,EAAE,YACzC,uBAAC,+CAAsB,IAAC,WAAW,EAAE,IAAA,8CAAwB,EAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAA,kDAA4B,EAAC,MAAM,CAAC,GAAI,GACpH,IACF,EAEN,uBAAC,2BAAY,IACX,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,EACrH,gBAAgB,EAAE,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EACpE,aAAa,EACX,MAAM,CAAC,IAAI,KAAK,MAAM;oBACpB,CAAC,CAAC;wBACE,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU;wBACpC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM;wBAC5B,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK;wBAC1B,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,eAAe;wBAC9C,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,gBAAgB;wBAChD,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa;qBAC3C;oBACH,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ;wBACxB,CAAC,CAAC,aAAa;wBACf,CAAC,CAAC,UAAU,EAElB,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAC7C,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,MAAM,CAAC,IAAI,KAAK,QAAQ,EAC9B,KAAK,EAAE,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,GAC9G,IACE,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { generateUuid, Nullable } from 'quidproquo-core';\nimport {\n EventDocEffect,\n EventDocEvent,\n EventDocStatus,\n isMaintenancePubliclyVisible,\n MaintenanceEffect,\n maintenanceEventDoc,\n MaintenanceLevel,\n MaintenanceType,\n MaintenanceUpdateEntry,\n toMaintenancePublicState,\n} from 'quidproquo-features';\nimport { useAuthAccessToken, useBaseUrlResolvers } from 'quidproquo-web-react';\n\nimport { useEffect, useMemo, useState } from 'react';\nimport AddIcon from '@mui/icons-material/Add';\nimport ArrowBackIcon from '@mui/icons-material/ArrowBack';\nimport DeleteIcon from '@mui/icons-material/Delete';\nimport EditIcon from '@mui/icons-material/Edit';\nimport EngineeringIcon from '@mui/icons-material/Engineering';\nimport {\n Alert,\n Box,\n Button,\n Chip,\n CircularProgress,\n Divider,\n IconButton,\n Paper,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n Typography,\n} from '@mui/material';\n\nimport { appendMaintenanceEvent, fetchMaintenanceEvents } from './logic';\nimport { MaintenanceUserPreview } from './MaintenanceUserPreview';\nimport { MaintenanceUpdateFormPrefill, MaintenanceUpdateFormValues, UpdateDialog } from './UpdateDialog';\n\ntype MaintenanceEditorProps = {\n docId: string;\n onBack: () => void;\n};\n\ntype DialogMode = { kind: 'closed' } | { kind: 'add' } | { kind: 'edit'; update: MaintenanceUpdateEntry } | { kind: 'reopen' };\n\n// One maintenance: a read-only header card with the CURRENT folded state, and\n// the update feed it derives from. The UPDATE is the only mutation — adding one\n// (prefilled from the last, ETA blank against the running clock) moves the whole\n// status; editing/deleting entries re-derives, so deleting the newest rolls the\n// card back. Closing publishes; reopening demands a fresh update (level resets\n// to Low in the prefill) so a maintenance closed at High never reopens locked.\nexport function MaintenanceEditor({ docId, onBack }: MaintenanceEditorProps) {\n const urlResolvers = useBaseUrlResolvers();\n const accessToken = useAuthAccessToken();\n\n const [events, setEvents] = useState<EventDocEvent[] | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n const [dialog, setDialog] = useState<DialogMode>({ kind: 'closed' });\n\n const folded = useMemo(() => (events ? maintenanceEventDoc.views.document.fold(events) : null), [events]);\n const isClosed = folded?.status === EventDocStatus.Published;\n\n useEffect(() => {\n const load = async () => {\n setError(null);\n try {\n setEvents(await fetchMaintenanceEvents(docId, urlResolvers.getApiUrl(), accessToken));\n } catch (loadError) {\n setError(`Failed to load maintenance: ${loadError}`);\n }\n };\n load();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [docId]);\n\n const applyEvent = async (type: string, data: unknown): Promise<boolean> => {\n setBusy(true);\n setError(null);\n try {\n const event = await appendMaintenanceEvent(docId, type, data, urlResolvers.getApiUrl(), accessToken);\n setEvents((prev) => (prev ? [...prev, event] : [event]));\n return true;\n } catch (appendError) {\n setError(`Failed to save change: ${appendError}`);\n return false;\n } finally {\n setBusy(false);\n }\n };\n\n if (!folded) {\n return (\n <Box sx={{ display: 'flex', justifyContent: 'center', p: 6 }}>{error ? <Alert severity=\"error\">{error}</Alert> : <CircularProgress />}</Box>\n );\n }\n\n const updatesNewestFirst = [...folded.updates].reverse();\n const lastUpdate: Nullable<MaintenanceUpdateEntry> = folded.updates[folded.updates.length - 1] ?? null;\n\n const addPrefill: MaintenanceUpdateFormPrefill = {\n bannerText: folded.bannerText,\n reason: folded.reason,\n level: folded.level,\n maintenanceType: folded.maintenanceType,\n affectedServices: folded.affectedServices,\n internalNotes: '',\n };\n\n // Reopen is \"create from inside\": reason/type/services carry over for\n // convenience, but the level RESETS to Low and there is no running clock.\n const reopenPrefill: MaintenanceUpdateFormPrefill = {\n ...addPrefill,\n level: MaintenanceLevel.Low,\n };\n\n const onDialogSave = async (values: MaintenanceUpdateFormValues) => {\n if (dialog.kind === 'edit') {\n await applyEvent(MaintenanceEffect.EditUpdate, { updateId: dialog.update.id, ...values });\n } else if (dialog.kind === 'reopen') {\n const reopened = await applyEvent(EventDocEffect.CreateDraft, undefined);\n if (reopened) {\n await applyEvent(MaintenanceEffect.AddUpdate, { updateId: generateUuid(), ...values });\n }\n } else {\n await applyEvent(MaintenanceEffect.AddUpdate, { updateId: generateUuid(), ...values });\n }\n setDialog({ kind: 'closed' });\n };\n\n return (\n <Box sx={{ p: 3, display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>\n <IconButton aria-label=\"Back to maintenance list\" onClick={onBack}>\n <ArrowBackIcon />\n </IconButton>\n <Typography color=\"text.secondary\" variant=\"body2\">\n Maintenance\n </Typography>\n </Box>\n\n {error && <Alert severity=\"error\">{error}</Alert>}\n\n {/* 70/30: the editor on the left, the what-users-see mock on the right. */}\n <Box sx={{ display: 'flex', gap: 3, alignItems: 'flex-start' }}>\n <Box sx={{ flex: '1 1 70%', minWidth: 0, display: 'flex', flexDirection: 'column', gap: 2 }}>\n {/* The current folded state — read-only; it moves only via updates. */}\n <Paper sx={{ p: 3, display: 'flex', flexDirection: 'column', gap: 1.5 }} variant=\"outlined\">\n <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2 }}>\n <EngineeringIcon color={isClosed ? 'disabled' : 'warning'} sx={{ fontSize: 40 }} />\n <Box sx={{ flexGrow: 1 }}>\n <Typography variant=\"h5\">{folded.bannerText || folded.name}</Typography>\n {folded.reason && folded.reason !== folded.bannerText && (\n <Typography color=\"text.secondary\" variant=\"body2\">\n Latest: {folded.reason}\n </Typography>\n )}\n <Box sx={{ display: 'flex', gap: 1, mt: 1, flexWrap: 'wrap' }}>\n {isClosed ? <Chip label=\"Closed\" size=\"small\" /> : <Chip color=\"warning\" label=\"Active\" size=\"small\" />}\n <Chip\n color={\n folded.level === MaintenanceLevel.High && !isClosed ? 'error' : folded.level === MaintenanceLevel.Info ? 'info' : 'default'\n }\n label={\n folded.level === MaintenanceLevel.High\n ? 'High — UI locked'\n : folded.level === MaintenanceLevel.Info\n ? 'Info — banner'\n : folded.level === MaintenanceLevel.Internal\n ? 'Internal — hidden from users'\n : 'Low — banner only'\n }\n size=\"small\"\n variant={folded.level === MaintenanceLevel.High ? 'filled' : 'outlined'}\n />\n <Chip label={folded.maintenanceType === MaintenanceType.Incident ? 'Incident' : 'Deploy'} size=\"small\" variant=\"outlined\" />\n {folded.etaEndsAt && <Chip label={`Ends ~${new Date(folded.etaEndsAt).toLocaleTimeString()}`} size=\"small\" variant=\"outlined\" />}\n <Chip\n label={folded.affectedServices ? `Affected: ${folded.affectedServices.join(', ')}` : 'All services'}\n size=\"small\"\n variant=\"outlined\"\n />\n </Box>\n </Box>\n {isClosed ? (\n <Button disabled={busy} onClick={() => setDialog({ kind: 'reopen' })} variant=\"contained\">\n Reopen maintenance\n </Button>\n ) : (\n <Button\n color=\"success\"\n disabled={busy}\n onClick={() => applyEvent(EventDocEffect.Publish, { effectiveFrom: new Date().toISOString() })}\n variant=\"contained\"\n >\n Close maintenance\n </Button>\n )}\n </Box>\n {lastUpdate?.internalNotes && (\n <Typography color=\"text.secondary\" sx={{ fontStyle: 'italic' }} variant=\"body2\">\n Internal: {lastUpdate.internalNotes}\n </Typography>\n )}\n </Paper>\n\n <Divider />\n\n <Box sx={{ display: 'flex', alignItems: 'center' }}>\n <Typography sx={{ flexGrow: 1 }} variant=\"h6\">\n Updates\n </Typography>\n <Button disabled={isClosed || busy} onClick={() => setDialog({ kind: 'add' })} startIcon={<AddIcon />} variant=\"outlined\">\n Add update\n </Button>\n </Box>\n\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Status</TableCell>\n <TableCell>Level</TableCell>\n <TableCell>ETA</TableCell>\n <TableCell>Internal notes</TableCell>\n <TableCell>Posted</TableCell>\n <TableCell align=\"right\">Actions</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {updatesNewestFirst.map((update) => (\n <TableRow key={update.id} hover>\n <TableCell sx={{ maxWidth: 420 }}>{update.reason}</TableCell>\n <TableCell>\n <Chip\n color={update.level === MaintenanceLevel.High ? 'error' : update.level === MaintenanceLevel.Info ? 'info' : 'default'}\n label={update.level}\n size=\"small\"\n variant={update.level === MaintenanceLevel.High ? 'filled' : 'outlined'}\n />\n </TableCell>\n <TableCell>{update.etaSetAt ? (update.etaDurationMins === null ? 'Cleared' : `${update.etaDurationMins}m`) : '—'}</TableCell>\n <TableCell sx={{ maxWidth: 360 }}>\n {update.internalNotes ? (\n <Typography color=\"text.secondary\" sx={{ fontStyle: 'italic' }} variant=\"body2\">\n {update.internalNotes}\n </Typography>\n ) : (\n '—'\n )}\n </TableCell>\n <TableCell sx={{ whiteSpace: 'nowrap' }}>\n {new Date(update.createdAt).toLocaleString()} — {update.createdByDisplayName}\n {update.updatedAt ? ' (edited)' : ''}\n </TableCell>\n <TableCell align=\"right\" sx={{ whiteSpace: 'nowrap' }}>\n {!isClosed && (\n <>\n <IconButton aria-label=\"Edit update\" disabled={busy} onClick={() => setDialog({ kind: 'edit', update })} size=\"small\">\n <EditIcon fontSize=\"small\" />\n </IconButton>\n <IconButton\n aria-label=\"Delete update\"\n disabled={busy}\n onClick={() => applyEvent(MaintenanceEffect.RemoveUpdate, { updateId: update.id })}\n size=\"small\"\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButton>\n </>\n )}\n </TableCell>\n </TableRow>\n ))}\n {folded.updates.length === 0 && (\n <TableRow>\n <TableCell colSpan={6}>\n <Typography color=\"text.secondary\" sx={{ p: 1 }} variant=\"body2\">\n No updates posted yet.\n </Typography>\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </Box>\n\n <Box sx={{ flex: '0 0 30%', minWidth: 300 }}>\n <MaintenanceUserPreview publicState={toMaintenancePublicState(folded)} visible={isMaintenancePubliclyVisible(folded)} />\n </Box>\n </Box>\n\n <UpdateDialog\n busy={busy}\n confirmLabel={dialog.kind === 'reopen' ? 'Reopen maintenance' : dialog.kind === 'edit' ? 'Save update' : 'Add update'}\n currentEtaEndsAt={dialog.kind === 'reopen' ? null : folded.etaEndsAt}\n initialValues={\n dialog.kind === 'edit'\n ? {\n bannerText: dialog.update.bannerText,\n reason: dialog.update.reason,\n level: dialog.update.level,\n maintenanceType: dialog.update.maintenanceType,\n affectedServices: dialog.update.affectedServices,\n internalNotes: dialog.update.internalNotes,\n }\n : dialog.kind === 'reopen'\n ? reopenPrefill\n : addPrefill\n }\n onCancel={() => setDialog({ kind: 'closed' })}\n onSave={onDialogSave}\n open={dialog.kind !== 'closed'}\n title={dialog.kind === 'reopen' ? 'Reopen maintenance' : dialog.kind === 'edit' ? 'Edit update' : 'Add update'}\n />\n </Box>\n );\n}\n"]}
@@ -14,6 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.MaintenanceList = MaintenanceList;
16
16
  const jsx_runtime_1 = require("react/jsx-runtime");
17
+ const quidproquo_core_1 = require("quidproquo-core");
17
18
  const quidproquo_features_1 = require("quidproquo-features");
18
19
  const quidproquo_web_react_1 = require("quidproquo-web-react");
19
20
  const react_1 = require("react");
@@ -67,7 +68,7 @@ function MaintenanceList({ onOpen }) {
67
68
  try {
68
69
  const apiBaseUrl = urlResolvers.getApiUrl();
69
70
  const summary = yield (0, logic_1.createMaintenance)(values.bannerText || values.reason, values.maintenanceType.toLowerCase(), apiBaseUrl, accessToken);
70
- yield (0, logic_1.appendMaintenanceEvent)(summary.id, quidproquo_features_1.MaintenanceEffect.AddUpdate, Object.assign({ updateId: crypto.randomUUID() }, values), apiBaseUrl, accessToken);
71
+ yield (0, logic_1.appendMaintenanceEvent)(summary.id, quidproquo_features_1.MaintenanceEffect.AddUpdate, Object.assign({ updateId: (0, quidproquo_core_1.generateUuid)() }, values), apiBaseUrl, accessToken);
71
72
  setCreateOpen(false);
72
73
  onOpen(summary.id);
73
74
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MaintenanceList.js","sourceRoot":"","sources":["../../../src/Maintenance/MaintenanceList.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;AA4BA,0CAiHC;;AA7ID,6DAAgI;AAChI,+DAA+E;AAE/E,iCAA4C;AAC5C,kEAA8C;AAC9C,0EAAsD;AACtD,4CAAyI;AAEzI,mCAA+F;AAC/F,iDAA2E;AAE3E,MAAM,cAAc,GAAG;IACrB,UAAU,EAAE,2CAA2C;IACvD,MAAM,EAAE,qBAAqB;IAC7B,KAAK,EAAE,sCAAgB,CAAC,GAAG;IAC3B,eAAe,EAAE,qCAAe,CAAC,MAAM;IACvC,gBAAgB,EAAE,IAAI;IACtB,aAAa,EAAE,EAAE;CAClB,CAAC;AAMF,8EAA8E;AAC9E,6EAA6E;AAC7E,6EAA6E;AAC7E,6DAA6D;AAC7D,SAAgB,eAAe,CAAC,EAAE,MAAM,EAAwB;IAC9D,MAAM,YAAY,GAAG,IAAA,0CAAmB,GAAE,CAAC;IAC3C,MAAM,WAAW,GAAG,IAAA,yCAAkB,GAAE,CAAC;IAEzC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,IAAA,gBAAQ,EAAoB,EAAE,CAAC,CAAC;IAClE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAgB,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAChD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAEpD,MAAM,IAAI,GAAG,GAAS,EAAE;QACtB,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACH,YAAY,CAAC,MAAM,IAAA,iCAAyB,EAAC,YAAY,CAAC,SAAS,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;QACvF,CAAC;QAAC,OAAO,SAAS,EAAE,CAAC;YACnB,QAAQ,CAAC,gCAAgC,SAAS,EAAE,CAAC,CAAC;QACxD,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAA,CAAC;IAEF,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,EAAE,CAAC;QACP,uDAAuD;IACzD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,8EAA8E;IAC9E,8EAA8E;IAC9E,MAAM,QAAQ,GAAG,CAAO,MAAmC,EAAE,EAAE;QAC7D,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,YAAY,CAAC,SAAS,EAAE,CAAC;YAC5C,MAAM,OAAO,GAAG,MAAM,IAAA,yBAAiB,EAAC,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;YAE3I,MAAM,IAAA,8BAAsB,EAAC,OAAO,CAAC,EAAE,EAAE,uCAAiB,CAAC,SAAS,kBAAI,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE,IAAK,MAAM,GAAI,UAAU,EAAE,WAAW,CAAC,CAAC;YAE7I,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACrB,CAAC;QAAC,OAAO,WAAW,EAAE,CAAC;YACrB,QAAQ,CAAC,iCAAiC,WAAW,EAAE,CAAC,CAAC;QAC3D,CAAC;gBAAS,CAAC;YACT,WAAW,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,CAAA,CAAC;IAEF,OAAO,CACL,wBAAC,cAAG,IAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,aACjE,wBAAC,cAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,aACxD,uBAAC,qBAAU,IAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,OAAO,EAAC,IAAI,4BAEhC,EACb,uBAAC,iBAAM,IAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,uBAAC,iBAAW,KAAG,wBAExC,EACT,uBAAC,iBAAM,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,uBAAC,aAAO,KAAG,EAAE,OAAO,EAAC,WAAW,gCAE9E,IACL,EAEL,KAAK,IAAI,uBAAC,gBAAK,IAAC,QAAQ,EAAC,OAAO,YAAE,KAAK,GAAS,EAEhD,OAAO,CAAC,CAAC,CAAC,CACT,uBAAC,cAAG,IAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,YAC1D,uBAAC,2BAAgB,KAAG,GAChB,CACP,CAAC,CAAC,CAAC,CACF,wBAAC,gBAAK,IAAC,IAAI,EAAC,OAAO,aACjB,uBAAC,oBAAS,cACR,wBAAC,mBAAQ,eACP,uBAAC,oBAAS,yBAAmB,EAC7B,uBAAC,oBAAS,yBAAmB,EAC7B,uBAAC,oBAAS,0BAAoB,EAC9B,uBAAC,oBAAS,0BAAoB,IACrB,GACD,EACZ,wBAAC,oBAAS,eACP,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;gCACzB,MAAM,IAAI,GAAG,IAAA,wCAAkB,EAAC,OAAO,CAAC,CAAC;gCACzC,OAAO,CACL,wBAAC,mBAAQ,IAAkB,KAAK,QAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,aAC3F,uBAAC,oBAAS,cAAE,OAAO,CAAC,IAAI,GAAa,EACrC,uBAAC,oBAAS,cAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,uBAAC,eAAI,IAAC,KAAK,EAAC,SAAS,EAAC,KAAK,EAAC,QAAQ,EAAC,IAAI,EAAC,OAAO,GAAG,CAAC,CAAC,CAAC,uBAAC,eAAI,IAAC,KAAK,EAAC,QAAQ,EAAC,IAAI,EAAC,OAAO,GAAG,GAAa,EACpI,uBAAC,oBAAS,cAAE,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,GAAa,EACrE,uBAAC,oBAAS,cAAE,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,GAAa,KAJxD,OAAO,CAAC,EAAE,CAKd,CACZ,CAAC;4BACJ,CAAC,CAAC,EACD,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,CACzB,uBAAC,mBAAQ,cACP,uBAAC,oBAAS,IAAC,OAAO,EAAE,CAAC,YACnB,uBAAC,qBAAU,IAAC,KAAK,EAAC,gBAAgB,EAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAC,OAAO,qCAEnD,GACH,GACH,CACZ,IACS,IACN,CACT,EAED,uBAAC,2BAAY,IACX,IAAI,EAAE,QAAQ,EACd,YAAY,EAAC,mBAAmB,EAChC,aAAa,EAAE,cAAc,EAC7B,QAAQ,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,EACpC,MAAM,EAAE,QAAQ,EAChB,IAAI,EAAE,UAAU,EAChB,KAAK,EAAC,iBAAiB,GACvB,IACE,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { EventDocSummary, MaintenanceEffect, MaintenanceLevel, MaintenanceType, toEventDocListItem } from 'quidproquo-features';\nimport { useAuthAccessToken, useBaseUrlResolvers } from 'quidproquo-web-react';\n\nimport { useEffect, useState } from 'react';\nimport AddIcon from '@mui/icons-material/Add';\nimport RefreshIcon from '@mui/icons-material/Refresh';\nimport { Alert, Box, Button, Chip, CircularProgress, Table, TableBody, TableCell, TableHead, TableRow, Typography } from '@mui/material';\n\nimport { appendMaintenanceEvent, createMaintenance, fetchMaintenanceSummaries } from './logic';\nimport { MaintenanceUpdateFormValues, UpdateDialog } from './UpdateDialog';\n\nconst CREATE_PREFILL = {\n bannerText: 'The site is undergoing a scheduled update',\n reason: 'Maintenance started',\n level: MaintenanceLevel.Low,\n maintenanceType: MaintenanceType.Deploy,\n affectedServices: null,\n internalNotes: '',\n};\n\ntype MaintenanceListProps = {\n onOpen: (docId: string) => void;\n};\n\n// All maintenances, newest first — active (open draft) vs closed (published).\n// \"New maintenance\" BEGINS one: the doc is created, its initial settings are\n// appended (level last, so a High lock only engages once the reason/type/eta\n// are already in the broadcast state), and the editor opens.\nexport function MaintenanceList({ onOpen }: MaintenanceListProps) {\n const urlResolvers = useBaseUrlResolvers();\n const accessToken = useAuthAccessToken();\n\n const [summaries, setSummaries] = useState<EventDocSummary[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [creating, setCreating] = useState(false);\n const [createOpen, setCreateOpen] = useState(false);\n\n const load = async () => {\n setLoading(true);\n setError(null);\n try {\n setSummaries(await fetchMaintenanceSummaries(urlResolvers.getApiUrl(), accessToken));\n } catch (loadError) {\n setError(`Failed to load maintenances: ${loadError}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n load();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Create = the first update: one doc, one ADD_UPDATE carrying the full status\n // snapshot — the maintenance is live (and broadcast) from that single append.\n const onCreate = async (values: MaintenanceUpdateFormValues) => {\n setCreating(true);\n setError(null);\n try {\n const apiBaseUrl = urlResolvers.getApiUrl();\n const summary = await createMaintenance(values.bannerText || values.reason, values.maintenanceType.toLowerCase(), apiBaseUrl, accessToken);\n\n await appendMaintenanceEvent(summary.id, MaintenanceEffect.AddUpdate, { updateId: crypto.randomUUID(), ...values }, apiBaseUrl, accessToken);\n\n setCreateOpen(false);\n onOpen(summary.id);\n } catch (createError) {\n setError(`Failed to create maintenance: ${createError}`);\n } finally {\n setCreating(false);\n }\n };\n\n return (\n <Box sx={{ p: 3, display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>\n <Typography sx={{ flexGrow: 1 }} variant=\"h5\">\n Maintenance\n </Typography>\n <Button onClick={load} startIcon={<RefreshIcon />}>\n Refresh\n </Button>\n <Button onClick={() => setCreateOpen(true)} startIcon={<AddIcon />} variant=\"contained\">\n New maintenance\n </Button>\n </Box>\n\n {error && <Alert severity=\"error\">{error}</Alert>}\n\n {loading ? (\n <Box sx={{ display: 'flex', justifyContent: 'center', p: 4 }}>\n <CircularProgress />\n </Box>\n ) : (\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Reason</TableCell>\n <TableCell>Status</TableCell>\n <TableCell>Updated</TableCell>\n <TableCell>Created</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {summaries.map((summary) => {\n const item = toEventDocListItem(summary);\n return (\n <TableRow key={summary.id} hover onClick={() => onOpen(summary.id)} sx={{ cursor: 'pointer' }}>\n <TableCell>{summary.name}</TableCell>\n <TableCell>{item.hasDraft ? <Chip color=\"warning\" label=\"Active\" size=\"small\" /> : <Chip label=\"Closed\" size=\"small\" />}</TableCell>\n <TableCell>{new Date(summary.updatedAt).toLocaleString()}</TableCell>\n <TableCell>{new Date(summary.createdAt).toLocaleString()}</TableCell>\n </TableRow>\n );\n })}\n {summaries.length === 0 && (\n <TableRow>\n <TableCell colSpan={4}>\n <Typography color=\"text.secondary\" sx={{ p: 2 }} variant=\"body2\">\n No maintenances yet.\n </Typography>\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n )}\n\n <UpdateDialog\n busy={creating}\n confirmLabel=\"Begin maintenance\"\n initialValues={CREATE_PREFILL}\n onCancel={() => setCreateOpen(false)}\n onSave={onCreate}\n open={createOpen}\n title=\"New maintenance\"\n />\n </Box>\n );\n}\n"]}
1
+ {"version":3,"file":"MaintenanceList.js","sourceRoot":"","sources":["../../../src/Maintenance/MaintenanceList.tsx"],"names":[],"mappings":"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","sourcesContent":["import { generateUuid } from 'quidproquo-core';\nimport { EventDocSummary, MaintenanceEffect, MaintenanceLevel, MaintenanceType, toEventDocListItem } from 'quidproquo-features';\nimport { useAuthAccessToken, useBaseUrlResolvers } from 'quidproquo-web-react';\n\nimport { useEffect, useState } from 'react';\nimport AddIcon from '@mui/icons-material/Add';\nimport RefreshIcon from '@mui/icons-material/Refresh';\nimport { Alert, Box, Button, Chip, CircularProgress, Table, TableBody, TableCell, TableHead, TableRow, Typography } from '@mui/material';\n\nimport { appendMaintenanceEvent, createMaintenance, fetchMaintenanceSummaries } from './logic';\nimport { MaintenanceUpdateFormValues, UpdateDialog } from './UpdateDialog';\n\nconst CREATE_PREFILL = {\n bannerText: 'The site is undergoing a scheduled update',\n reason: 'Maintenance started',\n level: MaintenanceLevel.Low,\n maintenanceType: MaintenanceType.Deploy,\n affectedServices: null,\n internalNotes: '',\n};\n\ntype MaintenanceListProps = {\n onOpen: (docId: string) => void;\n};\n\n// All maintenances, newest first — active (open draft) vs closed (published).\n// \"New maintenance\" BEGINS one: the doc is created, its initial settings are\n// appended (level last, so a High lock only engages once the reason/type/eta\n// are already in the broadcast state), and the editor opens.\nexport function MaintenanceList({ onOpen }: MaintenanceListProps) {\n const urlResolvers = useBaseUrlResolvers();\n const accessToken = useAuthAccessToken();\n\n const [summaries, setSummaries] = useState<EventDocSummary[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [creating, setCreating] = useState(false);\n const [createOpen, setCreateOpen] = useState(false);\n\n const load = async () => {\n setLoading(true);\n setError(null);\n try {\n setSummaries(await fetchMaintenanceSummaries(urlResolvers.getApiUrl(), accessToken));\n } catch (loadError) {\n setError(`Failed to load maintenances: ${loadError}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n load();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Create = the first update: one doc, one ADD_UPDATE carrying the full status\n // snapshot — the maintenance is live (and broadcast) from that single append.\n const onCreate = async (values: MaintenanceUpdateFormValues) => {\n setCreating(true);\n setError(null);\n try {\n const apiBaseUrl = urlResolvers.getApiUrl();\n const summary = await createMaintenance(values.bannerText || values.reason, values.maintenanceType.toLowerCase(), apiBaseUrl, accessToken);\n\n await appendMaintenanceEvent(summary.id, MaintenanceEffect.AddUpdate, { updateId: generateUuid(), ...values }, apiBaseUrl, accessToken);\n\n setCreateOpen(false);\n onOpen(summary.id);\n } catch (createError) {\n setError(`Failed to create maintenance: ${createError}`);\n } finally {\n setCreating(false);\n }\n };\n\n return (\n <Box sx={{ p: 3, display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>\n <Typography sx={{ flexGrow: 1 }} variant=\"h5\">\n Maintenance\n </Typography>\n <Button onClick={load} startIcon={<RefreshIcon />}>\n Refresh\n </Button>\n <Button onClick={() => setCreateOpen(true)} startIcon={<AddIcon />} variant=\"contained\">\n New maintenance\n </Button>\n </Box>\n\n {error && <Alert severity=\"error\">{error}</Alert>}\n\n {loading ? (\n <Box sx={{ display: 'flex', justifyContent: 'center', p: 4 }}>\n <CircularProgress />\n </Box>\n ) : (\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Reason</TableCell>\n <TableCell>Status</TableCell>\n <TableCell>Updated</TableCell>\n <TableCell>Created</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {summaries.map((summary) => {\n const item = toEventDocListItem(summary);\n return (\n <TableRow key={summary.id} hover onClick={() => onOpen(summary.id)} sx={{ cursor: 'pointer' }}>\n <TableCell>{summary.name}</TableCell>\n <TableCell>{item.hasDraft ? <Chip color=\"warning\" label=\"Active\" size=\"small\" /> : <Chip label=\"Closed\" size=\"small\" />}</TableCell>\n <TableCell>{new Date(summary.updatedAt).toLocaleString()}</TableCell>\n <TableCell>{new Date(summary.createdAt).toLocaleString()}</TableCell>\n </TableRow>\n );\n })}\n {summaries.length === 0 && (\n <TableRow>\n <TableCell colSpan={4}>\n <Typography color=\"text.secondary\" sx={{ p: 2 }} variant=\"body2\">\n No maintenances yet.\n </Typography>\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n )}\n\n <UpdateDialog\n busy={creating}\n confirmLabel=\"Begin maintenance\"\n initialValues={CREATE_PREFILL}\n onCancel={() => setCreateOpen(false)}\n onSave={onCreate}\n open={createOpen}\n title=\"New maintenance\"\n />\n </Box>\n );\n}\n"]}
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.appendMaintenanceEvent = exports.fetchMaintenanceEvents = exports.createMaintenance = exports.fetchMaintenanceSummaries = void 0;
13
+ const quidproquo_core_1 = require("quidproquo-core");
13
14
  const quidproquo_features_1 = require("quidproquo-features");
14
15
  const logic_1 = require("../../logic");
15
16
  // Thin fetch layer over the maintenance event-doc REST routes
@@ -39,7 +40,7 @@ const appendMaintenanceEvent = (docId, type, data, apiBaseUrl, accessToken) => _
39
40
  data,
40
41
  metadata: {
41
42
  version: quidproquo_features_1.MAINTENANCE_SCHEMA_VERSION,
42
- clientMessageId: crypto.randomUUID(),
43
+ clientMessageId: (0, quidproquo_core_1.generateUuid)(),
43
44
  },
44
45
  },
45
46
  };
@@ -1 +1 @@
1
- {"version":3,"file":"maintenanceApi.js","sourceRoot":"","sources":["../../../../src/Maintenance/logic/maintenanceApi.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,6DAA0I;AAE1I,uCAA4D;AAE5D,8DAA8D;AAC9D,8EAA8E;AAC9E,yEAAyE;AAEzE,MAAM,cAAc,GAAG,MAAM,yCAAmB,EAAE,CAAC;AAE5C,MAAM,yBAAyB,GAAG,CAAO,UAAkB,EAAE,WAAoB,EAA8B,EAAE,kDACtH,OAAA,IAAA,qBAAa,EAAoB,cAAc,EAAE,UAAU,EAAE,WAAW,CAAC,CAAA,GAAA,CAAC;AAD/D,QAAA,yBAAyB,6BACsC;AAErE,MAAM,iBAAiB,GAAG,CAAO,IAAY,EAAE,IAAY,EAAE,UAAkB,EAAE,WAAoB,EAA4B,EAAE,kDACxI,OAAA,IAAA,sBAAc,EAAkB,cAAc,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,WAAW,CAAC,CAAA,GAAA,CAAC;AAD9E,QAAA,iBAAiB,qBAC6D;AAEpF,MAAM,sBAAsB,GAAG,CAAO,KAAa,EAAE,UAAkB,EAAE,WAAoB,EAA4B,EAAE;IAChI,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,IAAI,WAAW,GAAuB,SAAS,CAAC;IAEhD,GAAG,CAAC;QACF,MAAM,KAAK,GAAW,WAAW,CAAC,CAAC,CAAC,gBAAgB,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3F,MAAM,IAAI,GAAgC,MAAM,IAAA,qBAAa,EAC3D,GAAG,cAAc,IAAI,KAAK,UAAU,KAAK,EAAE,EAC3C,UAAU,EACV,WAAW,CACZ,CAAC;QAEF,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;IACjC,CAAC,QAAQ,WAAW,EAAE;IAEtB,OAAO,MAAM,CAAC;AAChB,CAAC,CAAA,CAAC;AAjBW,QAAA,sBAAsB,0BAiBjC;AAEK,MAAM,sBAAsB,GAAG,CACpC,KAAa,EACb,IAAY,EACZ,IAAa,EACb,UAAkB,EAClB,WAAoB,EACI,EAAE;IAC1B,MAAM,KAAK,GAAuB;QAChC,IAAI;QACJ,OAAO,EAAE;YACP,IAAI;YACJ,QAAQ,EAAE;gBACR,OAAO,EAAE,gDAA0B;gBACnC,eAAe,EAAE,MAAM,CAAC,UAAU,EAAE;aACrC;SACF;KACF,CAAC;IAEF,OAAO,IAAA,sBAAc,EAAgB,GAAG,cAAc,IAAI,KAAK,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AAC5G,CAAC,CAAA,CAAC;AAnBW,QAAA,sBAAsB,0BAmBjC","sourcesContent":["import { QpqPagedData } from 'quidproquo-core';\nimport { EventDocEvent, EventDocEventInput, EventDocSummary, MAINTENANCE_SCHEMA_VERSION, maintenanceBasePath } from 'quidproquo-features';\n\nimport { apiRequestGet, apiRequestPost } from '../../logic';\n\n// Thin fetch layer over the maintenance event-doc REST routes\n// (defineEventDocRoutes mounts them under /v1). The editor folds locally with\n// maintenanceEventDoc.fold, so this only moves summaries and raw events.\n\nconst collectionPath = `/v1${maintenanceBasePath}`;\n\nexport const fetchMaintenanceSummaries = async (apiBaseUrl: string, accessToken?: string): Promise<EventDocSummary[]> =>\n apiRequestGet<EventDocSummary[]>(collectionPath, apiBaseUrl, accessToken);\n\nexport const createMaintenance = async (name: string, code: string, apiBaseUrl: string, accessToken?: string): Promise<EventDocSummary> =>\n apiRequestPost<EventDocSummary>(collectionPath, { name, code }, apiBaseUrl, accessToken);\n\nexport const fetchMaintenanceEvents = async (docId: string, apiBaseUrl: string, accessToken?: string): Promise<EventDocEvent[]> => {\n const events: EventDocEvent[] = [];\n let nextPageKey: string | undefined = undefined;\n\n do {\n const query: string = nextPageKey ? `?nextPageKey=${encodeURIComponent(nextPageKey)}` : '';\n const page: QpqPagedData<EventDocEvent> = await apiRequestGet<QpqPagedData<EventDocEvent>>(\n `${collectionPath}/${docId}/events${query}`,\n apiBaseUrl,\n accessToken,\n );\n\n events.push(...page.items);\n nextPageKey = page.nextPageKey;\n } while (nextPageKey);\n\n return events;\n};\n\nexport const appendMaintenanceEvent = async (\n docId: string,\n type: string,\n data: unknown,\n apiBaseUrl: string,\n accessToken?: string,\n): Promise<EventDocEvent> => {\n const input: EventDocEventInput = {\n type,\n payload: {\n data,\n metadata: {\n version: MAINTENANCE_SCHEMA_VERSION,\n clientMessageId: crypto.randomUUID(),\n },\n },\n };\n\n return apiRequestPost<EventDocEvent>(`${collectionPath}/${docId}/events`, input, apiBaseUrl, accessToken);\n};\n"]}
1
+ {"version":3,"file":"maintenanceApi.js","sourceRoot":"","sources":["../../../../src/Maintenance/logic/maintenanceApi.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAA6D;AAC7D,6DAA0I;AAE1I,uCAA4D;AAE5D,8DAA8D;AAC9D,8EAA8E;AAC9E,yEAAyE;AAEzE,MAAM,cAAc,GAAG,MAAM,yCAAmB,EAAE,CAAC;AAE5C,MAAM,yBAAyB,GAAG,CAAO,UAAkB,EAAE,WAAoB,EAA8B,EAAE,kDACtH,OAAA,IAAA,qBAAa,EAAoB,cAAc,EAAE,UAAU,EAAE,WAAW,CAAC,CAAA,GAAA,CAAC;AAD/D,QAAA,yBAAyB,6BACsC;AAErE,MAAM,iBAAiB,GAAG,CAAO,IAAY,EAAE,IAAY,EAAE,UAAkB,EAAE,WAAoB,EAA4B,EAAE,kDACxI,OAAA,IAAA,sBAAc,EAAkB,cAAc,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,WAAW,CAAC,CAAA,GAAA,CAAC;AAD9E,QAAA,iBAAiB,qBAC6D;AAEpF,MAAM,sBAAsB,GAAG,CAAO,KAAa,EAAE,UAAkB,EAAE,WAAoB,EAA4B,EAAE;IAChI,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,IAAI,WAAW,GAAuB,SAAS,CAAC;IAEhD,GAAG,CAAC;QACF,MAAM,KAAK,GAAW,WAAW,CAAC,CAAC,CAAC,gBAAgB,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3F,MAAM,IAAI,GAAgC,MAAM,IAAA,qBAAa,EAC3D,GAAG,cAAc,IAAI,KAAK,UAAU,KAAK,EAAE,EAC3C,UAAU,EACV,WAAW,CACZ,CAAC;QAEF,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;IACjC,CAAC,QAAQ,WAAW,EAAE;IAEtB,OAAO,MAAM,CAAC;AAChB,CAAC,CAAA,CAAC;AAjBW,QAAA,sBAAsB,0BAiBjC;AAEK,MAAM,sBAAsB,GAAG,CACpC,KAAa,EACb,IAAY,EACZ,IAAa,EACb,UAAkB,EAClB,WAAoB,EACI,EAAE;IAC1B,MAAM,KAAK,GAAuB;QAChC,IAAI;QACJ,OAAO,EAAE;YACP,IAAI;YACJ,QAAQ,EAAE;gBACR,OAAO,EAAE,gDAA0B;gBACnC,eAAe,EAAE,IAAA,8BAAY,GAAE;aAChC;SACF;KACF,CAAC;IAEF,OAAO,IAAA,sBAAc,EAAgB,GAAG,cAAc,IAAI,KAAK,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AAC5G,CAAC,CAAA,CAAC;AAnBW,QAAA,sBAAsB,0BAmBjC","sourcesContent":["import { generateUuid, QpqPagedData } from 'quidproquo-core';\nimport { EventDocEvent, EventDocEventInput, EventDocSummary, MAINTENANCE_SCHEMA_VERSION, maintenanceBasePath } from 'quidproquo-features';\n\nimport { apiRequestGet, apiRequestPost } from '../../logic';\n\n// Thin fetch layer over the maintenance event-doc REST routes\n// (defineEventDocRoutes mounts them under /v1). The editor folds locally with\n// maintenanceEventDoc.fold, so this only moves summaries and raw events.\n\nconst collectionPath = `/v1${maintenanceBasePath}`;\n\nexport const fetchMaintenanceSummaries = async (apiBaseUrl: string, accessToken?: string): Promise<EventDocSummary[]> =>\n apiRequestGet<EventDocSummary[]>(collectionPath, apiBaseUrl, accessToken);\n\nexport const createMaintenance = async (name: string, code: string, apiBaseUrl: string, accessToken?: string): Promise<EventDocSummary> =>\n apiRequestPost<EventDocSummary>(collectionPath, { name, code }, apiBaseUrl, accessToken);\n\nexport const fetchMaintenanceEvents = async (docId: string, apiBaseUrl: string, accessToken?: string): Promise<EventDocEvent[]> => {\n const events: EventDocEvent[] = [];\n let nextPageKey: string | undefined = undefined;\n\n do {\n const query: string = nextPageKey ? `?nextPageKey=${encodeURIComponent(nextPageKey)}` : '';\n const page: QpqPagedData<EventDocEvent> = await apiRequestGet<QpqPagedData<EventDocEvent>>(\n `${collectionPath}/${docId}/events${query}`,\n apiBaseUrl,\n accessToken,\n );\n\n events.push(...page.items);\n nextPageKey = page.nextPageKey;\n } while (nextPageKey);\n\n return events;\n};\n\nexport const appendMaintenanceEvent = async (\n docId: string,\n type: string,\n data: unknown,\n apiBaseUrl: string,\n accessToken?: string,\n): Promise<EventDocEvent> => {\n const input: EventDocEventInput = {\n type,\n payload: {\n data,\n metadata: {\n version: MAINTENANCE_SCHEMA_VERSION,\n clientMessageId: generateUuid(),\n },\n },\n };\n\n return apiRequestPost<EventDocEvent>(`${collectionPath}/${docId}/events`, input, apiBaseUrl, accessToken);\n};\n"]}
@@ -17,7 +17,7 @@ const askApplySessionEventToLog_1 = require("./askApplySessionEventToLog");
17
17
  // so it can dispatch into the admin runtime's state like any story.
18
18
  const getApplySessionEventActionProcessor = () => (qpqConfig) => __awaiter(void 0, void 0, void 0, function* () {
19
19
  return ({
20
- [AdminSessionActionType_1.AdminSessionActionType.applyEvent]: (0, quidproquo_core_1.getProcessCustomImplementation)(qpqConfig, askApplySessionEventToLog_1.askApplySessionEventToLog, 'Apply Admin Session Event', null, () => new Date().toISOString(), () => globalThis.crypto.randomUUID()),
20
+ [AdminSessionActionType_1.AdminSessionActionType.applyEvent]: (0, quidproquo_core_1.getProcessCustomImplementation)(qpqConfig, askApplySessionEventToLog_1.askApplySessionEventToLog, 'Apply Admin Session Event', null, () => new Date().toISOString(), () => (0, quidproquo_core_1.generateUuid)()),
21
21
  });
22
22
  });
23
23
  exports.getApplySessionEventActionProcessor = getApplySessionEventActionProcessor;
@@ -1 +1 @@
1
- {"version":3,"file":"getApplySessionEventActionProcessor.js","sourceRoot":"","sources":["../../../../src/adminApp/actions/getApplySessionEventActionProcessor.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAA+E;AAI/E,qEAAkE;AAElE,2EAAwE;AAExE,gFAAgF;AAChF,oEAAoE;AAC7D,MAAM,mCAAmC,GAAsD,GAAG,EAAE,CAAC,CAAO,SAAS,EAAE,EAAE;IAAC,OAAA,CAAC;QAChI,CAAC,+CAAsB,CAAC,UAAU,CAAC,EAAE,IAAA,gDAA8B,EACjE,SAAS,EACT,qDAAyB,EACzB,2BAA2B,EAC3B,IAAI,EACJ,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAC9B,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE,CACrC;KACF,CAAC,CAAA;EAAA,CAAC;AATU,QAAA,mCAAmC,uCAS7C","sourcesContent":["import { getProcessCustomImplementation, ProcessorFor } from 'quidproquo-core';\nimport { ActionProcessorListResolverFactory } from 'quidproquo-web-react';\n\nimport { AdminAppState } from '../AdminAppState';\nimport { AdminSessionActionType } from './AdminSessionActionType';\nimport { askApplySessionEventBase } from './askApplySessionEvent';\nimport { askApplySessionEventToLog } from './askApplySessionEventToLog';\n\n// Runs the ApplyEvent story in a sub-runtime that inherits the live processors,\n// so it can dispatch into the admin runtime's state like any story.\nexport const getApplySessionEventActionProcessor: ActionProcessorListResolverFactory<AdminAppState> = () => async (qpqConfig) => ({\n [AdminSessionActionType.applyEvent]: getProcessCustomImplementation<ProcessorFor<typeof askApplySessionEventBase>>(\n qpqConfig,\n askApplySessionEventToLog,\n 'Apply Admin Session Event',\n null,\n () => new Date().toISOString(),\n () => globalThis.crypto.randomUUID(),\n ),\n});\n"]}
1
+ {"version":3,"file":"getApplySessionEventActionProcessor.js","sourceRoot":"","sources":["../../../../src/adminApp/actions/getApplySessionEventActionProcessor.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAA6F;AAI7F,qEAAkE;AAElE,2EAAwE;AAExE,gFAAgF;AAChF,oEAAoE;AAC7D,MAAM,mCAAmC,GAAsD,GAAG,EAAE,CAAC,CAAO,SAAS,EAAE,EAAE;IAAC,OAAA,CAAC;QAChI,CAAC,+CAAsB,CAAC,UAAU,CAAC,EAAE,IAAA,gDAA8B,EACjE,SAAS,EACT,qDAAyB,EACzB,2BAA2B,EAC3B,IAAI,EACJ,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAC9B,GAAG,EAAE,CAAC,IAAA,8BAAY,GAAE,CACrB;KACF,CAAC,CAAA;EAAA,CAAC;AATU,QAAA,mCAAmC,uCAS7C","sourcesContent":["import { generateUuid, getProcessCustomImplementation, ProcessorFor } from 'quidproquo-core';\nimport { ActionProcessorListResolverFactory } from 'quidproquo-web-react';\n\nimport { AdminAppState } from '../AdminAppState';\nimport { AdminSessionActionType } from './AdminSessionActionType';\nimport { askApplySessionEventBase } from './askApplySessionEvent';\nimport { askApplySessionEventToLog } from './askApplySessionEventToLog';\n\n// Runs the ApplyEvent story in a sub-runtime that inherits the live processors,\n// so it can dispatch into the admin runtime's state like any story.\nexport const getApplySessionEventActionProcessor: ActionProcessorListResolverFactory<AdminAppState> = () => async (qpqConfig) => ({\n [AdminSessionActionType.applyEvent]: getProcessCustomImplementation<ProcessorFor<typeof askApplySessionEventBase>>(\n qpqConfig,\n askApplySessionEventToLog,\n 'Apply Admin Session Event',\n null,\n () => new Date().toISOString(),\n () => generateUuid(),\n ),\n});\n"]}
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { generateUuid } from 'quidproquo-core';
2
3
  import { EventDocEffect, EventDocStatus, isMaintenancePubliclyVisible, MaintenanceEffect, maintenanceEventDoc, MaintenanceLevel, MaintenanceType, toMaintenancePublicState, } from 'quidproquo-features';
3
4
  import { useAuthAccessToken, useBaseUrlResolvers } from 'quidproquo-web-react';
4
5
  import { useEffect, useMemo, useState } from 'react';
@@ -81,11 +82,11 @@ export function MaintenanceEditor({ docId, onBack }) {
81
82
  else if (dialog.kind === 'reopen') {
82
83
  const reopened = await applyEvent(EventDocEffect.CreateDraft, undefined);
83
84
  if (reopened) {
84
- await applyEvent(MaintenanceEffect.AddUpdate, { updateId: crypto.randomUUID(), ...values });
85
+ await applyEvent(MaintenanceEffect.AddUpdate, { updateId: generateUuid(), ...values });
85
86
  }
86
87
  }
87
88
  else {
88
- await applyEvent(MaintenanceEffect.AddUpdate, { updateId: crypto.randomUUID(), ...values });
89
+ await applyEvent(MaintenanceEffect.AddUpdate, { updateId: generateUuid(), ...values });
89
90
  }
90
91
  setDialog({ kind: 'closed' });
91
92
  };
@@ -1 +1 @@
1
- {"version":3,"file":"MaintenanceEditor.js","sourceRoot":"","sources":["../../../src/Maintenance/MaintenanceEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Nullable } from 'quidproquo-core';\nimport {\n EventDocEffect,\n EventDocEvent,\n EventDocStatus,\n isMaintenancePubliclyVisible,\n MaintenanceEffect,\n maintenanceEventDoc,\n MaintenanceLevel,\n MaintenanceType,\n MaintenanceUpdateEntry,\n toMaintenancePublicState,\n} from 'quidproquo-features';\nimport { useAuthAccessToken, useBaseUrlResolvers } from 'quidproquo-web-react';\n\nimport { useEffect, useMemo, useState } from 'react';\nimport AddIcon from '@mui/icons-material/Add';\nimport ArrowBackIcon from '@mui/icons-material/ArrowBack';\nimport DeleteIcon from '@mui/icons-material/Delete';\nimport EditIcon from '@mui/icons-material/Edit';\nimport EngineeringIcon from '@mui/icons-material/Engineering';\nimport {\n Alert,\n Box,\n Button,\n Chip,\n CircularProgress,\n Divider,\n IconButton,\n Paper,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n Typography,\n} from '@mui/material';\n\nimport { appendMaintenanceEvent, fetchMaintenanceEvents } from './logic';\nimport { MaintenanceUserPreview } from './MaintenanceUserPreview';\nimport { MaintenanceUpdateFormPrefill, MaintenanceUpdateFormValues, UpdateDialog } from './UpdateDialog';\n\ntype MaintenanceEditorProps = {\n docId: string;\n onBack: () => void;\n};\n\ntype DialogMode = { kind: 'closed' } | { kind: 'add' } | { kind: 'edit'; update: MaintenanceUpdateEntry } | { kind: 'reopen' };\n\n// One maintenance: a read-only header card with the CURRENT folded state, and\n// the update feed it derives from. The UPDATE is the only mutation — adding one\n// (prefilled from the last, ETA blank against the running clock) moves the whole\n// status; editing/deleting entries re-derives, so deleting the newest rolls the\n// card back. Closing publishes; reopening demands a fresh update (level resets\n// to Low in the prefill) so a maintenance closed at High never reopens locked.\nexport function MaintenanceEditor({ docId, onBack }: MaintenanceEditorProps) {\n const urlResolvers = useBaseUrlResolvers();\n const accessToken = useAuthAccessToken();\n\n const [events, setEvents] = useState<EventDocEvent[] | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n const [dialog, setDialog] = useState<DialogMode>({ kind: 'closed' });\n\n const folded = useMemo(() => (events ? maintenanceEventDoc.views.document.fold(events) : null), [events]);\n const isClosed = folded?.status === EventDocStatus.Published;\n\n useEffect(() => {\n const load = async () => {\n setError(null);\n try {\n setEvents(await fetchMaintenanceEvents(docId, urlResolvers.getApiUrl(), accessToken));\n } catch (loadError) {\n setError(`Failed to load maintenance: ${loadError}`);\n }\n };\n load();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [docId]);\n\n const applyEvent = async (type: string, data: unknown): Promise<boolean> => {\n setBusy(true);\n setError(null);\n try {\n const event = await appendMaintenanceEvent(docId, type, data, urlResolvers.getApiUrl(), accessToken);\n setEvents((prev) => (prev ? [...prev, event] : [event]));\n return true;\n } catch (appendError) {\n setError(`Failed to save change: ${appendError}`);\n return false;\n } finally {\n setBusy(false);\n }\n };\n\n if (!folded) {\n return (\n <Box sx={{ display: 'flex', justifyContent: 'center', p: 6 }}>{error ? <Alert severity=\"error\">{error}</Alert> : <CircularProgress />}</Box>\n );\n }\n\n const updatesNewestFirst = [...folded.updates].reverse();\n const lastUpdate: Nullable<MaintenanceUpdateEntry> = folded.updates[folded.updates.length - 1] ?? null;\n\n const addPrefill: MaintenanceUpdateFormPrefill = {\n bannerText: folded.bannerText,\n reason: folded.reason,\n level: folded.level,\n maintenanceType: folded.maintenanceType,\n affectedServices: folded.affectedServices,\n internalNotes: '',\n };\n\n // Reopen is \"create from inside\": reason/type/services carry over for\n // convenience, but the level RESETS to Low and there is no running clock.\n const reopenPrefill: MaintenanceUpdateFormPrefill = {\n ...addPrefill,\n level: MaintenanceLevel.Low,\n };\n\n const onDialogSave = async (values: MaintenanceUpdateFormValues) => {\n if (dialog.kind === 'edit') {\n await applyEvent(MaintenanceEffect.EditUpdate, { updateId: dialog.update.id, ...values });\n } else if (dialog.kind === 'reopen') {\n const reopened = await applyEvent(EventDocEffect.CreateDraft, undefined);\n if (reopened) {\n await applyEvent(MaintenanceEffect.AddUpdate, { updateId: crypto.randomUUID(), ...values });\n }\n } else {\n await applyEvent(MaintenanceEffect.AddUpdate, { updateId: crypto.randomUUID(), ...values });\n }\n setDialog({ kind: 'closed' });\n };\n\n return (\n <Box sx={{ p: 3, display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>\n <IconButton aria-label=\"Back to maintenance list\" onClick={onBack}>\n <ArrowBackIcon />\n </IconButton>\n <Typography color=\"text.secondary\" variant=\"body2\">\n Maintenance\n </Typography>\n </Box>\n\n {error && <Alert severity=\"error\">{error}</Alert>}\n\n {/* 70/30: the editor on the left, the what-users-see mock on the right. */}\n <Box sx={{ display: 'flex', gap: 3, alignItems: 'flex-start' }}>\n <Box sx={{ flex: '1 1 70%', minWidth: 0, display: 'flex', flexDirection: 'column', gap: 2 }}>\n {/* The current folded state — read-only; it moves only via updates. */}\n <Paper sx={{ p: 3, display: 'flex', flexDirection: 'column', gap: 1.5 }} variant=\"outlined\">\n <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2 }}>\n <EngineeringIcon color={isClosed ? 'disabled' : 'warning'} sx={{ fontSize: 40 }} />\n <Box sx={{ flexGrow: 1 }}>\n <Typography variant=\"h5\">{folded.bannerText || folded.name}</Typography>\n {folded.reason && folded.reason !== folded.bannerText && (\n <Typography color=\"text.secondary\" variant=\"body2\">\n Latest: {folded.reason}\n </Typography>\n )}\n <Box sx={{ display: 'flex', gap: 1, mt: 1, flexWrap: 'wrap' }}>\n {isClosed ? <Chip label=\"Closed\" size=\"small\" /> : <Chip color=\"warning\" label=\"Active\" size=\"small\" />}\n <Chip\n color={\n folded.level === MaintenanceLevel.High && !isClosed ? 'error' : folded.level === MaintenanceLevel.Info ? 'info' : 'default'\n }\n label={\n folded.level === MaintenanceLevel.High\n ? 'High — UI locked'\n : folded.level === MaintenanceLevel.Info\n ? 'Info — banner'\n : folded.level === MaintenanceLevel.Internal\n ? 'Internal — hidden from users'\n : 'Low — banner only'\n }\n size=\"small\"\n variant={folded.level === MaintenanceLevel.High ? 'filled' : 'outlined'}\n />\n <Chip label={folded.maintenanceType === MaintenanceType.Incident ? 'Incident' : 'Deploy'} size=\"small\" variant=\"outlined\" />\n {folded.etaEndsAt && <Chip label={`Ends ~${new Date(folded.etaEndsAt).toLocaleTimeString()}`} size=\"small\" variant=\"outlined\" />}\n <Chip\n label={folded.affectedServices ? `Affected: ${folded.affectedServices.join(', ')}` : 'All services'}\n size=\"small\"\n variant=\"outlined\"\n />\n </Box>\n </Box>\n {isClosed ? (\n <Button disabled={busy} onClick={() => setDialog({ kind: 'reopen' })} variant=\"contained\">\n Reopen maintenance\n </Button>\n ) : (\n <Button\n color=\"success\"\n disabled={busy}\n onClick={() => applyEvent(EventDocEffect.Publish, { effectiveFrom: new Date().toISOString() })}\n variant=\"contained\"\n >\n Close maintenance\n </Button>\n )}\n </Box>\n {lastUpdate?.internalNotes && (\n <Typography color=\"text.secondary\" sx={{ fontStyle: 'italic' }} variant=\"body2\">\n Internal: {lastUpdate.internalNotes}\n </Typography>\n )}\n </Paper>\n\n <Divider />\n\n <Box sx={{ display: 'flex', alignItems: 'center' }}>\n <Typography sx={{ flexGrow: 1 }} variant=\"h6\">\n Updates\n </Typography>\n <Button disabled={isClosed || busy} onClick={() => setDialog({ kind: 'add' })} startIcon={<AddIcon />} variant=\"outlined\">\n Add update\n </Button>\n </Box>\n\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Status</TableCell>\n <TableCell>Level</TableCell>\n <TableCell>ETA</TableCell>\n <TableCell>Internal notes</TableCell>\n <TableCell>Posted</TableCell>\n <TableCell align=\"right\">Actions</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {updatesNewestFirst.map((update) => (\n <TableRow key={update.id} hover>\n <TableCell sx={{ maxWidth: 420 }}>{update.reason}</TableCell>\n <TableCell>\n <Chip\n color={update.level === MaintenanceLevel.High ? 'error' : update.level === MaintenanceLevel.Info ? 'info' : 'default'}\n label={update.level}\n size=\"small\"\n variant={update.level === MaintenanceLevel.High ? 'filled' : 'outlined'}\n />\n </TableCell>\n <TableCell>{update.etaSetAt ? (update.etaDurationMins === null ? 'Cleared' : `${update.etaDurationMins}m`) : '—'}</TableCell>\n <TableCell sx={{ maxWidth: 360 }}>\n {update.internalNotes ? (\n <Typography color=\"text.secondary\" sx={{ fontStyle: 'italic' }} variant=\"body2\">\n {update.internalNotes}\n </Typography>\n ) : (\n '—'\n )}\n </TableCell>\n <TableCell sx={{ whiteSpace: 'nowrap' }}>\n {new Date(update.createdAt).toLocaleString()} — {update.createdByDisplayName}\n {update.updatedAt ? ' (edited)' : ''}\n </TableCell>\n <TableCell align=\"right\" sx={{ whiteSpace: 'nowrap' }}>\n {!isClosed && (\n <>\n <IconButton aria-label=\"Edit update\" disabled={busy} onClick={() => setDialog({ kind: 'edit', update })} size=\"small\">\n <EditIcon fontSize=\"small\" />\n </IconButton>\n <IconButton\n aria-label=\"Delete update\"\n disabled={busy}\n onClick={() => applyEvent(MaintenanceEffect.RemoveUpdate, { updateId: update.id })}\n size=\"small\"\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButton>\n </>\n )}\n </TableCell>\n </TableRow>\n ))}\n {folded.updates.length === 0 && (\n <TableRow>\n <TableCell colSpan={6}>\n <Typography color=\"text.secondary\" sx={{ p: 1 }} variant=\"body2\">\n No updates posted yet.\n </Typography>\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </Box>\n\n <Box sx={{ flex: '0 0 30%', minWidth: 300 }}>\n <MaintenanceUserPreview publicState={toMaintenancePublicState(folded)} visible={isMaintenancePubliclyVisible(folded)} />\n </Box>\n </Box>\n\n <UpdateDialog\n busy={busy}\n confirmLabel={dialog.kind === 'reopen' ? 'Reopen maintenance' : dialog.kind === 'edit' ? 'Save update' : 'Add update'}\n currentEtaEndsAt={dialog.kind === 'reopen' ? null : folded.etaEndsAt}\n initialValues={\n dialog.kind === 'edit'\n ? {\n bannerText: dialog.update.bannerText,\n reason: dialog.update.reason,\n level: dialog.update.level,\n maintenanceType: dialog.update.maintenanceType,\n affectedServices: dialog.update.affectedServices,\n internalNotes: dialog.update.internalNotes,\n }\n : dialog.kind === 'reopen'\n ? reopenPrefill\n : addPrefill\n }\n onCancel={() => setDialog({ kind: 'closed' })}\n onSave={onDialogSave}\n open={dialog.kind !== 'closed'}\n title={dialog.kind === 'reopen' ? 'Reopen maintenance' : dialog.kind === 'edit' ? 'Edit update' : 'Add update'}\n />\n </Box>\n );\n}\n"]}
1
+ {"version":3,"file":"MaintenanceEditor.js","sourceRoot":"","sources":["../../../src/Maintenance/MaintenanceEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import { generateUuid, Nullable } from 'quidproquo-core';\nimport {\n EventDocEffect,\n EventDocEvent,\n EventDocStatus,\n isMaintenancePubliclyVisible,\n MaintenanceEffect,\n maintenanceEventDoc,\n MaintenanceLevel,\n MaintenanceType,\n MaintenanceUpdateEntry,\n toMaintenancePublicState,\n} from 'quidproquo-features';\nimport { useAuthAccessToken, useBaseUrlResolvers } from 'quidproquo-web-react';\n\nimport { useEffect, useMemo, useState } from 'react';\nimport AddIcon from '@mui/icons-material/Add';\nimport ArrowBackIcon from '@mui/icons-material/ArrowBack';\nimport DeleteIcon from '@mui/icons-material/Delete';\nimport EditIcon from '@mui/icons-material/Edit';\nimport EngineeringIcon from '@mui/icons-material/Engineering';\nimport {\n Alert,\n Box,\n Button,\n Chip,\n CircularProgress,\n Divider,\n IconButton,\n Paper,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n Typography,\n} from '@mui/material';\n\nimport { appendMaintenanceEvent, fetchMaintenanceEvents } from './logic';\nimport { MaintenanceUserPreview } from './MaintenanceUserPreview';\nimport { MaintenanceUpdateFormPrefill, MaintenanceUpdateFormValues, UpdateDialog } from './UpdateDialog';\n\ntype MaintenanceEditorProps = {\n docId: string;\n onBack: () => void;\n};\n\ntype DialogMode = { kind: 'closed' } | { kind: 'add' } | { kind: 'edit'; update: MaintenanceUpdateEntry } | { kind: 'reopen' };\n\n// One maintenance: a read-only header card with the CURRENT folded state, and\n// the update feed it derives from. The UPDATE is the only mutation — adding one\n// (prefilled from the last, ETA blank against the running clock) moves the whole\n// status; editing/deleting entries re-derives, so deleting the newest rolls the\n// card back. Closing publishes; reopening demands a fresh update (level resets\n// to Low in the prefill) so a maintenance closed at High never reopens locked.\nexport function MaintenanceEditor({ docId, onBack }: MaintenanceEditorProps) {\n const urlResolvers = useBaseUrlResolvers();\n const accessToken = useAuthAccessToken();\n\n const [events, setEvents] = useState<EventDocEvent[] | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n const [dialog, setDialog] = useState<DialogMode>({ kind: 'closed' });\n\n const folded = useMemo(() => (events ? maintenanceEventDoc.views.document.fold(events) : null), [events]);\n const isClosed = folded?.status === EventDocStatus.Published;\n\n useEffect(() => {\n const load = async () => {\n setError(null);\n try {\n setEvents(await fetchMaintenanceEvents(docId, urlResolvers.getApiUrl(), accessToken));\n } catch (loadError) {\n setError(`Failed to load maintenance: ${loadError}`);\n }\n };\n load();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [docId]);\n\n const applyEvent = async (type: string, data: unknown): Promise<boolean> => {\n setBusy(true);\n setError(null);\n try {\n const event = await appendMaintenanceEvent(docId, type, data, urlResolvers.getApiUrl(), accessToken);\n setEvents((prev) => (prev ? [...prev, event] : [event]));\n return true;\n } catch (appendError) {\n setError(`Failed to save change: ${appendError}`);\n return false;\n } finally {\n setBusy(false);\n }\n };\n\n if (!folded) {\n return (\n <Box sx={{ display: 'flex', justifyContent: 'center', p: 6 }}>{error ? <Alert severity=\"error\">{error}</Alert> : <CircularProgress />}</Box>\n );\n }\n\n const updatesNewestFirst = [...folded.updates].reverse();\n const lastUpdate: Nullable<MaintenanceUpdateEntry> = folded.updates[folded.updates.length - 1] ?? null;\n\n const addPrefill: MaintenanceUpdateFormPrefill = {\n bannerText: folded.bannerText,\n reason: folded.reason,\n level: folded.level,\n maintenanceType: folded.maintenanceType,\n affectedServices: folded.affectedServices,\n internalNotes: '',\n };\n\n // Reopen is \"create from inside\": reason/type/services carry over for\n // convenience, but the level RESETS to Low and there is no running clock.\n const reopenPrefill: MaintenanceUpdateFormPrefill = {\n ...addPrefill,\n level: MaintenanceLevel.Low,\n };\n\n const onDialogSave = async (values: MaintenanceUpdateFormValues) => {\n if (dialog.kind === 'edit') {\n await applyEvent(MaintenanceEffect.EditUpdate, { updateId: dialog.update.id, ...values });\n } else if (dialog.kind === 'reopen') {\n const reopened = await applyEvent(EventDocEffect.CreateDraft, undefined);\n if (reopened) {\n await applyEvent(MaintenanceEffect.AddUpdate, { updateId: generateUuid(), ...values });\n }\n } else {\n await applyEvent(MaintenanceEffect.AddUpdate, { updateId: generateUuid(), ...values });\n }\n setDialog({ kind: 'closed' });\n };\n\n return (\n <Box sx={{ p: 3, display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>\n <IconButton aria-label=\"Back to maintenance list\" onClick={onBack}>\n <ArrowBackIcon />\n </IconButton>\n <Typography color=\"text.secondary\" variant=\"body2\">\n Maintenance\n </Typography>\n </Box>\n\n {error && <Alert severity=\"error\">{error}</Alert>}\n\n {/* 70/30: the editor on the left, the what-users-see mock on the right. */}\n <Box sx={{ display: 'flex', gap: 3, alignItems: 'flex-start' }}>\n <Box sx={{ flex: '1 1 70%', minWidth: 0, display: 'flex', flexDirection: 'column', gap: 2 }}>\n {/* The current folded state — read-only; it moves only via updates. */}\n <Paper sx={{ p: 3, display: 'flex', flexDirection: 'column', gap: 1.5 }} variant=\"outlined\">\n <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 2 }}>\n <EngineeringIcon color={isClosed ? 'disabled' : 'warning'} sx={{ fontSize: 40 }} />\n <Box sx={{ flexGrow: 1 }}>\n <Typography variant=\"h5\">{folded.bannerText || folded.name}</Typography>\n {folded.reason && folded.reason !== folded.bannerText && (\n <Typography color=\"text.secondary\" variant=\"body2\">\n Latest: {folded.reason}\n </Typography>\n )}\n <Box sx={{ display: 'flex', gap: 1, mt: 1, flexWrap: 'wrap' }}>\n {isClosed ? <Chip label=\"Closed\" size=\"small\" /> : <Chip color=\"warning\" label=\"Active\" size=\"small\" />}\n <Chip\n color={\n folded.level === MaintenanceLevel.High && !isClosed ? 'error' : folded.level === MaintenanceLevel.Info ? 'info' : 'default'\n }\n label={\n folded.level === MaintenanceLevel.High\n ? 'High — UI locked'\n : folded.level === MaintenanceLevel.Info\n ? 'Info — banner'\n : folded.level === MaintenanceLevel.Internal\n ? 'Internal — hidden from users'\n : 'Low — banner only'\n }\n size=\"small\"\n variant={folded.level === MaintenanceLevel.High ? 'filled' : 'outlined'}\n />\n <Chip label={folded.maintenanceType === MaintenanceType.Incident ? 'Incident' : 'Deploy'} size=\"small\" variant=\"outlined\" />\n {folded.etaEndsAt && <Chip label={`Ends ~${new Date(folded.etaEndsAt).toLocaleTimeString()}`} size=\"small\" variant=\"outlined\" />}\n <Chip\n label={folded.affectedServices ? `Affected: ${folded.affectedServices.join(', ')}` : 'All services'}\n size=\"small\"\n variant=\"outlined\"\n />\n </Box>\n </Box>\n {isClosed ? (\n <Button disabled={busy} onClick={() => setDialog({ kind: 'reopen' })} variant=\"contained\">\n Reopen maintenance\n </Button>\n ) : (\n <Button\n color=\"success\"\n disabled={busy}\n onClick={() => applyEvent(EventDocEffect.Publish, { effectiveFrom: new Date().toISOString() })}\n variant=\"contained\"\n >\n Close maintenance\n </Button>\n )}\n </Box>\n {lastUpdate?.internalNotes && (\n <Typography color=\"text.secondary\" sx={{ fontStyle: 'italic' }} variant=\"body2\">\n Internal: {lastUpdate.internalNotes}\n </Typography>\n )}\n </Paper>\n\n <Divider />\n\n <Box sx={{ display: 'flex', alignItems: 'center' }}>\n <Typography sx={{ flexGrow: 1 }} variant=\"h6\">\n Updates\n </Typography>\n <Button disabled={isClosed || busy} onClick={() => setDialog({ kind: 'add' })} startIcon={<AddIcon />} variant=\"outlined\">\n Add update\n </Button>\n </Box>\n\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Status</TableCell>\n <TableCell>Level</TableCell>\n <TableCell>ETA</TableCell>\n <TableCell>Internal notes</TableCell>\n <TableCell>Posted</TableCell>\n <TableCell align=\"right\">Actions</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {updatesNewestFirst.map((update) => (\n <TableRow key={update.id} hover>\n <TableCell sx={{ maxWidth: 420 }}>{update.reason}</TableCell>\n <TableCell>\n <Chip\n color={update.level === MaintenanceLevel.High ? 'error' : update.level === MaintenanceLevel.Info ? 'info' : 'default'}\n label={update.level}\n size=\"small\"\n variant={update.level === MaintenanceLevel.High ? 'filled' : 'outlined'}\n />\n </TableCell>\n <TableCell>{update.etaSetAt ? (update.etaDurationMins === null ? 'Cleared' : `${update.etaDurationMins}m`) : '—'}</TableCell>\n <TableCell sx={{ maxWidth: 360 }}>\n {update.internalNotes ? (\n <Typography color=\"text.secondary\" sx={{ fontStyle: 'italic' }} variant=\"body2\">\n {update.internalNotes}\n </Typography>\n ) : (\n '—'\n )}\n </TableCell>\n <TableCell sx={{ whiteSpace: 'nowrap' }}>\n {new Date(update.createdAt).toLocaleString()} — {update.createdByDisplayName}\n {update.updatedAt ? ' (edited)' : ''}\n </TableCell>\n <TableCell align=\"right\" sx={{ whiteSpace: 'nowrap' }}>\n {!isClosed && (\n <>\n <IconButton aria-label=\"Edit update\" disabled={busy} onClick={() => setDialog({ kind: 'edit', update })} size=\"small\">\n <EditIcon fontSize=\"small\" />\n </IconButton>\n <IconButton\n aria-label=\"Delete update\"\n disabled={busy}\n onClick={() => applyEvent(MaintenanceEffect.RemoveUpdate, { updateId: update.id })}\n size=\"small\"\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButton>\n </>\n )}\n </TableCell>\n </TableRow>\n ))}\n {folded.updates.length === 0 && (\n <TableRow>\n <TableCell colSpan={6}>\n <Typography color=\"text.secondary\" sx={{ p: 1 }} variant=\"body2\">\n No updates posted yet.\n </Typography>\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n </Box>\n\n <Box sx={{ flex: '0 0 30%', minWidth: 300 }}>\n <MaintenanceUserPreview publicState={toMaintenancePublicState(folded)} visible={isMaintenancePubliclyVisible(folded)} />\n </Box>\n </Box>\n\n <UpdateDialog\n busy={busy}\n confirmLabel={dialog.kind === 'reopen' ? 'Reopen maintenance' : dialog.kind === 'edit' ? 'Save update' : 'Add update'}\n currentEtaEndsAt={dialog.kind === 'reopen' ? null : folded.etaEndsAt}\n initialValues={\n dialog.kind === 'edit'\n ? {\n bannerText: dialog.update.bannerText,\n reason: dialog.update.reason,\n level: dialog.update.level,\n maintenanceType: dialog.update.maintenanceType,\n affectedServices: dialog.update.affectedServices,\n internalNotes: dialog.update.internalNotes,\n }\n : dialog.kind === 'reopen'\n ? reopenPrefill\n : addPrefill\n }\n onCancel={() => setDialog({ kind: 'closed' })}\n onSave={onDialogSave}\n open={dialog.kind !== 'closed'}\n title={dialog.kind === 'reopen' ? 'Reopen maintenance' : dialog.kind === 'edit' ? 'Edit update' : 'Add update'}\n />\n </Box>\n );\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { generateUuid } from 'quidproquo-core';
2
3
  import { MaintenanceEffect, MaintenanceLevel, MaintenanceType, toEventDocListItem } from 'quidproquo-features';
3
4
  import { useAuthAccessToken, useBaseUrlResolvers } from 'quidproquo-web-react';
4
5
  import { useEffect, useState } from 'react';
@@ -52,7 +53,7 @@ export function MaintenanceList({ onOpen }) {
52
53
  try {
53
54
  const apiBaseUrl = urlResolvers.getApiUrl();
54
55
  const summary = await createMaintenance(values.bannerText || values.reason, values.maintenanceType.toLowerCase(), apiBaseUrl, accessToken);
55
- await appendMaintenanceEvent(summary.id, MaintenanceEffect.AddUpdate, { updateId: crypto.randomUUID(), ...values }, apiBaseUrl, accessToken);
56
+ await appendMaintenanceEvent(summary.id, MaintenanceEffect.AddUpdate, { updateId: generateUuid(), ...values }, apiBaseUrl, accessToken);
56
57
  setCreateOpen(false);
57
58
  onOpen(summary.id);
58
59
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MaintenanceList.js","sourceRoot":"","sources":["../../../src/Maintenance/MaintenanceList.tsx"],"names":[],"mappings":"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","sourcesContent":["import { EventDocSummary, MaintenanceEffect, MaintenanceLevel, MaintenanceType, toEventDocListItem } from 'quidproquo-features';\nimport { useAuthAccessToken, useBaseUrlResolvers } from 'quidproquo-web-react';\n\nimport { useEffect, useState } from 'react';\nimport AddIcon from '@mui/icons-material/Add';\nimport RefreshIcon from '@mui/icons-material/Refresh';\nimport { Alert, Box, Button, Chip, CircularProgress, Table, TableBody, TableCell, TableHead, TableRow, Typography } from '@mui/material';\n\nimport { appendMaintenanceEvent, createMaintenance, fetchMaintenanceSummaries } from './logic';\nimport { MaintenanceUpdateFormValues, UpdateDialog } from './UpdateDialog';\n\nconst CREATE_PREFILL = {\n bannerText: 'The site is undergoing a scheduled update',\n reason: 'Maintenance started',\n level: MaintenanceLevel.Low,\n maintenanceType: MaintenanceType.Deploy,\n affectedServices: null,\n internalNotes: '',\n};\n\ntype MaintenanceListProps = {\n onOpen: (docId: string) => void;\n};\n\n// All maintenances, newest first — active (open draft) vs closed (published).\n// \"New maintenance\" BEGINS one: the doc is created, its initial settings are\n// appended (level last, so a High lock only engages once the reason/type/eta\n// are already in the broadcast state), and the editor opens.\nexport function MaintenanceList({ onOpen }: MaintenanceListProps) {\n const urlResolvers = useBaseUrlResolvers();\n const accessToken = useAuthAccessToken();\n\n const [summaries, setSummaries] = useState<EventDocSummary[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [creating, setCreating] = useState(false);\n const [createOpen, setCreateOpen] = useState(false);\n\n const load = async () => {\n setLoading(true);\n setError(null);\n try {\n setSummaries(await fetchMaintenanceSummaries(urlResolvers.getApiUrl(), accessToken));\n } catch (loadError) {\n setError(`Failed to load maintenances: ${loadError}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n load();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Create = the first update: one doc, one ADD_UPDATE carrying the full status\n // snapshot — the maintenance is live (and broadcast) from that single append.\n const onCreate = async (values: MaintenanceUpdateFormValues) => {\n setCreating(true);\n setError(null);\n try {\n const apiBaseUrl = urlResolvers.getApiUrl();\n const summary = await createMaintenance(values.bannerText || values.reason, values.maintenanceType.toLowerCase(), apiBaseUrl, accessToken);\n\n await appendMaintenanceEvent(summary.id, MaintenanceEffect.AddUpdate, { updateId: crypto.randomUUID(), ...values }, apiBaseUrl, accessToken);\n\n setCreateOpen(false);\n onOpen(summary.id);\n } catch (createError) {\n setError(`Failed to create maintenance: ${createError}`);\n } finally {\n setCreating(false);\n }\n };\n\n return (\n <Box sx={{ p: 3, display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>\n <Typography sx={{ flexGrow: 1 }} variant=\"h5\">\n Maintenance\n </Typography>\n <Button onClick={load} startIcon={<RefreshIcon />}>\n Refresh\n </Button>\n <Button onClick={() => setCreateOpen(true)} startIcon={<AddIcon />} variant=\"contained\">\n New maintenance\n </Button>\n </Box>\n\n {error && <Alert severity=\"error\">{error}</Alert>}\n\n {loading ? (\n <Box sx={{ display: 'flex', justifyContent: 'center', p: 4 }}>\n <CircularProgress />\n </Box>\n ) : (\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Reason</TableCell>\n <TableCell>Status</TableCell>\n <TableCell>Updated</TableCell>\n <TableCell>Created</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {summaries.map((summary) => {\n const item = toEventDocListItem(summary);\n return (\n <TableRow key={summary.id} hover onClick={() => onOpen(summary.id)} sx={{ cursor: 'pointer' }}>\n <TableCell>{summary.name}</TableCell>\n <TableCell>{item.hasDraft ? <Chip color=\"warning\" label=\"Active\" size=\"small\" /> : <Chip label=\"Closed\" size=\"small\" />}</TableCell>\n <TableCell>{new Date(summary.updatedAt).toLocaleString()}</TableCell>\n <TableCell>{new Date(summary.createdAt).toLocaleString()}</TableCell>\n </TableRow>\n );\n })}\n {summaries.length === 0 && (\n <TableRow>\n <TableCell colSpan={4}>\n <Typography color=\"text.secondary\" sx={{ p: 2 }} variant=\"body2\">\n No maintenances yet.\n </Typography>\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n )}\n\n <UpdateDialog\n busy={creating}\n confirmLabel=\"Begin maintenance\"\n initialValues={CREATE_PREFILL}\n onCancel={() => setCreateOpen(false)}\n onSave={onCreate}\n open={createOpen}\n title=\"New maintenance\"\n />\n </Box>\n );\n}\n"]}
1
+ {"version":3,"file":"MaintenanceList.js","sourceRoot":"","sources":["../../../src/Maintenance/MaintenanceList.tsx"],"names":[],"mappings":"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","sourcesContent":["import { generateUuid } from 'quidproquo-core';\nimport { EventDocSummary, MaintenanceEffect, MaintenanceLevel, MaintenanceType, toEventDocListItem } from 'quidproquo-features';\nimport { useAuthAccessToken, useBaseUrlResolvers } from 'quidproquo-web-react';\n\nimport { useEffect, useState } from 'react';\nimport AddIcon from '@mui/icons-material/Add';\nimport RefreshIcon from '@mui/icons-material/Refresh';\nimport { Alert, Box, Button, Chip, CircularProgress, Table, TableBody, TableCell, TableHead, TableRow, Typography } from '@mui/material';\n\nimport { appendMaintenanceEvent, createMaintenance, fetchMaintenanceSummaries } from './logic';\nimport { MaintenanceUpdateFormValues, UpdateDialog } from './UpdateDialog';\n\nconst CREATE_PREFILL = {\n bannerText: 'The site is undergoing a scheduled update',\n reason: 'Maintenance started',\n level: MaintenanceLevel.Low,\n maintenanceType: MaintenanceType.Deploy,\n affectedServices: null,\n internalNotes: '',\n};\n\ntype MaintenanceListProps = {\n onOpen: (docId: string) => void;\n};\n\n// All maintenances, newest first — active (open draft) vs closed (published).\n// \"New maintenance\" BEGINS one: the doc is created, its initial settings are\n// appended (level last, so a High lock only engages once the reason/type/eta\n// are already in the broadcast state), and the editor opens.\nexport function MaintenanceList({ onOpen }: MaintenanceListProps) {\n const urlResolvers = useBaseUrlResolvers();\n const accessToken = useAuthAccessToken();\n\n const [summaries, setSummaries] = useState<EventDocSummary[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [creating, setCreating] = useState(false);\n const [createOpen, setCreateOpen] = useState(false);\n\n const load = async () => {\n setLoading(true);\n setError(null);\n try {\n setSummaries(await fetchMaintenanceSummaries(urlResolvers.getApiUrl(), accessToken));\n } catch (loadError) {\n setError(`Failed to load maintenances: ${loadError}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n load();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Create = the first update: one doc, one ADD_UPDATE carrying the full status\n // snapshot — the maintenance is live (and broadcast) from that single append.\n const onCreate = async (values: MaintenanceUpdateFormValues) => {\n setCreating(true);\n setError(null);\n try {\n const apiBaseUrl = urlResolvers.getApiUrl();\n const summary = await createMaintenance(values.bannerText || values.reason, values.maintenanceType.toLowerCase(), apiBaseUrl, accessToken);\n\n await appendMaintenanceEvent(summary.id, MaintenanceEffect.AddUpdate, { updateId: generateUuid(), ...values }, apiBaseUrl, accessToken);\n\n setCreateOpen(false);\n onOpen(summary.id);\n } catch (createError) {\n setError(`Failed to create maintenance: ${createError}`);\n } finally {\n setCreating(false);\n }\n };\n\n return (\n <Box sx={{ p: 3, display: 'flex', flexDirection: 'column', gap: 2 }}>\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>\n <Typography sx={{ flexGrow: 1 }} variant=\"h5\">\n Maintenance\n </Typography>\n <Button onClick={load} startIcon={<RefreshIcon />}>\n Refresh\n </Button>\n <Button onClick={() => setCreateOpen(true)} startIcon={<AddIcon />} variant=\"contained\">\n New maintenance\n </Button>\n </Box>\n\n {error && <Alert severity=\"error\">{error}</Alert>}\n\n {loading ? (\n <Box sx={{ display: 'flex', justifyContent: 'center', p: 4 }}>\n <CircularProgress />\n </Box>\n ) : (\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Reason</TableCell>\n <TableCell>Status</TableCell>\n <TableCell>Updated</TableCell>\n <TableCell>Created</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {summaries.map((summary) => {\n const item = toEventDocListItem(summary);\n return (\n <TableRow key={summary.id} hover onClick={() => onOpen(summary.id)} sx={{ cursor: 'pointer' }}>\n <TableCell>{summary.name}</TableCell>\n <TableCell>{item.hasDraft ? <Chip color=\"warning\" label=\"Active\" size=\"small\" /> : <Chip label=\"Closed\" size=\"small\" />}</TableCell>\n <TableCell>{new Date(summary.updatedAt).toLocaleString()}</TableCell>\n <TableCell>{new Date(summary.createdAt).toLocaleString()}</TableCell>\n </TableRow>\n );\n })}\n {summaries.length === 0 && (\n <TableRow>\n <TableCell colSpan={4}>\n <Typography color=\"text.secondary\" sx={{ p: 2 }} variant=\"body2\">\n No maintenances yet.\n </Typography>\n </TableCell>\n </TableRow>\n )}\n </TableBody>\n </Table>\n )}\n\n <UpdateDialog\n busy={creating}\n confirmLabel=\"Begin maintenance\"\n initialValues={CREATE_PREFILL}\n onCancel={() => setCreateOpen(false)}\n onSave={onCreate}\n open={createOpen}\n title=\"New maintenance\"\n />\n </Box>\n );\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { generateUuid } from 'quidproquo-core';
1
2
  import { MAINTENANCE_SCHEMA_VERSION, maintenanceBasePath } from 'quidproquo-features';
2
3
  import { apiRequestGet, apiRequestPost } from '../../logic';
3
4
  // Thin fetch layer over the maintenance event-doc REST routes
@@ -24,7 +25,7 @@ export const appendMaintenanceEvent = async (docId, type, data, apiBaseUrl, acce
24
25
  data,
25
26
  metadata: {
26
27
  version: MAINTENANCE_SCHEMA_VERSION,
27
- clientMessageId: crypto.randomUUID(),
28
+ clientMessageId: generateUuid(),
28
29
  },
29
30
  },
30
31
  };
@@ -1 +1 @@
1
- {"version":3,"file":"maintenanceApi.js","sourceRoot":"","sources":["../../../../src/Maintenance/logic/maintenanceApi.ts"],"names":[],"mappings":"AACA,OAAO,EAAsD,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1I,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE5D,8DAA8D;AAC9D,8EAA8E;AAC9E,yEAAyE;AAEzE,MAAM,cAAc,GAAG,MAAM,mBAAmB,EAAE,CAAC;AAEnD,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,EAAE,UAAkB,EAAE,WAAoB,EAA8B,EAAE,CACtH,aAAa,CAAoB,cAAc,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AAE5E,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,IAAY,EAAE,IAAY,EAAE,UAAkB,EAAE,WAAoB,EAA4B,EAAE,CACxI,cAAc,CAAkB,cAAc,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AAE3F,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EAAE,KAAa,EAAE,UAAkB,EAAE,WAAoB,EAA4B,EAAE;IAChI,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,IAAI,WAAW,GAAuB,SAAS,CAAC;IAEhD,GAAG,CAAC;QACF,MAAM,KAAK,GAAW,WAAW,CAAC,CAAC,CAAC,gBAAgB,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3F,MAAM,IAAI,GAAgC,MAAM,aAAa,CAC3D,GAAG,cAAc,IAAI,KAAK,UAAU,KAAK,EAAE,EAC3C,UAAU,EACV,WAAW,CACZ,CAAC;QAEF,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;IACjC,CAAC,QAAQ,WAAW,EAAE;IAEtB,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EACzC,KAAa,EACb,IAAY,EACZ,IAAa,EACb,UAAkB,EAClB,WAAoB,EACI,EAAE;IAC1B,MAAM,KAAK,GAAuB;QAChC,IAAI;QACJ,OAAO,EAAE;YACP,IAAI;YACJ,QAAQ,EAAE;gBACR,OAAO,EAAE,0BAA0B;gBACnC,eAAe,EAAE,MAAM,CAAC,UAAU,EAAE;aACrC;SACF;KACF,CAAC;IAEF,OAAO,cAAc,CAAgB,GAAG,cAAc,IAAI,KAAK,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AAC5G,CAAC,CAAC","sourcesContent":["import { QpqPagedData } from 'quidproquo-core';\nimport { EventDocEvent, EventDocEventInput, EventDocSummary, MAINTENANCE_SCHEMA_VERSION, maintenanceBasePath } from 'quidproquo-features';\n\nimport { apiRequestGet, apiRequestPost } from '../../logic';\n\n// Thin fetch layer over the maintenance event-doc REST routes\n// (defineEventDocRoutes mounts them under /v1). The editor folds locally with\n// maintenanceEventDoc.fold, so this only moves summaries and raw events.\n\nconst collectionPath = `/v1${maintenanceBasePath}`;\n\nexport const fetchMaintenanceSummaries = async (apiBaseUrl: string, accessToken?: string): Promise<EventDocSummary[]> =>\n apiRequestGet<EventDocSummary[]>(collectionPath, apiBaseUrl, accessToken);\n\nexport const createMaintenance = async (name: string, code: string, apiBaseUrl: string, accessToken?: string): Promise<EventDocSummary> =>\n apiRequestPost<EventDocSummary>(collectionPath, { name, code }, apiBaseUrl, accessToken);\n\nexport const fetchMaintenanceEvents = async (docId: string, apiBaseUrl: string, accessToken?: string): Promise<EventDocEvent[]> => {\n const events: EventDocEvent[] = [];\n let nextPageKey: string | undefined = undefined;\n\n do {\n const query: string = nextPageKey ? `?nextPageKey=${encodeURIComponent(nextPageKey)}` : '';\n const page: QpqPagedData<EventDocEvent> = await apiRequestGet<QpqPagedData<EventDocEvent>>(\n `${collectionPath}/${docId}/events${query}`,\n apiBaseUrl,\n accessToken,\n );\n\n events.push(...page.items);\n nextPageKey = page.nextPageKey;\n } while (nextPageKey);\n\n return events;\n};\n\nexport const appendMaintenanceEvent = async (\n docId: string,\n type: string,\n data: unknown,\n apiBaseUrl: string,\n accessToken?: string,\n): Promise<EventDocEvent> => {\n const input: EventDocEventInput = {\n type,\n payload: {\n data,\n metadata: {\n version: MAINTENANCE_SCHEMA_VERSION,\n clientMessageId: crypto.randomUUID(),\n },\n },\n };\n\n return apiRequestPost<EventDocEvent>(`${collectionPath}/${docId}/events`, input, apiBaseUrl, accessToken);\n};\n"]}
1
+ {"version":3,"file":"maintenanceApi.js","sourceRoot":"","sources":["../../../../src/Maintenance/logic/maintenanceApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAgB,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAsD,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1I,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE5D,8DAA8D;AAC9D,8EAA8E;AAC9E,yEAAyE;AAEzE,MAAM,cAAc,GAAG,MAAM,mBAAmB,EAAE,CAAC;AAEnD,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,EAAE,UAAkB,EAAE,WAAoB,EAA8B,EAAE,CACtH,aAAa,CAAoB,cAAc,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AAE5E,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,IAAY,EAAE,IAAY,EAAE,UAAkB,EAAE,WAAoB,EAA4B,EAAE,CACxI,cAAc,CAAkB,cAAc,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AAE3F,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EAAE,KAAa,EAAE,UAAkB,EAAE,WAAoB,EAA4B,EAAE;IAChI,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,IAAI,WAAW,GAAuB,SAAS,CAAC;IAEhD,GAAG,CAAC;QACF,MAAM,KAAK,GAAW,WAAW,CAAC,CAAC,CAAC,gBAAgB,kBAAkB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3F,MAAM,IAAI,GAAgC,MAAM,aAAa,CAC3D,GAAG,cAAc,IAAI,KAAK,UAAU,KAAK,EAAE,EAC3C,UAAU,EACV,WAAW,CACZ,CAAC;QAEF,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;IACjC,CAAC,QAAQ,WAAW,EAAE;IAEtB,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EACzC,KAAa,EACb,IAAY,EACZ,IAAa,EACb,UAAkB,EAClB,WAAoB,EACI,EAAE;IAC1B,MAAM,KAAK,GAAuB;QAChC,IAAI;QACJ,OAAO,EAAE;YACP,IAAI;YACJ,QAAQ,EAAE;gBACR,OAAO,EAAE,0BAA0B;gBACnC,eAAe,EAAE,YAAY,EAAE;aAChC;SACF;KACF,CAAC;IAEF,OAAO,cAAc,CAAgB,GAAG,cAAc,IAAI,KAAK,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AAC5G,CAAC,CAAC","sourcesContent":["import { generateUuid, QpqPagedData } from 'quidproquo-core';\nimport { EventDocEvent, EventDocEventInput, EventDocSummary, MAINTENANCE_SCHEMA_VERSION, maintenanceBasePath } from 'quidproquo-features';\n\nimport { apiRequestGet, apiRequestPost } from '../../logic';\n\n// Thin fetch layer over the maintenance event-doc REST routes\n// (defineEventDocRoutes mounts them under /v1). The editor folds locally with\n// maintenanceEventDoc.fold, so this only moves summaries and raw events.\n\nconst collectionPath = `/v1${maintenanceBasePath}`;\n\nexport const fetchMaintenanceSummaries = async (apiBaseUrl: string, accessToken?: string): Promise<EventDocSummary[]> =>\n apiRequestGet<EventDocSummary[]>(collectionPath, apiBaseUrl, accessToken);\n\nexport const createMaintenance = async (name: string, code: string, apiBaseUrl: string, accessToken?: string): Promise<EventDocSummary> =>\n apiRequestPost<EventDocSummary>(collectionPath, { name, code }, apiBaseUrl, accessToken);\n\nexport const fetchMaintenanceEvents = async (docId: string, apiBaseUrl: string, accessToken?: string): Promise<EventDocEvent[]> => {\n const events: EventDocEvent[] = [];\n let nextPageKey: string | undefined = undefined;\n\n do {\n const query: string = nextPageKey ? `?nextPageKey=${encodeURIComponent(nextPageKey)}` : '';\n const page: QpqPagedData<EventDocEvent> = await apiRequestGet<QpqPagedData<EventDocEvent>>(\n `${collectionPath}/${docId}/events${query}`,\n apiBaseUrl,\n accessToken,\n );\n\n events.push(...page.items);\n nextPageKey = page.nextPageKey;\n } while (nextPageKey);\n\n return events;\n};\n\nexport const appendMaintenanceEvent = async (\n docId: string,\n type: string,\n data: unknown,\n apiBaseUrl: string,\n accessToken?: string,\n): Promise<EventDocEvent> => {\n const input: EventDocEventInput = {\n type,\n payload: {\n data,\n metadata: {\n version: MAINTENANCE_SCHEMA_VERSION,\n clientMessageId: generateUuid(),\n },\n },\n };\n\n return apiRequestPost<EventDocEvent>(`${collectionPath}/${docId}/events`, input, apiBaseUrl, accessToken);\n};\n"]}
@@ -1,9 +1,9 @@
1
- import { getProcessCustomImplementation } from 'quidproquo-core';
1
+ import { generateUuid, getProcessCustomImplementation } from 'quidproquo-core';
2
2
  import { AdminSessionActionType } from './AdminSessionActionType';
3
3
  import { askApplySessionEventToLog } from './askApplySessionEventToLog';
4
4
  // Runs the ApplyEvent story in a sub-runtime that inherits the live processors,
5
5
  // so it can dispatch into the admin runtime's state like any story.
6
6
  export const getApplySessionEventActionProcessor = () => async (qpqConfig) => ({
7
- [AdminSessionActionType.applyEvent]: getProcessCustomImplementation(qpqConfig, askApplySessionEventToLog, 'Apply Admin Session Event', null, () => new Date().toISOString(), () => globalThis.crypto.randomUUID()),
7
+ [AdminSessionActionType.applyEvent]: getProcessCustomImplementation(qpqConfig, askApplySessionEventToLog, 'Apply Admin Session Event', null, () => new Date().toISOString(), () => generateUuid()),
8
8
  });
9
9
  //# sourceMappingURL=getApplySessionEventActionProcessor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"getApplySessionEventActionProcessor.js","sourceRoot":"","sources":["../../../../src/adminApp/actions/getApplySessionEventActionProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAgB,MAAM,iBAAiB,CAAC;AAI/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAExE,gFAAgF;AAChF,oEAAoE;AACpE,MAAM,CAAC,MAAM,mCAAmC,GAAsD,GAAG,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;IAChI,CAAC,sBAAsB,CAAC,UAAU,CAAC,EAAE,8BAA8B,CACjE,SAAS,EACT,yBAAyB,EACzB,2BAA2B,EAC3B,IAAI,EACJ,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAC9B,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE,CACrC;CACF,CAAC,CAAC","sourcesContent":["import { getProcessCustomImplementation, ProcessorFor } from 'quidproquo-core';\nimport { ActionProcessorListResolverFactory } from 'quidproquo-web-react';\n\nimport { AdminAppState } from '../AdminAppState';\nimport { AdminSessionActionType } from './AdminSessionActionType';\nimport { askApplySessionEventBase } from './askApplySessionEvent';\nimport { askApplySessionEventToLog } from './askApplySessionEventToLog';\n\n// Runs the ApplyEvent story in a sub-runtime that inherits the live processors,\n// so it can dispatch into the admin runtime's state like any story.\nexport const getApplySessionEventActionProcessor: ActionProcessorListResolverFactory<AdminAppState> = () => async (qpqConfig) => ({\n [AdminSessionActionType.applyEvent]: getProcessCustomImplementation<ProcessorFor<typeof askApplySessionEventBase>>(\n qpqConfig,\n askApplySessionEventToLog,\n 'Apply Admin Session Event',\n null,\n () => new Date().toISOString(),\n () => globalThis.crypto.randomUUID(),\n ),\n});\n"]}
1
+ {"version":3,"file":"getApplySessionEventActionProcessor.js","sourceRoot":"","sources":["../../../../src/adminApp/actions/getApplySessionEventActionProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,8BAA8B,EAAgB,MAAM,iBAAiB,CAAC;AAI7F,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAExE,gFAAgF;AAChF,oEAAoE;AACpE,MAAM,CAAC,MAAM,mCAAmC,GAAsD,GAAG,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;IAChI,CAAC,sBAAsB,CAAC,UAAU,CAAC,EAAE,8BAA8B,CACjE,SAAS,EACT,yBAAyB,EACzB,2BAA2B,EAC3B,IAAI,EACJ,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAC9B,GAAG,EAAE,CAAC,YAAY,EAAE,CACrB;CACF,CAAC,CAAC","sourcesContent":["import { generateUuid, getProcessCustomImplementation, ProcessorFor } from 'quidproquo-core';\nimport { ActionProcessorListResolverFactory } from 'quidproquo-web-react';\n\nimport { AdminAppState } from '../AdminAppState';\nimport { AdminSessionActionType } from './AdminSessionActionType';\nimport { askApplySessionEventBase } from './askApplySessionEvent';\nimport { askApplySessionEventToLog } from './askApplySessionEventToLog';\n\n// Runs the ApplyEvent story in a sub-runtime that inherits the live processors,\n// so it can dispatch into the admin runtime's state like any story.\nexport const getApplySessionEventActionProcessor: ActionProcessorListResolverFactory<AdminAppState> = () => async (qpqConfig) => ({\n [AdminSessionActionType.applyEvent]: getProcessCustomImplementation<ProcessorFor<typeof askApplySessionEventBase>>(\n qpqConfig,\n askApplySessionEventToLog,\n 'Apply Admin Session Event',\n null,\n () => new Date().toISOString(),\n () => generateUuid(),\n ),\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quidproquo-web-admin",
3
- "version": "0.1.27",
3
+ "version": "0.1.29",
4
4
  "description": "",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -47,12 +47,12 @@
47
47
  "date-fns": "^2.30.0",
48
48
  "dayjs": "^1.11.7",
49
49
  "javascript-time-ago": "^2.5.9",
50
- "quidproquo-core": "0.1.27",
51
- "quidproquo-features": "0.1.27",
52
- "quidproquo-tsconfig": "0.1.27",
53
- "quidproquo-web": "0.1.27",
54
- "quidproquo-web-react": "0.1.27",
55
- "quidproquo-webserver": "0.1.27",
50
+ "quidproquo-core": "0.1.29",
51
+ "quidproquo-features": "0.1.29",
52
+ "quidproquo-tsconfig": "0.1.29",
53
+ "quidproquo-web": "0.1.29",
54
+ "quidproquo-web-react": "0.1.29",
55
+ "quidproquo-webserver": "0.1.29",
56
56
  "react": ">=18.3.1",
57
57
  "react-d3-tree": "^3.6.6",
58
58
  "react-dom": "18.3.1",