@aglyn/plugins-events-calendar 1.0.0-beta.143
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.
- package/LICENSE +201 -0
- package/README.md +7 -0
- package/package.json +47 -0
- package/src/index.d.ts +18 -0
- package/src/index.js +19 -0
- package/src/index.js.map +1 -0
- package/src/lib/components/event-list.d.ts +60 -0
- package/src/lib/components/event-list.js +298 -0
- package/src/lib/components/event-list.js.map +1 -0
- package/src/lib/components/events-console-page.d.ts +19 -0
- package/src/lib/components/events-console-page.js +530 -0
- package/src/lib/components/events-console-page.js.map +1 -0
- package/src/lib/constants/bundle-common.d.ts +26 -0
- package/src/lib/constants/bundle-common.js +26 -0
- package/src/lib/constants/bundle-common.js.map +1 -0
- package/src/lib/plugin.d.ts +25 -0
- package/src/lib/plugin.js +75 -0
- package/src/lib/plugin.js.map +1 -0
- package/src/lib/server.d.ts +17 -0
- package/src/lib/server.js +166 -0
- package/src/lib/server.js.map +1 -0
- package/src/lib/site.d.ts +28 -0
- package/src/lib/site.js +51 -0
- package/src/lib/site.js.map +1 -0
- package/src/lib/utils/generate-preset-id.d.ts +19 -0
- package/src/lib/utils/generate-preset-id.js +25 -0
- package/src/lib/utils/generate-preset-id.js.map +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/events-calendar/src/lib/components/events-console-page.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n createResourceUid,\n MEDIA_ALT_MAX_LENGTH,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport { type ConsolePluginPageProps } from '@aglyn/aglyn'\nimport { CardDisplay, useConfirmationContext } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { Timestamp } from '@aglyn/shared-util-timestamp'\nimport {\n ceilingedWindow,\n useFirestore,\n useFirestoreCollection,\n writeGuardedBySeed,\n} from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Button,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport {\n collection,\n deleteField,\n doc,\n limit,\n orderBy,\n query,\n setDoc,\n updateDoc,\n} from 'firebase/firestore'\nimport { useCallback, useMemo, useState } from 'react'\nimport { ListPagination } from '@aglyn/shared-ui-jsx/components/list-pagination.component'\nimport { TABLE_PAGE_SIZE_DEFAULT } from '@aglyn/shared-ui-jsx/const/table-pagination'\n\n/**\n * How many event documents this page reads.\n *\n * A CEILING, not a page size: the rows are filtered for soft deletes and\n * re-sorted after reading, so a server page would arrive holding anywhere\n * from zero to ten events and the count under it would be about candidates\n * rather than about events.\n */\nconst EVENT_CEILING = 200\n\ninterface EventDraft {\n id: string | null\n title: string\n startsAt: string\n endsAt: string\n location: string\n organizer: string\n description: string\n coverImage: string\n coverImageAlt: string\n status: 'draft' | 'published'\n}\n\ninterface EventRecord {\n $id: string\n title?: string\n startsAtMs?: number\n endsAtMs?: number\n location?: string\n organizer?: string\n description?: string\n coverImage?: string\n coverImageAlt?: string\n status?: 'draft' | 'published'\n deletedAt?: unknown\n}\n\n/**\n * A host's events.\n *\n * This was a hand-rolled `onSnapshot` with its own retry, and it carried a\n * FOURTH copy of the AGL-1066 defect: `attempt = 0` in the success handler.\n * Under `persistentLocalCache` the cached emission that precedes every\n * refusal handed the budget back, so `unreadable` — the whole point of the\n * counter — could not fire in the one state that needed it, a populated\n * editor over a read that had stopped working.\n *\n * Rather than repair a fourth counter, the copy is gone. `useFirestoreCollection`\n * is the same `onSnapshot`-plus-retry that absorbs the AGL-216/217\n * post-sign-in denial, and it carries the signals this page's save needs\n * (`fromCache`, and `serverDenied` for the refusal the budget cannot yet\n * express) plus denial reporting into `session-health` this page never had.\n * There was never a reason it could not: the file has imported from\n * `@aglyn/tenant-feature-instance` all along.\n */\nfunction useHostEvents(hostId: string): {\n events: EventRecord[]\n truncated: boolean\n fromCache: boolean\n unreadable: boolean\n} {\n const firestore = useFirestore()\n const { data, status, fromCache } = useFirestoreCollection<EventRecord>(\n () =>\n hostId\n ? query(\n collection(firestore, 'hosts', hostId, 'events'),\n /*\n * ORDERED, so the window is the newest 200 rather than a sample.\n *\n * A `limit()` with no `orderBy` returns documents in ID order, so\n * this was reading an arbitrary 200 of the collection and then\n * sorting them by date in the browser — which looks newest-first\n * and is not: a site past 200 events would simply never see the\n * ones whose ids sorted late, including the next one happening.\n *\n * `orderBy` DROPS documents missing the field, so it is only safe\n * once every writer is known to set it. All three checks pass for\n * `startsAtMs`: the only writer refuses a save without it (the\n * guard a few lines below), the server feed already orders by it,\n * and `events` is not in `IMPORTABLE_FIELDS`, so nothing else\n * writes a row here.\n */\n orderBy('startsAtMs', 'desc'),\n /*\n * One document more than the ceiling, so \"there is more than\n * this\" is a fact rather than a comparison against the cap —\n * which is wrong in exactly the case it matters, a site holding\n * precisely 200 events. The probe row is dropped below and is\n * never rendered or counted.\n */\n limit(EVENT_CEILING + 1),\n )\n : null,\n [firestore, hostId],\n { idField: '$id' },\n )\n\n const { rows, truncated } = ceilingedWindow<EventRecord>(data, EVENT_CEILING)\n return { events: rows, truncated, fromCache, unreadable: status === 'error' }\n}\n\n/** datetime-local ↔ epoch-ms without timezone surprises. */\nfunction toLocalInput(ms: number | null | undefined): string {\n if (!ms) return ''\n const date = new Date(ms)\n const pad = (value: number) => String(value).padStart(2, '0')\n return (\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-` +\n `${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`\n )\n}\n\n/**\n * Events manager (AGL-145 → AGL-394): the Event Calendar add-on's console\n * surface, now owned by the plugin so the console shell renders it through\n * the ConsoleExtension registry rather than a hardcoded page. Events carry\n * schedule/location/organizer/cover and a draft/published status; visitors\n * see published events through the Event List canvas element.\n *\n * Reaching this component means the org holds `eventCalendar`. The shell\n * resolves that entitlement and renders its own refusal instead of mounting\n * anything an extension registered (AGL-2484), so there is no unentitled\n * state to render here; the sentence a refused org reads is registered as\n * this plugin's `upgradeNotice` in `plugin.ts`.\n */\nexport function EventsConsolePage(props: ConsolePluginPageProps) {\n const { hostId } = props\n const firestore = useFirestore()\n const { enqueueSnackbar } = useSnackbar()\n const { confirm } = useConfirmationContext()\n\n const {\n events: eventDocs,\n /**\n * The rows this editor is seeded from are unconfirmed by the server\n * (AGL-1358). Editing copies a whole stored event into `draft` and one\n * `setDoc` writes all of it back, so `merge: true` protects nothing.\n * `status` is the field that costs the most: a cached seed can\n * UNPUBLISH a live, indexed event — or republish one that was pulled\n * down — from the Save button of an unrelated edit, and `endsAtMs` is\n * rewritten on every save whether or not anyone touched the schedule.\n */\n fromCache: eventsFromCache,\n truncated: eventsTruncated,\n unreadable: eventsUnreadable,\n } = useHostEvents(hostId)\n const events = eventDocs\n .filter((event) => !event.deletedAt)\n .sort((a, b) => (b.startsAtMs ?? 0) - (a.startsAtMs ?? 0))\n\n /*\n * The page is a SLICE of the ceiling this page already holds. Sorting is\n * allowed here for the reason it is not allowed on a server-paged list: the\n * whole window is in hand, so newest-first is the order of the window and\n * not of one arbitrary page inside it.\n */\n const [page, setPage] = useState(0)\n const [pageSize, setPageSize] = useState(TABLE_PAGE_SIZE_DEFAULT)\n const visibleEvents = useMemo(\n () => events.slice(page * pageSize, page * pageSize + pageSize),\n [events, page, pageSize],\n )\n\n const [draft, setDraft] = useState<EventDraft | null>(null)\n\n const handleSave = useCallback(async () => {\n if (!draft || !draft.title.trim()) return\n const startsAtMs = draft.startsAt ? new Date(draft.startsAt).getTime() : 0\n const endsAtMs = draft.endsAt ? new Date(draft.endsAt).getTime() : 0\n if (!startsAtMs) {\n return void enqueueSnackbar('Set a start time', {\n variant: 'warning',\n persist: false,\n })\n }\n try {\n const id = draft.id ?? createResourceUid()\n /**\n * Refuse an EDIT whose seed the server never confirmed (AGL-1358).\n *\n * One `setDoc` serves create and edit here, so the guard has to be\n * conditioned on `draft.id` rather than sitting on a branch of its\n * own. A NEW event is built from blanks at a fresh uid and can\n * overwrite nothing, while the first snapshot of any listener is\n * `fromCache: true` — an unconditional guard would refuse every\n * create, which is the common case, not a corner.\n *\n * The guard WRAPS the write. An early return is a shape you can keep\n * while losing the protection; here the write is only reachable\n * through the verdict.\n */\n const verdict = await writeGuardedBySeed(\n {\n subject: 'event',\n unreadable: Boolean(draft.id) && eventsUnreadable,\n fromCache: Boolean(draft.id) && eventsFromCache,\n },\n async () => {\n await setDoc(\n doc(firestore, 'hosts', hostId, 'events', id),\n {\n title: draft.title.trim().slice(0, 150),\n startsAtMs,\n ...(endsAtMs > startsAtMs\n ? { endsAtMs }\n : { endsAtMs: startsAtMs + 60 * 60 * 1000 }),\n ...(draft.location.trim() && {\n location: draft.location.trim().slice(0, 200),\n }),\n ...(draft.organizer.trim() && {\n organizer: draft.organizer.trim().slice(0, 100),\n }),\n ...(draft.description.trim() && {\n description: draft.description.trim().slice(0, 2000),\n }),\n ...(draft.coverImage.trim() && {\n coverImage: draft.coverImage.trim(),\n }),\n // AGL-2418. This is a `merge` write, so clearing the box has\n // to DELETE the key — leaving it out would silently keep the\n // old sentence describing a picture that changed, which is\n // worse than never having offered the field. Tied to the\n // cover: a description with no image describes nothing.\n ...(draft.coverImage.trim() && draft.coverImageAlt.trim()\n ? {\n coverImageAlt: draft.coverImageAlt\n .trim()\n .slice(0, MEDIA_ALT_MAX_LENGTH),\n }\n : { coverImageAlt: deleteField() }),\n status: draft.status,\n updatedAt: Timestamp.now(),\n ...(draft.id ? {} : { createdAt: Timestamp.now() }),\n },\n { merge: true },\n )\n },\n )\n // Before `setDraft(null)`, so a refusal keeps the dialog open with\n // what was typed — in the same warning vocabulary as the start-time\n // refusal above it.\n if (!verdict.ok) {\n return void enqueueSnackbar(verdict.message, {\n variant: 'warning',\n persist: false,\n })\n }\n setDraft(null)\n enqueueSnackbar('Event saved', { variant: 'success', persist: false })\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n }, [\n draft,\n firestore,\n hostId,\n enqueueSnackbar,\n eventsFromCache,\n eventsUnreadable,\n ])\n\n const handleDelete = useCallback(\n (event: EventRecord) => async () => {\n const confirmed = await confirm({\n title: 'Delete this event?',\n description: `\"${event.title}\" disappears from your site.`,\n confirmationText: 'Delete',\n confirmationButtonProps: { color: 'error' },\n })\n .then(() => true)\n .catch(() => false)\n if (!confirmed) return\n await updateDoc(doc(firestore, 'hosts', hostId, 'events', event.$id), {\n deletedAt: Timestamp.now(),\n })\n },\n [confirm, firestore, hostId],\n )\n\n return (\n <CardDisplay\n header={'Events'}\n help={pluginDocsHelp('events', { anchor: '#manage-events' })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={1}>\n {events.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Create events here, then drop an Event List element on any ' +\n 'screen — published events render with SEO Event markup.'}\n </Typography>\n ) : (\n visibleEvents.map((event) => (\n <Stack\n key={event.$id}\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center' }}\n >\n <Chip\n size=\"small\"\n label={event.status ?? 'draft'}\n color={event.status === 'published' ? 'success' : 'default'}\n />\n <Stack sx={{ flex: 1, minWidth: 0 }}>\n <Typography variant=\"body2\" noWrap>\n {event.title}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {new Date(event.startsAtMs ?? 0).toLocaleString()}\n {event.location ? ` · ${event.location}` : ''}\n </Typography>\n </Stack>\n <Button\n size=\"small\"\n onClick={() =>\n setDraft({\n id: event.$id,\n title: event.title ?? '',\n startsAt: toLocalInput(event.startsAtMs),\n endsAt: toLocalInput(event.endsAtMs),\n location: event.location ?? '',\n organizer: event.organizer ?? '',\n description: event.description ?? '',\n coverImage: event.coverImage ?? '',\n coverImageAlt: event.coverImageAlt ?? '',\n status: event.status ?? 'draft',\n })\n }\n >\n {'Edit'}\n </Button>\n <Button size=\"small\" color=\"error\" onClick={handleDelete(event)}>\n {'Delete'}\n </Button>\n </Stack>\n ))\n )}\n {events.length === 0 ? null : (\n <ListPagination\n page={page}\n pageSize={pageSize}\n rowCount={visibleEvents.length}\n // The events this page HOLDS, after the soft-deleted ones are\n // dropped — a slice of rows already read, so the total is exact\n // for the window. The alert below says when the window is short\n // of the site.\n count={events.length}\n onPageChange={setPage}\n onPageSizeChange={setPageSize}\n />\n )}\n {eventsTruncated ? (\n <Alert severity=\"info\">\n {`Showing the newest ${EVENT_CEILING} events. This site has ` +\n 'more, and the older ones are not reachable from here.'}\n </Alert>\n ) : null}\n <Button\n size=\"small\"\n color=\"primary\"\n sx={{ alignSelf: 'flex-start' }}\n onClick={() =>\n setDraft({\n id: null,\n title: '',\n startsAt: '',\n endsAt: '',\n location: '',\n organizer: '',\n description: '',\n coverImage: '',\n coverImageAlt: '',\n status: 'draft',\n })\n }\n >\n {'Add event'}\n </Button>\n </Stack>\n\n <Dialog\n open={Boolean(draft)}\n onClose={() => setDraft(null)}\n maxWidth=\"sm\"\n fullWidth\n >\n <DialogTitle>{draft?.id ? 'Edit event' : 'Add event'}</DialogTitle>\n <DialogContent\n sx={{ display: 'flex', flexDirection: 'column', gap: 1.5, pt: 1 }}\n >\n <TextField\n label=\"Title\"\n value={draft?.title ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, title: event.target.value } : prev,\n )\n }\n size=\"small\"\n autoFocus\n sx={{ mt: 1 }}\n />\n <Stack direction=\"row\" spacing={1}>\n <TextField\n label=\"Starts\"\n type=\"datetime-local\"\n value={draft?.startsAt ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, startsAt: event.target.value } : prev,\n )\n }\n size=\"small\"\n slotProps={{ inputLabel: { shrink: true } }}\n sx={{ flex: 1 }}\n />\n <TextField\n label=\"Ends\"\n type=\"datetime-local\"\n value={draft?.endsAt ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, endsAt: event.target.value } : prev,\n )\n }\n size=\"small\"\n slotProps={{ inputLabel: { shrink: true } }}\n sx={{ flex: 1 }}\n />\n </Stack>\n <Stack direction=\"row\" spacing={1}>\n <TextField\n label=\"Location\"\n value={draft?.location ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, location: event.target.value } : prev,\n )\n }\n size=\"small\"\n sx={{ flex: 1 }}\n />\n <TextField\n label=\"Organizer\"\n value={draft?.organizer ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, organizer: event.target.value } : prev,\n )\n }\n size=\"small\"\n sx={{ flex: 1 }}\n />\n </Stack>\n <TextField\n label=\"Cover image URL\"\n value={draft?.coverImage ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, coverImage: event.target.value } : prev,\n )\n }\n size=\"small\"\n />\n {/*\n AGL-2418, matching the collection entry editor's wording. Shown\n only beside a cover, because a description with nothing to\n describe is a field nobody can answer. Left empty the thumbnail\n renders `alt=\"\"`, which is right here — the title sits next to\n it — so this is for the cover that carries something the title\n does not: a face, a venue, a poster with the lineup on it.\n */}\n {draft?.coverImage?.trim() ? (\n <TextField\n label=\"Cover image description\"\n placeholder=\"What the picture shows\"\n value={draft?.coverImageAlt ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev\n ? {\n ...prev,\n coverImageAlt: event.target.value.slice(\n 0,\n MEDIA_ALT_MAX_LENGTH,\n ),\n }\n : prev,\n )\n }\n size=\"small\"\n helperText={\n 'Read aloud by screen readers. Leave empty if the picture is decorative.'\n }\n />\n ) : null}\n <TextField\n label=\"Description\"\n value={draft?.description ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, description: event.target.value } : prev,\n )\n }\n size=\"small\"\n multiline\n minRows={3}\n />\n </DialogContent>\n <DialogActions sx={{ justifyContent: 'space-between' }}>\n <Button\n onClick={() =>\n setDraft((prev) =>\n prev\n ? {\n ...prev,\n status:\n prev.status === 'published' ? 'draft' : 'published',\n }\n : prev,\n )\n }\n >\n {draft?.status === 'published' ? 'Set to draft' : 'Set published'}\n </Button>\n <Stack direction=\"row\" spacing={1}>\n <Button onClick={() => setDraft(null)}>{'Cancel'}</Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={!draft?.title.trim()}\n onClick={handleSave}\n >\n {'Save event'}\n </Button>\n </Stack>\n </DialogActions>\n </Dialog>\n </CardDisplay>\n )\n}\nEventsConsolePage.displayName = 'EventsConsolePage'\n\nexport default EventsConsolePage\n"],"names":["createResourceUid","MEDIA_ALT_MAX_LENGTH","pluginDocsHelp","CardDisplay","useConfirmationContext","useSnackbar","Timestamp","ceilingedWindow","useFirestore","useFirestoreCollection","writeGuardedBySeed","Alert","Button","Chip","Dialog","DialogActions","DialogContent","DialogTitle","Stack","TextField","Typography","collection","deleteField","doc","limit","orderBy","query","setDoc","updateDoc","useCallback","useMemo","useState","ListPagination","TABLE_PAGE_SIZE_DEFAULT","EVENT_CEILING","useHostEvents","hostId","firestore","data","status","fromCache","idField","rows","truncated","events","unreadable","toLocalInput","ms","date","Date","pad","value","String","padStart","getFullYear","getMonth","getDate","getHours","getMinutes","EventsConsolePage","props","draft","enqueueSnackbar","confirm","eventDocs","eventsFromCache","eventsTruncated","eventsUnreadable","filter","event","deletedAt","sort","a","b","startsAtMs","page","setPage","pageSize","setPageSize","visibleEvents","slice","setDraft","handleSave","title","trim","startsAt","getTime","endsAtMs","endsAt","variant","persist","id","verdict","subject","Boolean","location","organizer","description","coverImage","coverImageAlt","updatedAt","now","createdAt","merge","ok","message","error","console","allowDuplicate","handleDelete","confirmed","confirmationText","confirmationButtonProps","color","then","catch","$id","header","help","anchor","contentGutterX","contentGutterY","spacing","length","map","direction","sx","alignItems","size","label","flex","minWidth","noWrap","toLocaleString","onClick","rowCount","count","onPageChange","onPageSizeChange","severity","alignSelf","open","onClose","maxWidth","fullWidth","display","flexDirection","gap","pt","onChange","prev","target","autoFocus","mt","type","slotProps","inputLabel","shrink","placeholder","helperText","multiline","minRows","justifyContent","disabled","displayName"],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* The bundle id, persisted as `pluginId` on every node this bundle places.
|
|
19
|
+
*
|
|
20
|
+
* Rendering resolves by `componentId` alone, so a node naming another bundle
|
|
21
|
+
* still draws — but `requiredSitePlugins` reads `pluginId` to decide which
|
|
22
|
+
* chunks must register before first paint, so one that names the wrong bundle
|
|
23
|
+
* draws LATE. `tools/scripts/backfill-node-plugin-ids.mjs` is what keeps saved
|
|
24
|
+
* nodes agreeing with this string.
|
|
25
|
+
*/
|
|
26
|
+
export declare const BUNDLE_ID = "events-calendar";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /**
|
|
17
|
+
* The bundle id, persisted as `pluginId` on every node this bundle places.
|
|
18
|
+
*
|
|
19
|
+
* Rendering resolves by `componentId` alone, so a node naming another bundle
|
|
20
|
+
* still draws — but `requiredSitePlugins` reads `pluginId` to decide which
|
|
21
|
+
* chunks must register before first paint, so one that names the wrong bundle
|
|
22
|
+
* draws LATE. `tools/scripts/backfill-node-plugin-ids.mjs` is what keeps saved
|
|
23
|
+
* nodes agreeing with this string.
|
|
24
|
+
*/ export const BUNDLE_ID = 'events-calendar';
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=bundle-common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/events-calendar/src/lib/constants/bundle-common.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The bundle id, persisted as `pluginId` on every node this bundle places.\n *\n * Rendering resolves by `componentId` alone, so a node naming another bundle\n * still draws — but `requiredSitePlugins` reads `pluginId` to decide which\n * chunks must register before first paint, so one that names the wrong bundle\n * draws LATE. `tools/scripts/backfill-node-plugin-ids.mjs` is what keeps saved\n * nodes agreeing with this string.\n */\nexport const BUNDLE_ID = 'events-calendar'\n"],"names":["BUNDLE_ID"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;CAQC,GACD,OAAO,MAAMA,YAAY,kBAAiB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Console half only: registers the Events nav item + page + dashboard card
|
|
19
|
+
* in the ConsoleExtension registry. Safe to call at console app load — it
|
|
20
|
+
* pulls no besigner/canvas code (the page is lazy). The shell renders the
|
|
21
|
+
* nav item and, through its generic plugin route, the page — so the Events
|
|
22
|
+
* surface exists without any edit to the console's own nav or page files.
|
|
23
|
+
*/
|
|
24
|
+
export declare function registerEventsCalendarConsole(): void;
|
|
25
|
+
export * from './site';
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ import * as Aglyn from "@aglyn/aglyn";
|
|
17
|
+
import { mdiCalendarMonthOutline } from "@aglyn/shared-data-mdi";
|
|
18
|
+
import { lazy } from "react";
|
|
19
|
+
import { BUNDLE_ID } from "./constants/bundle-common.js";
|
|
20
|
+
/**
|
|
21
|
+
* The console page is code-split: the shell registers the extension at app
|
|
22
|
+
* load for the nav strip, but the manager UI only loads when a user opens
|
|
23
|
+
* the Events page (the shell's plugin route wraps it in Suspense).
|
|
24
|
+
*/ const EventsConsolePage = lazy(()=>import("./components/events-console-page.js"));
|
|
25
|
+
/**
|
|
26
|
+
* Console half only: registers the Events nav item + page + dashboard card
|
|
27
|
+
* in the ConsoleExtension registry. Safe to call at console app load — it
|
|
28
|
+
* pulls no besigner/canvas code (the page is lazy). The shell renders the
|
|
29
|
+
* nav item and, through its generic plugin route, the page — so the Events
|
|
30
|
+
* surface exists without any edit to the console's own nav or page files.
|
|
31
|
+
*/ export function registerEventsCalendarConsole() {
|
|
32
|
+
Aglyn.registerConsoleExtension({
|
|
33
|
+
pluginId: BUNDLE_ID,
|
|
34
|
+
displayName: 'Events Calendar',
|
|
35
|
+
featureFlag: 'eventCalendar',
|
|
36
|
+
// `eventCalendar` is false on every plan — it is sold as a per-org
|
|
37
|
+
// add-on and nothing else — so the shell's generic "not included in your
|
|
38
|
+
// current plan" would send a reader to compare tiers that all say no.
|
|
39
|
+
// The price comes from the constant the invoice is built from, so this
|
|
40
|
+
// sentence cannot drift away from what a purchase actually charges.
|
|
41
|
+
upgradeNotice: {
|
|
42
|
+
message: 'The Event Calendar is a paid add-on ' + `($${Aglyn.EVENT_CALENDAR_ADDON_MONTHLY_USD}/mo for your whole ` + `workspace, supported directly by ${Aglyn.PLATFORM_BRAND_NAME}). ` + 'Enable it from Billing → Add-ons.',
|
|
43
|
+
billingAnchor: 'addons'
|
|
44
|
+
},
|
|
45
|
+
navItems: [
|
|
46
|
+
{
|
|
47
|
+
label: 'Events',
|
|
48
|
+
href: '/events',
|
|
49
|
+
// Reuse the existing release-flag nav-tab so staff-preview gating
|
|
50
|
+
// is unchanged now that the tab comes from the plugin (AGL-394).
|
|
51
|
+
navTabId: 'nav-tab-events',
|
|
52
|
+
icon: {
|
|
53
|
+
path: mdiCalendarMonthOutline.path
|
|
54
|
+
},
|
|
55
|
+
header: {
|
|
56
|
+
title: 'Events',
|
|
57
|
+
icon: {
|
|
58
|
+
path: mdiCalendarMonthOutline.path
|
|
59
|
+
},
|
|
60
|
+
docsTopic: 'events'
|
|
61
|
+
},
|
|
62
|
+
Component: EventsConsolePage
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
dashboardCards: [
|
|
66
|
+
{
|
|
67
|
+
cardId: 'events-upcoming',
|
|
68
|
+
title: 'Upcoming events'
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
export * from "./site.js";
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/plugins/events-calendar/src/lib/plugin.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { mdiCalendarMonthOutline } from '@aglyn/shared-data-mdi'\nimport { lazy } from 'react'\nimport { BUNDLE_ID } from './constants/bundle-common'\n\n/**\n * The console page is code-split: the shell registers the extension at app\n * load for the nav strip, but the manager UI only loads when a user opens\n * the Events page (the shell's plugin route wraps it in Suspense).\n */\nconst EventsConsolePage = lazy(() => import('./components/events-console-page'))\n\n/**\n * Console half only: registers the Events nav item + page + dashboard card\n * in the ConsoleExtension registry. Safe to call at console app load — it\n * pulls no besigner/canvas code (the page is lazy). The shell renders the\n * nav item and, through its generic plugin route, the page — so the Events\n * surface exists without any edit to the console's own nav or page files.\n */\nexport function registerEventsCalendarConsole(): void {\n Aglyn.registerConsoleExtension({\n pluginId: BUNDLE_ID,\n displayName: 'Events Calendar',\n featureFlag: 'eventCalendar',\n // `eventCalendar` is false on every plan — it is sold as a per-org\n // add-on and nothing else — so the shell's generic \"not included in your\n // current plan\" would send a reader to compare tiers that all say no.\n // The price comes from the constant the invoice is built from, so this\n // sentence cannot drift away from what a purchase actually charges.\n upgradeNotice: {\n message:\n 'The Event Calendar is a paid add-on ' +\n `($${Aglyn.EVENT_CALENDAR_ADDON_MONTHLY_USD}/mo for your whole ` +\n `workspace, supported directly by ${Aglyn.PLATFORM_BRAND_NAME}). ` +\n 'Enable it from Billing → Add-ons.',\n billingAnchor: 'addons',\n },\n navItems: [\n {\n label: 'Events',\n href: '/events',\n // Reuse the existing release-flag nav-tab so staff-preview gating\n // is unchanged now that the tab comes from the plugin (AGL-394).\n navTabId: 'nav-tab-events',\n icon: { path: mdiCalendarMonthOutline.path },\n header: {\n title: 'Events',\n icon: { path: mdiCalendarMonthOutline.path },\n docsTopic: 'events',\n },\n Component: EventsConsolePage,\n },\n ],\n dashboardCards: [{ cardId: 'events-upcoming', title: 'Upcoming events' }],\n })\n}\n\nexport * from './site'\n"],"names":["Aglyn","mdiCalendarMonthOutline","lazy","BUNDLE_ID","EventsConsolePage","registerEventsCalendarConsole","registerConsoleExtension","pluginId","displayName","featureFlag","upgradeNotice","message","EVENT_CALENDAR_ADDON_MONTHLY_USD","PLATFORM_BRAND_NAME","billingAnchor","navItems","label","href","navTabId","icon","path","header","title","docsTopic","Component","dashboardCards","cardId"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,uBAAuB,QAAQ,yBAAwB;AAChE,SAASC,IAAI,QAAQ,QAAO;AAC5B,SAASC,SAAS,QAAQ,+BAA2B;AAErD;;;;CAIC,GACD,MAAMC,oBAAoBF,KAAK,IAAM,MAAM,CAAC;AAE5C;;;;;;CAMC,GACD,OAAO,SAASG;IACdL,MAAMM,wBAAwB,CAAC;QAC7BC,UAAUJ;QACVK,aAAa;QACbC,aAAa;QACb,mEAAmE;QACnE,yEAAyE;QACzE,sEAAsE;QACtE,uEAAuE;QACvE,oEAAoE;QACpEC,eAAe;YACbC,SACE,yCACA,CAAC,EAAE,EAAEX,MAAMY,gCAAgC,CAAC,mBAAmB,CAAC,GAChE,CAAC,iCAAiC,EAAEZ,MAAMa,mBAAmB,CAAC,GAAG,CAAC,GAClE;YACFC,eAAe;QACjB;QACAC,UAAU;YACR;gBACEC,OAAO;gBACPC,MAAM;gBACN,kEAAkE;gBAClE,iEAAiE;gBACjEC,UAAU;gBACVC,MAAM;oBAAEC,MAAMnB,wBAAwBmB,IAAI;gBAAC;gBAC3CC,QAAQ;oBACNC,OAAO;oBACPH,MAAM;wBAAEC,MAAMnB,wBAAwBmB,IAAI;oBAAC;oBAC3CG,WAAW;gBACb;gBACAC,WAAWpB;YACb;SACD;QACDqB,gBAAgB;YAAC;gBAAEC,QAAQ;gBAAmBJ,OAAO;YAAkB;SAAE;IAC3E;AACF;AAEA,cAAc,YAAQ"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
export declare function registerEventsCalendarApi(): void;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /**
|
|
17
|
+
* Server half of the events-calendar plugin (AGL-396): the reference API
|
|
18
|
+
* migration. Registers the public `events/list` handler with the plugin API
|
|
19
|
+
* registry; the app dispatcher serves it at the unchanged `/api/events/list`
|
|
20
|
+
* URL. This module imports firebase-admin, so it is NOT re-exported from the
|
|
21
|
+
* plugin's client barrel — apps import `@aglyn/plugins-events-calendar/server`
|
|
22
|
+
* only from their (server-only) API dispatcher.
|
|
23
|
+
*/ import { checkEntitlement, isSiteEventType, registerPluginApiRoute, resolveSocialImage } from "@aglyn/aglyn/server";
|
|
24
|
+
import { firebaseAdmin, getOrgForHost } from "@aglyn/tenant-data-admin";
|
|
25
|
+
import { dispatchHostAutomation } from "@aglyn/tenant-runtime";
|
|
26
|
+
/**
|
|
27
|
+
* Public event listing (AGL-145): published events for the Event List canvas
|
|
28
|
+
* element. Drafts never leave the server; the paid `eventCalendar` add-on
|
|
29
|
+
* gates plan-holding workspaces (dark-launch workspaces pass). Sorted by start;
|
|
30
|
+
* `mode=past` flips the window.
|
|
31
|
+
*/ const eventsListHandler = async (req, res)=>{
|
|
32
|
+
var _req_query_hostId;
|
|
33
|
+
if (req.method !== 'GET') {
|
|
34
|
+
return res.status(405).json({
|
|
35
|
+
error: 'Method not allowed'
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const hostId = String((_req_query_hostId = req.query['hostId']) != null ? _req_query_hostId : '');
|
|
39
|
+
const mode = req.query['mode'] === 'past' ? 'past' : 'upcoming';
|
|
40
|
+
if (!hostId) return res.status(400).json({
|
|
41
|
+
error: 'Missing hostId'
|
|
42
|
+
});
|
|
43
|
+
try {
|
|
44
|
+
var _hostSnapshot_get, _hostSnapshot_get1;
|
|
45
|
+
const firestore = firebaseAdmin.app().firestore();
|
|
46
|
+
const hostRef = firestore.collection('hosts').doc(hostId);
|
|
47
|
+
const hostSnapshot = await hostRef.get();
|
|
48
|
+
if (!hostSnapshot.exists) {
|
|
49
|
+
return res.status(404).json({
|
|
50
|
+
error: 'Unknown site'
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
{
|
|
54
|
+
var _this;
|
|
55
|
+
// Plan/quota gates ride the owning org's doc (AGL-238).
|
|
56
|
+
const org = (_this = await getOrgForHost(hostId)) == null ? void 0 : _this.org;
|
|
57
|
+
if (!checkEntitlement(org, 'eventCalendar')) {
|
|
58
|
+
return res.status(200).json({
|
|
59
|
+
events: []
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const nowMs = Date.now();
|
|
64
|
+
const eventsQuery = mode === 'past' ? hostRef.collection('events').where('startsAtMs', '<', nowMs).orderBy('startsAtMs', 'desc').limit(50) : hostRef.collection('events').where('startsAtMs', '>=', nowMs).orderBy('startsAtMs', 'asc').limit(50);
|
|
65
|
+
// The site's own identity, for absolutizing the cover below (AGL-1351).
|
|
66
|
+
// The host doc is already in hand — this costs no read.
|
|
67
|
+
const host = {
|
|
68
|
+
$id: hostId,
|
|
69
|
+
cname: (_hostSnapshot_get = hostSnapshot.get('cname')) != null ? _hostSnapshot_get : null,
|
|
70
|
+
subdomain: (_hostSnapshot_get1 = hostSnapshot.get('subdomain')) != null ? _hostSnapshot_get1 : null
|
|
71
|
+
};
|
|
72
|
+
const snapshot = await eventsQuery.get();
|
|
73
|
+
const events = snapshot.docs.filter((doc)=>doc.get('status') === 'published' && !doc.get('deletedAt')).map((doc)=>{
|
|
74
|
+
var _doc_get, _doc_get1, _doc_get2, _doc_get3, _doc_get4, _doc_get5, _ref, _doc_get6;
|
|
75
|
+
var _resolveSocialImage;
|
|
76
|
+
return {
|
|
77
|
+
$id: doc.id,
|
|
78
|
+
title: (_doc_get = doc.get('title')) != null ? _doc_get : '',
|
|
79
|
+
startsAtMs: Number((_doc_get1 = doc.get('startsAtMs')) != null ? _doc_get1 : 0),
|
|
80
|
+
endsAtMs: Number((_doc_get2 = doc.get('endsAtMs')) != null ? _doc_get2 : 0),
|
|
81
|
+
location: (_doc_get3 = doc.get('location')) != null ? _doc_get3 : null,
|
|
82
|
+
organizer: (_doc_get4 = doc.get('organizer')) != null ? _doc_get4 : null,
|
|
83
|
+
description: (_doc_get5 = doc.get('description')) != null ? _doc_get5 : null,
|
|
84
|
+
// ABSOLUTE, resolved here rather than shipped as stored (AGL-1351).
|
|
85
|
+
//
|
|
86
|
+
// "Cover image URL" is a free text field, so what an author types is
|
|
87
|
+
// frequently a site-relative path — which the browser resolves against
|
|
88
|
+
// the page and a crawler reading the `Event` JSON-LD cannot resolve at
|
|
89
|
+
// all. That is the AGL-1337/AGL-1343 defect a third time over, and it
|
|
90
|
+
// is fixed HERE because this is the only place that knows which site
|
|
91
|
+
// the events belong to: `EventList` is a client block whose
|
|
92
|
+
// `useSite()` carries a `hostId` and no origin, and in Preview the
|
|
93
|
+
// page origin is the console's, not the site's.
|
|
94
|
+
//
|
|
95
|
+
// Absolutizing also repairs the visible thumbnail on that surface: a
|
|
96
|
+
// relative cover in Preview resolved against the console and 404'd.
|
|
97
|
+
coverImage: (_ref = (_resolveSocialImage = resolveSocialImage({
|
|
98
|
+
sources: [
|
|
99
|
+
{
|
|
100
|
+
image: doc.get('coverImage')
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
host
|
|
104
|
+
})) == null ? void 0 : _resolveSocialImage.url) != null ? _ref : null,
|
|
105
|
+
// The author's description of that cover (AGL-2418). Passed through
|
|
106
|
+
// as stored — unlike the URL beside it there is nothing to resolve,
|
|
107
|
+
// and the renderer owns the "blank means decorative" decision.
|
|
108
|
+
coverImageAlt: (_doc_get6 = doc.get('coverImageAlt')) != null ? _doc_get6 : null
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
// Cacheable: published events change rarely; CDN may hold for a minute.
|
|
112
|
+
res.setHeader('Cache-Control', 'public, s-maxage=60');
|
|
113
|
+
return res.status(200).json({
|
|
114
|
+
events
|
|
115
|
+
});
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error(error);
|
|
118
|
+
return res.status(500).json({
|
|
119
|
+
error: 'Event listing failed'
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
/** Registers the events-calendar plugin's API routes with the dispatcher. */ /**
|
|
124
|
+
* Site-event dispatch (AGL-256): the page runtime evaluates client-side
|
|
125
|
+
* trigger conditions (scroll thresholds, selectors, dwell time) and posts
|
|
126
|
+
* the fired action here so its SERVER steps run. Only site-event actions
|
|
127
|
+
* dispatch this way — server events keep their own emitters. Payload
|
|
128
|
+
* fields are bounded strings; the run cap and `actions` entitlement gate
|
|
129
|
+
* inside the runner.
|
|
130
|
+
*/ const eventsDispatchHandler = async (req, res)=>{
|
|
131
|
+
var _ref, _ref1, _ref2;
|
|
132
|
+
var _req_body, _req_body1, _req_body2, _req_body3;
|
|
133
|
+
if (req.method !== 'POST') {
|
|
134
|
+
return res.status(405).json({
|
|
135
|
+
error: 'Method not allowed'
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
const hostId = String((_ref = (_req_body = req.body) == null ? void 0 : _req_body.hostId) != null ? _ref : '');
|
|
139
|
+
const actionId = String((_ref1 = (_req_body1 = req.body) == null ? void 0 : _req_body1.actionId) != null ? _ref1 : '');
|
|
140
|
+
const event = String((_ref2 = (_req_body2 = req.body) == null ? void 0 : _req_body2.event) != null ? _ref2 : '');
|
|
141
|
+
if (!hostId || !actionId || !isSiteEventType(event)) {
|
|
142
|
+
return res.status(400).json({
|
|
143
|
+
error: 'Bad dispatch'
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
const raw = (_req_body3 = req.body) == null ? void 0 : _req_body3.payload;
|
|
147
|
+
const payload = {};
|
|
148
|
+
if (raw && typeof raw === 'object') {
|
|
149
|
+
for (const [key, value] of Object.entries(raw).slice(0, 20)){
|
|
150
|
+
if (/^[a-zA-Z][a-zA-Z0-9_]{0,39}$/.test(key)) {
|
|
151
|
+
payload[key] = String(value).slice(0, 500);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const alerts = await dispatchHostAutomation(hostId, actionId, event, payload);
|
|
156
|
+
return res.status(200).json({
|
|
157
|
+
ok: true,
|
|
158
|
+
alerts
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
export function registerEventsCalendarApi() {
|
|
162
|
+
registerPluginApiRoute('events/list', eventsListHandler);
|
|
163
|
+
registerPluginApiRoute('events/dispatch', eventsDispatchHandler);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/plugins/events-calendar/src/lib/server.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Server half of the events-calendar plugin (AGL-396): the reference API\n * migration. Registers the public `events/list` handler with the plugin API\n * registry; the app dispatcher serves it at the unchanged `/api/events/list`\n * URL. This module imports firebase-admin, so it is NOT re-exported from the\n * plugin's client barrel — apps import `@aglyn/plugins-events-calendar/server`\n * only from their (server-only) API dispatcher.\n */\n\nimport {\n checkEntitlement,\n isSiteEventType,\n registerPluginApiRoute,\n resolveSocialImage,\n type PluginApiHandler,\n} from '@aglyn/aglyn/server'\nimport { firebaseAdmin, getOrgForHost } from '@aglyn/tenant-data-admin'\nimport { dispatchHostAutomation } from '@aglyn/tenant-runtime'\n\n/**\n * Public event listing (AGL-145): published events for the Event List canvas\n * element. Drafts never leave the server; the paid `eventCalendar` add-on\n * gates plan-holding workspaces (dark-launch workspaces pass). Sorted by start;\n * `mode=past` flips the window.\n */\nconst eventsListHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'GET') {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n const hostId = String(req.query['hostId'] ?? '')\n const mode = req.query['mode'] === 'past' ? 'past' : 'upcoming'\n if (!hostId) return res.status(400).json({ error: 'Missing hostId' })\n\n try {\n const firestore = firebaseAdmin.app().firestore()\n const hostRef = firestore.collection('hosts').doc(hostId)\n const hostSnapshot = await hostRef.get()\n if (!hostSnapshot.exists) {\n return res.status(404).json({ error: 'Unknown site' })\n }\n {\n // Plan/quota gates ride the owning org's doc (AGL-238).\n const org = (await getOrgForHost(hostId))?.org\n if (!checkEntitlement(org as never, 'eventCalendar')) {\n return res.status(200).json({ events: [] })\n }\n }\n\n const nowMs = Date.now()\n const eventsQuery =\n mode === 'past'\n ? hostRef\n .collection('events')\n .where('startsAtMs', '<', nowMs)\n .orderBy('startsAtMs', 'desc')\n .limit(50)\n : hostRef\n .collection('events')\n .where('startsAtMs', '>=', nowMs)\n .orderBy('startsAtMs', 'asc')\n .limit(50)\n // The site's own identity, for absolutizing the cover below (AGL-1351).\n // The host doc is already in hand — this costs no read.\n const host = {\n $id: hostId,\n cname: hostSnapshot.get('cname') ?? null,\n subdomain: hostSnapshot.get('subdomain') ?? null,\n }\n\n const snapshot = await eventsQuery.get()\n const events = snapshot.docs\n .filter(\n (doc) => doc.get('status') === 'published' && !doc.get('deletedAt'),\n )\n .map((doc) => ({\n $id: doc.id,\n title: doc.get('title') ?? '',\n startsAtMs: Number(doc.get('startsAtMs') ?? 0),\n endsAtMs: Number(doc.get('endsAtMs') ?? 0),\n location: doc.get('location') ?? null,\n organizer: doc.get('organizer') ?? null,\n description: doc.get('description') ?? null,\n // ABSOLUTE, resolved here rather than shipped as stored (AGL-1351).\n //\n // \"Cover image URL\" is a free text field, so what an author types is\n // frequently a site-relative path — which the browser resolves against\n // the page and a crawler reading the `Event` JSON-LD cannot resolve at\n // all. That is the AGL-1337/AGL-1343 defect a third time over, and it\n // is fixed HERE because this is the only place that knows which site\n // the events belong to: `EventList` is a client block whose\n // `useSite()` carries a `hostId` and no origin, and in Preview the\n // page origin is the console's, not the site's.\n //\n // Absolutizing also repairs the visible thumbnail on that surface: a\n // relative cover in Preview resolved against the console and 404'd.\n coverImage:\n resolveSocialImage({\n sources: [{ image: doc.get('coverImage') }],\n host,\n })?.url ?? null,\n // The author's description of that cover (AGL-2418). Passed through\n // as stored — unlike the URL beside it there is nothing to resolve,\n // and the renderer owns the \"blank means decorative\" decision.\n coverImageAlt: doc.get('coverImageAlt') ?? null,\n }))\n // Cacheable: published events change rarely; CDN may hold for a minute.\n res.setHeader('Cache-Control', 'public, s-maxage=60')\n return res.status(200).json({ events })\n } catch (error) {\n console.error(error)\n return res.status(500).json({ error: 'Event listing failed' })\n }\n}\n\n/** Registers the events-calendar plugin's API routes with the dispatcher. */\n/**\n * Site-event dispatch (AGL-256): the page runtime evaluates client-side\n * trigger conditions (scroll thresholds, selectors, dwell time) and posts\n * the fired action here so its SERVER steps run. Only site-event actions\n * dispatch this way — server events keep their own emitters. Payload\n * fields are bounded strings; the run cap and `actions` entitlement gate\n * inside the runner.\n */\nconst eventsDispatchHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') {\n return res.status(405).json({ error: 'Method not allowed' })\n }\n const hostId = String(req.body?.hostId ?? '')\n const actionId = String(req.body?.actionId ?? '')\n const event = String(req.body?.event ?? '')\n if (!hostId || !actionId || !isSiteEventType(event)) {\n return res.status(400).json({ error: 'Bad dispatch' })\n }\n const raw = req.body?.payload\n const payload: Record<string, string> = {}\n if (raw && typeof raw === 'object') {\n for (const [key, value] of Object.entries(raw).slice(0, 20)) {\n if (/^[a-zA-Z][a-zA-Z0-9_]{0,39}$/.test(key)) {\n payload[key] = String(value).slice(0, 500)\n }\n }\n }\n const alerts = await dispatchHostAutomation(hostId, actionId, event, payload)\n return res.status(200).json({ ok: true, alerts })\n}\n\nexport function registerEventsCalendarApi(): void {\n registerPluginApiRoute('events/list', eventsListHandler)\n registerPluginApiRoute('events/dispatch', eventsDispatchHandler)\n}\n"],"names":["checkEntitlement","isSiteEventType","registerPluginApiRoute","resolveSocialImage","firebaseAdmin","getOrgForHost","dispatchHostAutomation","eventsListHandler","req","res","method","status","json","error","hostId","String","query","mode","hostSnapshot","firestore","app","hostRef","collection","doc","get","exists","org","events","nowMs","Date","now","eventsQuery","where","orderBy","limit","host","$id","cname","subdomain","snapshot","docs","filter","map","id","title","startsAtMs","Number","endsAtMs","location","organizer","description","coverImage","sources","image","url","coverImageAlt","setHeader","console","eventsDispatchHandler","body","actionId","event","raw","payload","key","value","Object","entries","slice","test","alerts","ok","registerEventsCalendarApi"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import * as Aglyn from '@aglyn/aglyn';
|
|
18
|
+
/**
|
|
19
|
+
* Events Calendar feature plugin (AGL-313): the reference extraction of
|
|
20
|
+
* the AGL-277 pattern. The `event-list` component moved here from
|
|
21
|
+
* `plugins-mui` — component ids resolve by componentId, so legacy
|
|
22
|
+
* screen nodes persisted with pluginId 'mui' keep rendering; the mui
|
|
23
|
+
* bundle no longer registers it. The console half declares the Events
|
|
24
|
+
* nav/dashboard surface through the ConsoleExtension registry, gated by
|
|
25
|
+
* the `eventCalendar` entitlement.
|
|
26
|
+
*/
|
|
27
|
+
export declare const EVENTS_CALENDAR_BUNDLE: Aglyn.FeatureBundleEntry[];
|
|
28
|
+
export declare function registerEventsCalendarPlugin(): void;
|
package/src/lib/site.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ import * as Aglyn from "@aglyn/aglyn";
|
|
17
|
+
import { mdiCalendarMonthOutline } from "@aglyn/shared-data-mdi";
|
|
18
|
+
import * as EventList from "./components/event-list.js";
|
|
19
|
+
import { BUNDLE_ID } from "./constants/bundle-common.js";
|
|
20
|
+
/**
|
|
21
|
+
* Events Calendar feature plugin (AGL-313): the reference extraction of
|
|
22
|
+
* the AGL-277 pattern. The `event-list` component moved here from
|
|
23
|
+
* `plugins-mui` — component ids resolve by componentId, so legacy
|
|
24
|
+
* screen nodes persisted with pluginId 'mui' keep rendering; the mui
|
|
25
|
+
* bundle no longer registers it. The console half declares the Events
|
|
26
|
+
* nav/dashboard surface through the ConsoleExtension registry, gated by
|
|
27
|
+
* the `eventCalendar` entitlement.
|
|
28
|
+
*/ export const EVENTS_CALENDAR_BUNDLE = [
|
|
29
|
+
{
|
|
30
|
+
component: EventList.default,
|
|
31
|
+
schema: EventList.schema,
|
|
32
|
+
presets: EventList.presets
|
|
33
|
+
}
|
|
34
|
+
];
|
|
35
|
+
export function registerEventsCalendarPlugin() {
|
|
36
|
+
// The canvas half only. The console registers the console half through its
|
|
37
|
+
// own `console` surface, and a published page must never load console code
|
|
38
|
+
// (AGL-3116): this runs on every page that places one of these elements.
|
|
39
|
+
if (Aglyn.plugins.getDependency(BUNDLE_ID)) return;
|
|
40
|
+
Aglyn.plugins.addDependency(Aglyn.defineUiFeatureBundle({
|
|
41
|
+
bundleId: BUNDLE_ID,
|
|
42
|
+
displayName: 'Events Calendar',
|
|
43
|
+
description: 'Published events list with schema.org markup',
|
|
44
|
+
icon: {
|
|
45
|
+
path: mdiCalendarMonthOutline.path
|
|
46
|
+
},
|
|
47
|
+
components: EVENTS_CALENDAR_BUNDLE
|
|
48
|
+
}, Aglyn.components));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=site.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/plugins/events-calendar/src/lib/site.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { mdiCalendarMonthOutline } from '@aglyn/shared-data-mdi'\nimport * as EventList from './components/event-list'\nimport { BUNDLE_ID } from './constants/bundle-common'\n\n/**\n * Events Calendar feature plugin (AGL-313): the reference extraction of\n * the AGL-277 pattern. The `event-list` component moved here from\n * `plugins-mui` — component ids resolve by componentId, so legacy\n * screen nodes persisted with pluginId 'mui' keep rendering; the mui\n * bundle no longer registers it. The console half declares the Events\n * nav/dashboard surface through the ConsoleExtension registry, gated by\n * the `eventCalendar` entitlement.\n */\nexport const EVENTS_CALENDAR_BUNDLE: Aglyn.FeatureBundleEntry[] = [\n {\n component: EventList.default,\n schema: EventList.schema,\n presets: EventList.presets,\n },\n]\n\nexport function registerEventsCalendarPlugin(): void {\n // The canvas half only. The console registers the console half through its\n // own `console` surface, and a published page must never load console code\n // (AGL-3116): this runs on every page that places one of these elements.\n if (Aglyn.plugins.getDependency(BUNDLE_ID)) return\n Aglyn.plugins.addDependency(\n Aglyn.defineUiFeatureBundle(\n {\n bundleId: BUNDLE_ID,\n displayName: 'Events Calendar',\n description: 'Published events list with schema.org markup',\n icon: { path: mdiCalendarMonthOutline.path },\n components: EVENTS_CALENDAR_BUNDLE,\n },\n Aglyn.components,\n ),\n )\n}\n"],"names":["Aglyn","mdiCalendarMonthOutline","EventList","BUNDLE_ID","EVENTS_CALENDAR_BUNDLE","component","default","schema","presets","registerEventsCalendarPlugin","plugins","getDependency","addDependency","defineUiFeatureBundle","bundleId","displayName","description","icon","path","components"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,uBAAuB,QAAQ,yBAAwB;AAChE,YAAYC,eAAe,6BAAyB;AACpD,SAASC,SAAS,QAAQ,+BAA2B;AAErD;;;;;;;;CAQC,GACD,OAAO,MAAMC,yBAAqD;IAChE;QACEC,WAAWH,UAAUI,OAAO;QAC5BC,QAAQL,UAAUK,MAAM;QACxBC,SAASN,UAAUM,OAAO;IAC5B;CACD,CAAA;AAED,OAAO,SAASC;IACd,2EAA2E;IAC3E,2EAA2E;IAC3E,yEAAyE;IACzE,IAAIT,MAAMU,OAAO,CAACC,aAAa,CAACR,YAAY;IAC5CH,MAAMU,OAAO,CAACE,aAAa,CACzBZ,MAAMa,qBAAqB,CACzB;QACEC,UAAUX;QACVY,aAAa;QACbC,aAAa;QACbC,MAAM;YAAEC,MAAMjB,wBAAwBiB,IAAI;QAAC;QAC3CC,YAAYf;IACd,GACAJ,MAAMmB,UAAU;AAGtB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import type { ComponentId } from '@aglyn/aglyn';
|
|
18
|
+
export declare const generatePresetId: (componentId: ComponentId, ...other: string[]) => ComponentId;
|
|
19
|
+
export default generatePresetId;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
17
|
+
export const generatePresetId = (componentId, ...other)=>{
|
|
18
|
+
return `${BUNDLE_ID}:${[
|
|
19
|
+
componentId,
|
|
20
|
+
...other
|
|
21
|
+
].join('.')}`;
|
|
22
|
+
};
|
|
23
|
+
export default generatePresetId;
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=generate-preset-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/events-calendar/src/lib/utils/generate-preset-id.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ComponentId } from '@aglyn/aglyn'\nimport { BUNDLE_ID } from '../constants/bundle-common'\n\nexport const generatePresetId = (\n componentId: ComponentId,\n ...other: string[]\n): ComponentId => {\n return `${BUNDLE_ID}:${[componentId, ...other].join('.')}`\n}\n\nexport default generatePresetId\n"],"names":["BUNDLE_ID","generatePresetId","componentId","other","join"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAGD,SAASA,SAAS,QAAQ,gCAA4B;AAEtD,OAAO,MAAMC,mBAAmB,CAC9BC,aACA,GAAGC;IAEH,OAAO,GAAGH,UAAU,CAAC,EAAE;QAACE;WAAgBC;KAAM,CAACC,IAAI,CAAC,MAAM;AAC5D,EAAC;AAED,eAAeH,iBAAgB"}
|