varminer-app-header 2.6.2 → 2.6.4
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/AppHeader.js +506 -0
- package/dist/DrawerContext.js +22 -0
- package/dist/LanguageSelector.js +82 -0
- package/dist/autoInjectTenantFallbackCss.d.ts +2 -0
- package/dist/autoInjectTenantFallbackCss.d.ts.map +1 -0
- package/dist/generatedTenantFallbackCss.d.ts +3 -0
- package/dist/generatedTenantFallbackCss.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +104 -12
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +104 -12
- package/dist/index.js.map +1 -1
- package/dist/injectTenantFallbackCss.d.ts +2 -0
- package/dist/injectTenantFallbackCss.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/utils/localStorage.d.ts +2 -1
- package/dist/utils/localStorage.d.ts.map +1 -1
- package/dist/utils/localStorage.js +571 -0
- package/dist/utils/translations.js +25 -0
- package/package.json +4 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generatedTenantFallbackCss.d.ts","sourceRoot":"","sources":["../src/generatedTenantFallbackCss.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,iBAAiB,ukZAAo8W,CAAC;AAE59W,eAAe,iBAAiB,CAAC"}
|
package/dist/index.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
.MuiToolbar-root{background-color:var(--color-header-bg,var(--color-white))!important;height:var(--size-header-height,65px)!important;min-height:var(--size-header-height,65px)!important;padding-left:15px!important}.MuiToolbar-root,.MuiToolbar-root .MuiButtonBase-root{color:var(--color-brand-primary,var(--color-brand-primary))!important}.MuiToolbar-root .MuiButtonBase-root{margin-right:0}.app-header{flex-shrink:0}.app-header,.app-header .MuiAppBar-root{background-color:var(--color-header-bg,var(--color-white))!important;height:var(--size-header-height,65px)!important}.app-header .MuiAppBar-root{box-shadow:none!important;left:0;position:fixed!important;right:0;top:0;z-index:var(--size-header-zindex,200)!important}.app-header .MuiPaper-root:only-of-type{border-bottom:1px solid var(--color-border-header,var(--color-border-header));box-shadow:none!important;padding:0!important}.var{color:var(--color-brand-accent,var(--color-brand-accent))!important}.miner,.var{font:500 20px var(--font-brand-semibold,"OpenSans-SemiBold",sans-serif)}.miner{color:var(--color-brand-deep-navy,var(--color-brand-deep-navy))!important}.account-menu:has(.profile-menu-section) .MuiList-root .MuiListItem-root .MuiListItemText-root .MuiTypography-root.profile-name{color:var(--color-profile-name,var(--color-brand-primary));font:600 16px/28px var(--font-brand-semibold,"OpenSans-SemiBold",sans-serif)}.account-menu:has(.profile-menu-section) .MuiList-root .MuiListItem-root .MuiListItemText-root .MuiTypography-root.profile-email{color:var(--color-profile-email,var(--color-text-secondary-alpha));font:400 14px/24px var(--font-brand-regular,"OpenSans-Regular",sans-serif);text-decoration:underline}.account-menu:has(.profile-menu-section) .MuiList-root .MuiListItem-root .MuiListItemText-root .MuiTypography-root.profile-role{color:var(--color-profile-role,var(--color-text-muted-alpha));font:400 12px/28px var(--font-brand-regular,"OpenSans-Regular",sans-serif);text-transform:uppercase}.account-menu:has(.profile-menu-item) .profile-menu-item{padding:10px 15px 5px}.account-menu:has(.profile-menu-item) .MuiMenu-paper{background:var(--color-menu-bg-gradient,linear-gradient(180deg,var(--color-white),var(--color-selected-row),var(--color-selected-row)));box-shadow:none!important;color:var(--color-menu-text,var(--color-black));margin:0;max-width:var(--size-menu-width,280px);width:var(--size-menu-width,280px)}.account-menu:has(.profile-menu-item) .MuiMenu-paper .MuiListItemAvatar-root{min-width:40px;padding:10px}.account-menu:has(.profile-menu-item) .MuiMenu-paper .MuiListItemAvatar-root .MuiAvatar-circular{height:40px;margin-left:-10px;margin-right:0;width:40px}.account-menu:has(.profile-menu-item) .MuiMenu-paper .MuiMenuItem-root:first-of-type{margin-top:10px}.account-menu:has(.profile-menu-item) .MuiMenu-paper .MuiMenuItem-root .MuiListItemIcon-root .MuiSvgIcon-root{color:var(--color-brand-primary,var(--color-brand-primary))}
|
package/dist/index.d.ts
CHANGED
|
@@ -98,7 +98,8 @@ interface HeaderAuthState {
|
|
|
98
98
|
*/
|
|
99
99
|
declare function setHeaderAuth(auth: HeaderAuthState | null): void;
|
|
100
100
|
/**
|
|
101
|
-
* User display data:
|
|
101
|
+
* User display data: prefers linn-i-am-userDetails (IAM), falls back to
|
|
102
|
+
* persist:userdb → profileInformation.userDetails, then authDetails.auth.user.
|
|
102
103
|
*/
|
|
103
104
|
declare const getUserDataFromStorage: () => {
|
|
104
105
|
name: string;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,+BAA+B,CAAC;AACvC,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACrE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,sBAAsB,EACtB,+BAA+B,EAC/B,0BAA0B,EAC1B,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,EACpB,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,eAAe,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.esm.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
.MuiToolbar-root{background-color:var(--color-header-bg,var(--color-white))!important;height:var(--size-header-height,65px)!important;min-height:var(--size-header-height,65px)!important;padding-left:15px!important}.MuiToolbar-root,.MuiToolbar-root .MuiButtonBase-root{color:var(--color-brand-primary,var(--color-brand-primary))!important}.MuiToolbar-root .MuiButtonBase-root{margin-right:0}.app-header{flex-shrink:0}.app-header,.app-header .MuiAppBar-root{background-color:var(--color-header-bg,var(--color-white))!important;height:var(--size-header-height,65px)!important}.app-header .MuiAppBar-root{box-shadow:none!important;left:0;position:fixed!important;right:0;top:0;z-index:var(--size-header-zindex,200)!important}.app-header .MuiPaper-root:only-of-type{border-bottom:1px solid var(--color-border-header,var(--color-border-header));box-shadow:none!important;padding:0!important}.var{color:var(--color-brand-accent,var(--color-brand-accent))!important}.miner,.var{font:500 20px var(--font-brand-semibold,"OpenSans-SemiBold",sans-serif)}.miner{color:var(--color-brand-deep-navy,var(--color-brand-deep-navy))!important}.account-menu:has(.profile-menu-section) .MuiList-root .MuiListItem-root .MuiListItemText-root .MuiTypography-root.profile-name{color:var(--color-profile-name,var(--color-brand-primary));font:600 16px/28px var(--font-brand-semibold,"OpenSans-SemiBold",sans-serif)}.account-menu:has(.profile-menu-section) .MuiList-root .MuiListItem-root .MuiListItemText-root .MuiTypography-root.profile-email{color:var(--color-profile-email,var(--color-text-secondary-alpha));font:400 14px/24px var(--font-brand-regular,"OpenSans-Regular",sans-serif);text-decoration:underline}.account-menu:has(.profile-menu-section) .MuiList-root .MuiListItem-root .MuiListItemText-root .MuiTypography-root.profile-role{color:var(--color-profile-role,var(--color-text-muted-alpha));font:400 12px/28px var(--font-brand-regular,"OpenSans-Regular",sans-serif);text-transform:uppercase}.account-menu:has(.profile-menu-item) .profile-menu-item{padding:10px 15px 5px}.account-menu:has(.profile-menu-item) .MuiMenu-paper{background:var(--color-menu-bg-gradient,linear-gradient(180deg,var(--color-white),var(--color-selected-row),var(--color-selected-row)));box-shadow:none!important;color:var(--color-menu-text,var(--color-black));margin:0;max-width:var(--size-menu-width,280px);width:var(--size-menu-width,280px)}.account-menu:has(.profile-menu-item) .MuiMenu-paper .MuiListItemAvatar-root{min-width:40px;padding:10px}.account-menu:has(.profile-menu-item) .MuiMenu-paper .MuiListItemAvatar-root .MuiAvatar-circular{height:40px;margin-left:-10px;margin-right:0;width:40px}.account-menu:has(.profile-menu-item) .MuiMenu-paper .MuiMenuItem-root:first-of-type{margin-top:10px}.account-menu:has(.profile-menu-item) .MuiMenu-paper .MuiMenuItem-root .MuiListItemIcon-root .MuiSvgIcon-root{color:var(--color-brand-primary,var(--color-brand-primary))}
|
package/dist/index.esm.js
CHANGED
|
@@ -14,6 +14,40 @@ import * as React from 'react';
|
|
|
14
14
|
import React__default from 'react';
|
|
15
15
|
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
|
|
16
16
|
|
|
17
|
+
const tenantFallbackCss = "/* ================================================================\r\n TENANT MODULE CSS — varminer-app-header-npm-fe\r\n Auto-generated by generate-tenant-css.js\r\n Branch scanned: Development\r\n Covers: CSS var() references, SCSS $variables, and hardcoded\r\n brand values detected in component files.\r\n ================================================================ */\r\n\r\n\r\n\n/* ── FONT FACES: local dev fallback (generate-tenant-css) ────────────── */\n/* @font-face rules for local dev fallback. In production the CDN\n tenant.css @font-face declarations (built by generate-tenant-all.js)\n load via injectTenantCss() and override these automatically.\n To change the local font path, update LOCAL_FONT_BASE_URL above. */\n@font-face {\n font-family: \"OpenSans-Light\";\n src: url(\"/asset/font/OpenSans-Light.ttf\") format(\"truetype\");\n font-weight: 300;\n font-style: normal;\n font-display: swap;\n}\n@font-face {\n font-family: \"OpenSans-LightItalic\";\n src: url(\"/asset/font/OpenSans-LightItalic.ttf\") format(\"truetype\");\n font-weight: 300;\n font-style: italic;\n font-display: swap;\n}\n@font-face {\n font-family: \"OpenSans-Regular\";\n src: url(\"/asset/font/OpenSans-Regular.ttf\") format(\"truetype\");\n font-weight: 400;\n font-style: normal;\n font-display: swap;\n}\n@font-face {\n font-family: \"OpenSans-Italic\";\n src: url(\"/asset/font/OpenSans-Italic.ttf\") format(\"truetype\");\n font-weight: 400;\n font-style: italic;\n font-display: swap;\n}\n@font-face {\n font-family: \"OpenSans-Medium\";\n src: url(\"/asset/font/OpenSans-Medium.ttf\") format(\"truetype\");\n font-weight: 500;\n font-style: normal;\n font-display: swap;\n}\n@font-face {\n font-family: \"OpenSans-MediumItalic\";\n src: url(\"/asset/font/OpenSans-MediumItalic.ttf\") format(\"truetype\");\n font-weight: 500;\n font-style: italic;\n font-display: swap;\n}\n@font-face {\n font-family: \"OpenSans-SemiBold\";\n src: url(\"/asset/font/OpenSans-SemiBold.ttf\") format(\"truetype\");\n font-weight: 600;\n font-style: normal;\n font-display: swap;\n}\n@font-face {\n font-family: \"OpenSans-SemiBoldItalic\";\n src: url(\"/asset/font/OpenSans-SemiBoldItalic.ttf\") format(\"truetype\");\n font-weight: 600;\n font-style: italic;\n font-display: swap;\n}\n@font-face {\n font-family: \"OpenSans-Bold\";\n src: url(\"/asset/font/OpenSans-Bold.ttf\") format(\"truetype\");\n font-weight: 700;\n font-style: normal;\n font-display: swap;\n}\n@font-face {\n font-family: \"OpenSans-BoldItalic\";\n src: url(\"/asset/font/OpenSans-BoldItalic.ttf\") format(\"truetype\");\n font-weight: 700;\n font-style: italic;\n font-display: swap;\n}\n@font-face {\n font-family: \"OpenSans-ExtraBold\";\n src: url(\"/asset/font/OpenSans-ExtraBold.ttf\") format(\"truetype\");\n font-weight: 800;\n font-style: normal;\n font-display: swap;\n}\n@font-face {\n font-family: \"OpenSans-ExtraBoldItalic\";\n src: url(\"/asset/font/OpenSans-ExtraBoldItalic.ttf\") format(\"truetype\");\n font-weight: 800;\n font-style: italic;\n font-display: swap;\n}\n/* ── END FONT FACES ── */\n\n/* ── FONT FACES: local dev fallback (generate-tenant-css) ────────────── */\r\n/* @font-face rules for local dev fallback. In production the CDN\r\n tenant.css @font-face declarations (built by generate-tenant-all.js)\r\n load via injectTenantCss() and override these automatically.\r\n To change the local font path, update LOCAL_FONT_BASE_URL above. */\r\n@font-face {\r\n font-family: \"OpenSans-Light\";\r\n src: url(\"/asset/font/OpenSans-Light.ttf\") format(\"truetype\");\r\n font-weight: 300;\r\n font-style: normal;\r\n font-display: swap;\r\n}\r\n@font-face {\r\n font-family: \"OpenSans-LightItalic\";\r\n src: url(\"/asset/font/OpenSans-LightItalic.ttf\") format(\"truetype\");\r\n font-weight: 300;\r\n font-style: italic;\r\n font-display: swap;\r\n}\r\n@font-face {\r\n font-family: \"OpenSans-Regular\";\r\n src: url(\"/asset/font/OpenSans-Regular.ttf\") format(\"truetype\");\r\n font-weight: 400;\r\n font-style: normal;\r\n font-display: swap;\r\n}\r\n@font-face {\r\n font-family: \"OpenSans-Italic\";\r\n src: url(\"/asset/font/OpenSans-Italic.ttf\") format(\"truetype\");\r\n font-weight: 400;\r\n font-style: italic;\r\n font-display: swap;\r\n}\r\n@font-face {\r\n font-family: \"OpenSans-Medium\";\r\n src: url(\"/asset/font/OpenSans-Medium.ttf\") format(\"truetype\");\r\n font-weight: 500;\r\n font-style: normal;\r\n font-display: swap;\r\n}\r\n@font-face {\r\n font-family: \"OpenSans-MediumItalic\";\r\n src: url(\"/asset/font/OpenSans-MediumItalic.ttf\") format(\"truetype\");\r\n font-weight: 500;\r\n font-style: italic;\r\n font-display: swap;\r\n}\r\n@font-face {\r\n font-family: \"OpenSans-SemiBold\";\r\n src: url(\"/asset/font/OpenSans-SemiBold.ttf\") format(\"truetype\");\r\n font-weight: 600;\r\n font-style: normal;\r\n font-display: swap;\r\n}\r\n@font-face {\r\n font-family: \"OpenSans-SemiBoldItalic\";\r\n src: url(\"/asset/font/OpenSans-SemiBoldItalic.ttf\") format(\"truetype\");\r\n font-weight: 600;\r\n font-style: italic;\r\n font-display: swap;\r\n}\r\n@font-face {\r\n font-family: \"OpenSans-Bold\";\r\n src: url(\"/asset/font/OpenSans-Bold.ttf\") format(\"truetype\");\r\n font-weight: 700;\r\n font-style: normal;\r\n font-display: swap;\r\n}\r\n@font-face {\r\n font-family: \"OpenSans-BoldItalic\";\r\n src: url(\"/asset/font/OpenSans-BoldItalic.ttf\") format(\"truetype\");\r\n font-weight: 700;\r\n font-style: italic;\r\n font-display: swap;\r\n}\r\n@font-face {\r\n font-family: \"OpenSans-ExtraBold\";\r\n src: url(\"/asset/font/OpenSans-ExtraBold.ttf\") format(\"truetype\");\r\n font-weight: 800;\r\n font-style: normal;\r\n font-display: swap;\r\n}\r\n@font-face {\r\n font-family: \"OpenSans-ExtraBoldItalic\";\r\n src: url(\"/asset/font/OpenSans-ExtraBoldItalic.ttf\") format(\"truetype\");\r\n font-weight: 800;\r\n font-style: italic;\r\n font-display: swap;\r\n}\r\n/* ── END FONT FACES ── */\r\n\r\n/* ═══════════════════════════════════════════════════════════════\r\n MODULE: app-header (varminer-app-header-npm-fe)\r\n CSS custom-properties consumed by this micro-frontend.\r\n These are default / fallback values overridden by tenant.css.\r\n ═══════════════════════════════════════════════════════════════ */\r\n:root {\r\n --color-border-header: #e5e9eb;\r\n --color-brand-accent: #1aa7ee;\r\n --color-brand-deep-navy: #0f1e75;\r\n --color-brand-primary: #1e2f97;\r\n --color-brand-primary-hover-bg: rgba(30, 47, 151, 0.04);\r\n --color-header-bg: #ffffff;\r\n --color-menu-bg-gradient: linear-gradient(180deg, #fff, #ddf7ff, #ddf7ff);\r\n --color-menu-bg-gradient-end: #ddf7ff;\r\n --color-menu-shadow: rgba(0,0,0,0.32);\r\n --color-menu-text: #000;\r\n --color-profile-email: rgba(0, 0, 0, 0.6);\r\n --color-profile-name: #1e2f97;\r\n --color-profile-role: rgba(0, 0, 0, 0.38);\r\n --color-status-offline: #808080;\r\n --color-status-online: #44b700;\r\n --font-brand-regular: OpenSans-Regular, Roboto, sans-serif;\r\n --font-brand-semibold: OpenSans-SemiBold, Roboto, sans-serif;\r\n --image-logo-svg: url(\"asset/logo.svg\");\r\n --size-header-height: 65px;\r\n --size-header-zindex: 200;\r\n --size-menu-width: 280px;\r\n\n /* ── Auto-discovered on 2026-03-17 ── */\n --color-white: #fff;\n --color-hex-aacccc: #acc;\n --color-selected-row: #ddf7ff;\n --color-black: #000;\n --color-text-secondary-alpha: rgba(0, 0, 0, 0.6);\n --color-text-muted-alpha: rgba(0, 0, 0, 0.38);\n --color-brand-primary-dark: #0b1659;\n --color-primary-dark: #111c56;\n --color-brand-navy-header: #13257b;\n --color-brand-accent-hover: #0a8bcc;\n --color-brand-switch: #657bfd;\n --color-brand-secondary: #3f8cff;\n --color-igv-gradient-start: #1e3c72;\n --color-igv-gradient-end: #2a5298;\n --color-bg-page: #f5f9ff;\n --color-bg-title-section: #e6f2ff;\n --color-bg-dialog: #f7fbff;\n --color-bg-panel: #e3f4fd;\n --color-bg-side-menu-hover: #e3f2fd;\n --color-bg-subtle: #f5f5f5;\n --color-bg-scrollbar-track: #f1f1f1;\n --Grey-50: #ebeff5;\n --color-border-blue: #b5e6ff;\n --color-border-default: #dadada;\n --color-border-sky-blue-300: #4fc4ff;\n --color-border-light: #e4e4e4;\n --color-border-chip: #bdbdbd;\n --color-text-heading: #27323d;\n --color-text-dark: #0f172a;\n --color-text-input: #0a0a0a;\n --color-text-muted-slate: #64748b;\n --Grey-600: #586d81;\n --Grey-400: #7c8fa3;\n --color-status-success: #4caf50;\n --color-status-success-dark: #2e7d32;\n --color-status-warning: #ef6c00;\n --color-status-error: #d32f2f;\n --color-scrollbar-thumb: #1976d2;\n --color-scrollbar-track: #e3edf7;\n --color-side-menu-active-bg: #1565c0;\n --color-column-rows-even: #edfbff;\n --color-bg-error-row: #fcefef;\n --color-bg-error-row-hover: #f9e0e0;\n --color-border-error-row: #e78e8e;\n --color-bg-warning-row: #fff5ed;\n --color-bg-warning-row-hover: #ffe8d6;\n --color-border-warning-row: #e8a87c;\n --color-bg-success-row: #eff5ef;\n --color-bg-success-row-hover: #e5ede5;\n --color-shadow-dark: #b3b3b3;\n --color-bg-success-toast: #edf7ed;\n --color-bg-error-toast: #ffebee;\n --color-text-success-toast: #1e4620;\n --color-text-error-toast: #c62828;\n --color-gene-type-uncertain: #5034ee;\n --color-gene-type-candidate: #ff9800;\n --color-gene-type-known: #2196f3;\n --color-border-disabled: #ccc;\n --color-scrollbar-handle: #888;\n --color-text-placeholder: #666;\n --color-scrollbar-handle-dark: #555;\n --color-text-dark-secondary: #333;\n --color-text-near-black: #222;\n --color-hex-e0e0e0: #e0e0e0;\n --color-hex-c0c0c0: #c0c0c0;\n --color-hex-f8f9fa: #f8f9fa;\n --color-brand-primary-active-bg: rgba(30, 47, 151, 0.08);\n --color-chip-background: rgba(30, 47, 151, 0.12);\n --color-border-brand-muted: rgba(30, 47, 151, 0.23);\n --color-accent-hover-subtle: rgba(26, 167, 238, 0.04);\n --color-accent-hover-bg: rgba(26, 167, 238, 0.08);\n --color-accent-selected: rgba(26, 167, 238, 0.12);\n --color-accent-selected-dark: rgba(26, 167, 238, 0.16);\n --color-accent-light: rgba(26, 167, 238, 0.34);\n --color-accent-border: rgba(26, 167, 238, 0.54);\n --color-shadow-dialog: rgba(8, 37, 68, 0.18);\n --color-shadow-card: rgba(10, 33, 62, 0.08);\n --color-shadow-card-hover: rgba(10, 33, 62, 0.16);\n --color-deep-navy-hover-bg: rgba(15, 30, 117, 0.08);\n --color-shadow-body: rgba(15, 23, 42, 0.08);\n --color-white-overlay: rgba(255, 255, 255, 0.1);\n --color-action-hover-bg: rgba(0, 0, 0, 0.04);\n --color-overlay-subtle: rgba(0, 0, 0, 0.10);\n --color-divider: rgba(0, 0, 0, 0.12);\n --color-overlay-medium: rgba(0, 0, 0, 0.14);\n --color-shadow-light: rgba(0, 0, 0, 0.15);\n --color-shadow-medium: rgba(0, 0, 0, 0.20);\n --color-border-outline: rgba(0, 0, 0, 0.26);\n --color-border-medium: rgba(0, 0, 0, 0.5);\n --color-icon-default: rgba(0, 0, 0, 0.54);\n --color-action-active: rgba(0, 0, 0, 0.56);\n --color-border-dark: rgba(0, 0, 0, 0.7);\n --color-text-primary-alpha: rgba(0, 0, 0, 0.87);\n\n /* ── Auto-discovered on 2026-03-17 ── */\n --color-header-accent: #aacccc;\n --color-error-pink: #dc004e;\n --color-text-disabled: #999999;\n --color-overlay-40: rgba(0, 0, 0, 0.4);\n --color-white-70: rgba(255, 255, 255, 0.7);\n --color-white-90: rgba(255, 255, 255, 0.9);\n --color-white-95: rgba(255, 255, 255, 0.95);\n --color-success-90: rgba(76, 175, 80, 0.9);\n --color-error-solid: rgba(211, 47, 47, 1);\n --color-error-50: rgba(211, 47, 47, 0.5);\n --color-rgba-000000: rgb(0,0,0);\n}\n";
|
|
18
|
+
|
|
19
|
+
const TENANT_FALLBACK_STYLE_ID = "tenant-fallback-css";
|
|
20
|
+
function rewriteFallbackAssetUrls(cssText) {
|
|
21
|
+
const baseUrl = import.meta.env?.BASE_URL ?? "/";
|
|
22
|
+
const normalizedBaseUrl = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
23
|
+
return cssText.replace(/url\((["']?)\/asset\//g, `url($1${normalizedBaseUrl}asset/`);
|
|
24
|
+
}
|
|
25
|
+
function injectTenantFallbackCss(cssText) {
|
|
26
|
+
if (typeof document === "undefined")
|
|
27
|
+
return;
|
|
28
|
+
const rewrittenCss = rewriteFallbackAssetUrls(cssText);
|
|
29
|
+
const existingStyle = document.getElementById(TENANT_FALLBACK_STYLE_ID);
|
|
30
|
+
if (existingStyle) {
|
|
31
|
+
if (existingStyle.textContent?.includes(rewrittenCss))
|
|
32
|
+
return;
|
|
33
|
+
existingStyle.textContent = existingStyle.textContent
|
|
34
|
+
? `${existingStyle.textContent}\n\n${rewrittenCss}`
|
|
35
|
+
: rewrittenCss;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const style = document.createElement("style");
|
|
39
|
+
style.id = TENANT_FALLBACK_STYLE_ID;
|
|
40
|
+
style.textContent = rewrittenCss;
|
|
41
|
+
const tenantCssLink = document.querySelector('link[rel="stylesheet"][href*="tenant.css"]');
|
|
42
|
+
if (tenantCssLink) {
|
|
43
|
+
document.head.insertBefore(style, tenantCssLink);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
document.head.appendChild(style);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
injectTenantFallbackCss(tenantFallbackCss);
|
|
50
|
+
|
|
17
51
|
const DrawerContext = React.createContext({
|
|
18
52
|
isDrawerOpen: false,
|
|
19
53
|
openDrawer: () => { },
|
|
@@ -74,21 +108,79 @@ function setHeaderAuth(auth) {
|
|
|
74
108
|
}
|
|
75
109
|
}
|
|
76
110
|
/**
|
|
77
|
-
* User display data:
|
|
111
|
+
* User display data: prefers linn-i-am-userDetails (IAM), falls back to
|
|
112
|
+
* persist:userdb → profileInformation.userDetails, then authDetails.auth.user.
|
|
78
113
|
*/
|
|
79
114
|
const getUserDataFromStorage = () => {
|
|
115
|
+
// Primary source: IAM app sets this after OTP verification
|
|
80
116
|
const iamUser = getStoredUserDetails();
|
|
81
|
-
if (
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
117
|
+
if (iamUser) {
|
|
118
|
+
const name = [iamUser.firstName, iamUser.lastName].filter(Boolean).join(" ").trim();
|
|
119
|
+
const role = iamUser.roles?.length ? iamUser.roles[0] : iamUser.workInfo?.jobTitle ?? "";
|
|
120
|
+
return {
|
|
121
|
+
name: name || "",
|
|
122
|
+
email: iamUser.email || "",
|
|
123
|
+
role: role || "",
|
|
124
|
+
avatar: undefined,
|
|
125
|
+
initials: name ? name.split(/\s+/).map((s) => s[0]).join("").slice(0, 2).toUpperCase() : undefined,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// Fallback: read from persist:userdb which is written by the IAM/login app
|
|
129
|
+
try {
|
|
130
|
+
const raw = localStorage.getItem("persist:userdb");
|
|
131
|
+
if (!raw)
|
|
132
|
+
return null;
|
|
133
|
+
const outer = JSON.parse(raw);
|
|
134
|
+
const parseNested = (v) => {
|
|
135
|
+
if (typeof v === "string") {
|
|
136
|
+
try {
|
|
137
|
+
return JSON.parse(v);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return v;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return v;
|
|
144
|
+
};
|
|
145
|
+
// profileInformation.userDetails has firstName, lastName, email, roles[]
|
|
146
|
+
const profileInfo = parseNested(outer.profileInformation);
|
|
147
|
+
const userDetails = profileInfo?.userDetails;
|
|
148
|
+
if (userDetails && (userDetails.firstName || userDetails.lastName || userDetails.email)) {
|
|
149
|
+
const first = userDetails.firstName || "";
|
|
150
|
+
const last = userDetails.lastName || "";
|
|
151
|
+
const name = [first, last].filter(Boolean).join(" ").trim();
|
|
152
|
+
const roles = userDetails.roles;
|
|
153
|
+
const role = roles?.length ? roles[0] : userDetails.jobTitle ?? "";
|
|
154
|
+
return {
|
|
155
|
+
name,
|
|
156
|
+
email: userDetails.email || "",
|
|
157
|
+
role: role || "",
|
|
158
|
+
avatar: undefined,
|
|
159
|
+
initials: name ? name.split(/\s+/).map((s) => s[0]).join("").slice(0, 2).toUpperCase() : undefined,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// authDetails.auth.user has firstname/lastname (lowercase n) + activeRole
|
|
163
|
+
const authDetailsRaw = parseNested(outer.authDetails);
|
|
164
|
+
const auth = authDetailsRaw?.auth;
|
|
165
|
+
const userObj = auth?.user;
|
|
166
|
+
if (auth && (userObj?.firstname || userObj?.lastname)) {
|
|
167
|
+
const first = userObj?.firstname || "";
|
|
168
|
+
const last = userObj?.lastname || "";
|
|
169
|
+
const name = [first, last].filter(Boolean).join(" ").trim();
|
|
170
|
+
const role = auth.activeRole || "";
|
|
171
|
+
return {
|
|
172
|
+
name,
|
|
173
|
+
email: "",
|
|
174
|
+
role,
|
|
175
|
+
avatar: undefined,
|
|
176
|
+
initials: name ? name.split(/\s+/).map((s) => s[0]).join("").slice(0, 2).toUpperCase() : undefined,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// ignore parse errors
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
92
184
|
};
|
|
93
185
|
const getNotificationCountFromStorage = () => {
|
|
94
186
|
const userDbString = localStorage.getItem("persist:userdb");
|