@dashadmin/dash-admin 1.3.45 → 1.3.47
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/components/i18n/BridgedLocalesMenuButton.js +1 -2
- package/dist/components/menu/DarkToggleMode.js +1 -1
- package/dist/components/subscription/PlanPricesSettings.js +4 -2
- package/dist/components/tenancy/GlobalTenantWrapper.js +64 -0
- package/dist/components/tenancy/TenantSwitcher.js +389 -0
- package/dist/contexts/com/components/EchoNotificationsCenter.js +40 -0
- package/dist/default-theme/menu/AppMenuComponents/expanded/SidebarItem.js +1 -0
- package/dist/index.js +60 -40
- package/dist/pages/Profile.js +32 -38
- package/dist/providers/i18n/en.js +33 -0
- package/dist/providers/i18n/es.js +33 -0
- package/dist/resources/User/components/AvatarUploadField.js +61 -0
- package/dist/resources/User/components/PasswordFields.js +67 -0
- package/dist/resources/User/getProfileMenu.js +36 -0
- package/dist/resources/User/profileResource.js +33 -0
- package/dist/resources/User/userLayout.js +58 -0
- package/dist/resources/User/userResource.js +90 -0
- package/dist/resources/User/userSchema.js +206 -0
- package/dist/resources/User/usersFilters.js +22 -0
- package/dist/systemResources.js +30 -19
- package/package.json +1 -1
- package/src/components/i18n/BridgedLocalesMenuButton.tsx +1 -2
- package/src/components/menu/DarkToggleMode.tsx +1 -1
- package/src/components/subscription/PlanPricesSettings.tsx +2 -2
- package/src/components/tenancy/GlobalTenantWrapper.tsx +84 -0
- package/src/components/tenancy/TenantSwitcher.tsx +485 -0
- package/src/contexts/com/components/EchoNotificationsCenter.tsx +65 -0
- package/src/default-theme/menu/AppMaterialMenu.tsx +1 -1
- package/src/default-theme/menu/AppMenuComponents/expanded/SidebarItem.tsx +1 -0
- package/src/default-theme/menu/SidebarActions.tsx +1 -1
- package/src/index.tsx +15 -0
- package/src/pages/Profile.tsx +69 -107
- package/src/providers/i18n/en.ts +33 -0
- package/src/providers/i18n/es.ts +33 -0
- package/src/resources/User/components/AvatarUploadField.tsx +57 -0
- package/src/resources/User/components/PasswordFields.tsx +73 -0
- package/src/resources/User/getProfileMenu.ts +57 -0
- package/src/resources/User/profileResource.tsx +51 -0
- package/src/resources/User/userLayout.tsx +62 -0
- package/src/resources/User/userResource.tsx +111 -0
- package/src/resources/User/userSchema.tsx +213 -0
- package/src/resources/User/usersFilters.tsx +21 -0
- package/src/systemResources.tsx +31 -20
|
@@ -77,8 +77,7 @@ const BridgedLocalesMenuButton = ({
|
|
|
77
77
|
IconButton,
|
|
78
78
|
{
|
|
79
79
|
onClick: handleClick,
|
|
80
|
-
|
|
81
|
-
size: "small",
|
|
80
|
+
className: "dash-icon-button-color dash-icon-button-bg",
|
|
82
81
|
"aria-label": "change language",
|
|
83
82
|
"aria-controls": open ? "locale-menu" : void 0,
|
|
84
83
|
"aria-haspopup": "true",
|
|
@@ -26,7 +26,7 @@ const DarkToggleMode = () => {
|
|
|
26
26
|
setMode(storedTheme);
|
|
27
27
|
}
|
|
28
28
|
}, []);
|
|
29
|
-
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("div", { onClick, children: /* @__PURE__ */ jsx(DashThemeHelperProvider, { children: /* @__PURE__ */ jsx(
|
|
29
|
+
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("div", { className: "dash-theme-mode-switcher", onClick, children: /* @__PURE__ */ jsx(DashThemeHelperProvider, { children: /* @__PURE__ */ jsx(
|
|
30
30
|
Avatar,
|
|
31
31
|
{
|
|
32
32
|
sizes: "small",
|
|
@@ -40,7 +40,8 @@ const PlanPricesView = () => {
|
|
|
40
40
|
const plan = useRecordContext();
|
|
41
41
|
const prices = plan == null ? void 0 : plan.prices;
|
|
42
42
|
const { data: currencies, isLoading } = useGetList(
|
|
43
|
-
"
|
|
43
|
+
"system/currency",
|
|
44
|
+
// core "shared master data" — works for every domain, unlike ecommerce/currency (kitchntabs-backend-domain only)
|
|
44
45
|
{
|
|
45
46
|
pagination: { page: 1, perPage: 100 },
|
|
46
47
|
sort: { field: "code", order: "ASC" },
|
|
@@ -118,7 +119,8 @@ const PlanPricesEdit = ({ method }) => {
|
|
|
118
119
|
const formContext = useFormContext();
|
|
119
120
|
const { register, setValue, watch } = formContext;
|
|
120
121
|
const { data: currencies, isLoading, error } = useGetList(
|
|
121
|
-
"
|
|
122
|
+
"system/currency",
|
|
123
|
+
// core "shared master data" — works for every domain, unlike ecommerce/currency (kitchntabs-backend-domain only)
|
|
122
124
|
{
|
|
123
125
|
pagination: { page: 1, perPage: 100 },
|
|
124
126
|
sort: { field: "code", order: "ASC" },
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __spreadValues = (a, b) => {
|
|
7
|
+
for (var prop in b || (b = {}))
|
|
8
|
+
if (__hasOwnProp.call(b, prop))
|
|
9
|
+
__defNormalProp(a, prop, b[prop]);
|
|
10
|
+
if (__getOwnPropSymbols)
|
|
11
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
+
if (__propIsEnum.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
}
|
|
15
|
+
return a;
|
|
16
|
+
};
|
|
17
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
18
|
+
import { AuthPersistenceService } from "dash-auth";
|
|
19
|
+
import { DASH_REDUX_ACTIONS } from "dash-admin-state";
|
|
20
|
+
import { useDispatch } from "react-redux";
|
|
21
|
+
import DashThemeContext from "../../default-theme/DashThemeContext";
|
|
22
|
+
import React, { useEffect } from "react";
|
|
23
|
+
const GlobalTenantWrapper = (props) => {
|
|
24
|
+
const {
|
|
25
|
+
tenantData = null,
|
|
26
|
+
children
|
|
27
|
+
} = props;
|
|
28
|
+
const dispatch = useDispatch();
|
|
29
|
+
const themeContext = React.useContext(DashThemeContext);
|
|
30
|
+
const recreateTheme = themeContext == null ? void 0 : themeContext.recreateTheme;
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
var _a, _b, _c;
|
|
33
|
+
if (!tenantData) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (tenantData.tenantImages) {
|
|
37
|
+
const logos = __spreadValues(__spreadValues(__spreadValues({}, ((_a = tenantData.tenantImages.horizontal_logo) == null ? void 0 : _a.original) && {
|
|
38
|
+
horizontalLogo: tenantData.tenantImages.horizontal_logo.original
|
|
39
|
+
}), ((_b = tenantData.tenantImages.squared_logo) == null ? void 0 : _b.original) && {
|
|
40
|
+
squaredLogo: tenantData.tenantImages.squared_logo.original
|
|
41
|
+
}), ((_c = tenantData.tenantImages.banner) == null ? void 0 : _c.original) && {
|
|
42
|
+
loginBackground: tenantData.tenantImages.banner.original
|
|
43
|
+
});
|
|
44
|
+
dispatch(DASH_REDUX_ACTIONS.setPanelSettings(logos));
|
|
45
|
+
}
|
|
46
|
+
if (tenantData.tenantSettings && recreateTheme) {
|
|
47
|
+
recreateTheme(tenantData.tenantSettings);
|
|
48
|
+
}
|
|
49
|
+
const publicAuthData = {
|
|
50
|
+
auth: {
|
|
51
|
+
tenantImages: tenantData.tenantImages,
|
|
52
|
+
tenantSettings: tenantData.tenantSettings,
|
|
53
|
+
tenant: tenantData.tenant
|
|
54
|
+
},
|
|
55
|
+
systemValues: tenantData.systemValues
|
|
56
|
+
};
|
|
57
|
+
AuthPersistenceService.saveAuth(publicAuthData);
|
|
58
|
+
}, [tenantData]);
|
|
59
|
+
return /* @__PURE__ */ jsx(Fragment, {});
|
|
60
|
+
};
|
|
61
|
+
var GlobalTenantWrapper_default = GlobalTenantWrapper;
|
|
62
|
+
export {
|
|
63
|
+
GlobalTenantWrapper_default as default
|
|
64
|
+
};
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __async = (__this, __arguments, generator) => {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
var fulfilled = (value) => {
|
|
23
|
+
try {
|
|
24
|
+
step(generator.next(value));
|
|
25
|
+
} catch (e) {
|
|
26
|
+
reject(e);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var rejected = (value) => {
|
|
30
|
+
try {
|
|
31
|
+
step(generator.throw(value));
|
|
32
|
+
} catch (e) {
|
|
33
|
+
reject(e);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
37
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
41
|
+
import { useState, useRef, useEffect, useCallback } from "react";
|
|
42
|
+
import {
|
|
43
|
+
Avatar,
|
|
44
|
+
Box,
|
|
45
|
+
Typography,
|
|
46
|
+
CircularProgress
|
|
47
|
+
} from "@mui/material";
|
|
48
|
+
import BusinessIcon from "@mui/icons-material/Business";
|
|
49
|
+
import StoreIcon from "@mui/icons-material/Store";
|
|
50
|
+
import SwapHorizIcon from "@mui/icons-material/SwapHoriz";
|
|
51
|
+
import ReactDOM from "react-dom";
|
|
52
|
+
import { dashStorage } from "dash-utils";
|
|
53
|
+
import { AuthPersistenceService } from "dash-auth";
|
|
54
|
+
import { DASHAdminSystemConstants, getEnv } from "dash-constants";
|
|
55
|
+
import { useAxios } from "dash-axios-hook";
|
|
56
|
+
import { updateDomCssVariables } from "dash-utils";
|
|
57
|
+
import DASHLayoutSettings from "../../theme/AppLayoutSetting";
|
|
58
|
+
import { useDispatch, useSelector } from "react-redux";
|
|
59
|
+
import { setPanelSettings } from "dash-admin-state/redux/actions/Common";
|
|
60
|
+
import { useWindowSize } from "dash-utils";
|
|
61
|
+
import { setAuthEvent } from "../../contexts/auth";
|
|
62
|
+
const dispatchTenantSwitchEvent = (detail) => {
|
|
63
|
+
window.dispatchEvent(new CustomEvent("tenant_switch", { detail }));
|
|
64
|
+
};
|
|
65
|
+
const getActiveTenantId = () => {
|
|
66
|
+
if (!isTenantImpersonationEnabled()) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
return dashStorage.getItem("active_tenant_id") || null;
|
|
70
|
+
};
|
|
71
|
+
const isTenantImpersonationEnabled = () => {
|
|
72
|
+
const val = DASHAdminSystemConstants.system.ENABLE_TENANT_IMPERSONATION;
|
|
73
|
+
if (typeof val === "boolean") return val;
|
|
74
|
+
if (typeof val === "string") return val === "true" || val === "1";
|
|
75
|
+
return !!val;
|
|
76
|
+
};
|
|
77
|
+
const TenantSwitcher = ({
|
|
78
|
+
defaultHorizontalLogo,
|
|
79
|
+
defaultSquaredLogo,
|
|
80
|
+
defaultLoginBackground
|
|
81
|
+
}) => {
|
|
82
|
+
var _a, _b;
|
|
83
|
+
const axios = useAxios();
|
|
84
|
+
const dispatch = useDispatch();
|
|
85
|
+
const windowSize = useWindowSize();
|
|
86
|
+
const [open, setOpen] = useState(false);
|
|
87
|
+
const [switching, setSwitching] = useState(false);
|
|
88
|
+
const avatarRef = useRef(null);
|
|
89
|
+
const menuRef = useRef(null);
|
|
90
|
+
const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });
|
|
91
|
+
const timeoutRef = useRef(null);
|
|
92
|
+
const [webView, setWebView] = useState(false);
|
|
93
|
+
const [activeTenantId, setActiveTenantId] = useState(
|
|
94
|
+
getActiveTenantId()
|
|
95
|
+
);
|
|
96
|
+
const panelSettings = useSelector(
|
|
97
|
+
(state) => {
|
|
98
|
+
var _a2;
|
|
99
|
+
return (_a2 = state.common) == null ? void 0 : _a2.panelSettings;
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
const sidebarPosition = (panelSettings == null ? void 0 : panelSettings.sidebarPosition) || "left";
|
|
103
|
+
const systemValues = AuthPersistenceService.getSystemValues();
|
|
104
|
+
const tenants = (systemValues == null ? void 0 : systemValues.tenants) || [];
|
|
105
|
+
const tenancy = systemValues == null ? void 0 : systemValues.tenancy;
|
|
106
|
+
const auth = AuthPersistenceService.getAuth();
|
|
107
|
+
const currentTenantName = activeTenantId ? ((_a = tenants.find((t) => t.id === activeTenantId)) == null ? void 0 : _a.name) || "Tenant" : (tenancy == null ? void 0 : tenancy.public_name) || ((_b = auth == null ? void 0 : auth.tenant) == null ? void 0 : _b.name) || "Tenancy Account";
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
if (document.body.classList.contains("webview")) {
|
|
110
|
+
setWebView(true);
|
|
111
|
+
}
|
|
112
|
+
}, []);
|
|
113
|
+
if (!isTenantImpersonationEnabled() || tenants.length === 0) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
const calculateMenuPosition = () => {
|
|
117
|
+
if (avatarRef.current && windowSize.width && windowSize.height) {
|
|
118
|
+
const rect = avatarRef.current.getBoundingClientRect();
|
|
119
|
+
const menuWidth = 230;
|
|
120
|
+
const menuHeight = 120;
|
|
121
|
+
let left = rect.left + window.scrollX;
|
|
122
|
+
let top = rect.top + window.scrollY;
|
|
123
|
+
if (left + menuWidth > windowSize.width) {
|
|
124
|
+
left = windowSize.width - menuWidth - 10;
|
|
125
|
+
}
|
|
126
|
+
if (left < 10) {
|
|
127
|
+
left = 10;
|
|
128
|
+
}
|
|
129
|
+
if (sidebarPosition === "bottom") {
|
|
130
|
+
top = rect.top + window.scrollY - menuHeight - 10;
|
|
131
|
+
}
|
|
132
|
+
setMenuPosition({
|
|
133
|
+
top,
|
|
134
|
+
left: left + 40
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
const handleMouseEnter = (e) => {
|
|
139
|
+
e.preventDefault();
|
|
140
|
+
if (timeoutRef.current) {
|
|
141
|
+
clearTimeout(timeoutRef.current);
|
|
142
|
+
timeoutRef.current = null;
|
|
143
|
+
}
|
|
144
|
+
setOpen(true);
|
|
145
|
+
calculateMenuPosition();
|
|
146
|
+
};
|
|
147
|
+
const handleClick = (e) => {
|
|
148
|
+
e.preventDefault();
|
|
149
|
+
setOpen((prev) => !prev);
|
|
150
|
+
calculateMenuPosition();
|
|
151
|
+
};
|
|
152
|
+
const handleMouseLeave = () => {
|
|
153
|
+
if (!webView) {
|
|
154
|
+
timeoutRef.current = setTimeout(() => setOpen(false), 150);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
const handleMenuMouseEnter = () => {
|
|
158
|
+
if (timeoutRef.current) {
|
|
159
|
+
clearTimeout(timeoutRef.current);
|
|
160
|
+
timeoutRef.current = null;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
const handleMenuMouseLeave = () => {
|
|
164
|
+
if (!webView) {
|
|
165
|
+
setOpen(false);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
useEffect(() => {
|
|
169
|
+
return () => {
|
|
170
|
+
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
171
|
+
};
|
|
172
|
+
}, []);
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
if (open) calculateMenuPosition();
|
|
175
|
+
}, [open, windowSize.width]);
|
|
176
|
+
const handleSwitch = useCallback((tenantId) => __async(null, null, function* () {
|
|
177
|
+
var _a2, _b2, _c, _d, _e, _f, _g, _h;
|
|
178
|
+
if (switching) return;
|
|
179
|
+
if (tenantId === activeTenantId) {
|
|
180
|
+
setOpen(false);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
setSwitching(true);
|
|
184
|
+
setOpen(false);
|
|
185
|
+
try {
|
|
186
|
+
const isTenancyLevel = tenantId === null;
|
|
187
|
+
const authEndpoint = getEnv("APP_GETAUTH_ENDPOINT") || "auth/tenancyAuth";
|
|
188
|
+
const headers = {};
|
|
189
|
+
if (!isTenancyLevel && tenantId) {
|
|
190
|
+
headers["X-Tenant-Id"] = tenantId;
|
|
191
|
+
}
|
|
192
|
+
if (tenantId) {
|
|
193
|
+
dashStorage.setItem("active_tenant_id", tenantId);
|
|
194
|
+
dashStorage.setItem("tenant_id", tenantId);
|
|
195
|
+
} else {
|
|
196
|
+
dashStorage.removeItem("active_tenant_id");
|
|
197
|
+
dashStorage.removeItem("tenant_id");
|
|
198
|
+
}
|
|
199
|
+
const { data: authData } = yield axios.get(authEndpoint, { headers });
|
|
200
|
+
AuthPersistenceService.saveAuth(authData);
|
|
201
|
+
dashStorage.setItem("authenticated", "true");
|
|
202
|
+
dashStorage.setItem("user", JSON.stringify(authData.user));
|
|
203
|
+
if ((_a2 = authData.user) == null ? void 0 : _a2.roles) {
|
|
204
|
+
dashStorage.setItem("roles", JSON.stringify(authData.user.roles));
|
|
205
|
+
}
|
|
206
|
+
setAuthEvent({
|
|
207
|
+
authenticated: true,
|
|
208
|
+
user: authData.user,
|
|
209
|
+
auth: authData.auth,
|
|
210
|
+
token: dashStorage.getItem("token"),
|
|
211
|
+
roles: (_b2 = authData.user) == null ? void 0 : _b2.roles
|
|
212
|
+
});
|
|
213
|
+
const tenantSettings = (_c = authData.auth) == null ? void 0 : _c.tenantSettings;
|
|
214
|
+
try {
|
|
215
|
+
const currentThemeMode = document.documentElement.getAttribute("data-theme") || DASHLayoutSettings.THEME_TYPE_DARK;
|
|
216
|
+
updateDomCssVariables(currentThemeMode, tenantSettings == null ? void 0 : tenantSettings.colors, tenantSettings == null ? void 0 : tenantSettings.values);
|
|
217
|
+
} catch (err) {
|
|
218
|
+
console.error("[TenantSwitcher] Error updating CSS variables:", err);
|
|
219
|
+
}
|
|
220
|
+
const tenantImages = (_d = authData.auth) == null ? void 0 : _d.tenantImages;
|
|
221
|
+
if (tenantImages) {
|
|
222
|
+
AuthPersistenceService.setTenantImages(tenantImages);
|
|
223
|
+
dispatch(setPanelSettings(__spreadProps(__spreadValues({}, panelSettings || {}), {
|
|
224
|
+
horizontalLogo: ((_e = tenantImages.horizontal_logo) == null ? void 0 : _e.original) || (panelSettings == null ? void 0 : panelSettings.horizontalLogo),
|
|
225
|
+
squaredLogo: ((_f = tenantImages.squared_logo) == null ? void 0 : _f.original) || (panelSettings == null ? void 0 : panelSettings.squaredLogo),
|
|
226
|
+
loginBackground: ((_g = tenantImages.banner) == null ? void 0 : _g.original) || (panelSettings == null ? void 0 : panelSettings.loginBackground)
|
|
227
|
+
})));
|
|
228
|
+
} else {
|
|
229
|
+
AuthPersistenceService.clearTenantImages();
|
|
230
|
+
dispatch(setPanelSettings(__spreadProps(__spreadValues({}, panelSettings || {}), {
|
|
231
|
+
horizontalLogo: defaultHorizontalLogo,
|
|
232
|
+
squaredLogo: defaultSquaredLogo,
|
|
233
|
+
loginBackground: defaultLoginBackground
|
|
234
|
+
})));
|
|
235
|
+
}
|
|
236
|
+
if (tenantSettings) {
|
|
237
|
+
AuthPersistenceService.setTenantSettings(tenantSettings);
|
|
238
|
+
} else {
|
|
239
|
+
AuthPersistenceService.clearTenantSettings();
|
|
240
|
+
}
|
|
241
|
+
setActiveTenantId(tenantId);
|
|
242
|
+
const tenantName = isTenancyLevel ? (tenancy == null ? void 0 : tenancy.public_name) || "Tenancy Account" : ((_h = tenants.find((t) => t.id === tenantId)) == null ? void 0 : _h.name) || "Tenant";
|
|
243
|
+
dispatchTenantSwitchEvent({
|
|
244
|
+
tenantId,
|
|
245
|
+
tenantName,
|
|
246
|
+
isTenanancyLevel: isTenancyLevel
|
|
247
|
+
});
|
|
248
|
+
console.log(`[TenantSwitcher] Switched to ${isTenancyLevel ? "Tenancy Account" : tenantName} (${tenantId})`);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
console.error("[TenantSwitcher] Switch failed:", error);
|
|
251
|
+
if (activeTenantId) {
|
|
252
|
+
dashStorage.setItem("active_tenant_id", activeTenantId);
|
|
253
|
+
dashStorage.setItem("tenant_id", activeTenantId);
|
|
254
|
+
} else {
|
|
255
|
+
dashStorage.removeItem("active_tenant_id");
|
|
256
|
+
dashStorage.removeItem("tenant_id");
|
|
257
|
+
}
|
|
258
|
+
} finally {
|
|
259
|
+
setSwitching(false);
|
|
260
|
+
}
|
|
261
|
+
}), [activeTenantId, switching, axios, dispatch, panelSettings, tenants, tenancy, defaultHorizontalLogo, defaultSquaredLogo, defaultLoginBackground]);
|
|
262
|
+
const isSelected = (id) => id === activeTenantId;
|
|
263
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
264
|
+
/* @__PURE__ */ jsx(
|
|
265
|
+
"div",
|
|
266
|
+
__spreadProps(__spreadValues({
|
|
267
|
+
ref: avatarRef,
|
|
268
|
+
className: "dash-tenant-switcher-trigger"
|
|
269
|
+
}, !webView ? { onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave } : { onClick: handleClick }), {
|
|
270
|
+
style: { cursor: "pointer", display: "flex", alignItems: "center" },
|
|
271
|
+
children: switching ? /* @__PURE__ */ jsx(
|
|
272
|
+
CircularProgress,
|
|
273
|
+
{
|
|
274
|
+
className: "dash-icon-button-color dash-icon-button-bg",
|
|
275
|
+
size: 30
|
|
276
|
+
}
|
|
277
|
+
) : /* @__PURE__ */ jsx(
|
|
278
|
+
Avatar,
|
|
279
|
+
{
|
|
280
|
+
className: "dash-icon-button-color dash-icon-button-bg",
|
|
281
|
+
sx: {
|
|
282
|
+
width: 30,
|
|
283
|
+
height: 30,
|
|
284
|
+
fontSize: "0.8rem"
|
|
285
|
+
},
|
|
286
|
+
children: activeTenantId ? /* @__PURE__ */ jsx(StoreIcon, { sx: { fontSize: 18 } }) : /* @__PURE__ */ jsx(BusinessIcon, { sx: { fontSize: 18 } })
|
|
287
|
+
}
|
|
288
|
+
)
|
|
289
|
+
})
|
|
290
|
+
),
|
|
291
|
+
open && ReactDOM.createPortal(
|
|
292
|
+
/* @__PURE__ */ jsx(
|
|
293
|
+
"div",
|
|
294
|
+
{
|
|
295
|
+
ref: menuRef,
|
|
296
|
+
className: "dash-tenant-switcher-portal",
|
|
297
|
+
onMouseEnter: !webView ? handleMenuMouseEnter : void 0,
|
|
298
|
+
onMouseLeave: !webView ? handleMenuMouseLeave : void 0,
|
|
299
|
+
children: /* @__PURE__ */ jsxs(
|
|
300
|
+
"div",
|
|
301
|
+
{
|
|
302
|
+
className: "dash-tenant-switcher-menu",
|
|
303
|
+
style: {
|
|
304
|
+
top: menuPosition.top,
|
|
305
|
+
left: menuPosition.left,
|
|
306
|
+
zIndex: 1e4,
|
|
307
|
+
position: "absolute"
|
|
308
|
+
},
|
|
309
|
+
children: [
|
|
310
|
+
/* @__PURE__ */ jsx(Box, { sx: { px: 2, py: 1.5, borderBottom: "1px solid rgba(255,255,255,0.08)" }, children: /* @__PURE__ */ jsxs(Typography, { variant: "caption", sx: { color: "text.secondary", fontWeight: 600, textTransform: "uppercase", letterSpacing: 0.5 }, children: [
|
|
311
|
+
/* @__PURE__ */ jsx(SwapHorizIcon, { sx: { fontSize: 14, mr: 0.5, verticalAlign: "middle" } }),
|
|
312
|
+
"Switch Environment"
|
|
313
|
+
] }) }),
|
|
314
|
+
/* @__PURE__ */ jsxs(
|
|
315
|
+
"div",
|
|
316
|
+
{
|
|
317
|
+
onClick: () => handleSwitch(null),
|
|
318
|
+
style: {
|
|
319
|
+
padding: "10px 16px",
|
|
320
|
+
cursor: "pointer",
|
|
321
|
+
display: "flex",
|
|
322
|
+
alignItems: "center",
|
|
323
|
+
gap: 10,
|
|
324
|
+
backgroundColor: isSelected(null) ? "rgba(var(--dash-primary-rgb, 25, 118, 210), 0.15)" : "transparent",
|
|
325
|
+
borderLeft: isSelected(null) ? "3px solid var(--dash-primary, #1976d2)" : "3px solid transparent",
|
|
326
|
+
transition: "background-color 0.15s ease"
|
|
327
|
+
},
|
|
328
|
+
onMouseOver: (e) => {
|
|
329
|
+
if (!isSelected(null)) e.currentTarget.style.backgroundColor = "rgba(255,255,255,0.05)";
|
|
330
|
+
},
|
|
331
|
+
onMouseOut: (e) => {
|
|
332
|
+
if (!isSelected(null)) e.currentTarget.style.backgroundColor = "transparent";
|
|
333
|
+
},
|
|
334
|
+
children: [
|
|
335
|
+
/* @__PURE__ */ jsx(BusinessIcon, { sx: { fontSize: 20, color: isSelected(null) ? "primary.main" : "text.secondary" } }),
|
|
336
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
337
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { fontWeight: isSelected(null) ? 600 : 400, color: isSelected(null) ? "primary.main" : "text.primary" }, children: (tenancy == null ? void 0 : tenancy.public_name) || "Tenancy Account" }),
|
|
338
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", sx: { color: "text.secondary" }, children: "Manager Account" })
|
|
339
|
+
] })
|
|
340
|
+
]
|
|
341
|
+
}
|
|
342
|
+
),
|
|
343
|
+
/* @__PURE__ */ jsx(Box, { sx: { borderTop: "1px solid rgba(255,255,255,0.06)", mx: 1 } }),
|
|
344
|
+
tenants.map((tenant) => /* @__PURE__ */ jsxs(
|
|
345
|
+
"div",
|
|
346
|
+
{
|
|
347
|
+
onClick: () => handleSwitch(tenant.id),
|
|
348
|
+
style: {
|
|
349
|
+
padding: "10px 16px",
|
|
350
|
+
cursor: "pointer",
|
|
351
|
+
display: "flex",
|
|
352
|
+
alignItems: "center",
|
|
353
|
+
gap: 10,
|
|
354
|
+
backgroundColor: isSelected(tenant.id) ? "rgba(var(--dash-primary-rgb, 25, 118, 210), 0.15)" : "transparent",
|
|
355
|
+
borderLeft: isSelected(tenant.id) ? "3px solid var(--dash-primary, #1976d2)" : "3px solid transparent",
|
|
356
|
+
transition: "background-color 0.15s ease"
|
|
357
|
+
},
|
|
358
|
+
onMouseOver: (e) => {
|
|
359
|
+
if (!isSelected(tenant.id)) e.currentTarget.style.backgroundColor = "rgba(255,255,255,0.05)";
|
|
360
|
+
},
|
|
361
|
+
onMouseOut: (e) => {
|
|
362
|
+
if (!isSelected(tenant.id)) e.currentTarget.style.backgroundColor = "transparent";
|
|
363
|
+
},
|
|
364
|
+
children: [
|
|
365
|
+
/* @__PURE__ */ jsx(StoreIcon, { sx: { fontSize: 20, color: isSelected(tenant.id) ? "primary.main" : "text.secondary" } }),
|
|
366
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
367
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { fontWeight: isSelected(tenant.id) ? 600 : 400, color: isSelected(tenant.id) ? "primary.main" : "text.primary" }, children: tenant.name }),
|
|
368
|
+
tenant.slug && /* @__PURE__ */ jsx(Typography, { variant: "caption", sx: { color: "text.secondary" }, children: tenant.slug })
|
|
369
|
+
] })
|
|
370
|
+
]
|
|
371
|
+
},
|
|
372
|
+
tenant.id
|
|
373
|
+
))
|
|
374
|
+
]
|
|
375
|
+
}
|
|
376
|
+
)
|
|
377
|
+
}
|
|
378
|
+
),
|
|
379
|
+
document.body
|
|
380
|
+
)
|
|
381
|
+
] });
|
|
382
|
+
};
|
|
383
|
+
var TenantSwitcher_default = TenantSwitcher;
|
|
384
|
+
export {
|
|
385
|
+
TenantSwitcher_default as default,
|
|
386
|
+
dispatchTenantSwitchEvent,
|
|
387
|
+
getActiveTenantId,
|
|
388
|
+
isTenantImpersonationEnabled
|
|
389
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useContext, useEffect } from "react";
|
|
3
|
+
import { NotificationsCenter, useNotificationsCenter } from "dash-components";
|
|
4
|
+
import LaravelEchoContext from "../LaravelEchoContext";
|
|
5
|
+
const spanishLabels = {
|
|
6
|
+
title: "Notificaciones",
|
|
7
|
+
markAll: "Marcar todas",
|
|
8
|
+
noNotifications: "No hay notificaciones",
|
|
9
|
+
close: "Cerrar",
|
|
10
|
+
acknowledge: "Entendido",
|
|
11
|
+
customer: "Cliente:",
|
|
12
|
+
store: "Tienda:",
|
|
13
|
+
received: "Recibido:",
|
|
14
|
+
now: "Ahora",
|
|
15
|
+
minutesAgo: "m",
|
|
16
|
+
hoursAgo: "h",
|
|
17
|
+
daysAgo: "d"
|
|
18
|
+
};
|
|
19
|
+
const EchoNotificationsCenter = () => {
|
|
20
|
+
const { lastEvent } = useContext(LaravelEchoContext);
|
|
21
|
+
const hook = useNotificationsCenter({ labels: spanishLabels });
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
var _a, _b;
|
|
24
|
+
if (lastEvent && lastEvent.type === "urgency-alert") {
|
|
25
|
+
const notification = lastEvent == null ? void 0 : lastEvent.notificationPayload;
|
|
26
|
+
hook.addNotification({
|
|
27
|
+
title: (notification == null ? void 0 : notification.title) || "Alerta",
|
|
28
|
+
message: (notification == null ? void 0 : notification.message) || "",
|
|
29
|
+
customer: ((_a = notification == null ? void 0 : notification.customer_info) == null ? void 0 : _a.name) ? `${notification.customer_info.name} - Mesa ${notification.customer_info.table}` : "",
|
|
30
|
+
store: ((_b = notification == null ? void 0 : notification.store_info) == null ? void 0 : _b.name) || "",
|
|
31
|
+
data: notification
|
|
32
|
+
}, { showDialog: true, showToast: true, toastSeverity: "warning" });
|
|
33
|
+
}
|
|
34
|
+
}, [lastEvent]);
|
|
35
|
+
return /* @__PURE__ */ jsx(NotificationsCenter, { notificationsHook: hook });
|
|
36
|
+
};
|
|
37
|
+
var EchoNotificationsCenter_default = EchoNotificationsCenter;
|
|
38
|
+
export {
|
|
39
|
+
EchoNotificationsCenter_default as default
|
|
40
|
+
};
|