@the-portland-company/shell 0.75.2 → 0.76.1
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/CHANGELOG.md +18 -0
- package/dist/active-org.cjs +119 -0
- package/dist/active-org.cjs.map +1 -1
- package/dist/active-org.d.cts +62 -2
- package/dist/active-org.d.ts +62 -2
- package/dist/active-org.js +1 -1
- package/dist/app-chrome.cjs +223 -14
- package/dist/app-chrome.cjs.map +1 -1
- package/dist/app-chrome.d.cts +34 -2
- package/dist/app-chrome.d.ts +34 -2
- package/dist/app-chrome.js +124 -13
- package/dist/app-chrome.js.map +1 -1
- package/dist/{chunk-2DXTSTII.js → chunk-6KX3DWBC.js} +27 -8
- package/dist/chunk-6KX3DWBC.js.map +1 -0
- package/dist/chunk-BWV52AT6.js +171 -0
- package/dist/chunk-BWV52AT6.js.map +1 -0
- package/dist/native.cjs +25 -5
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +36 -3
- package/dist/native.d.ts +36 -3
- package/dist/native.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-2DXTSTII.js.map +0 -1
- package/dist/chunk-W2HITMV5.js +0 -64
- package/dist/chunk-W2HITMV5.js.map +0 -1
package/dist/app-chrome.d.cts
CHANGED
|
@@ -188,6 +188,8 @@ type PolitogyFrameData = {
|
|
|
188
188
|
devNotes?: ChromeDevNotesConfig;
|
|
189
189
|
/** Controlled org state for apps that own active-org + switching. */
|
|
190
190
|
org?: ControlledOrgState;
|
|
191
|
+
/** Auth-owned active org from verified token claims (v2). Wins over `org`. */
|
|
192
|
+
tokenOrg?: TokenOrgState;
|
|
191
193
|
/**
|
|
192
194
|
* App-owned children for a standard nav entry this app owns (Contacts).
|
|
193
195
|
* `count` is the live contact total, pre-formatted ("31.9K"), drawn
|
|
@@ -393,6 +395,34 @@ type ControlledOrgState = {
|
|
|
393
395
|
*/
|
|
394
396
|
onExternalSwitch?: (id: string) => void;
|
|
395
397
|
};
|
|
398
|
+
/**
|
|
399
|
+
* Auth-owned active org (Global-Rules v38, UI-Platform v46). The app server
|
|
400
|
+
* passes the VERIFIED token claims; the shell never resolves the org itself.
|
|
401
|
+
*/
|
|
402
|
+
type TokenOrgState = {
|
|
403
|
+
/** `org_id` claim from the app's verified token (full uuid). */
|
|
404
|
+
orgId: string | null;
|
|
405
|
+
/** `org_role` claim (raw VRM Core role). */
|
|
406
|
+
orgRole?: string | null;
|
|
407
|
+
/**
|
|
408
|
+
* The switcher list from the app server (names for the pill). When given,
|
|
409
|
+
* the chrome `/api/orgs` call is skipped. When absent it is the fallback.
|
|
410
|
+
*/
|
|
411
|
+
orgs?: (NavOrgOption & {
|
|
412
|
+
rawRole?: string | null;
|
|
413
|
+
})[];
|
|
414
|
+
/**
|
|
415
|
+
* Server action that re-exchanges for tokens on `orgId`. Called after the
|
|
416
|
+
* IdP accepted the switch (shared) or for a per-tab override (`perTab`).
|
|
417
|
+
*/
|
|
418
|
+
onReexchange: (orgId: string, opts: {
|
|
419
|
+
perTab: boolean;
|
|
420
|
+
}) => void | Promise<void>;
|
|
421
|
+
/** IdP base override (default: auth / auth-staging by host). */
|
|
422
|
+
authBaseUrl?: string;
|
|
423
|
+
/** Called when the IdP refuses a switch (403 not a member, 401 no session). */
|
|
424
|
+
onSwitchError?: (err: unknown) => void;
|
|
425
|
+
};
|
|
396
426
|
type ChromeDevNotesConfig = {
|
|
397
427
|
/** Override the DevNotes API base (default: `${proxyBasePath}/devnotes`). */
|
|
398
428
|
basePath?: string;
|
|
@@ -417,7 +447,7 @@ type ChromeDevNotesConfig = {
|
|
|
417
447
|
* <ShellFrame …/>
|
|
418
448
|
* </PolitogyAppChrome>
|
|
419
449
|
*/
|
|
420
|
-
declare function PolitogyAppChrome({ storagePrefix, proxyBasePath, fetchJson: fetchJsonOverride, devNotes, org, identity, children, }: {
|
|
450
|
+
declare function PolitogyAppChrome({ storagePrefix, proxyBasePath, fetchJson: fetchJsonOverride, devNotes, org, tokenOrg, identity, children, }: {
|
|
421
451
|
storagePrefix: string;
|
|
422
452
|
proxyBasePath?: string;
|
|
423
453
|
/**
|
|
@@ -430,6 +460,8 @@ declare function PolitogyAppChrome({ storagePrefix, proxyBasePath, fetchJson: fe
|
|
|
430
460
|
devNotes?: ChromeDevNotesConfig;
|
|
431
461
|
/** Controlled org state — the app owns active-org + switching (Contacts). */
|
|
432
462
|
org?: ControlledOrgState;
|
|
463
|
+
/** Auth-owned active org from verified token claims (v2). Wins over `org`. */
|
|
464
|
+
tokenOrg?: TokenOrgState;
|
|
433
465
|
identity: ChromeIdentity;
|
|
434
466
|
children: ReactNode;
|
|
435
467
|
}): react_jsx_runtime.JSX.Element;
|
|
@@ -502,4 +534,4 @@ type UseChromeModeArg = ModeId | {
|
|
|
502
534
|
*/
|
|
503
535
|
declare function useChromeMode(arg?: UseChromeModeArg): NavMode;
|
|
504
536
|
|
|
505
|
-
export { type BootPhase, type BootProgress, type BootStageId, type ChromeDevNotesConfig, type ChromeIdentity, ChromeTopBarActions, type ControlledOrgState, LoadingScreen, POLITOGY_APPS, PolitogyAppChrome, PolitogyAppFrame, type PolitogyAppKey, type PolitogyAppMode, type PolitogyAppSession, type PolitogyBuildMeta, type PolitogyFrameData, type PolitogyFrameGrant, type PolitogyGrantedFrame, type ResolvedIdentity, deriveBreadcrumbs, looksLikeEmail, resolveIdentity, standardNavIcons, useChromeFooter, useChromeIdentity, useChromeMode, useChromeState, useChromeUserMenu, useIsSuperAdmin };
|
|
537
|
+
export { type BootPhase, type BootProgress, type BootStageId, type ChromeDevNotesConfig, type ChromeIdentity, ChromeTopBarActions, type ControlledOrgState, LoadingScreen, POLITOGY_APPS, PolitogyAppChrome, PolitogyAppFrame, type PolitogyAppKey, type PolitogyAppMode, type PolitogyAppSession, type PolitogyBuildMeta, type PolitogyFrameData, type PolitogyFrameGrant, type PolitogyGrantedFrame, type ResolvedIdentity, type TokenOrgState, deriveBreadcrumbs, looksLikeEmail, resolveIdentity, standardNavIcons, useChromeFooter, useChromeIdentity, useChromeMode, useChromeState, useChromeUserMenu, useIsSuperAdmin };
|
package/dist/app-chrome.d.ts
CHANGED
|
@@ -188,6 +188,8 @@ type PolitogyFrameData = {
|
|
|
188
188
|
devNotes?: ChromeDevNotesConfig;
|
|
189
189
|
/** Controlled org state for apps that own active-org + switching. */
|
|
190
190
|
org?: ControlledOrgState;
|
|
191
|
+
/** Auth-owned active org from verified token claims (v2). Wins over `org`. */
|
|
192
|
+
tokenOrg?: TokenOrgState;
|
|
191
193
|
/**
|
|
192
194
|
* App-owned children for a standard nav entry this app owns (Contacts).
|
|
193
195
|
* `count` is the live contact total, pre-formatted ("31.9K"), drawn
|
|
@@ -393,6 +395,34 @@ type ControlledOrgState = {
|
|
|
393
395
|
*/
|
|
394
396
|
onExternalSwitch?: (id: string) => void;
|
|
395
397
|
};
|
|
398
|
+
/**
|
|
399
|
+
* Auth-owned active org (Global-Rules v38, UI-Platform v46). The app server
|
|
400
|
+
* passes the VERIFIED token claims; the shell never resolves the org itself.
|
|
401
|
+
*/
|
|
402
|
+
type TokenOrgState = {
|
|
403
|
+
/** `org_id` claim from the app's verified token (full uuid). */
|
|
404
|
+
orgId: string | null;
|
|
405
|
+
/** `org_role` claim (raw VRM Core role). */
|
|
406
|
+
orgRole?: string | null;
|
|
407
|
+
/**
|
|
408
|
+
* The switcher list from the app server (names for the pill). When given,
|
|
409
|
+
* the chrome `/api/orgs` call is skipped. When absent it is the fallback.
|
|
410
|
+
*/
|
|
411
|
+
orgs?: (NavOrgOption & {
|
|
412
|
+
rawRole?: string | null;
|
|
413
|
+
})[];
|
|
414
|
+
/**
|
|
415
|
+
* Server action that re-exchanges for tokens on `orgId`. Called after the
|
|
416
|
+
* IdP accepted the switch (shared) or for a per-tab override (`perTab`).
|
|
417
|
+
*/
|
|
418
|
+
onReexchange: (orgId: string, opts: {
|
|
419
|
+
perTab: boolean;
|
|
420
|
+
}) => void | Promise<void>;
|
|
421
|
+
/** IdP base override (default: auth / auth-staging by host). */
|
|
422
|
+
authBaseUrl?: string;
|
|
423
|
+
/** Called when the IdP refuses a switch (403 not a member, 401 no session). */
|
|
424
|
+
onSwitchError?: (err: unknown) => void;
|
|
425
|
+
};
|
|
396
426
|
type ChromeDevNotesConfig = {
|
|
397
427
|
/** Override the DevNotes API base (default: `${proxyBasePath}/devnotes`). */
|
|
398
428
|
basePath?: string;
|
|
@@ -417,7 +447,7 @@ type ChromeDevNotesConfig = {
|
|
|
417
447
|
* <ShellFrame …/>
|
|
418
448
|
* </PolitogyAppChrome>
|
|
419
449
|
*/
|
|
420
|
-
declare function PolitogyAppChrome({ storagePrefix, proxyBasePath, fetchJson: fetchJsonOverride, devNotes, org, identity, children, }: {
|
|
450
|
+
declare function PolitogyAppChrome({ storagePrefix, proxyBasePath, fetchJson: fetchJsonOverride, devNotes, org, tokenOrg, identity, children, }: {
|
|
421
451
|
storagePrefix: string;
|
|
422
452
|
proxyBasePath?: string;
|
|
423
453
|
/**
|
|
@@ -430,6 +460,8 @@ declare function PolitogyAppChrome({ storagePrefix, proxyBasePath, fetchJson: fe
|
|
|
430
460
|
devNotes?: ChromeDevNotesConfig;
|
|
431
461
|
/** Controlled org state — the app owns active-org + switching (Contacts). */
|
|
432
462
|
org?: ControlledOrgState;
|
|
463
|
+
/** Auth-owned active org from verified token claims (v2). Wins over `org`. */
|
|
464
|
+
tokenOrg?: TokenOrgState;
|
|
433
465
|
identity: ChromeIdentity;
|
|
434
466
|
children: ReactNode;
|
|
435
467
|
}): react_jsx_runtime.JSX.Element;
|
|
@@ -502,4 +534,4 @@ type UseChromeModeArg = ModeId | {
|
|
|
502
534
|
*/
|
|
503
535
|
declare function useChromeMode(arg?: UseChromeModeArg): NavMode;
|
|
504
536
|
|
|
505
|
-
export { type BootPhase, type BootProgress, type BootStageId, type ChromeDevNotesConfig, type ChromeIdentity, ChromeTopBarActions, type ControlledOrgState, LoadingScreen, POLITOGY_APPS, PolitogyAppChrome, PolitogyAppFrame, type PolitogyAppKey, type PolitogyAppMode, type PolitogyAppSession, type PolitogyBuildMeta, type PolitogyFrameData, type PolitogyFrameGrant, type PolitogyGrantedFrame, type ResolvedIdentity, deriveBreadcrumbs, looksLikeEmail, resolveIdentity, standardNavIcons, useChromeFooter, useChromeIdentity, useChromeMode, useChromeState, useChromeUserMenu, useIsSuperAdmin };
|
|
537
|
+
export { type BootPhase, type BootProgress, type BootStageId, type ChromeDevNotesConfig, type ChromeIdentity, ChromeTopBarActions, type ControlledOrgState, LoadingScreen, POLITOGY_APPS, PolitogyAppChrome, PolitogyAppFrame, type PolitogyAppKey, type PolitogyAppMode, type PolitogyAppSession, type PolitogyBuildMeta, type PolitogyFrameData, type PolitogyFrameGrant, type PolitogyGrantedFrame, type ResolvedIdentity, type TokenOrgState, deriveBreadcrumbs, looksLikeEmail, resolveIdentity, standardNavIcons, useChromeFooter, useChromeIdentity, useChromeMode, useChromeState, useChromeUserMenu, useIsSuperAdmin };
|
package/dist/app-chrome.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { broadcastLogout, watchLogout } from './chunk-LL6LSJAH.js';
|
|
3
|
-
import { clearBetaBannerDismissal, standardPolitogyNav, standardNavIcons, isNavItemActive, NavAppShell, NavChromeProvider, TopBarWidgetSlot, FuelAction, SpecOverlayAction, NotificationsAction, SupportAction, useChromeMe, useThemePreference,
|
|
4
|
-
export { standardNavIcons } from './chunk-
|
|
3
|
+
import { clearBetaBannerDismissal, standardPolitogyNav, standardNavIcons, isNavItemActive, NavAppShell, NavChromeProvider, TopBarWidgetSlot, FuelAction, SpecOverlayAction, NotificationsAction, SupportAction, useChromeMe, useThemePreference, useNavChromeDedupedFetch, useChromeOrgs, useNavChromeFetcher } from './chunk-6KX3DWBC.js';
|
|
4
|
+
export { standardNavIcons } from './chunk-6KX3DWBC.js';
|
|
5
5
|
import { warnDeprecated } from './chunk-MY6G3LMN.js';
|
|
6
6
|
import './chunk-BHRVZPZ7.js';
|
|
7
|
-
import { NAV_DISPLAY_DEFAULT, resolveNavDisplay,
|
|
8
|
-
import {
|
|
7
|
+
import { NAV_DISPLAY_DEFAULT, resolveNavDisplay, writeNavDisplayLocal, writeNavDisplayCookie, isNavDisplayPreference, NAV_DISPLAY_STORAGE_KEY, readNavDisplayCookie } from './chunk-7YVJ7HQG.js';
|
|
8
|
+
import { readOrgSelectorFromUrl, matchOrgSelector, isOrgId, switchActiveOrg, ACTIVE_ORG_QUERY_PARAM, ORG_ID_QUERY_PARAM, orgIdTail, writeActiveOrgCookie, resolveActiveOrg, readActiveOrgCookie } from './chunk-BWV52AT6.js';
|
|
9
9
|
import { createContext, useMemo, useRef, useEffect, useState, useCallback, useContext } from 'react';
|
|
10
10
|
import { DevNotesMenu, createDevNotesClient, DevNotesProvider, DevNotesTaskListModal, DevNotesOverlay } from '@the-portland-company/devnotes';
|
|
11
11
|
import { LuNotebookPen, LuContactRound, LuMegaphone, LuFilePenLine } from 'react-icons/lu';
|
|
@@ -605,6 +605,7 @@ function PolitogyAppFrame({
|
|
|
605
605
|
fetchJson: data?.fetchJson,
|
|
606
606
|
devNotes: data?.devNotes,
|
|
607
607
|
org: data?.org,
|
|
608
|
+
tokenOrg: data?.tokenOrg,
|
|
608
609
|
identity: {
|
|
609
610
|
userId: session.userId,
|
|
610
611
|
userName: session.userName ?? null,
|
|
@@ -885,6 +886,107 @@ var ChromeStateContext = createContext(null);
|
|
|
885
886
|
function useChromeState() {
|
|
886
887
|
return useContext(ChromeStateContext);
|
|
887
888
|
}
|
|
889
|
+
function TokenChromeStateProvider({
|
|
890
|
+
tokenOrg,
|
|
891
|
+
children
|
|
892
|
+
}) {
|
|
893
|
+
const { orgs: fetchedOrgs, loading: orgsFetching, error: orgsError } = useChromeOrgs({
|
|
894
|
+
enabled: !tokenOrg.orgs
|
|
895
|
+
});
|
|
896
|
+
const [navDisplay, setNavDisplayState] = useState(NAV_DISPLAY_DEFAULT);
|
|
897
|
+
const [pendingOrg, setPendingOrg] = useState(null);
|
|
898
|
+
const tokenOrgRef = useRef(tokenOrg);
|
|
899
|
+
tokenOrgRef.current = tokenOrg;
|
|
900
|
+
useEffect(() => {
|
|
901
|
+
setNavDisplayState(resolveNavDisplay());
|
|
902
|
+
}, []);
|
|
903
|
+
const orgs = useMemo(
|
|
904
|
+
() => tokenOrg.orgs ?? (fetchedOrgs ?? []).map((o) => ({
|
|
905
|
+
id: o.id,
|
|
906
|
+
name: o.name,
|
|
907
|
+
logoUrl: o.logoUrl,
|
|
908
|
+
brandColor: o.brandColor,
|
|
909
|
+
role: o.role,
|
|
910
|
+
rawRole: o.rawRole ?? null
|
|
911
|
+
})),
|
|
912
|
+
[tokenOrg.orgs, fetchedOrgs]
|
|
913
|
+
);
|
|
914
|
+
const [urlSelector] = useState(
|
|
915
|
+
() => typeof window === "undefined" ? null : readOrgSelectorFromUrl(window.location.search)
|
|
916
|
+
);
|
|
917
|
+
const overrideOrg = useMemo(
|
|
918
|
+
() => urlSelector ? matchOrgSelector(urlSelector, orgs)?.id ?? null : null,
|
|
919
|
+
[urlSelector, orgs]
|
|
920
|
+
);
|
|
921
|
+
const orgId = pendingOrg ?? (tokenOrg.orgId && overrideOrg ? overrideOrg : tokenOrg.orgId);
|
|
922
|
+
const reexchangedFor = useRef(null);
|
|
923
|
+
useEffect(() => {
|
|
924
|
+
if (!overrideOrg || !tokenOrg.orgId || overrideOrg === tokenOrg.orgId) return;
|
|
925
|
+
if (reexchangedFor.current === overrideOrg) return;
|
|
926
|
+
reexchangedFor.current = overrideOrg;
|
|
927
|
+
void Promise.resolve(tokenOrgRef.current.onReexchange(overrideOrg, { perTab: true })).catch(
|
|
928
|
+
() => {
|
|
929
|
+
}
|
|
930
|
+
);
|
|
931
|
+
}, [overrideOrg, tokenOrg.orgId]);
|
|
932
|
+
useEffect(() => {
|
|
933
|
+
if (pendingOrg && tokenOrg.orgId === pendingOrg) setPendingOrg(null);
|
|
934
|
+
}, [pendingOrg, tokenOrg.orgId]);
|
|
935
|
+
const setOrgId = useCallback((id) => {
|
|
936
|
+
const current = tokenOrgRef.current;
|
|
937
|
+
if (!isOrgId(id) || id === (current.orgId ?? null)) return;
|
|
938
|
+
setPendingOrg(id);
|
|
939
|
+
void (async () => {
|
|
940
|
+
try {
|
|
941
|
+
const claims = await switchActiveOrg(id, { authBaseUrl: current.authBaseUrl });
|
|
942
|
+
try {
|
|
943
|
+
const url = new URL(window.location.href);
|
|
944
|
+
url.searchParams.delete(ACTIVE_ORG_QUERY_PARAM);
|
|
945
|
+
url.searchParams.set(ORG_ID_QUERY_PARAM, orgIdTail(claims.orgId));
|
|
946
|
+
window.history.replaceState(window.history.state, "", url.toString());
|
|
947
|
+
} catch {
|
|
948
|
+
}
|
|
949
|
+
await tokenOrgRef.current.onReexchange(claims.orgId, { perTab: false });
|
|
950
|
+
} catch (err) {
|
|
951
|
+
setPendingOrg(null);
|
|
952
|
+
tokenOrgRef.current.onSwitchError?.(err);
|
|
953
|
+
}
|
|
954
|
+
})();
|
|
955
|
+
}, []);
|
|
956
|
+
const setNavDisplay = useCallback((m) => {
|
|
957
|
+
setNavDisplayState(m);
|
|
958
|
+
writeNavDisplayLocal(m);
|
|
959
|
+
writeNavDisplayCookie(m);
|
|
960
|
+
}, []);
|
|
961
|
+
useEffect(() => {
|
|
962
|
+
if (!isOrgId(orgId)) return;
|
|
963
|
+
try {
|
|
964
|
+
const url = new URL(window.location.href);
|
|
965
|
+
const tail = orgIdTail(orgId);
|
|
966
|
+
if (url.searchParams.has(ACTIVE_ORG_QUERY_PARAM) || url.searchParams.get(ORG_ID_QUERY_PARAM) !== tail) {
|
|
967
|
+
url.searchParams.delete(ACTIVE_ORG_QUERY_PARAM);
|
|
968
|
+
url.searchParams.set(ORG_ID_QUERY_PARAM, tail);
|
|
969
|
+
window.history.replaceState(window.history.state, "", url.toString());
|
|
970
|
+
}
|
|
971
|
+
} catch {
|
|
972
|
+
}
|
|
973
|
+
}, [orgId]);
|
|
974
|
+
useEffect(() => {
|
|
975
|
+
if (isOrgId(tokenOrg.orgId) && !pendingOrg) writeActiveOrgCookie(tokenOrg.orgId);
|
|
976
|
+
}, [tokenOrg.orgId, pendingOrg]);
|
|
977
|
+
const value = useMemo(
|
|
978
|
+
() => ({
|
|
979
|
+
orgId,
|
|
980
|
+
setOrgId,
|
|
981
|
+
orgs,
|
|
982
|
+
orgsLoading: !tokenOrg.orgs && orgsFetching && !orgsError && !fetchedOrgs,
|
|
983
|
+
navDisplay,
|
|
984
|
+
setNavDisplay
|
|
985
|
+
}),
|
|
986
|
+
[orgId, setOrgId, orgs, tokenOrg.orgs, orgsFetching, orgsError, fetchedOrgs, navDisplay, setNavDisplay]
|
|
987
|
+
);
|
|
988
|
+
return /* @__PURE__ */ jsx(ChromeStateContext.Provider, { value, children });
|
|
989
|
+
}
|
|
888
990
|
function ChromeStateProvider({
|
|
889
991
|
controlledOrg,
|
|
890
992
|
children
|
|
@@ -1188,6 +1290,7 @@ function PolitogyAppChrome({
|
|
|
1188
1290
|
fetchJson: fetchJsonOverride,
|
|
1189
1291
|
devNotes,
|
|
1190
1292
|
org,
|
|
1293
|
+
tokenOrg,
|
|
1191
1294
|
identity,
|
|
1192
1295
|
children
|
|
1193
1296
|
}) {
|
|
@@ -1206,7 +1309,7 @@ function PolitogyAppChrome({
|
|
|
1206
1309
|
[proxyBasePath]
|
|
1207
1310
|
);
|
|
1208
1311
|
const fetchJson = fetchJsonOverride ?? proxyFetchJson;
|
|
1209
|
-
|
|
1312
|
+
const devNotesTree = /* @__PURE__ */ jsx(
|
|
1210
1313
|
AppDevNotes,
|
|
1211
1314
|
{
|
|
1212
1315
|
storagePrefix,
|
|
@@ -1215,11 +1318,13 @@ function PolitogyAppChrome({
|
|
|
1215
1318
|
identity,
|
|
1216
1319
|
children
|
|
1217
1320
|
}
|
|
1218
|
-
)
|
|
1321
|
+
);
|
|
1322
|
+
return /* @__PURE__ */ jsx(NavChromeProvider, { fetchJson, children: tokenOrg ? /* @__PURE__ */ jsx(TokenChromeStateProvider, { tokenOrg, children: devNotesTree }) : /* @__PURE__ */ jsx(ChromeStateProvider, { controlledOrg: org, children: devNotesTree }) });
|
|
1219
1323
|
}
|
|
1220
1324
|
function ChromeTopBarActions() {
|
|
1221
1325
|
const state = useChromeState();
|
|
1222
1326
|
if (!state) return null;
|
|
1327
|
+
const settledOrgId = state.orgsLoading ? null : state.orgId;
|
|
1223
1328
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1224
1329
|
/* @__PURE__ */ jsx(
|
|
1225
1330
|
TopBarWidgetSlot,
|
|
@@ -1229,10 +1334,10 @@ function ChromeTopBarActions() {
|
|
|
1229
1334
|
children: /* @__PURE__ */ jsx(ChromeDevNotesMenu, {})
|
|
1230
1335
|
}
|
|
1231
1336
|
),
|
|
1232
|
-
/* @__PURE__ */ jsx(FuelAction, { orgId:
|
|
1337
|
+
/* @__PURE__ */ jsx(FuelAction, { orgId: settledOrgId }),
|
|
1233
1338
|
/* @__PURE__ */ jsx(SpecOverlayAction, { orgId: state.orgId, orgName: state.orgs.find((o) => o.id === state.orgId)?.name ?? null }),
|
|
1234
|
-
/* @__PURE__ */ jsx(NotificationsAction, { orgId:
|
|
1235
|
-
/* @__PURE__ */ jsx(SupportAction, { orgId: state.orgId })
|
|
1339
|
+
/* @__PURE__ */ jsx(NotificationsAction, { orgId: settledOrgId }),
|
|
1340
|
+
/* @__PURE__ */ jsx(SupportAction, { orgId: state.orgId, orgs: state.orgs.length ? state.orgs : void 0 })
|
|
1236
1341
|
] });
|
|
1237
1342
|
}
|
|
1238
1343
|
function ChromeDevNotesMenu() {
|
|
@@ -1318,7 +1423,8 @@ var MODE_DEFS = [
|
|
|
1318
1423
|
function useChromeMode(arg = {}) {
|
|
1319
1424
|
const { fallbackModeId = "relationship", pinnedModeId } = typeof arg === "string" ? { fallbackModeId: arg, pinnedModeId: void 0 } : arg;
|
|
1320
1425
|
const ctx = useContext(ChromeStateContext);
|
|
1321
|
-
const
|
|
1426
|
+
const dedupedFetch = useNavChromeDedupedFetch();
|
|
1427
|
+
const { me, loaded: meLoaded } = useChromeMe();
|
|
1322
1428
|
const orgId = ctx?.orgId ?? null;
|
|
1323
1429
|
const [entitled, setEntitled] = useState(null);
|
|
1324
1430
|
const [selectedModeId, setSelectedModeId] = useState(null);
|
|
@@ -1330,9 +1436,14 @@ function useChromeMode(arg = {}) {
|
|
|
1330
1436
|
}
|
|
1331
1437
|
}, []);
|
|
1332
1438
|
useEffect(() => {
|
|
1333
|
-
if (!
|
|
1439
|
+
if (!dedupedFetch || !orgId || !meLoaded) return;
|
|
1440
|
+
const bootMe = me;
|
|
1441
|
+
if (bootMe && bootMe.account === orgId && bootMe.modes !== void 0) {
|
|
1442
|
+
setEntitled(bootMe.modes ?? null);
|
|
1443
|
+
return;
|
|
1444
|
+
}
|
|
1334
1445
|
let cancelled = false;
|
|
1335
|
-
|
|
1446
|
+
dedupedFetch("me", { headers: { "x-contacts-org": orgId } }, { orgId }).then((data) => {
|
|
1336
1447
|
if (cancelled) return;
|
|
1337
1448
|
const modes = data?.modes ?? null;
|
|
1338
1449
|
setEntitled(modes);
|
|
@@ -1341,7 +1452,7 @@ function useChromeMode(arg = {}) {
|
|
|
1341
1452
|
return () => {
|
|
1342
1453
|
cancelled = true;
|
|
1343
1454
|
};
|
|
1344
|
-
}, [
|
|
1455
|
+
}, [dedupedFetch, me, meLoaded, orgId]);
|
|
1345
1456
|
const options = MODE_DEFS.filter((m) => entitled?.[m.id]);
|
|
1346
1457
|
const pinned = pinnedModeId ? MODE_DEFS.find((m) => m.id === pinnedModeId) ?? null : null;
|
|
1347
1458
|
const selected = selectedModeId ? options.find((m) => m.id === selectedModeId) ?? null : null;
|