@eintrek/erp-shell 0.1.35 → 0.1.37
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/dist/index.esm.js +34 -2
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +34 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -363,7 +363,22 @@ function useInvalidateQueriesOnOrgChange(organizationId) {
|
|
|
363
363
|
// still hit the invalidate path below.
|
|
364
364
|
if (wasEmpty)
|
|
365
365
|
return;
|
|
366
|
-
|
|
366
|
+
// Remove, not invalidate.
|
|
367
|
+
//
|
|
368
|
+
// invalidateQueries marks entries stale and refetches the mounted ones,
|
|
369
|
+
// which leaves the previous organisation's rows sitting in the cache and
|
|
370
|
+
// on screen until a refetch lands. Any query whose key does not carry the
|
|
371
|
+
// organisation — and the request is scoped by the X-Organization-ID
|
|
372
|
+
// header, so most keys have no reason to — then reads as a cache hit for
|
|
373
|
+
// the new organisation and renders the old one's data under the new
|
|
374
|
+
// one's name. A colleague found /O26000021/employee showing three
|
|
375
|
+
// employees belonging to O26000033, with the breadcrumb and the title
|
|
376
|
+
// both correct.
|
|
377
|
+
//
|
|
378
|
+
// Dropping the entries costs a loading state after every switch, which is
|
|
379
|
+
// the honest thing to show: nothing fetched under one tenant is worth
|
|
380
|
+
// keeping once the tenant changes.
|
|
381
|
+
queryClient.removeQueries();
|
|
367
382
|
}, [organizationId, queryClient]);
|
|
368
383
|
}
|
|
369
384
|
/**
|
|
@@ -1114,6 +1129,23 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
|
|
|
1114
1129
|
lastOrgKeyRef.current = currentOrgKey;
|
|
1115
1130
|
}
|
|
1116
1131
|
const contentOrgKey = lastOrgKeyRef.current;
|
|
1132
|
+
// Hold the page back until the active organisation is the one the URL names.
|
|
1133
|
+
//
|
|
1134
|
+
// The sync effect above writes the cookie through a server action, which is
|
|
1135
|
+
// a round trip. Until it lands, getOrgFromCookie() still answers with the
|
|
1136
|
+
// previous organisation and every request the page fires on mount carries
|
|
1137
|
+
// it — so /O26000021/work-record asked about O26000033 and was correctly
|
|
1138
|
+
// told there was nothing there. An empty table is the mild version: the
|
|
1139
|
+
// create form posts to the same header, so a record could be filed against
|
|
1140
|
+
// a company the user was not looking at.
|
|
1141
|
+
//
|
|
1142
|
+
// Only while the two genuinely disagree. A code naming no organisation of
|
|
1143
|
+
// the caller's is left to the app to refuse, and a page with no code in its
|
|
1144
|
+
// path is unaffected.
|
|
1145
|
+
const orgContextIsStale = !!orgFromCode &&
|
|
1146
|
+
organizationId !== null &&
|
|
1147
|
+
organizationId !== undefined &&
|
|
1148
|
+
String(organizationId) !== String(orgFromCode.id);
|
|
1117
1149
|
// ≤1024px: sidebar renders as a modal overlay (backdrop dims content). >1024px:
|
|
1118
1150
|
// sidebar is docked and the content gets a left margin to clear it.
|
|
1119
1151
|
const [isSidebarModalLayout, setIsSidebarModalLayout] = React.useState(false);
|
|
@@ -1160,7 +1192,7 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
|
|
|
1160
1192
|
const contentMargin = open && !isSidebarModalLayout ? "ml-[21.5rem]" : "";
|
|
1161
1193
|
const needsLeftGutter = !(open && !isSidebarModalLayout);
|
|
1162
1194
|
const wrap = permissionProvider ?? ((c) => c);
|
|
1163
|
-
return (jsxs("div", { className: "flex min-h-screen w-full bg-background", children: [open && (jsx("div", { className: "fixed left-0 top-0 z-50 h-screen", children: sidebar })), open && isSidebarModalLayout && (jsx("button", { type: "button", "aria-label": "\u0E1B\u0E34\u0E14\u0E40\u0E21\u0E19\u0E39", className: "fixed inset-0 z-40 bg-black/50", onClick: () => setOpen(false) })), jsx("div", { className: cx("relative flex min-w-0 flex-1 flex-col transition-all", contentMargin), children: jsxs("main", { className: "flex flex-1 flex-col min-h-screen gap-4", children: [jsxs("div", { className: "sticky top-0 z-30 shrink-0 w-full", children: [jsx(HeaderBackground, {}), jsxs("header", { className: "relative shrink-0 gap-2 py-4 h-auto min-h-[123.5px] w-full z-10", children: [jsxs("div", { className: "flex w-full items-center gap-2 px-3 sm:px-4 lg:px-6", children: [jsx(SidebarTrigger, { className: "shrink-0 text-white hover:bg-white/10" }), jsx("div", { className: "flex-1 min-w-0", children: breadcrumb })] }), jsx("div", { id: "header-title" })] })] }), jsx(Suspense, { fallback: jsx("div", { className: "relative z-10 min-h-[calc(100vh-8rem)]", children: jsx("div", { className: "flex h-full items-center justify-center", children: jsxs("div", { className: "space-y-4 text-center", children: [jsx("div", { className: "mx-auto h-8 w-8 animate-spin rounded-full border-b-2 border-primary" }), jsx("p", { className: "text-sm text-muted-foreground", children: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E42\u0E2B\u0E25\u0E14..." })] }) }) }), children: jsx("div", { className: cx("relative z-10 pr-6", needsLeftGutter && "pl-6"), children: wrap(children) }, `org-${contentOrgKey}`) })] }) })] }));
|
|
1195
|
+
return (jsxs("div", { className: "flex min-h-screen w-full bg-background", children: [open && (jsx("div", { className: "fixed left-0 top-0 z-50 h-screen", children: sidebar })), open && isSidebarModalLayout && (jsx("button", { type: "button", "aria-label": "\u0E1B\u0E34\u0E14\u0E40\u0E21\u0E19\u0E39", className: "fixed inset-0 z-40 bg-black/50", onClick: () => setOpen(false) })), jsx("div", { className: cx("relative flex min-w-0 flex-1 flex-col transition-all", contentMargin), children: jsxs("main", { className: "flex flex-1 flex-col min-h-screen gap-4", children: [jsxs("div", { className: "sticky top-0 z-30 shrink-0 w-full", children: [jsx(HeaderBackground, {}), jsxs("header", { className: "relative shrink-0 gap-2 py-4 h-auto min-h-[123.5px] w-full z-10", children: [jsxs("div", { className: "flex w-full items-center gap-2 px-3 sm:px-4 lg:px-6", children: [jsx(SidebarTrigger, { className: "shrink-0 text-white hover:bg-white/10" }), jsx("div", { className: "flex-1 min-w-0", children: breadcrumb })] }), jsx("div", { id: "header-title" })] })] }), jsx(Suspense, { fallback: jsx("div", { className: "relative z-10 min-h-[calc(100vh-8rem)]", children: jsx("div", { className: "flex h-full items-center justify-center", children: jsxs("div", { className: "space-y-4 text-center", children: [jsx("div", { className: "mx-auto h-8 w-8 animate-spin rounded-full border-b-2 border-primary" }), jsx("p", { className: "text-sm text-muted-foreground", children: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E42\u0E2B\u0E25\u0E14..." })] }) }) }), children: jsx("div", { className: cx("relative z-10 pr-6", needsLeftGutter && "pl-6"), children: orgContextIsStale ? loadingComponent : wrap(children) }, `org-${contentOrgKey}`) })] }) })] }));
|
|
1164
1196
|
}
|
|
1165
1197
|
/** Local tiny classnames helper — avoids pulling clsx/tailwind-merge into
|
|
1166
1198
|
* the shell just for the layout file. Falsy values are skipped. */
|