@aglyn/plugins-inbox 1.0.0-beta.179 → 1.0.0-beta.180
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/package.json +10 -10
- package/src/lib/components/contacts-card.component.d.ts +10 -2
- package/src/lib/components/contacts-card.component.js +94 -41
- package/src/lib/components/contacts-card.component.js.map +1 -1
- package/src/lib/components/inbox-attribution-zone.d.ts +9 -1
- package/src/lib/components/inbox-attribution-zone.js +1 -1
- package/src/lib/components/inbox-attribution-zone.js.map +1 -1
- package/src/lib/components/inbox-console-page.d.ts +4 -0
- package/src/lib/components/inbox-console-page.js +119 -13
- package/src/lib/components/inbox-console-page.js.map +1 -1
- package/src/lib/components/inbox-console-sections.d.ts +13 -0
- package/src/lib/components/inbox-console-sections.js +18 -3
- package/src/lib/components/inbox-console-sections.js.map +1 -1
- package/src/lib/components/inbox-glance-card.component.js +6 -1
- package/src/lib/components/inbox-glance-card.component.js.map +1 -1
- package/src/lib/components/inbox-org-sites.d.ts +27 -0
- package/src/lib/components/inbox-org-sites.js +31 -0
- package/src/lib/components/inbox-org-sites.js.map +1 -0
- package/src/lib/components/submissions-card.component.d.ts +10 -2
- package/src/lib/components/submissions-card.component.js +89 -29
- package/src/lib/components/submissions-card.component.js.map +1 -1
- package/src/lib/components/use-inbox-site-pick.d.ts +38 -0
- package/src/lib/components/use-inbox-site-pick.js +99 -0
- package/src/lib/components/use-inbox-site-pick.js.map +1 -0
- package/src/lib/components/use-record-route-context.d.ts +8 -3
- package/src/lib/components/use-record-route-context.js +10 -6
- package/src/lib/components/use-record-route-context.js.map +1 -1
- package/src/lib/plugin.d.ts +4 -3
- package/src/lib/plugin.js +35 -5
- package/src/lib/plugin.js.map +1 -1
|
@@ -0,0 +1,99 @@
|
|
|
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
|
+
*/ 'use client';
|
|
17
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
18
|
+
const NO_HOSTS = [];
|
|
19
|
+
/**
|
|
20
|
+
* The session's memory of the pick, per org. Session storage, as the CRM's
|
|
21
|
+
* create-site pick is kept: the section rail is a set of routes, so the page
|
|
22
|
+
* mounts again on every section, and a filter that reset on each one would
|
|
23
|
+
* read as the rail having thrown the reader's choice away.
|
|
24
|
+
*/ export const inboxSitePickKey = (orgId)=>`aglyn.inbox.site.${orgId}`;
|
|
25
|
+
function readPick(orgId) {
|
|
26
|
+
try {
|
|
27
|
+
return window.sessionStorage.getItem(inboxSitePickKey(orgId));
|
|
28
|
+
} catch (unused) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function writePick(orgId, hostId) {
|
|
33
|
+
try {
|
|
34
|
+
if (hostId) window.sessionStorage.setItem(inboxSitePickKey(orgId), hostId);
|
|
35
|
+
else window.sessionStorage.removeItem(inboxSitePickKey(orgId));
|
|
36
|
+
} catch (unused) {
|
|
37
|
+
// A browser that refuses storage still gets the pick for this page.
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The org Inbox's site filter. Handed no mount — under a site — it answers
|
|
42
|
+
* no pick and is never ready, and the page reads its own `hostId` instead.
|
|
43
|
+
*/ export function useInboxSitePick(mount) {
|
|
44
|
+
var _ref, _ref1;
|
|
45
|
+
const orgId = (_ref = mount == null ? void 0 : mount.orgId) != null ? _ref : null;
|
|
46
|
+
const hosts = (_ref1 = mount == null ? void 0 : mount.hosts) != null ? _ref1 : NO_HOSTS;
|
|
47
|
+
const hostsReady = Boolean(mount == null ? void 0 : mount.hostsReady);
|
|
48
|
+
/*
|
|
49
|
+
* Read after mount, not in the initializer, so the server and the first
|
|
50
|
+
* client paint agree. Held with the org it was read for, so a switch of
|
|
51
|
+
* workspace never applies one org's pick to another's sites.
|
|
52
|
+
*/ const [memory, setMemory] = useState(null);
|
|
53
|
+
useEffect(()=>{
|
|
54
|
+
if (orgId) setMemory({
|
|
55
|
+
orgId,
|
|
56
|
+
hostId: readPick(orgId)
|
|
57
|
+
});
|
|
58
|
+
}, [
|
|
59
|
+
orgId
|
|
60
|
+
]);
|
|
61
|
+
const loaded = Boolean(orgId) && (memory == null ? void 0 : memory.orgId) === orgId;
|
|
62
|
+
const hostId = useMemo(()=>{
|
|
63
|
+
if (!hostsReady) return null;
|
|
64
|
+
if (hosts.length === 1) return hosts[0].id;
|
|
65
|
+
const remembered = loaded ? memory == null ? void 0 : memory.hostId : null;
|
|
66
|
+
// A remembered site the list no longer carries is forgotten, not read.
|
|
67
|
+
return remembered && hosts.some((host)=>host.id === remembered) ? remembered : null;
|
|
68
|
+
}, [
|
|
69
|
+
hostsReady,
|
|
70
|
+
hosts,
|
|
71
|
+
loaded,
|
|
72
|
+
memory
|
|
73
|
+
]);
|
|
74
|
+
const options = useMemo(()=>hosts.length > 1 ? hosts.map((host)=>({
|
|
75
|
+
value: host.id,
|
|
76
|
+
label: host.name || host.subdomain || host.id
|
|
77
|
+
})) : [], [
|
|
78
|
+
hosts
|
|
79
|
+
]);
|
|
80
|
+
const setHostId = useCallback((next)=>{
|
|
81
|
+
if (!orgId) return;
|
|
82
|
+
setMemory({
|
|
83
|
+
orgId,
|
|
84
|
+
hostId: next
|
|
85
|
+
});
|
|
86
|
+
writePick(orgId, next);
|
|
87
|
+
}, [
|
|
88
|
+
orgId
|
|
89
|
+
]);
|
|
90
|
+
return {
|
|
91
|
+
hostId,
|
|
92
|
+
ready: loaded && hostsReady,
|
|
93
|
+
options,
|
|
94
|
+
setHostId
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
export default useInboxSitePick;
|
|
98
|
+
|
|
99
|
+
//# sourceMappingURL=use-inbox-site-pick.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/inbox/src/lib/components/use-inbox-site-pick.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'use client'\n\nimport type { ConsolePluginOrgMount } from '@aglyn/aglyn'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\n\n/**\n * The site the organization's Inbox is narrowed to (AGL-3303).\n *\n * `hostId` is `null` for every site at once — the default — or the one site\n * the reader picked, whose own view the page then draws: its submissions\n * with their form filter, its members beside its leads, its campaigns and\n * its ceiling notices. An organization with ONE site has nothing to choose\n * between, so that site is the pick and no picker is offered.\n */\nexport interface InboxSitePick {\n hostId: string | null\n /**\n * False until the remembered pick has been read and the org's sites have\n * settled. A section drawn before then would open the every-site reads for\n * a page about to switch to one site's, and bill both.\n */\n ready: boolean\n /** The sites to choose between, by name — empty when there is one or none. */\n options: ReadonlyArray<{ value: string; label: string }>\n setHostId: (hostId: string | null) => void\n}\n\nconst NO_HOSTS: ConsolePluginOrgMount['hosts'] = []\n\n/**\n * The session's memory of the pick, per org. Session storage, as the CRM's\n * create-site pick is kept: the section rail is a set of routes, so the page\n * mounts again on every section, and a filter that reset on each one would\n * read as the rail having thrown the reader's choice away.\n */\nexport const inboxSitePickKey = (orgId: string) => `aglyn.inbox.site.${orgId}`\n\nfunction readPick(orgId: string): string | null {\n try {\n return window.sessionStorage.getItem(inboxSitePickKey(orgId))\n } catch {\n return null\n }\n}\n\nfunction writePick(orgId: string, hostId: string | null): void {\n try {\n if (hostId) window.sessionStorage.setItem(inboxSitePickKey(orgId), hostId)\n else window.sessionStorage.removeItem(inboxSitePickKey(orgId))\n } catch {\n // A browser that refuses storage still gets the pick for this page.\n }\n}\n\n/**\n * The org Inbox's site filter. Handed no mount — under a site — it answers\n * no pick and is never ready, and the page reads its own `hostId` instead.\n */\nexport function useInboxSitePick(\n mount: ConsolePluginOrgMount | undefined,\n): InboxSitePick {\n const orgId = mount?.orgId ?? null\n const hosts = mount?.hosts ?? NO_HOSTS\n const hostsReady = Boolean(mount?.hostsReady)\n /*\n * Read after mount, not in the initializer, so the server and the first\n * client paint agree. Held with the org it was read for, so a switch of\n * workspace never applies one org's pick to another's sites.\n */\n const [memory, setMemory] = useState<{\n orgId: string\n hostId: string | null\n } | null>(null)\n useEffect(() => {\n if (orgId) setMemory({ orgId, hostId: readPick(orgId) })\n }, [orgId])\n const loaded = Boolean(orgId) && memory?.orgId === orgId\n\n const hostId = useMemo(() => {\n if (!hostsReady) return null\n if (hosts.length === 1) return hosts[0].id\n const remembered = loaded ? memory?.hostId : null\n // A remembered site the list no longer carries is forgotten, not read.\n return remembered && hosts.some((host) => host.id === remembered)\n ? remembered\n : null\n }, [hostsReady, hosts, loaded, memory])\n\n const options = useMemo(\n () =>\n hosts.length > 1\n ? hosts.map((host) => ({\n value: host.id,\n label: host.name || host.subdomain || host.id,\n }))\n : [],\n [hosts],\n )\n\n const setHostId = useCallback(\n (next: string | null) => {\n if (!orgId) return\n setMemory({ orgId, hostId: next })\n writePick(orgId, next)\n },\n [orgId],\n )\n\n return { hostId, ready: loaded && hostsReady, options, setHostId }\n}\n\nexport default useInboxSitePick\n"],"names":["useCallback","useEffect","useMemo","useState","NO_HOSTS","inboxSitePickKey","orgId","readPick","window","sessionStorage","getItem","writePick","hostId","setItem","removeItem","useInboxSitePick","mount","hosts","hostsReady","Boolean","memory","setMemory","loaded","length","id","remembered","some","host","options","map","value","label","name","subdomain","setHostId","next","ready"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAGA,SAASA,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AAwBjE,MAAMC,WAA2C,EAAE;AAEnD;;;;;CAKC,GACD,OAAO,MAAMC,mBAAmB,CAACC,QAAkB,CAAC,iBAAiB,EAAEA,OAAO,CAAA;AAE9E,SAASC,SAASD,KAAa;IAC7B,IAAI;QACF,OAAOE,OAAOC,cAAc,CAACC,OAAO,CAACL,iBAAiBC;IACxD,EAAE,eAAM;QACN,OAAO;IACT;AACF;AAEA,SAASK,UAAUL,KAAa,EAAEM,MAAqB;IACrD,IAAI;QACF,IAAIA,QAAQJ,OAAOC,cAAc,CAACI,OAAO,CAACR,iBAAiBC,QAAQM;aAC9DJ,OAAOC,cAAc,CAACK,UAAU,CAACT,iBAAiBC;IACzD,EAAE,eAAM;IACN,oEAAoE;IACtE;AACF;AAEA;;;CAGC,GACD,OAAO,SAASS,iBACdC,KAAwC;;IAExC,MAAMV,gBAAQU,yBAAAA,MAAOV,KAAK,mBAAI;IAC9B,MAAMW,iBAAQD,yBAAAA,MAAOC,KAAK,oBAAIb;IAC9B,MAAMc,aAAaC,QAAQH,yBAAAA,MAAOE,UAAU;IAC5C;;;;GAIC,GACD,MAAM,CAACE,QAAQC,UAAU,GAAGlB,SAGlB;IACVF,UAAU;QACR,IAAIK,OAAOe,UAAU;YAAEf;YAAOM,QAAQL,SAASD;QAAO;IACxD,GAAG;QAACA;KAAM;IACV,MAAMgB,SAASH,QAAQb,UAAUc,CAAAA,0BAAAA,OAAQd,KAAK,MAAKA;IAEnD,MAAMM,SAASV,QAAQ;QACrB,IAAI,CAACgB,YAAY,OAAO;QACxB,IAAID,MAAMM,MAAM,KAAK,GAAG,OAAON,KAAK,CAAC,EAAE,CAACO,EAAE;QAC1C,MAAMC,aAAaH,SAASF,0BAAAA,OAAQR,MAAM,GAAG;QAC7C,uEAAuE;QACvE,OAAOa,cAAcR,MAAMS,IAAI,CAAC,CAACC,OAASA,KAAKH,EAAE,KAAKC,cAClDA,aACA;IACN,GAAG;QAACP;QAAYD;QAAOK;QAAQF;KAAO;IAEtC,MAAMQ,UAAU1B,QACd,IACEe,MAAMM,MAAM,GAAG,IACXN,MAAMY,GAAG,CAAC,CAACF,OAAU,CAAA;gBACnBG,OAAOH,KAAKH,EAAE;gBACdO,OAAOJ,KAAKK,IAAI,IAAIL,KAAKM,SAAS,IAAIN,KAAKH,EAAE;YAC/C,CAAA,KACA,EAAE,EACR;QAACP;KAAM;IAGT,MAAMiB,YAAYlC,YAChB,CAACmC;QACC,IAAI,CAAC7B,OAAO;QACZe,UAAU;YAAEf;YAAOM,QAAQuB;QAAK;QAChCxB,UAAUL,OAAO6B;IACnB,GACA;QAAC7B;KAAM;IAGT,OAAO;QAAEM;QAAQwB,OAAOd,UAAUJ;QAAYU;QAASM;IAAU;AACnE;AAEA,eAAenB,iBAAgB"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { PluginRecordRouteContext } from '@aglyn/aglyn/plugin-manager/plugin-record-routes';
|
|
2
2
|
/**
|
|
3
|
-
* Where this console is — the organization and the site
|
|
4
|
-
* record-route registry for a link, or `null` until the route
|
|
5
|
-
* (AGL-2608).
|
|
3
|
+
* Where this console is — the organization, and the site when there is one —
|
|
4
|
+
* for asking the record-route registry for a link, or `null` until the route
|
|
5
|
+
* params settle (AGL-2608).
|
|
6
6
|
*
|
|
7
7
|
* Both are already in the URL, so no document is read to build a link. What
|
|
8
8
|
* the Inbox does NOT know is the address itself: the plugin that keeps people
|
|
@@ -10,6 +10,11 @@ import type { PluginRecordRouteContext } from '@aglyn/aglyn/plugin-manager/plugi
|
|
|
10
10
|
* `pluginRecordHref('lead', context, id)`. It lists leads; wherever they are
|
|
11
11
|
* worked is that plugin's to say, and a workspace without one gets text
|
|
12
12
|
* instead of a link.
|
|
13
|
+
*
|
|
14
|
+
* On the organization's Inbox the URL names no site, and `host: null` asks
|
|
15
|
+
* for the organization's address (AGL-3303) — the registry's own contract
|
|
16
|
+
* for a surface with no site, which a route answers with `null` for any
|
|
17
|
+
* kind it has no org-level page for.
|
|
13
18
|
*/
|
|
14
19
|
export declare function useRecordRouteContext(): PluginRecordRouteContext | null;
|
|
15
20
|
export default useRecordRouteContext;
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
*/ 'use client';
|
|
17
17
|
import { useParams } from "next/navigation";
|
|
18
18
|
/**
|
|
19
|
-
* Where this console is — the organization and the site
|
|
20
|
-
* record-route registry for a link, or `null` until the route
|
|
21
|
-
* (AGL-2608).
|
|
19
|
+
* Where this console is — the organization, and the site when there is one —
|
|
20
|
+
* for asking the record-route registry for a link, or `null` until the route
|
|
21
|
+
* params settle (AGL-2608).
|
|
22
22
|
*
|
|
23
23
|
* Both are already in the URL, so no document is read to build a link. What
|
|
24
24
|
* the Inbox does NOT know is the address itself: the plugin that keeps people
|
|
@@ -26,14 +26,18 @@ import { useParams } from "next/navigation";
|
|
|
26
26
|
* `pluginRecordHref('lead', context, id)`. It lists leads; wherever they are
|
|
27
27
|
* worked is that plugin's to say, and a workspace without one gets text
|
|
28
28
|
* instead of a link.
|
|
29
|
+
*
|
|
30
|
+
* On the organization's Inbox the URL names no site, and `host: null` asks
|
|
31
|
+
* for the organization's address (AGL-3303) — the registry's own contract
|
|
32
|
+
* for a surface with no site, which a route answers with `null` for any
|
|
33
|
+
* kind it has no org-level page for.
|
|
29
34
|
*/ export function useRecordRouteContext() {
|
|
30
35
|
const params = useParams();
|
|
31
36
|
const orgSlug = params == null ? void 0 : params.orgSlug;
|
|
32
|
-
|
|
33
|
-
if (!orgSlug || !host) return null;
|
|
37
|
+
if (!orgSlug) return null;
|
|
34
38
|
return {
|
|
35
39
|
orgSlug,
|
|
36
|
-
host
|
|
40
|
+
host: (params == null ? void 0 : params.host) || null
|
|
37
41
|
};
|
|
38
42
|
}
|
|
39
43
|
export default useRecordRouteContext;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/inbox/src/lib/components/use-record-route-context.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'use client'\n\nimport type { PluginRecordRouteContext } from '@aglyn/aglyn/plugin-manager/plugin-record-routes'\nimport { useParams } from 'next/navigation'\n\n/**\n * Where this console is — the organization and the site
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/inbox/src/lib/components/use-record-route-context.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'use client'\n\nimport type { PluginRecordRouteContext } from '@aglyn/aglyn/plugin-manager/plugin-record-routes'\nimport { useParams } from 'next/navigation'\n\n/**\n * Where this console is — the organization, and the site when there is one —\n * for asking the record-route registry for a link, or `null` until the route\n * params settle (AGL-2608).\n *\n * Both are already in the URL, so no document is read to build a link. What\n * the Inbox does NOT know is the address itself: the plugin that keeps people\n * publishes where a lead or a contact is read, and the Inbox asks\n * `pluginRecordHref('lead', context, id)`. It lists leads; wherever they are\n * worked is that plugin's to say, and a workspace without one gets text\n * instead of a link.\n *\n * On the organization's Inbox the URL names no site, and `host: null` asks\n * for the organization's address (AGL-3303) — the registry's own contract\n * for a surface with no site, which a route answers with `null` for any\n * kind it has no org-level page for.\n */\nexport function useRecordRouteContext(): PluginRecordRouteContext | null {\n const params = useParams<{ orgSlug: string; host: string }>()\n const orgSlug = params?.orgSlug\n if (!orgSlug) return null\n return { orgSlug, host: params?.host || null }\n}\n\nexport default useRecordRouteContext\n"],"names":["useParams","useRecordRouteContext","params","orgSlug","host"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAGA,SAASA,SAAS,QAAQ,kBAAiB;AAE3C;;;;;;;;;;;;;;;;CAgBC,GACD,OAAO,SAASC;IACd,MAAMC,SAASF;IACf,MAAMG,UAAUD,0BAAAA,OAAQC,OAAO;IAC/B,IAAI,CAACA,SAAS,OAAO;IACrB,OAAO;QAAEA;QAASC,MAAMF,CAAAA,0BAAAA,OAAQE,IAAI,KAAI;IAAK;AAC/C;AAEA,eAAeH,sBAAqB"}
|
package/src/lib/plugin.d.ts
CHANGED
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
* Inbox feature plugin (AGL-395). Console-only — form submissions, site
|
|
19
19
|
* members/leads and campaigns live in Firestore and have no canvas element,
|
|
20
20
|
* so there is no UI bundle. The console half declares the Inbox nav + its
|
|
21
|
-
* three sections through the ConsoleExtension registry (always-on)
|
|
22
|
-
*
|
|
23
|
-
*
|
|
21
|
+
* three sections through the ConsoleExtension registry (always-on), once
|
|
22
|
+
* under each site and once for the organization (AGL-3303). The Campaigns
|
|
23
|
+
* section and the attribution shown inside a submission are zones this
|
|
24
|
+
* plugin hosts; the plugin that owns campaigns draws in them.
|
|
24
25
|
*/
|
|
25
26
|
export declare function registerInboxConsole(): void;
|
package/src/lib/plugin.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/ import * as Aglyn from "@aglyn/aglyn";
|
|
17
17
|
import { mdiInboxArrowDown } from "@aglyn/shared-data-mdi";
|
|
18
18
|
import { lazy } from "react";
|
|
19
|
-
import { INBOX_CONSOLE_SECTIONS } from "./components/inbox-console-sections.js";
|
|
19
|
+
import { INBOX_CONSOLE_SECTIONS, INBOX_ORG_CONSOLE_SECTIONS } from "./components/inbox-console-sections.js";
|
|
20
20
|
import { registerPluginZone } from "@aglyn/aglyn/plugin-manager/plugin-zones";
|
|
21
21
|
import { INBOX_CAMPAIGNS_ZONE, INBOX_RECORD_ATTRIBUTION_ZONE } from "./components/inbox-attribution-zone.js";
|
|
22
22
|
import { BUNDLE_ID } from "./constants/bundle-common.js";
|
|
@@ -30,9 +30,10 @@ import { BUNDLE_ID } from "./constants/bundle-common.js";
|
|
|
30
30
|
* Inbox feature plugin (AGL-395). Console-only — form submissions, site
|
|
31
31
|
* members/leads and campaigns live in Firestore and have no canvas element,
|
|
32
32
|
* so there is no UI bundle. The console half declares the Inbox nav + its
|
|
33
|
-
* three sections through the ConsoleExtension registry (always-on)
|
|
34
|
-
*
|
|
35
|
-
*
|
|
33
|
+
* three sections through the ConsoleExtension registry (always-on), once
|
|
34
|
+
* under each site and once for the organization (AGL-3303). The Campaigns
|
|
35
|
+
* section and the attribution shown inside a submission are zones this
|
|
36
|
+
* plugin hosts; the plugin that owns campaigns draws in them.
|
|
36
37
|
*/ export function registerInboxConsole() {
|
|
37
38
|
registerPluginZone({
|
|
38
39
|
zone: INBOX_RECORD_ATTRIBUTION_ZONE,
|
|
@@ -47,7 +48,7 @@ import { BUNDLE_ID } from "./constants/bundle-common.js";
|
|
|
47
48
|
zone: INBOX_CAMPAIGNS_ZONE,
|
|
48
49
|
label: 'The Inbox’s Campaigns section',
|
|
49
50
|
surface: 'console',
|
|
50
|
-
description: 'The body of the Inbox’s Campaigns tab. A widget here lists the site’s campaigns; it is handed the site and nothing else.'
|
|
51
|
+
description: 'The body of the Inbox’s Campaigns tab. A widget here lists the site’s campaigns; it is handed the site and nothing else — or, on the organization’s Inbox, no site (`hostId: null`) and the organization with its sites (`orgMount`), and lists every site’s.'
|
|
51
52
|
}, {
|
|
52
53
|
pluginId: BUNDLE_ID
|
|
53
54
|
});
|
|
@@ -95,6 +96,35 @@ import { BUNDLE_ID } from "./constants/bundle-common.js";
|
|
|
95
96
|
},
|
|
96
97
|
Component: InboxConsolePage
|
|
97
98
|
}
|
|
99
|
+
],
|
|
100
|
+
/*
|
|
101
|
+
* The ORGANIZATION's Inbox, at `/[orgSlug]/inbox` (AGL-3303): every
|
|
102
|
+
* site's submissions in one list, the organization's leads, and every
|
|
103
|
+
* campaign, with a site filter that narrows the page to one site's own
|
|
104
|
+
* view. The page is the same component; handed no site, it draws the
|
|
105
|
+
* org sections.
|
|
106
|
+
*
|
|
107
|
+
* It carries the SITE tab's id on purpose, as the org CRM and Marketing
|
|
108
|
+
* tabs do: `release_inbox` names `nav-tab-inbox`, so one flag holds both
|
|
109
|
+
* levels and the org Inbox cannot ship while the site's is switched off.
|
|
110
|
+
*/ orgNavItems: [
|
|
111
|
+
{
|
|
112
|
+
label: 'Inbox',
|
|
113
|
+
href: '/inbox',
|
|
114
|
+
sections: INBOX_ORG_CONSOLE_SECTIONS,
|
|
115
|
+
navTabId: 'nav-tab-inbox',
|
|
116
|
+
icon: {
|
|
117
|
+
path: mdiInboxArrowDown.path
|
|
118
|
+
},
|
|
119
|
+
header: {
|
|
120
|
+
title: 'Inbox',
|
|
121
|
+
icon: {
|
|
122
|
+
path: mdiInboxArrowDown.path
|
|
123
|
+
},
|
|
124
|
+
docsTopic: 'forms'
|
|
125
|
+
},
|
|
126
|
+
Component: InboxConsolePage
|
|
127
|
+
}
|
|
98
128
|
]
|
|
99
129
|
});
|
|
100
130
|
}
|
package/src/lib/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/plugins/inbox/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 { mdiInboxArrowDown } from '@aglyn/shared-data-mdi'\nimport { lazy } from 'react'\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/plugins/inbox/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 { mdiInboxArrowDown } from '@aglyn/shared-data-mdi'\nimport { lazy } from 'react'\nimport {\n INBOX_CONSOLE_SECTIONS,\n INBOX_ORG_CONSOLE_SECTIONS,\n} from './components/inbox-console-sections'\nimport { registerPluginZone } from '@aglyn/aglyn/plugin-manager/plugin-zones'\nimport {\n INBOX_CAMPAIGNS_ZONE,\n INBOX_RECORD_ATTRIBUTION_ZONE,\n} from './components/inbox-attribution-zone'\nimport { BUNDLE_ID } from './constants/bundle-common'\n\n/** Code-split: the Inbox console page only loads when opened. */\nconst InboxConsolePage = lazy(() => import('./components/inbox-console-page'))\n\n/**\n * Code-split: the submissions table loads when a form page asks for it. The\n * zone hands `hostId` and `formId`, which is what the table's own props are.\n */\nconst FormSubmissionsReader = lazy(\n () => import('./components/submissions-card.component'),\n)\n\n/** Dashboard glance card, loaded only where the shell renders the slot. */\nconst InboxGlanceCard = lazy(\n () => import('./components/inbox-glance-card.component'),\n)\n\n/**\n * Inbox feature plugin (AGL-395). Console-only — form submissions, site\n * members/leads and campaigns live in Firestore and have no canvas element,\n * so there is no UI bundle. The console half declares the Inbox nav + its\n * three sections through the ConsoleExtension registry (always-on), once\n * under each site and once for the organization (AGL-3303). The Campaigns\n * section and the attribution shown inside a submission are zones this\n * plugin hosts; the plugin that owns campaigns draws in them.\n */\nexport function registerInboxConsole(): void {\n registerPluginZone(\n {\n zone: INBOX_RECORD_ATTRIBUTION_ZONE,\n label: 'Where a lead or a submission came from',\n surface: 'console',\n description:\n 'In a lead’s “Where this came from” dialog and under an open submission. A widget here says which campaign or link brought it; it is handed the site, what the record is and its id, and it writes nothing.',\n },\n // Named, because a spec calls this registrar without the loader.\n { pluginId: BUNDLE_ID },\n )\n registerPluginZone(\n {\n zone: INBOX_CAMPAIGNS_ZONE,\n label: 'The Inbox’s Campaigns section',\n surface: 'console',\n description:\n 'The body of the Inbox’s Campaigns tab. A widget here lists the site’s campaigns; it is handed the site and nothing else — or, on the organization’s Inbox, no site (`hostId: null`) and the organization with its sites (`orgMount`), and lists every site’s.',\n },\n { pluginId: BUNDLE_ID },\n )\n Aglyn.registerConsoleExtension({\n pluginId: BUNDLE_ID,\n displayName: 'Inbox',\n // The host dashboard's inbox glance. A form submission is the one thing\n // on a site that is waiting for a REPLY, and until this it was two\n // clicks from the page an owner opens first.\n widgets: [\n {\n slot: Aglyn.CONSOLE_WIDGET_SLOTS.hostDashboard,\n widgetId: 'inbox-glance',\n title: 'Inbox',\n Component: InboxGlanceCard,\n },\n // One form's submissions, on the form's own page. The forms plugin\n // hosts the zone and hands it the site and the form; the reader is this\n // plugin's table, narrowed to that form, so the form page gets the same\n // ordered, paged walk the Inbox uses without importing it.\n {\n slot: 'formSubmissions',\n widgetId: 'inbox-form-submissions',\n title: 'Submissions',\n Component: FormSubmissionsReader,\n },\n ],\n navItems: [\n {\n label: 'Inbox',\n href: '/inbox',\n // Sections as ROUTES (AGL-2501): each is a real URL the shell\n // resolves and gates, so the page mounts the one being read.\n sections: INBOX_CONSOLE_SECTIONS,\n navTabId: 'nav-tab-inbox',\n icon: { path: mdiInboxArrowDown.path },\n header: {\n title: 'Inbox',\n icon: { path: mdiInboxArrowDown.path },\n docsTopic: 'forms',\n },\n Component: InboxConsolePage,\n },\n ],\n /*\n * The ORGANIZATION's Inbox, at `/[orgSlug]/inbox` (AGL-3303): every\n * site's submissions in one list, the organization's leads, and every\n * campaign, with a site filter that narrows the page to one site's own\n * view. The page is the same component; handed no site, it draws the\n * org sections.\n *\n * It carries the SITE tab's id on purpose, as the org CRM and Marketing\n * tabs do: `release_inbox` names `nav-tab-inbox`, so one flag holds both\n * levels and the org Inbox cannot ship while the site's is switched off.\n */\n orgNavItems: [\n {\n label: 'Inbox',\n href: '/inbox',\n sections: INBOX_ORG_CONSOLE_SECTIONS,\n navTabId: 'nav-tab-inbox',\n icon: { path: mdiInboxArrowDown.path },\n header: {\n title: 'Inbox',\n icon: { path: mdiInboxArrowDown.path },\n docsTopic: 'forms',\n },\n Component: InboxConsolePage,\n },\n ],\n })\n}\n"],"names":["Aglyn","mdiInboxArrowDown","lazy","INBOX_CONSOLE_SECTIONS","INBOX_ORG_CONSOLE_SECTIONS","registerPluginZone","INBOX_CAMPAIGNS_ZONE","INBOX_RECORD_ATTRIBUTION_ZONE","BUNDLE_ID","InboxConsolePage","FormSubmissionsReader","InboxGlanceCard","registerInboxConsole","zone","label","surface","description","pluginId","registerConsoleExtension","displayName","widgets","slot","CONSOLE_WIDGET_SLOTS","hostDashboard","widgetId","title","Component","navItems","href","sections","navTabId","icon","path","header","docsTopic","orgNavItems"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,iBAAiB,QAAQ,yBAAwB;AAC1D,SAASC,IAAI,QAAQ,QAAO;AAC5B,SACEC,sBAAsB,EACtBC,0BAA0B,QACrB,yCAAqC;AAC5C,SAASC,kBAAkB,QAAQ,2CAA0C;AAC7E,SACEC,oBAAoB,EACpBC,6BAA6B,QACxB,yCAAqC;AAC5C,SAASC,SAAS,QAAQ,+BAA2B;AAErD,+DAA+D,GAC/D,MAAMC,mBAAmBP,KAAK,IAAM,MAAM,CAAC;AAE3C;;;CAGC,GACD,MAAMQ,wBAAwBR,KAC5B,IAAM,MAAM,CAAC;AAGf,yEAAyE,GACzE,MAAMS,kBAAkBT,KACtB,IAAM,MAAM,CAAC;AAGf;;;;;;;;CAQC,GACD,OAAO,SAASU;IACdP,mBACE;QACEQ,MAAMN;QACNO,OAAO;QACPC,SAAS;QACTC,aACE;IACJ,GACA,iEAAiE;IACjE;QAAEC,UAAUT;IAAU;IAExBH,mBACE;QACEQ,MAAMP;QACNQ,OAAO;QACPC,SAAS;QACTC,aACE;IACJ,GACA;QAAEC,UAAUT;IAAU;IAExBR,MAAMkB,wBAAwB,CAAC;QAC7BD,UAAUT;QACVW,aAAa;QACb,wEAAwE;QACxE,mEAAmE;QACnE,6CAA6C;QAC7CC,SAAS;YACP;gBACEC,MAAMrB,MAAMsB,oBAAoB,CAACC,aAAa;gBAC9CC,UAAU;gBACVC,OAAO;gBACPC,WAAWf;YACb;YACA,mEAAmE;YACnE,wEAAwE;YACxE,wEAAwE;YACxE,2DAA2D;YAC3D;gBACEU,MAAM;gBACNG,UAAU;gBACVC,OAAO;gBACPC,WAAWhB;YACb;SACD;QACDiB,UAAU;YACR;gBACEb,OAAO;gBACPc,MAAM;gBACN,8DAA8D;gBAC9D,6DAA6D;gBAC7DC,UAAU1B;gBACV2B,UAAU;gBACVC,MAAM;oBAAEC,MAAM/B,kBAAkB+B,IAAI;gBAAC;gBACrCC,QAAQ;oBACNR,OAAO;oBACPM,MAAM;wBAAEC,MAAM/B,kBAAkB+B,IAAI;oBAAC;oBACrCE,WAAW;gBACb;gBACAR,WAAWjB;YACb;SACD;QACD;;;;;;;;;;KAUC,GACD0B,aAAa;YACX;gBACErB,OAAO;gBACPc,MAAM;gBACNC,UAAUzB;gBACV0B,UAAU;gBACVC,MAAM;oBAAEC,MAAM/B,kBAAkB+B,IAAI;gBAAC;gBACrCC,QAAQ;oBACNR,OAAO;oBACPM,MAAM;wBAAEC,MAAM/B,kBAAkB+B,IAAI;oBAAC;oBACrCE,WAAW;gBACb;gBACAR,WAAWjB;YACb;SACD;IACH;AACF"}
|