@burdenoff/microfe-planmagnet 2026.1001.2 → 2026.1001.3

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.
Files changed (62) hide show
  1. package/dist/planmagnet/PlanMagnetRoot.d.ts.map +1 -1
  2. package/dist/planmagnet/PlanMagnetRoot.js +160 -153
  3. package/dist/planmagnet/PlanMagnetRoot.js.map +1 -1
  4. package/dist/planmagnet/PlanMagnetRoutes.d.ts.map +1 -1
  5. package/dist/planmagnet/PlanMagnetRoutes.js +121 -109
  6. package/dist/planmagnet/PlanMagnetRoutes.js.map +1 -1
  7. package/dist/planmagnet/controls/MilestoneControls.d.ts +2 -0
  8. package/dist/planmagnet/controls/MilestoneControls.d.ts.map +1 -1
  9. package/dist/planmagnet/controls/MilestoneControls.js +89 -72
  10. package/dist/planmagnet/controls/MilestoneControls.js.map +1 -1
  11. package/dist/planmagnet/meetings/MeetingActionItemsPanel.d.ts +17 -0
  12. package/dist/planmagnet/meetings/MeetingActionItemsPanel.d.ts.map +1 -0
  13. package/dist/planmagnet/meetings/MeetingActionItemsPanel.js +218 -0
  14. package/dist/planmagnet/meetings/MeetingActionItemsPanel.js.map +1 -0
  15. package/dist/planmagnet/meetings/MeetingsCard.d.ts +7 -0
  16. package/dist/planmagnet/meetings/MeetingsCard.d.ts.map +1 -0
  17. package/dist/planmagnet/meetings/MeetingsCard.js +108 -0
  18. package/dist/planmagnet/meetings/MeetingsCard.js.map +1 -0
  19. package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.d.ts +9 -0
  20. package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.d.ts.map +1 -0
  21. package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.js +232 -0
  22. package/dist/planmagnet/meetings/ScheduleCeremoniesDialog.js.map +1 -0
  23. package/dist/planmagnet/meetings/ScheduleMeetingDialog.d.ts +19 -0
  24. package/dist/planmagnet/meetings/ScheduleMeetingDialog.d.ts.map +1 -0
  25. package/dist/planmagnet/meetings/ScheduleMeetingDialog.js +226 -0
  26. package/dist/planmagnet/meetings/ScheduleMeetingDialog.js.map +1 -0
  27. package/dist/planmagnet/meetings/UnlinkMeetingDialog.d.ts +14 -0
  28. package/dist/planmagnet/meetings/UnlinkMeetingDialog.d.ts.map +1 -0
  29. package/dist/planmagnet/meetings/UnlinkMeetingDialog.js +81 -0
  30. package/dist/planmagnet/meetings/UnlinkMeetingDialog.js.map +1 -0
  31. package/dist/planmagnet/meetings/meetingActions.d.ts +57 -0
  32. package/dist/planmagnet/meetings/meetingActions.d.ts.map +1 -0
  33. package/dist/planmagnet/meetings/meetingActions.js +51 -0
  34. package/dist/planmagnet/meetings/meetingActions.js.map +1 -0
  35. package/dist/planmagnet/meetings/meetingGraphql.d.ts +29 -0
  36. package/dist/planmagnet/meetings/meetingGraphql.d.ts.map +1 -0
  37. package/dist/planmagnet/meetings/meetingGraphql.js +166 -0
  38. package/dist/planmagnet/meetings/meetingGraphql.js.map +1 -0
  39. package/dist/planmagnet/meetings/meetingModel.d.ts +74 -0
  40. package/dist/planmagnet/meetings/meetingModel.d.ts.map +1 -0
  41. package/dist/planmagnet/meetings/meetingModel.js +88 -0
  42. package/dist/planmagnet/meetings/meetingModel.js.map +1 -0
  43. package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.d.ts +2 -0
  44. package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.d.ts.map +1 -0
  45. package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.js +197 -0
  46. package/dist/planmagnet/pages/MeetingsMeetingDetailPagePage.js.map +1 -0
  47. package/dist/planmagnet/pages/MeetingsMeetingsPagePage.d.ts +2 -0
  48. package/dist/planmagnet/pages/MeetingsMeetingsPagePage.d.ts.map +1 -0
  49. package/dist/planmagnet/pages/MeetingsMeetingsPagePage.js +173 -0
  50. package/dist/planmagnet/pages/MeetingsMeetingsPagePage.js.map +1 -0
  51. package/dist/planmagnet/pages/ProjectsMilestonesPagePage.d.ts.map +1 -1
  52. package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js +73 -52
  53. package/dist/planmagnet/pages/ProjectsMilestonesPagePage.js.map +1 -1
  54. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.d.ts.map +1 -1
  55. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js +205 -190
  56. package/dist/planmagnet/pages/ProjectsPlanningDetailPagePage.js.map +1 -1
  57. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.d.ts.map +1 -1
  58. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js +192 -187
  59. package/dist/planmagnet/pages/ProjectsProjectDetailPagePage.js.map +1 -1
  60. package/dist/planmagnet/reports/ShareDialog.js +65 -65
  61. package/dist/planmagnet/reports/ShareDialog.js.map +1 -1
  62. package/package.json +1 -1
@@ -0,0 +1,81 @@
1
+ import { mutationErrorMessage as e } from "../utils/graphqlErrors.js";
2
+ import { LEAVES_PAGE_CONTEXT as t, throwOnError as n } from "../utils/mutationResult.js";
3
+ import { ErrorLine as r } from "../controls/ConfirmButton.js";
4
+ import { DELETE_CALENDAR_EVENT as i, MEETING_QUERIES as a, UNLINK_PLANMAGNET_MEETING as o } from "./meetingGraphql.js";
5
+ import { useState as s } from "react";
6
+ import { Unlink as c } from "lucide-react";
7
+ import { useApolloClient as l, useMutation as u } from "@apollo/client/react";
8
+ import { jsx as d, jsxs as f } from "react/jsx-runtime";
9
+ import { Button as p, Checkbox as m, ResponsiveDialog as h, ResponsiveDialogContent as g, ResponsiveDialogDescription as _, ResponsiveDialogFooter as v, ResponsiveDialogHeader as y, ResponsiveDialogTitle as b, ResponsiveDialogTrigger as x } from "@burdenoff/fe-libs/ui";
10
+ import { clearGraphqlFetchResponseCache as S } from "@burdenoff/fe-libs/shared/graphql";
11
+ //#region src/planmagnet/meetings/UnlinkMeetingDialog.tsx
12
+ function C({ meetingId: C, calendarEventId: w, meetingTitle: T, onUnlinked: E }) {
13
+ let [D, O] = s(!1), [k, A] = s(!1), [j, M] = s(null), N = l(), [P, F] = u(o, {
14
+ refetchQueries: a.filter((e) => e !== "GetPlanmagnetMeeting"),
15
+ context: t
16
+ }), [I, L] = u(i, { context: t }), R = F.loading || L.loading, z = async () => {
17
+ M(null);
18
+ try {
19
+ await n(P({ variables: { id: C } }));
20
+ } catch (t) {
21
+ M(e(t, "The meeting could not be unlinked."));
22
+ return;
23
+ }
24
+ if (k) try {
25
+ await n(I({ variables: {
26
+ id: w,
27
+ scope: "ALL_EVENTS"
28
+ } }));
29
+ } catch (t) {
30
+ S(), N.refetchQueries({ include: ["GetPlanmagnetMeeting"] }), M("This meeting was unlinked, but the calendar event could not be deleted: " + e(t, "unknown reason"));
31
+ return;
32
+ }
33
+ O(!1), E();
34
+ };
35
+ return /* @__PURE__ */ f(h, {
36
+ open: D,
37
+ onOpenChange: (e) => {
38
+ O(e), e || (A(!1), M(null));
39
+ },
40
+ children: [/* @__PURE__ */ d(x, {
41
+ asChild: !0,
42
+ children: /* @__PURE__ */ f(p, {
43
+ size: "sm",
44
+ variant: "outline",
45
+ "data-testid": "unlink-meeting-trigger",
46
+ children: [/* @__PURE__ */ d(c, { className: "mr-1 h-4 w-4" }), "Unlink"]
47
+ })
48
+ }), /* @__PURE__ */ f(g, { children: [
49
+ /* @__PURE__ */ f(y, { children: [/* @__PURE__ */ f(b, { children: [
50
+ "Unlink \"",
51
+ T,
52
+ "\"?"
53
+ ] }), /* @__PURE__ */ d(_, { children: "PlanMagnet stops tracking this meeting — its agenda, notes and action-item links are gone. The calendar event itself stays, unless you also delete it below." })] }),
54
+ /* @__PURE__ */ f("label", {
55
+ className: "flex cursor-pointer items-start gap-2 text-sm",
56
+ children: [/* @__PURE__ */ d(m, {
57
+ checked: k,
58
+ onCheckedChange: (e) => A(e === !0),
59
+ "data-testid": "unlink-meeting-also-delete-event"
60
+ }), /* @__PURE__ */ d("span", { children: "Also delete the calendar event (cannot be undone here)." })]
61
+ }),
62
+ j && /* @__PURE__ */ d(r, { message: j }),
63
+ /* @__PURE__ */ f(v, { children: [/* @__PURE__ */ d(p, {
64
+ variant: "outline",
65
+ onClick: () => O(!1),
66
+ disabled: R,
67
+ children: "Keep it"
68
+ }), /* @__PURE__ */ d(p, {
69
+ onClick: () => void z(),
70
+ disabled: R,
71
+ className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
72
+ "data-testid": "unlink-meeting-confirm",
73
+ children: R ? "Unlinking…" : "Unlink meeting"
74
+ })] })
75
+ ] })]
76
+ });
77
+ }
78
+ //#endregion
79
+ export { C as UnlinkMeetingDialog };
80
+
81
+ //# sourceMappingURL=UnlinkMeetingDialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UnlinkMeetingDialog.js","names":[],"sources":["../../../src/planmagnet/meetings/UnlinkMeetingDialog.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useApolloClient, useMutation } from '@apollo/client/react';\nimport { clearGraphqlFetchResponseCache } from '@burdenoff/fe-libs/shared/graphql';\nimport {\n Button,\n Checkbox,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { Unlink } from 'lucide-react';\nimport { ErrorLine } from '../controls/ConfirmButton';\nimport { throwOnError, LEAVES_PAGE_CONTEXT } from '../utils/mutationResult';\nimport { mutationErrorMessage } from '../utils/graphqlErrors';\nimport {\n UNLINK_PLANMAGNET_MEETING,\n DELETE_CALENDAR_EVENT,\n MEETING_QUERIES,\n} from './meetingGraphql';\n\n/**\n * Unlinking a meeting removes PlanMagnet's own record of it (agenda/notes/action-item links) but — by\n * default — leaves the calendar event itself alone, since the event may still matter to its attendees even\n * once PlanMagnet stops tracking it. The opt-in checkbox deletes that event too, AS THE USER (same\n * `deleteEvent` the create-link compensation path uses), so an \"also delete\" refusal is shown exactly like any\n * other mutation refusal rather than silently leaving the event behind.\n */\nexport function UnlinkMeetingDialog({\n meetingId,\n calendarEventId,\n meetingTitle,\n onUnlinked,\n}: {\n meetingId: string;\n calendarEventId: string;\n meetingTitle: string;\n onUnlinked: () => void;\n}) {\n const [open, setOpen] = useState(false);\n const [alsoDeleteEvent, setAlsoDeleteEvent] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const client = useApolloClient();\n // Excludes 'GetPlanmagnetMeeting' — this PAGE's own query, for the meeting we are about to leave. Refetching\n // it would re-run against a now-unlinked meeting (see `LEAVES_PAGE_CONTEXT`'s doc comment); the list page\n // this navigates to reads 'ListPlanmagnetMeetings' fresh on its own mount regardless. That reasoning only\n // holds on the SUCCESS path, though — when the opt-in `deleteEvent` compensation below fails, we deliberately\n // stay on this page, and `GetPlanmagnetMeeting` is force-refetched there instead (see that catch block).\n const [unlink, unlinkState] = useMutation(UNLINK_PLANMAGNET_MEETING, {\n refetchQueries: MEETING_QUERIES.filter((q) => q !== 'GetPlanmagnetMeeting'),\n context: LEAVES_PAGE_CONTEXT,\n });\n // Only ever called right after a successful unlink, on the way OUT of this page (see `confirm` below) — same\n // `LEAVES_PAGE_CONTEXT` reasoning as `unlink` above applies here too.\n const [deleteEvent, deleteState] = useMutation(DELETE_CALENDAR_EVENT, {\n context: LEAVES_PAGE_CONTEXT,\n });\n const busy = unlinkState.loading || deleteState.loading;\n\n const confirm = async () => {\n setError(null);\n try {\n await throwOnError(unlink({ variables: { id: meetingId } }));\n } catch (e) {\n setError(mutationErrorMessage(e, 'The meeting could not be unlinked.'));\n return;\n }\n if (alsoDeleteEvent) {\n try {\n await throwOnError(\n deleteEvent({ variables: { id: calendarEventId, scope: 'ALL_EVENTS' } })\n );\n } catch (e) {\n // The unlink already succeeded — say so, rather than leaving a \"nothing happened\" impression when\n // PlanMagnet in fact no longer tracks this meeting; only the calendar event itself stayed behind.\n // Force this page's own `GetPlanmagnetMeeting` to refetch now (it was deliberately excluded from\n // `unlink`'s refetchQueries above, for the success path that navigates away before a refetch would\n // matter — this path doesn't navigate away, so the page must not keep showing the fully-populated,\n // now-stale meeting). `planmagnetMeeting(id)` is nullable and resolves to null for an unlinked\n // meeting, so this refetch falls through to the page's existing \"Meeting not found\" state. The cache\n // drop must come first: fe-libs' 15 s fetch-layer response cache would otherwise replay the\n // pre-unlink read if the refetch lands inside that window (same reasoning as `useLiveRefresh.ts`).\n clearGraphqlFetchResponseCache();\n void client.refetchQueries({ include: ['GetPlanmagnetMeeting'] });\n setError(\n `This meeting was unlinked, but the calendar event could not be deleted: ` +\n mutationErrorMessage(e, 'unknown reason')\n );\n return;\n }\n }\n setOpen(false);\n onUnlinked();\n };\n\n return (\n <ResponsiveDialog\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) {\n setAlsoDeleteEvent(false);\n setError(null);\n }\n }}\n >\n <ResponsiveDialogTrigger asChild>\n <Button size=\"sm\" variant=\"outline\" data-testid=\"unlink-meeting-trigger\">\n <Unlink className=\"mr-1 h-4 w-4\" />\n Unlink\n </Button>\n </ResponsiveDialogTrigger>\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Unlink &quot;{meetingTitle}&quot;?</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n PlanMagnet stops tracking this meeting — its agenda, notes and action-item links are\n gone. The calendar event itself stays, unless you also delete it below.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <label className=\"flex cursor-pointer items-start gap-2 text-sm\">\n <Checkbox\n checked={alsoDeleteEvent}\n onCheckedChange={(checked) => setAlsoDeleteEvent(checked === true)}\n data-testid=\"unlink-meeting-also-delete-event\"\n />\n <span>Also delete the calendar event (cannot be undone here).</span>\n </label>\n {error && <ErrorLine message={error} />}\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => setOpen(false)} disabled={busy}>\n Keep it\n </Button>\n <Button\n onClick={() => void confirm()}\n disabled={busy}\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n data-testid=\"unlink-meeting-confirm\"\n >\n {busy ? 'Unlinking…' : 'Unlink meeting'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":";;;;;;;;;;;AA+BA,SAAgB,EAAoB,EAClC,cACA,oBACA,iBACA,iBAMC;CACD,IAAM,CAAC,GAAM,KAAW,EAAS,GAAM,EACjC,CAAC,GAAiB,KAAsB,EAAS,GAAM,EACvD,CAAC,GAAO,KAAY,EAAwB,KAAK,EACjD,IAAS,GAAiB,EAM1B,CAAC,GAAQ,KAAe,EAAY,GAA2B;EACnE,gBAAgB,EAAgB,QAAQ,MAAM,MAAM,uBAAuB;EAC3E,SAAS;EACV,CAAC,EAGI,CAAC,GAAa,KAAe,EAAY,GAAuB,EACpE,SAAS,GACV,CAAC,EACI,IAAO,EAAY,WAAW,EAAY,SAE1C,IAAU,YAAY;AAC1B,IAAS,KAAK;AACd,MAAI;AACF,SAAM,EAAa,EAAO,EAAE,WAAW,EAAE,IAAI,GAAW,EAAE,CAAC,CAAC;WACrD,GAAG;AACV,KAAS,EAAqB,GAAG,qCAAqC,CAAC;AACvE;;AAEF,MAAI,EACF,KAAI;AACF,SAAM,EACJ,EAAY,EAAE,WAAW;IAAE,IAAI;IAAiB,OAAO;IAAc,EAAE,CAAC,CACzE;WACM,GAAG;AAYV,GAFA,GAAgC,EAC3B,EAAO,eAAe,EAAE,SAAS,CAAC,uBAAuB,EAAE,CAAC,EACjE,EACE,6EACE,EAAqB,GAAG,iBAAiB,CAC5C;AACD;;AAIJ,EADA,EAAQ,GAAM,EACd,GAAY;;AAGd,QACE,kBAAC,GAAD;EACQ;EACN,eAAe,MAAS;AAEtB,GADA,EAAQ,EAAK,EACR,MACH,EAAmB,GAAM,EACzB,EAAS,KAAK;;YANpB,CAUE,kBAAC,GAAD;GAAyB,SAAA;aACvB,kBAAC,GAAD;IAAQ,MAAK;IAAK,SAAQ;IAAU,eAAY;cAAhD,CACE,kBAAC,GAAD,EAAQ,WAAU,gBAAiB,CAAA,EAAA,SAE5B;;GACe,CAAA,EAC1B,kBAAC,GAAD,EAAA,UAAA;GACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA;IAAuB;IAAc;IAAa;IAA+B,EAAA,CAAA,EACjF,kBAAC,GAAD,EAAA,UAA6B,gKAGC,CAAA,CACP,EAAA,CAAA;GACzB,kBAAC,SAAD;IAAO,WAAU;cAAjB,CACE,kBAAC,GAAD;KACE,SAAS;KACT,kBAAkB,MAAY,EAAmB,MAAY,GAAK;KAClE,eAAY;KACZ,CAAA,EACF,kBAAC,QAAD,EAAA,UAAM,2DAA8D,CAAA,CAC9D;;GACP,KAAS,kBAAC,GAAD,EAAW,SAAS,GAAS,CAAA;GACvC,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;IAAQ,SAAQ;IAAU,eAAe,EAAQ,GAAM;IAAE,UAAU;cAAM;IAEhE,CAAA,EACT,kBAAC,GAAD;IACE,eAAe,KAAK,GAAS;IAC7B,UAAU;IACV,WAAU;IACV,eAAY;cAEX,IAAO,eAAe;IAChB,CAAA,CACc,EAAA,CAAA;GACD,EAAA,CAAA,CACT"}
@@ -0,0 +1,57 @@
1
+ import { MeetingKind } from './meetingModel';
2
+
3
+ /** The slice of an Apollo `useMutation` tuple's first element this helper needs — typed narrowly so a caller can
4
+ * pass its real mutate function straight through without an adapter. */
5
+ type MutateFn<TData> = (options: {
6
+ variables: Record<string, unknown>;
7
+ }) => Promise<{
8
+ data?: TData;
9
+ error?: unknown;
10
+ }>;
11
+ export interface CreateAndLinkMeetingParams {
12
+ createEvent: MutateFn<{
13
+ createEvent: {
14
+ id: string;
15
+ };
16
+ }>;
17
+ linkMeeting: MutateFn<{
18
+ planmagnetLinkMeeting: {
19
+ id: string;
20
+ };
21
+ }>;
22
+ deleteEvent: MutateFn<{
23
+ deleteEvent: boolean;
24
+ }>;
25
+ workspaceId: string;
26
+ calendarId: string;
27
+ title: string;
28
+ startIso: string;
29
+ endIso: string;
30
+ kind: MeetingKind;
31
+ projectId: string;
32
+ sprintId?: string | null;
33
+ milestoneId?: string | null;
34
+ agenda?: string;
35
+ rrule?: string;
36
+ timezone: string;
37
+ }
38
+ /**
39
+ * Creates the calendar event AS THE USER, then records the PlanMagnet link — the architecture every meeting
40
+ * feature in this MFE is built on (`PlanmagnetMeeting`'s doc comment, `graphql/wspace.graphql`:
41
+ * `planmagnetLinkMeeting` "never calls the Calendar API itself; it only validates and stores the link").
42
+ *
43
+ * If the link is refused, the event just created is deleted (best-effort — `ALL_EVENTS` scope, since an
44
+ * unlinked event was never a committed series) so a failed "schedule" never leaves an orphaned calendar event
45
+ * behind. A compensation failure is swallowed deliberately: the caller must see the LINK refusal (the real
46
+ * reason scheduling failed), never a secondary "cleanup also failed" message in its place.
47
+ *
48
+ * Both call sites (`ScheduleMeetingDialog`, `ScheduleCeremoniesDialog`) await this already wrapped in
49
+ * `throwOnError` semantics — every mutation inside is itself awaited through `throwOnError`, so nothing here
50
+ * can resolve silently on a refusal.
51
+ */
52
+ export declare function createAndLinkMeeting(p: CreateAndLinkMeetingParams): Promise<{
53
+ id: string;
54
+ }>;
55
+ export declare function meetingScheduleErrorMessage(e: unknown): string;
56
+ export {};
57
+ //# sourceMappingURL=meetingActions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meetingActions.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/meetings/meetingActions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;yEACyE;AACzE,KAAK,QAAQ,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE;IAC/B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,KAAK,OAAO,CAAC;IAAE,IAAI,CAAC,EAAE,KAAK,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAEjD,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,QAAQ,CAAC;QAAE,WAAW,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;IACvD,WAAW,EAAE,QAAQ,CAAC;QAAE,qBAAqB,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;IACjE,WAAW,EAAE,QAAQ,CAAC;QAAE,WAAW,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,0BAA0B,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CAsDjG;AAED,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAE9D"}
@@ -0,0 +1,51 @@
1
+ import { mutationErrorMessage as e } from "../utils/graphqlErrors.js";
2
+ import { throwOnError as t } from "../utils/mutationResult.js";
3
+ //#region src/planmagnet/meetings/meetingActions.ts
4
+ async function n(e) {
5
+ let n = (await t(e.createEvent({ variables: { input: {
6
+ calendarId: e.calendarId,
7
+ title: e.title,
8
+ startTime: e.startIso,
9
+ endTime: e.endIso,
10
+ eventType: "MEETING",
11
+ rrule: e.rrule,
12
+ isRecurring: !!e.rrule,
13
+ timezone: e.timezone,
14
+ description: e.agenda || void 0
15
+ } } }))).data?.createEvent.id;
16
+ if (!n) throw Error("The calendar event was not created.");
17
+ try {
18
+ let r = (await t(e.linkMeeting({ variables: {
19
+ workspaceId: e.workspaceId,
20
+ input: {
21
+ calendarEventId: n,
22
+ title: e.title,
23
+ kind: e.kind,
24
+ projectId: e.projectId,
25
+ sprintId: e.sprintId || void 0,
26
+ milestoneId: e.milestoneId || void 0,
27
+ startsAt: e.startIso,
28
+ endsAt: e.endIso,
29
+ agenda: e.agenda || void 0,
30
+ recurrenceRule: e.rrule
31
+ }
32
+ } }))).data?.planmagnetLinkMeeting;
33
+ if (!r) throw Error("The meeting could not be linked.");
34
+ return r;
35
+ } catch (r) {
36
+ try {
37
+ await t(e.deleteEvent({ variables: {
38
+ id: n,
39
+ scope: "ALL_EVENTS"
40
+ } }));
41
+ } catch {}
42
+ throw r;
43
+ }
44
+ }
45
+ function r(t) {
46
+ return e(t, "The meeting could not be scheduled.");
47
+ }
48
+ //#endregion
49
+ export { n as createAndLinkMeeting, r as meetingScheduleErrorMessage };
50
+
51
+ //# sourceMappingURL=meetingActions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meetingActions.js","names":[],"sources":["../../../src/planmagnet/meetings/meetingActions.ts"],"sourcesContent":["import { throwOnError } from '../utils/mutationResult';\nimport { mutationErrorMessage } from '../utils/graphqlErrors';\nimport type { MeetingKind } from './meetingModel';\n\n/** The slice of an Apollo `useMutation` tuple's first element this helper needs — typed narrowly so a caller can\n * pass its real mutate function straight through without an adapter. */\ntype MutateFn<TData> = (options: {\n variables: Record<string, unknown>;\n}) => Promise<{ data?: TData; error?: unknown }>;\n\nexport interface CreateAndLinkMeetingParams {\n createEvent: MutateFn<{ createEvent: { id: string } }>;\n linkMeeting: MutateFn<{ planmagnetLinkMeeting: { id: string } }>;\n deleteEvent: MutateFn<{ deleteEvent: boolean }>;\n workspaceId: string;\n calendarId: string;\n title: string;\n startIso: string;\n endIso: string;\n kind: MeetingKind;\n projectId: string;\n sprintId?: string | null;\n milestoneId?: string | null;\n agenda?: string;\n rrule?: string;\n timezone: string;\n}\n\n/**\n * Creates the calendar event AS THE USER, then records the PlanMagnet link — the architecture every meeting\n * feature in this MFE is built on (`PlanmagnetMeeting`'s doc comment, `graphql/wspace.graphql`:\n * `planmagnetLinkMeeting` \"never calls the Calendar API itself; it only validates and stores the link\").\n *\n * If the link is refused, the event just created is deleted (best-effort — `ALL_EVENTS` scope, since an\n * unlinked event was never a committed series) so a failed \"schedule\" never leaves an orphaned calendar event\n * behind. A compensation failure is swallowed deliberately: the caller must see the LINK refusal (the real\n * reason scheduling failed), never a secondary \"cleanup also failed\" message in its place.\n *\n * Both call sites (`ScheduleMeetingDialog`, `ScheduleCeremoniesDialog`) await this already wrapped in\n * `throwOnError` semantics — every mutation inside is itself awaited through `throwOnError`, so nothing here\n * can resolve silently on a refusal.\n */\nexport async function createAndLinkMeeting(p: CreateAndLinkMeetingParams): Promise<{ id: string }> {\n const eventResult = await throwOnError(\n p.createEvent({\n variables: {\n input: {\n calendarId: p.calendarId,\n title: p.title,\n startTime: p.startIso,\n endTime: p.endIso,\n eventType: 'MEETING',\n rrule: p.rrule,\n isRecurring: Boolean(p.rrule),\n timezone: p.timezone,\n description: p.agenda || undefined,\n },\n },\n })\n );\n const calendarEventId = eventResult.data?.createEvent.id;\n if (!calendarEventId) throw new Error('The calendar event was not created.');\n\n try {\n const linkResult = await throwOnError(\n p.linkMeeting({\n variables: {\n workspaceId: p.workspaceId,\n input: {\n calendarEventId,\n title: p.title,\n kind: p.kind,\n projectId: p.projectId,\n sprintId: p.sprintId || undefined,\n milestoneId: p.milestoneId || undefined,\n startsAt: p.startIso,\n endsAt: p.endIso,\n agenda: p.agenda || undefined,\n recurrenceRule: p.rrule,\n },\n },\n })\n );\n const meeting = linkResult.data?.planmagnetLinkMeeting;\n if (!meeting) throw new Error('The meeting could not be linked.');\n return meeting;\n } catch (linkError) {\n try {\n await throwOnError(\n p.deleteEvent({ variables: { id: calendarEventId, scope: 'ALL_EVENTS' } })\n );\n } catch {\n // Best-effort compensation only — see doc comment above.\n }\n throw linkError;\n }\n}\n\nexport function meetingScheduleErrorMessage(e: unknown): string {\n return mutationErrorMessage(e, 'The meeting could not be scheduled.');\n}\n"],"mappings":";;;AA0CA,eAAsB,EAAqB,GAAwD;CAkBjG,IAAM,KAjBc,MAAM,EACxB,EAAE,YAAY,EACZ,WAAW,EACT,OAAO;EACL,YAAY,EAAE;EACd,OAAO,EAAE;EACT,WAAW,EAAE;EACb,SAAS,EAAE;EACX,WAAW;EACX,OAAO,EAAE;EACT,aAAa,EAAQ,EAAE;EACvB,UAAU,EAAE;EACZ,aAAa,EAAE,UAAU,KAAA;EAC1B,EACF,EACF,CAAC,CACH,EACmC,MAAM,YAAY;AACtD,KAAI,CAAC,EAAiB,OAAU,MAAM,sCAAsC;AAE5E,KAAI;EAoBF,IAAM,KAnBa,MAAM,EACvB,EAAE,YAAY,EACZ,WAAW;GACT,aAAa,EAAE;GACf,OAAO;IACL;IACA,OAAO,EAAE;IACT,MAAM,EAAE;IACR,WAAW,EAAE;IACb,UAAU,EAAE,YAAY,KAAA;IACxB,aAAa,EAAE,eAAe,KAAA;IAC9B,UAAU,EAAE;IACZ,QAAQ,EAAE;IACV,QAAQ,EAAE,UAAU,KAAA;IACpB,gBAAgB,EAAE;IACnB;GACF,EACF,CAAC,CACH,EAC0B,MAAM;AACjC,MAAI,CAAC,EAAS,OAAU,MAAM,mCAAmC;AACjE,SAAO;UACA,GAAW;AAClB,MAAI;AACF,SAAM,EACJ,EAAE,YAAY,EAAE,WAAW;IAAE,IAAI;IAAiB,OAAO;IAAc,EAAE,CAAC,CAC3E;UACK;AAGR,QAAM;;;AAIV,SAAgB,EAA4B,GAAoB;AAC9D,QAAO,EAAqB,GAAG,sCAAsC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * GraphQL documents for PlanMagnet meetings (GAP-06, CWF-22/23), from two different subgraphs:
3
+ *
4
+ * - The platform **Calendar** module (`calendars`, `createEvent`, `deleteEvent`) — a meeting's real schedule
5
+ * lives here. The UI creates the calendar event AS THE USER, then links it below.
6
+ * - **PlanMagnet** itself (`planmagnetMeeting(s)`, `planmagnetLinkMeeting`, `planmagnetUpdateMeeting`,
7
+ * `planmagnetUnlinkMeeting`, the action-item mutations) — PlanMagnet-owned content (agenda/notes/kind) plus a
8
+ * read-only snapshot of the schedule for listing/sorting. See `PlanmagnetMeeting`'s doc comment in
9
+ * `graphql/wspace.graphql` for the full split, and `meetingActions.ts` for how the two are composed.
10
+ *
11
+ * Selection sets are written out in full rather than shared via fragment interpolation, same convention as
12
+ * `reports/reportGraphql.ts` (one literal per `gql` call; validated by `bun run validate:schema` against
13
+ * `graphql/wspace.graphql`).
14
+ */
15
+ export declare const SCHEDULE_MEETING_CALENDARS: import('graphql').DocumentNode;
16
+ export declare const CREATE_CALENDAR_EVENT: import('graphql').DocumentNode;
17
+ export declare const DELETE_CALENDAR_EVENT: import('graphql').DocumentNode;
18
+ /** Every query a meeting write should refresh. */
19
+ export declare const MEETING_QUERIES: string[];
20
+ export declare const LIST_PLANMAGNET_MEETINGS: import('graphql').DocumentNode;
21
+ export declare const GET_PLANMAGNET_MEETING: import('graphql').DocumentNode;
22
+ export declare const LINK_PLANMAGNET_MEETING: import('graphql').DocumentNode;
23
+ export declare const UPDATE_PLANMAGNET_MEETING: import('graphql').DocumentNode;
24
+ export declare const UNLINK_PLANMAGNET_MEETING: import('graphql').DocumentNode;
25
+ export declare const ADD_MEETING_ACTION_ITEM: import('graphql').DocumentNode;
26
+ export declare const REMOVE_MEETING_ACTION_ITEM: import('graphql').DocumentNode;
27
+ /** Minimal create, for "Add action item" (a brand-new work item attached to the meeting it was raised in). */
28
+ export declare const CREATE_MEETING_ACTION_WORK_ITEM: import('graphql').DocumentNode;
29
+ //# sourceMappingURL=meetingGraphql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meetingGraphql.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/meetings/meetingGraphql.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AAIH,eAAO,MAAM,0BAA0B,gCAatC,CAAC;AAEF,eAAO,MAAM,qBAAqB,gCAQjC,CAAC;AAEF,eAAO,MAAM,qBAAqB,gCAIjC,CAAC;AAIF,kDAAkD;AAClD,eAAO,MAAM,eAAe,UAAqD,CAAC;AAElF,eAAO,MAAM,wBAAwB,gCAiCpC,CAAC;AAEF,eAAO,MAAM,sBAAsB,gCA2ClC,CAAC;AAEF,eAAO,MAAM,uBAAuB,gCAenC,CAAC;AAEF,eAAO,MAAM,yBAAyB,gCAarC,CAAC;AAEF,eAAO,MAAM,yBAAyB,gCAIrC,CAAC;AAEF,eAAO,MAAM,uBAAuB,gCAanC,CAAC;AAEF,eAAO,MAAM,0BAA0B,gCAItC,CAAC;AAEF,8GAA8G;AAC9G,eAAO,MAAM,+BAA+B,gCAS3C,CAAC"}
@@ -0,0 +1,166 @@
1
+ import { gql as e } from "@apollo/client";
2
+ //#region src/planmagnet/meetings/meetingGraphql.ts
3
+ var t = e`
4
+ query ScheduleMeetingCalendars($pagination: CalendarPaginationInput) {
5
+ calendars(pagination: $pagination) {
6
+ calendars {
7
+ id
8
+ name
9
+ isDefault
10
+ calendarType
11
+ }
12
+ hasMore
13
+ total
14
+ }
15
+ }
16
+ `, n = e`
17
+ mutation ScheduleMeetingCreateEvent($input: CreateEventInput!) {
18
+ createEvent(input: $input) {
19
+ id
20
+ startTime
21
+ endTime
22
+ }
23
+ }
24
+ `, r = e`
25
+ mutation ScheduleMeetingDeleteEvent($id: ID!, $scope: UpdateScope) {
26
+ deleteEvent(id: $id, scope: $scope)
27
+ }
28
+ `, i = ["ListPlanmagnetMeetings", "GetPlanmagnetMeeting"], a = e`
29
+ query ListPlanmagnetMeetings(
30
+ $workspaceId: ID!
31
+ $filter: PlanmagnetMeetingFilter
32
+ $pagination: PlanmagnetPaginationInput
33
+ ) {
34
+ planmagnetMeetings(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {
35
+ items {
36
+ id
37
+ title
38
+ kind
39
+ startsAt
40
+ endsAt
41
+ calendarEventId
42
+ recurrenceRule
43
+ projectId
44
+ project {
45
+ id
46
+ name
47
+ }
48
+ sprintId
49
+ milestoneId
50
+ actionItems {
51
+ id
52
+ }
53
+ }
54
+ totalCount
55
+ pageInfo {
56
+ hasNextPage
57
+ endCursor
58
+ }
59
+ }
60
+ }
61
+ `, o = e`
62
+ query GetPlanmagnetMeeting($id: ID!) {
63
+ planmagnetMeeting(id: $id) {
64
+ id
65
+ title
66
+ kind
67
+ agenda
68
+ notes
69
+ startsAt
70
+ endsAt
71
+ calendarEventId
72
+ recurrenceRule
73
+ projectId
74
+ project {
75
+ id
76
+ name
77
+ }
78
+ sprintId
79
+ sprint {
80
+ id
81
+ name
82
+ }
83
+ milestoneId
84
+ milestone {
85
+ id
86
+ name
87
+ }
88
+ createdBy
89
+ createdAt
90
+ updatedBy
91
+ updatedAt
92
+ actionItems {
93
+ id
94
+ workItemId
95
+ workItem {
96
+ id
97
+ key
98
+ title
99
+ status
100
+ }
101
+ }
102
+ }
103
+ }
104
+ `, s = e`
105
+ mutation ScheduleMeetingLink($workspaceId: ID!, $input: PlanmagnetLinkMeetingInput!) {
106
+ planmagnetLinkMeeting(workspaceId: $workspaceId, input: $input) {
107
+ id
108
+ title
109
+ kind
110
+ startsAt
111
+ endsAt
112
+ calendarEventId
113
+ recurrenceRule
114
+ projectId
115
+ sprintId
116
+ milestoneId
117
+ }
118
+ }
119
+ `, c = e`
120
+ mutation MeetingDetailUpdate($id: ID!, $input: PlanmagnetUpdateMeetingInput!) {
121
+ planmagnetUpdateMeeting(id: $id, input: $input) {
122
+ id
123
+ title
124
+ kind
125
+ agenda
126
+ notes
127
+ startsAt
128
+ endsAt
129
+ recurrenceRule
130
+ }
131
+ }
132
+ `, l = e`
133
+ mutation MeetingDetailUnlink($id: ID!) {
134
+ planmagnetUnlinkMeeting(id: $id)
135
+ }
136
+ `, u = e`
137
+ mutation MeetingAddActionItem($meetingId: ID!, $workItemId: ID!) {
138
+ planmagnetAddMeetingActionItem(meetingId: $meetingId, workItemId: $workItemId) {
139
+ id
140
+ workItemId
141
+ workItem {
142
+ id
143
+ key
144
+ title
145
+ status
146
+ }
147
+ }
148
+ }
149
+ `, d = e`
150
+ mutation MeetingRemoveActionItem($meetingId: ID!, $workItemId: ID!) {
151
+ planmagnetRemoveMeetingActionItem(meetingId: $meetingId, workItemId: $workItemId)
152
+ }
153
+ `, f = e`
154
+ mutation MeetingCreateActionWorkItem($input: PlanmagnetCreateWorkItemInput!) {
155
+ planmagnetCreateWorkItem(input: $input) {
156
+ id
157
+ key
158
+ title
159
+ status
160
+ }
161
+ }
162
+ `;
163
+ //#endregion
164
+ export { u as ADD_MEETING_ACTION_ITEM, n as CREATE_CALENDAR_EVENT, f as CREATE_MEETING_ACTION_WORK_ITEM, r as DELETE_CALENDAR_EVENT, o as GET_PLANMAGNET_MEETING, s as LINK_PLANMAGNET_MEETING, a as LIST_PLANMAGNET_MEETINGS, i as MEETING_QUERIES, d as REMOVE_MEETING_ACTION_ITEM, t as SCHEDULE_MEETING_CALENDARS, l as UNLINK_PLANMAGNET_MEETING, c as UPDATE_PLANMAGNET_MEETING };
165
+
166
+ //# sourceMappingURL=meetingGraphql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meetingGraphql.js","names":[],"sources":["../../../src/planmagnet/meetings/meetingGraphql.ts"],"sourcesContent":["import { gql } from '@apollo/client';\n\n/**\n * GraphQL documents for PlanMagnet meetings (GAP-06, CWF-22/23), from two different subgraphs:\n *\n * - The platform **Calendar** module (`calendars`, `createEvent`, `deleteEvent`) — a meeting's real schedule\n * lives here. The UI creates the calendar event AS THE USER, then links it below.\n * - **PlanMagnet** itself (`planmagnetMeeting(s)`, `planmagnetLinkMeeting`, `planmagnetUpdateMeeting`,\n * `planmagnetUnlinkMeeting`, the action-item mutations) — PlanMagnet-owned content (agenda/notes/kind) plus a\n * read-only snapshot of the schedule for listing/sorting. See `PlanmagnetMeeting`'s doc comment in\n * `graphql/wspace.graphql` for the full split, and `meetingActions.ts` for how the two are composed.\n *\n * Selection sets are written out in full rather than shared via fragment interpolation, same convention as\n * `reports/reportGraphql.ts` (one literal per `gql` call; validated by `bun run validate:schema` against\n * `graphql/wspace.graphql`).\n */\n\n// ─── Platform Calendar ──────────────────────────────────────────────────────────────────────────────────────\n\nexport const SCHEDULE_MEETING_CALENDARS = gql`\n query ScheduleMeetingCalendars($pagination: CalendarPaginationInput) {\n calendars(pagination: $pagination) {\n calendars {\n id\n name\n isDefault\n calendarType\n }\n hasMore\n total\n }\n }\n`;\n\nexport const CREATE_CALENDAR_EVENT = gql`\n mutation ScheduleMeetingCreateEvent($input: CreateEventInput!) {\n createEvent(input: $input) {\n id\n startTime\n endTime\n }\n }\n`;\n\nexport const DELETE_CALENDAR_EVENT = gql`\n mutation ScheduleMeetingDeleteEvent($id: ID!, $scope: UpdateScope) {\n deleteEvent(id: $id, scope: $scope)\n }\n`;\n\n// ─── PlanMagnet meetings ────────────────────────────────────────────────────────────────────────────────────\n\n/** Every query a meeting write should refresh. */\nexport const MEETING_QUERIES = ['ListPlanmagnetMeetings', 'GetPlanmagnetMeeting'];\n\nexport const LIST_PLANMAGNET_MEETINGS = gql`\n query ListPlanmagnetMeetings(\n $workspaceId: ID!\n $filter: PlanmagnetMeetingFilter\n $pagination: PlanmagnetPaginationInput\n ) {\n planmagnetMeetings(workspaceId: $workspaceId, filter: $filter, pagination: $pagination) {\n items {\n id\n title\n kind\n startsAt\n endsAt\n calendarEventId\n recurrenceRule\n projectId\n project {\n id\n name\n }\n sprintId\n milestoneId\n actionItems {\n id\n }\n }\n totalCount\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n`;\n\nexport const GET_PLANMAGNET_MEETING = gql`\n query GetPlanmagnetMeeting($id: ID!) {\n planmagnetMeeting(id: $id) {\n id\n title\n kind\n agenda\n notes\n startsAt\n endsAt\n calendarEventId\n recurrenceRule\n projectId\n project {\n id\n name\n }\n sprintId\n sprint {\n id\n name\n }\n milestoneId\n milestone {\n id\n name\n }\n createdBy\n createdAt\n updatedBy\n updatedAt\n actionItems {\n id\n workItemId\n workItem {\n id\n key\n title\n status\n }\n }\n }\n }\n`;\n\nexport const LINK_PLANMAGNET_MEETING = gql`\n mutation ScheduleMeetingLink($workspaceId: ID!, $input: PlanmagnetLinkMeetingInput!) {\n planmagnetLinkMeeting(workspaceId: $workspaceId, input: $input) {\n id\n title\n kind\n startsAt\n endsAt\n calendarEventId\n recurrenceRule\n projectId\n sprintId\n milestoneId\n }\n }\n`;\n\nexport const UPDATE_PLANMAGNET_MEETING = gql`\n mutation MeetingDetailUpdate($id: ID!, $input: PlanmagnetUpdateMeetingInput!) {\n planmagnetUpdateMeeting(id: $id, input: $input) {\n id\n title\n kind\n agenda\n notes\n startsAt\n endsAt\n recurrenceRule\n }\n }\n`;\n\nexport const UNLINK_PLANMAGNET_MEETING = gql`\n mutation MeetingDetailUnlink($id: ID!) {\n planmagnetUnlinkMeeting(id: $id)\n }\n`;\n\nexport const ADD_MEETING_ACTION_ITEM = gql`\n mutation MeetingAddActionItem($meetingId: ID!, $workItemId: ID!) {\n planmagnetAddMeetingActionItem(meetingId: $meetingId, workItemId: $workItemId) {\n id\n workItemId\n workItem {\n id\n key\n title\n status\n }\n }\n }\n`;\n\nexport const REMOVE_MEETING_ACTION_ITEM = gql`\n mutation MeetingRemoveActionItem($meetingId: ID!, $workItemId: ID!) {\n planmagnetRemoveMeetingActionItem(meetingId: $meetingId, workItemId: $workItemId)\n }\n`;\n\n/** Minimal create, for \"Add action item\" (a brand-new work item attached to the meeting it was raised in). */\nexport const CREATE_MEETING_ACTION_WORK_ITEM = gql`\n mutation MeetingCreateActionWorkItem($input: PlanmagnetCreateWorkItemInput!) {\n planmagnetCreateWorkItem(input: $input) {\n id\n key\n title\n status\n }\n }\n`;\n"],"mappings":";;AAmBA,IAAa,IAA6B,CAAG;;;;;;;;;;;;;GAehC,IAAwB,CAAG;;;;;;;;GAU3B,IAAwB,CAAG;;;;GAS3B,IAAkB,CAAC,0BAA0B,uBAAuB,EAEpE,IAA2B,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmC9B,IAAyB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6C5B,IAA0B,CAAG;;;;;;;;;;;;;;;GAiB7B,IAA4B,CAAG;;;;;;;;;;;;;GAe/B,IAA4B,CAAG;;;;GAM/B,IAA0B,CAAG;;;;;;;;;;;;;GAe7B,IAA6B,CAAG;;;;GAOhC,IAAkC,CAAG"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Shared types, RRULE helpers and client-side validation for PlanMagnet meetings (GAP-06, CWF-22/23).
3
+ *
4
+ * A meeting is scheduled through the platform Calendar module (`createEvent`) and then recorded here
5
+ * (`planmagnetLinkMeeting`) — see `graphql/wspace.graphql`'s `PlanmagnetMeeting` doc comment and
6
+ * `meetingActions.ts` for the "who creates the calendar event" split this file's helpers serve.
7
+ */
8
+ /** Mirrors `PlanmagnetMeetingKind` (graphql/wspace.graphql). TEXT-backed server-side, not a Postgres enum, so a
9
+ * future value never needs an `ALTER TYPE` — this list is the only client-side validator, same contract as the
10
+ * server's. */
11
+ export declare const MEETING_KINDS: readonly ["STANDUP", "PLANNING", "REVIEW", "RETROSPECTIVE", "DEMO", "MILESTONE_CELEBRATION", "OTHER"];
12
+ export type MeetingKind = (typeof MEETING_KINDS)[number];
13
+ /** Server rule mirrored client-side (see `PlanmagnetMeetingKind.MILESTONE_CELEBRATION`'s doc comment in the
14
+ * schema): only this kind requires a milestone. */
15
+ export declare const MEETING_KIND_REQUIRES_MILESTONE: ReadonlySet<MeetingKind>;
16
+ export declare const RECURRENCE_OPTIONS: readonly ["NONE", "EVERY_WEEKDAY", "WEEKLY"];
17
+ export type RecurrenceOption = (typeof RECURRENCE_OPTIONS)[number];
18
+ export declare const RECURRENCE_LABELS: Record<RecurrenceOption, string>;
19
+ /** Common meeting lengths, in minutes, for the duration select. */
20
+ export declare const DURATION_OPTIONS_MINUTES: readonly [15, 30, 45, 60, 90, 120];
21
+ /**
22
+ * An ISO (UTC) instant -> the value a `<input type="datetime-local">` needs, in the VIEWER's own zone. Distinct
23
+ * from `timeShared.ts`'s `toDateInputValue`, which is for pure calendar-day fields and stays UTC — a meeting's
24
+ * start is a real moment, read in local wall-clock time (repo convention: moments show local, calendar days
25
+ * show UTC).
26
+ */
27
+ export declare function toLocalInputValue(iso: string | null | undefined): string;
28
+ /** The reverse of `toLocalInputValue`: a `datetime-local` value (viewer's local wall-clock, no zone suffix) -> an
29
+ * ISO UTC instant for the wire. `Date` parses a zone-less date-time string as local time, which is exactly the
30
+ * conversion wanted here. */
31
+ export declare function localInputValueToISO(value: string): string | null;
32
+ /** `startIso` plus a duration in minutes, as an ISO UTC instant. */
33
+ export declare function addMinutesIso(startIso: string, minutes: number): string;
34
+ /** Now, rounded up to the next half hour, as a `datetime-local` value — the dialog's default start. */
35
+ export declare function defaultLocalStart(from?: Date): string;
36
+ /** The viewer's IANA time zone, sent to `createEvent` so the server (and any other client) can re-derive what
37
+ * "every weekday" means for this series. Falls back to UTC if the runtime cannot report one. */
38
+ export declare function viewerTimeZone(): string;
39
+ /** An RFC 5545 UTC `UNTIL` value: `YYYYMMDDTHHMMSSZ`. Exported for callers (`ScheduleCeremoniesDialog`) that
40
+ * build an UNTIL-bearing RRULE by hand rather than through `buildRRule` (the standup's UNTIL is the sprint's
41
+ * own end day, not something the WEEKLY/EVERY_WEEKDAY picker above expresses). */
42
+ export declare function rruleUntil(until: Date): string;
43
+ /**
44
+ * Builds the RRULE written to BOTH the calendar event (`createEvent.input.rrule`) and the link's
45
+ * `recurrenceRule` snapshot — the two must agree, since the snapshot is display-only and the calendar event
46
+ * stays the source of truth for the real schedule (`PlanmagnetMeeting.recurrenceRule` doc comment).
47
+ *
48
+ * `startLocalValue` is the `datetime-local` value the recurrence's weekday is read from (the viewer's own
49
+ * wall-clock day — reading it from a UTC-shifted instant could land on the wrong day near midnight).
50
+ * `until`, when given, is the last UTC instant the series may recur through (sprint ceremonies' daily standup).
51
+ */
52
+ export declare function buildRRule(option: RecurrenceOption, startLocalValue: string, until?: Date | null): string | undefined;
53
+ /** A short, human summary of a calendar RRULE snapshot (display only — see `PlanmagnetMeeting.recurrenceRule`'s
54
+ * doc comment; the calendar event is the real schedule). */
55
+ export declare function summarizeRecurrence(rrule: string | null | undefined): string;
56
+ export interface MeetingDraft {
57
+ title: string;
58
+ calendarId: string;
59
+ startLocal: string;
60
+ durationMinutes: number;
61
+ kind: MeetingKind;
62
+ milestoneId?: string | null;
63
+ }
64
+ /**
65
+ * Client-side mirror of the rules `MeetingService` enforces: a calendar and a start are required to create the
66
+ * event at all; a positive duration keeps `endsAt` structurally after `startsAt` (these dialogs only ever take a
67
+ * start + a duration, never an independent end); `MILESTONE_CELEBRATION` requires a milestone (the schema's own
68
+ * doc comment on that enum value). Text-length caps are deliberately NOT mirrored here — the schema documents
69
+ * `agenda`/`notes` as "Length-capped" without publishing the number, so an over-length value is left to the
70
+ * server's own refusal, shown verbatim (never a guessed client-side limit that could be wrong in either
71
+ * direction).
72
+ */
73
+ export declare function validateMeetingDraft(draft: MeetingDraft): string | null;
74
+ //# sourceMappingURL=meetingModel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meetingModel.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/meetings/meetingModel.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;gBAEgB;AAChB,eAAO,MAAM,aAAa,uGAQhB,CAAC;AACX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD;oDACoD;AACpD,eAAO,MAAM,+BAA+B,EAAE,WAAW,CAAC,WAAW,CAEnE,CAAC;AAEH,eAAO,MAAM,kBAAkB,8CAA+C,CAAC;AAC/E,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAI9D,CAAC;AAEF,mEAAmE;AACnE,eAAO,MAAM,wBAAwB,oCAAqC,CAAC;AAI3E;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAKxE;AAED;;8BAE8B;AAC9B,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIjE;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,uGAAuG;AACvG,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,IAAiB,GAAG,MAAM,CASjE;AAED;iGACiG;AACjG,wBAAgB,cAAc,IAAI,MAAM,CAMvC;AAaD;;mFAEmF;AACnF,wBAAgB,UAAU,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,CAK9C;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,gBAAgB,EACxB,eAAe,EAAE,MAAM,EACvB,KAAK,CAAC,EAAE,IAAI,GAAG,IAAI,GAClB,MAAM,GAAG,SAAS,CAOpB;AAED;6DAC6D;AAC7D,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAe5E;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,WAAW,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAWvE"}
@@ -0,0 +1,88 @@
1
+ //#region src/planmagnet/meetings/meetingModel.ts
2
+ var e = [
3
+ "STANDUP",
4
+ "PLANNING",
5
+ "REVIEW",
6
+ "RETROSPECTIVE",
7
+ "DEMO",
8
+ "MILESTONE_CELEBRATION",
9
+ "OTHER"
10
+ ], t = new Set(["MILESTONE_CELEBRATION"]), n = [
11
+ "NONE",
12
+ "EVERY_WEEKDAY",
13
+ "WEEKLY"
14
+ ], r = {
15
+ NONE: "Does not repeat",
16
+ EVERY_WEEKDAY: "Every weekday",
17
+ WEEKLY: "Weekly"
18
+ }, i = [
19
+ 15,
20
+ 30,
21
+ 45,
22
+ 60,
23
+ 90,
24
+ 120
25
+ ], a = (e) => String(e).padStart(2, "0");
26
+ function o(e) {
27
+ if (!e) return "";
28
+ let t = new Date(e);
29
+ return Number.isNaN(t.getTime()) ? "" : `${t.getFullYear()}-${a(t.getMonth() + 1)}-${a(t.getDate())}T${a(t.getHours())}:${a(t.getMinutes())}`;
30
+ }
31
+ function s(e) {
32
+ if (!e) return null;
33
+ let t = new Date(e);
34
+ return Number.isNaN(t.getTime()) ? null : t.toISOString();
35
+ }
36
+ function c(e, t) {
37
+ return new Date(new Date(e).getTime() + t * 6e4).toISOString();
38
+ }
39
+ function l(e = /* @__PURE__ */ new Date()) {
40
+ let t = new Date(e);
41
+ return t.setSeconds(0, 0), t.getMinutes() > 30 ? t.setHours(t.getHours() + 1, 0, 0, 0) : t.getMinutes() > 0 && t.setMinutes(30, 0, 0), o(t.toISOString());
42
+ }
43
+ function u() {
44
+ try {
45
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
46
+ } catch {
47
+ return "UTC";
48
+ }
49
+ }
50
+ var d = [
51
+ "SU",
52
+ "MO",
53
+ "TU",
54
+ "WE",
55
+ "TH",
56
+ "FR",
57
+ "SA"
58
+ ], f = {
59
+ SU: "Sun",
60
+ MO: "Mon",
61
+ TU: "Tue",
62
+ WE: "Wed",
63
+ TH: "Thu",
64
+ FR: "Fri",
65
+ SA: "Sat"
66
+ };
67
+ function p(e) {
68
+ return e.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
69
+ }
70
+ function m(e, t, n) {
71
+ if (e === "NONE") return;
72
+ let r = n ? `;UNTIL=${p(n)}` : "";
73
+ if (e === "EVERY_WEEKDAY") return `FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR${r}`;
74
+ let i = new Date(t);
75
+ return `FREQ=WEEKLY;BYDAY=${Number.isNaN(i.getTime()) ? "MO" : d[i.getDay()]}${r}`;
76
+ }
77
+ function h(e) {
78
+ if (!e) return "Does not repeat";
79
+ let t = /BYDAY=([^;]+)/.exec(e)?.[1], n = /UNTIL=(\d{4})(\d{2})(\d{2})/.exec(e), r;
80
+ return r = t === "MO,TU,WE,TH,FR" ? "Every weekday" : t ? `Weekly on ${t.split(",").map((e) => f[e] ?? e).join(", ")}` : /FREQ=DAILY/.test(e) ? "Daily" : "Repeats", n && (r += ` until ${n[2]}/${n[3]}/${n[1]}`), r;
81
+ }
82
+ function g(e) {
83
+ return e.title.trim() ? e.calendarId ? e.startLocal ? !Number.isFinite(e.durationMinutes) || e.durationMinutes <= 0 ? "Duration must be at least 1 minute." : t.has(e.kind) && !e.milestoneId ? "A milestone celebration needs a milestone." : null : "Pick a start time." : "Pick a calendar." : "A title is required.";
84
+ }
85
+ //#endregion
86
+ export { i as DURATION_OPTIONS_MINUTES, e as MEETING_KINDS, r as RECURRENCE_LABELS, n as RECURRENCE_OPTIONS, c as addMinutesIso, m as buildRRule, l as defaultLocalStart, s as localInputValueToISO, p as rruleUntil, h as summarizeRecurrence, g as validateMeetingDraft, u as viewerTimeZone };
87
+
88
+ //# sourceMappingURL=meetingModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meetingModel.js","names":[],"sources":["../../../src/planmagnet/meetings/meetingModel.ts"],"sourcesContent":["/**\n * Shared types, RRULE helpers and client-side validation for PlanMagnet meetings (GAP-06, CWF-22/23).\n *\n * A meeting is scheduled through the platform Calendar module (`createEvent`) and then recorded here\n * (`planmagnetLinkMeeting`) — see `graphql/wspace.graphql`'s `PlanmagnetMeeting` doc comment and\n * `meetingActions.ts` for the \"who creates the calendar event\" split this file's helpers serve.\n */\n\n/** Mirrors `PlanmagnetMeetingKind` (graphql/wspace.graphql). TEXT-backed server-side, not a Postgres enum, so a\n * future value never needs an `ALTER TYPE` — this list is the only client-side validator, same contract as the\n * server's. */\nexport const MEETING_KINDS = [\n 'STANDUP',\n 'PLANNING',\n 'REVIEW',\n 'RETROSPECTIVE',\n 'DEMO',\n 'MILESTONE_CELEBRATION',\n 'OTHER',\n] as const;\nexport type MeetingKind = (typeof MEETING_KINDS)[number];\n\n/** Server rule mirrored client-side (see `PlanmagnetMeetingKind.MILESTONE_CELEBRATION`'s doc comment in the\n * schema): only this kind requires a milestone. */\nexport const MEETING_KIND_REQUIRES_MILESTONE: ReadonlySet<MeetingKind> = new Set([\n 'MILESTONE_CELEBRATION',\n]);\n\nexport const RECURRENCE_OPTIONS = ['NONE', 'EVERY_WEEKDAY', 'WEEKLY'] as const;\nexport type RecurrenceOption = (typeof RECURRENCE_OPTIONS)[number];\n\nexport const RECURRENCE_LABELS: Record<RecurrenceOption, string> = {\n NONE: 'Does not repeat',\n EVERY_WEEKDAY: 'Every weekday',\n WEEKLY: 'Weekly',\n};\n\n/** Common meeting lengths, in minutes, for the duration select. */\nexport const DURATION_OPTIONS_MINUTES = [15, 30, 45, 60, 90, 120] as const;\n\nconst pad = (n: number): string => String(n).padStart(2, '0');\n\n/**\n * An ISO (UTC) instant -> the value a `<input type=\"datetime-local\">` needs, in the VIEWER's own zone. Distinct\n * from `timeShared.ts`'s `toDateInputValue`, which is for pure calendar-day fields and stays UTC — a meeting's\n * start is a real moment, read in local wall-clock time (repo convention: moments show local, calendar days\n * show UTC).\n */\nexport function toLocalInputValue(iso: string | null | undefined): string {\n if (!iso) return '';\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return '';\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n\n/** The reverse of `toLocalInputValue`: a `datetime-local` value (viewer's local wall-clock, no zone suffix) -> an\n * ISO UTC instant for the wire. `Date` parses a zone-less date-time string as local time, which is exactly the\n * conversion wanted here. */\nexport function localInputValueToISO(value: string): string | null {\n if (!value) return null;\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d.toISOString();\n}\n\n/** `startIso` plus a duration in minutes, as an ISO UTC instant. */\nexport function addMinutesIso(startIso: string, minutes: number): string {\n return new Date(new Date(startIso).getTime() + minutes * 60_000).toISOString();\n}\n\n/** Now, rounded up to the next half hour, as a `datetime-local` value — the dialog's default start. */\nexport function defaultLocalStart(from: Date = new Date()): string {\n const d = new Date(from);\n d.setSeconds(0, 0);\n if (d.getMinutes() > 30) {\n d.setHours(d.getHours() + 1, 0, 0, 0);\n } else if (d.getMinutes() > 0) {\n d.setMinutes(30, 0, 0);\n }\n return toLocalInputValue(d.toISOString());\n}\n\n/** The viewer's IANA time zone, sent to `createEvent` so the server (and any other client) can re-derive what\n * \"every weekday\" means for this series. Falls back to UTC if the runtime cannot report one. */\nexport function viewerTimeZone(): string {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';\n } catch {\n return 'UTC';\n }\n}\n\nconst WEEKDAY_CODES = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'] as const;\nconst WEEKDAY_LABELS: Record<string, string> = {\n SU: 'Sun',\n MO: 'Mon',\n TU: 'Tue',\n WE: 'Wed',\n TH: 'Thu',\n FR: 'Fri',\n SA: 'Sat',\n};\n\n/** An RFC 5545 UTC `UNTIL` value: `YYYYMMDDTHHMMSSZ`. Exported for callers (`ScheduleCeremoniesDialog`) that\n * build an UNTIL-bearing RRULE by hand rather than through `buildRRule` (the standup's UNTIL is the sprint's\n * own end day, not something the WEEKLY/EVERY_WEEKDAY picker above expresses). */\nexport function rruleUntil(until: Date): string {\n return until\n .toISOString()\n .replace(/[-:]/g, '')\n .replace(/\\.\\d{3}Z$/, 'Z');\n}\n\n/**\n * Builds the RRULE written to BOTH the calendar event (`createEvent.input.rrule`) and the link's\n * `recurrenceRule` snapshot — the two must agree, since the snapshot is display-only and the calendar event\n * stays the source of truth for the real schedule (`PlanmagnetMeeting.recurrenceRule` doc comment).\n *\n * `startLocalValue` is the `datetime-local` value the recurrence's weekday is read from (the viewer's own\n * wall-clock day — reading it from a UTC-shifted instant could land on the wrong day near midnight).\n * `until`, when given, is the last UTC instant the series may recur through (sprint ceremonies' daily standup).\n */\nexport function buildRRule(\n option: RecurrenceOption,\n startLocalValue: string,\n until?: Date | null\n): string | undefined {\n if (option === 'NONE') return undefined;\n const untilPart = until ? `;UNTIL=${rruleUntil(until)}` : '';\n if (option === 'EVERY_WEEKDAY') return `FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR${untilPart}`;\n const start = new Date(startLocalValue);\n const day = Number.isNaN(start.getTime()) ? 'MO' : WEEKDAY_CODES[start.getDay()];\n return `FREQ=WEEKLY;BYDAY=${day}${untilPart}`;\n}\n\n/** A short, human summary of a calendar RRULE snapshot (display only — see `PlanmagnetMeeting.recurrenceRule`'s\n * doc comment; the calendar event is the real schedule). */\nexport function summarizeRecurrence(rrule: string | null | undefined): string {\n if (!rrule) return 'Does not repeat';\n const byday = /BYDAY=([^;]+)/.exec(rrule)?.[1];\n const until = /UNTIL=(\\d{4})(\\d{2})(\\d{2})/.exec(rrule);\n let base: string;\n if (byday === 'MO,TU,WE,TH,FR') base = 'Every weekday';\n else if (byday) {\n base = `Weekly on ${byday\n .split(',')\n .map((d) => WEEKDAY_LABELS[d] ?? d)\n .join(', ')}`;\n } else if (/FREQ=DAILY/.test(rrule)) base = 'Daily';\n else base = 'Repeats';\n if (until) base += ` until ${until[2]}/${until[3]}/${until[1]}`;\n return base;\n}\n\nexport interface MeetingDraft {\n title: string;\n calendarId: string;\n startLocal: string;\n durationMinutes: number;\n kind: MeetingKind;\n milestoneId?: string | null;\n}\n\n/**\n * Client-side mirror of the rules `MeetingService` enforces: a calendar and a start are required to create the\n * event at all; a positive duration keeps `endsAt` structurally after `startsAt` (these dialogs only ever take a\n * start + a duration, never an independent end); `MILESTONE_CELEBRATION` requires a milestone (the schema's own\n * doc comment on that enum value). Text-length caps are deliberately NOT mirrored here — the schema documents\n * `agenda`/`notes` as \"Length-capped\" without publishing the number, so an over-length value is left to the\n * server's own refusal, shown verbatim (never a guessed client-side limit that could be wrong in either\n * direction).\n */\nexport function validateMeetingDraft(draft: MeetingDraft): string | null {\n if (!draft.title.trim()) return 'A title is required.';\n if (!draft.calendarId) return 'Pick a calendar.';\n if (!draft.startLocal) return 'Pick a start time.';\n if (!Number.isFinite(draft.durationMinutes) || draft.durationMinutes <= 0) {\n return 'Duration must be at least 1 minute.';\n }\n if (MEETING_KIND_REQUIRES_MILESTONE.has(draft.kind) && !draft.milestoneId) {\n return 'A milestone celebration needs a milestone.';\n }\n return null;\n}\n"],"mappings":";AAWA,IAAa,IAAgB;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACD,EAKY,IAA4D,IAAI,IAAI,CAC/E,wBACD,CAAC,EAEW,IAAqB;CAAC;CAAQ;CAAiB;CAAS,EAGxD,IAAsD;CACjE,MAAM;CACN,eAAe;CACf,QAAQ;CACT,EAGY,IAA2B;CAAC;CAAI;CAAI;CAAI;CAAI;CAAI;CAAI,EAE3D,KAAO,MAAsB,OAAO,EAAE,CAAC,SAAS,GAAG,IAAI;AAQ7D,SAAgB,EAAkB,GAAwC;AACxE,KAAI,CAAC,EAAK,QAAO;CACjB,IAAM,IAAI,IAAI,KAAK,EAAI;AAEvB,QADI,OAAO,MAAM,EAAE,SAAS,CAAC,GAAS,KAC/B,GAAG,EAAE,aAAa,CAAC,GAAG,EAAI,EAAE,UAAU,GAAG,EAAE,CAAC,GAAG,EAAI,EAAE,SAAS,CAAC,CAAC,GAAG,EAAI,EAAE,UAAU,CAAC,CAAC,GAAG,EAAI,EAAE,YAAY,CAAC;;AAMpH,SAAgB,EAAqB,GAA8B;AACjE,KAAI,CAAC,EAAO,QAAO;CACnB,IAAM,IAAI,IAAI,KAAK,EAAM;AACzB,QAAO,OAAO,MAAM,EAAE,SAAS,CAAC,GAAG,OAAO,EAAE,aAAa;;AAI3D,SAAgB,EAAc,GAAkB,GAAyB;AACvE,QAAO,IAAI,KAAK,IAAI,KAAK,EAAS,CAAC,SAAS,GAAG,IAAU,IAAO,CAAC,aAAa;;AAIhF,SAAgB,EAAkB,oBAAa,IAAI,MAAM,EAAU;CACjE,IAAM,IAAI,IAAI,KAAK,EAAK;AAOxB,QANA,EAAE,WAAW,GAAG,EAAE,EACd,EAAE,YAAY,GAAG,KACnB,EAAE,SAAS,EAAE,UAAU,GAAG,GAAG,GAAG,GAAG,EAAE,GAC5B,EAAE,YAAY,GAAG,KAC1B,EAAE,WAAW,IAAI,GAAG,EAAE,EAEjB,EAAkB,EAAE,aAAa,CAAC;;AAK3C,SAAgB,IAAyB;AACvC,KAAI;AACF,SAAO,KAAK,gBAAgB,CAAC,iBAAiB,CAAC,YAAY;SACrD;AACN,SAAO;;;AAIX,IAAM,IAAgB;CAAC;CAAM;CAAM;CAAM;CAAM;CAAM;CAAM;CAAK,EAC1D,IAAyC;CAC7C,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACL;AAKD,SAAgB,EAAW,GAAqB;AAC9C,QAAO,EACJ,aAAa,CACb,QAAQ,SAAS,GAAG,CACpB,QAAQ,aAAa,IAAI;;AAY9B,SAAgB,EACd,GACA,GACA,GACoB;AACpB,KAAI,MAAW,OAAQ;CACvB,IAAM,IAAY,IAAQ,UAAU,EAAW,EAAM,KAAK;AAC1D,KAAI,MAAW,gBAAiB,QAAO,kCAAkC;CACzE,IAAM,IAAQ,IAAI,KAAK,EAAgB;AAEvC,QAAO,qBADK,OAAO,MAAM,EAAM,SAAS,CAAC,GAAG,OAAO,EAAc,EAAM,QAAQ,IAC7C;;AAKpC,SAAgB,EAAoB,GAA0C;AAC5E,KAAI,CAAC,EAAO,QAAO;CACnB,IAAM,IAAQ,gBAAgB,KAAK,EAAM,GAAG,IACtC,IAAQ,8BAA8B,KAAK,EAAM,EACnD;AAUJ,QATA,AAOK,IAPD,MAAU,mBAAyB,kBAC9B,IACA,aAAa,EACjB,MAAM,IAAI,CACV,KAAK,MAAM,EAAe,MAAM,EAAE,CAClC,KAAK,KAAK,KACJ,aAAa,KAAK,EAAM,GAAS,UAChC,WACR,MAAO,KAAQ,UAAU,EAAM,GAAG,GAAG,EAAM,GAAG,GAAG,EAAM,OACpD;;AAqBT,SAAgB,EAAqB,GAAoC;AAUvE,QATK,EAAM,MAAM,MAAM,GAClB,EAAM,aACN,EAAM,aACP,CAAC,OAAO,SAAS,EAAM,gBAAgB,IAAI,EAAM,mBAAmB,IAC/D,wCAEL,EAAgC,IAAI,EAAM,KAAK,IAAI,CAAC,EAAM,cACrD,+CAEF,OAPuB,uBADA,qBADE"}
@@ -0,0 +1,2 @@
1
+ export declare function MeetingsMeetingDetailPagePage(): import("react/jsx-runtime").JSX.Element;
2
+ //# sourceMappingURL=MeetingsMeetingDetailPagePage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MeetingsMeetingDetailPagePage.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/pages/MeetingsMeetingDetailPagePage.tsx"],"names":[],"mappings":"AAuHA,wBAAgB,6BAA6B,4CA4J5C"}