@dashadmin/dash-admin 1.3.45 → 1.3.46
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
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Card, Grid } from "@mui/material";
|
|
3
|
+
const userLayout = (render) => {
|
|
4
|
+
return /* @__PURE__ */ jsxs(Grid, { container: true, spacing: 1, children: [
|
|
5
|
+
/* @__PURE__ */ jsx(Grid, { size: { xs: 12, md: 4 }, children: /* @__PURE__ */ jsxs(Grid, { container: true, children: [
|
|
6
|
+
/* @__PURE__ */ jsx(Grid, { size: 12, children: /* @__PURE__ */ jsxs(Card, { sx: { mb: 1 }, className: "dash-widget", children: [
|
|
7
|
+
/* @__PURE__ */ jsx(
|
|
8
|
+
Box,
|
|
9
|
+
{
|
|
10
|
+
sx: { p: 1 },
|
|
11
|
+
style: { display: "flex", alignItems: "center" },
|
|
12
|
+
children: /* @__PURE__ */ jsx("span", { className: "card-title", children: "Avatar" })
|
|
13
|
+
}
|
|
14
|
+
),
|
|
15
|
+
/* @__PURE__ */ jsx(Box, { sx: { p: 1 }, children: render("Avatar") })
|
|
16
|
+
] }) }),
|
|
17
|
+
/* @__PURE__ */ jsx(Grid, { size: 12, children: /* @__PURE__ */ jsxs(Card, { sx: { mb: 1 }, className: "dash-widget", children: [
|
|
18
|
+
/* @__PURE__ */ jsx(
|
|
19
|
+
Box,
|
|
20
|
+
{
|
|
21
|
+
sx: { p: 1 },
|
|
22
|
+
style: { display: "flex", alignItems: "center" },
|
|
23
|
+
children: /* @__PURE__ */ jsx("span", { className: "card-title", children: "Credenciales" })
|
|
24
|
+
}
|
|
25
|
+
),
|
|
26
|
+
/* @__PURE__ */ jsx(Box, { sx: { p: 1 }, children: render("Credenciales") })
|
|
27
|
+
] }) })
|
|
28
|
+
] }) }),
|
|
29
|
+
/* @__PURE__ */ jsx(Grid, { size: { xs: 12, md: 8 }, children: /* @__PURE__ */ jsxs(Grid, { container: true, children: [
|
|
30
|
+
/* @__PURE__ */ jsx(Grid, { size: 12, children: /* @__PURE__ */ jsxs(Card, { sx: { mb: 1 }, className: "dash-widget", children: [
|
|
31
|
+
/* @__PURE__ */ jsx(
|
|
32
|
+
Box,
|
|
33
|
+
{
|
|
34
|
+
sx: { p: 1 },
|
|
35
|
+
style: { display: "flex", alignItems: "center" },
|
|
36
|
+
children: /* @__PURE__ */ jsx("span", { className: "card-title", children: "Datos del usuario" })
|
|
37
|
+
}
|
|
38
|
+
),
|
|
39
|
+
/* @__PURE__ */ jsx(Box, { sx: { p: 1 }, children: render("Datos del usuario") })
|
|
40
|
+
] }) }),
|
|
41
|
+
/* @__PURE__ */ jsx(Grid, { size: 12, children: /* @__PURE__ */ jsxs(Card, { sx: { mb: 1 }, className: "dash-widget", children: [
|
|
42
|
+
/* @__PURE__ */ jsx(
|
|
43
|
+
Box,
|
|
44
|
+
{
|
|
45
|
+
sx: { p: 1 },
|
|
46
|
+
style: { display: "flex", alignItems: "center" },
|
|
47
|
+
children: /* @__PURE__ */ jsx("span", { className: "card-title", children: "Configuraci\xF3n" })
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
/* @__PURE__ */ jsx(Box, { sx: { p: 1 }, children: render("Configuraci\xF3n") })
|
|
51
|
+
] }) })
|
|
52
|
+
] }) })
|
|
53
|
+
] });
|
|
54
|
+
};
|
|
55
|
+
var userLayout_default = userLayout;
|
|
56
|
+
export {
|
|
57
|
+
userLayout_default as default
|
|
58
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import ResourceTemplate from "../../templates/ResourceTemplate";
|
|
3
|
+
import Settings from "@mui/icons-material/Settings";
|
|
4
|
+
import { PaginationComponent } from "dash-components";
|
|
5
|
+
import { DASHAppConstants } from "dash-constants";
|
|
6
|
+
import { DASHAdminSystemConstants } from "dash-constants";
|
|
7
|
+
import userLayout from "./userLayout";
|
|
8
|
+
import userSchema from "./userSchema";
|
|
9
|
+
import { NoResults } from "../../components/misc/NoResults";
|
|
10
|
+
import usersFilters from "./usersFilters";
|
|
11
|
+
const userResource = {
|
|
12
|
+
filterWithSubmit: true,
|
|
13
|
+
roles: [
|
|
14
|
+
DASHAdminSystemConstants.system.DASH_SYSTEM_ROLE,
|
|
15
|
+
DASHAppConstants.system.TENANT_ROLE
|
|
16
|
+
],
|
|
17
|
+
component: ResourceTemplate,
|
|
18
|
+
trash: true,
|
|
19
|
+
model: "tenant/user",
|
|
20
|
+
schema: userSchema,
|
|
21
|
+
icon: /* @__PURE__ */ jsx(Settings, {}),
|
|
22
|
+
group: "resource.groups.configuration",
|
|
23
|
+
label: "resource.ecommerce.users.label",
|
|
24
|
+
menu: [
|
|
25
|
+
{
|
|
26
|
+
title: "Usuarios",
|
|
27
|
+
redirect: "/tenant/user"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
title: "\u{1F5D1}",
|
|
31
|
+
redirect: "/tenant/user/trash"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
resourceMenuDisabled: false,
|
|
35
|
+
refreshAfter: true,
|
|
36
|
+
/*customListActions: (props) => {
|
|
37
|
+
const { children } = props;
|
|
38
|
+
return <Card sx={{ mb: 2 }} className='dash-card-content dash-module top-toolbar'>{children}</Card>;
|
|
39
|
+
},*/
|
|
40
|
+
isFormData: true,
|
|
41
|
+
/** @deprecated TODO: side effects? seems is not implemented anywhere */
|
|
42
|
+
listEditButton: { enabled: true },
|
|
43
|
+
postFormatter: (params, _method) => {
|
|
44
|
+
if (!params.avatar) {
|
|
45
|
+
delete params.avatar;
|
|
46
|
+
}
|
|
47
|
+
return params;
|
|
48
|
+
},
|
|
49
|
+
dataGridProps: { stickyHeader: true, empty: /* @__PURE__ */ jsx(NoResults, {}), bulkActionButtons: false },
|
|
50
|
+
listProps: { perPage: DASHAdminSystemConstants.system.DEFAULT_PER_PAGE || 50, empty: false },
|
|
51
|
+
dataGridWrapper: (props) => {
|
|
52
|
+
const { children } = props;
|
|
53
|
+
return /* @__PURE__ */ jsx("div", { className: "sticky-header-wrapper", children });
|
|
54
|
+
},
|
|
55
|
+
redirectAfterUpdate: false,
|
|
56
|
+
createLayout: userLayout,
|
|
57
|
+
editLayout: userLayout,
|
|
58
|
+
formGroupMode: "layout",
|
|
59
|
+
/*exporter: (clients) => {
|
|
60
|
+
const clientsForExport = clients.map((client) => {
|
|
61
|
+
return client;
|
|
62
|
+
});
|
|
63
|
+
jsonExport(
|
|
64
|
+
clientsForExport,
|
|
65
|
+
{
|
|
66
|
+
//headers: ['id', 'title', 'author_name', 'body'] // order fields in the export
|
|
67
|
+
},
|
|
68
|
+
(err, csv) => {
|
|
69
|
+
downloadCSV(csv, 'clientes');
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
},*/
|
|
73
|
+
create: true,
|
|
74
|
+
edit: true,
|
|
75
|
+
view: false,
|
|
76
|
+
listViewButton: { enabled: false },
|
|
77
|
+
toolbarCreateButton: { enabled: true },
|
|
78
|
+
toolbarEditButton: { enabled: false },
|
|
79
|
+
toolbarExportButton: { enabled: false },
|
|
80
|
+
toolbarListButton: { enabled: true },
|
|
81
|
+
listDeleteButton: { enabled: true, props: { confirm: true } },
|
|
82
|
+
Pagination: PaginationComponent,
|
|
83
|
+
drawer: false,
|
|
84
|
+
mutationMode: "pessimistic",
|
|
85
|
+
referenceFilters: usersFilters
|
|
86
|
+
};
|
|
87
|
+
var userResource_default = userResource;
|
|
88
|
+
export {
|
|
89
|
+
userResource_default as default
|
|
90
|
+
};
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { SelectArrayInput } from "react-admin";
|
|
2
|
+
import { RutValidator } from "../../utils/validators";
|
|
3
|
+
import AvatarUploadField from "./components/AvatarUploadField";
|
|
4
|
+
import PasswordFields from "./components/PasswordFields";
|
|
5
|
+
const userSchema = [
|
|
6
|
+
{
|
|
7
|
+
tab: "Datos del usuario",
|
|
8
|
+
attribute: "id",
|
|
9
|
+
label: "Id",
|
|
10
|
+
type: String,
|
|
11
|
+
sortable: true,
|
|
12
|
+
inEdit: false,
|
|
13
|
+
inCreate: false
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
tab: "Datos del usuario",
|
|
17
|
+
attribute: "public_id",
|
|
18
|
+
label: "Rut",
|
|
19
|
+
type: String,
|
|
20
|
+
fieldOptions: { required: true, showDiv: true, fullWidth: true },
|
|
21
|
+
sortable: true,
|
|
22
|
+
inEdit: true,
|
|
23
|
+
inCreate: true,
|
|
24
|
+
inShow: true,
|
|
25
|
+
inList: false,
|
|
26
|
+
validate: (value) => {
|
|
27
|
+
if (!value) throw Error("El campo es requerido");
|
|
28
|
+
if (!RutValidator(value)) {
|
|
29
|
+
throw Error("El Rut es inv\xE1lido");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
tab: "Datos del usuario",
|
|
35
|
+
attribute: "name",
|
|
36
|
+
label: "Nombre",
|
|
37
|
+
type: String,
|
|
38
|
+
sortable: true,
|
|
39
|
+
inEdit: true,
|
|
40
|
+
inCreate: true,
|
|
41
|
+
inShow: false,
|
|
42
|
+
inList: false,
|
|
43
|
+
fieldOptions: { required: true }
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
tab: "Datos del usuario",
|
|
47
|
+
attribute: "lastname",
|
|
48
|
+
label: "Apellido",
|
|
49
|
+
type: String,
|
|
50
|
+
sortable: true,
|
|
51
|
+
inEdit: true,
|
|
52
|
+
inCreate: true,
|
|
53
|
+
inShow: true,
|
|
54
|
+
inList: false,
|
|
55
|
+
fieldOptions: { required: true }
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
tab: "Datos del usuario",
|
|
59
|
+
attribute: "full_name",
|
|
60
|
+
label: "Nombre",
|
|
61
|
+
type: String,
|
|
62
|
+
sortable: true,
|
|
63
|
+
inEdit: false,
|
|
64
|
+
inShow: true,
|
|
65
|
+
inCreate: false,
|
|
66
|
+
fieldOptions: { required: true }
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
tab: "Datos del usuario",
|
|
70
|
+
attribute: "email",
|
|
71
|
+
label: "Email",
|
|
72
|
+
type: String,
|
|
73
|
+
sortable: true,
|
|
74
|
+
inEdit: true,
|
|
75
|
+
inShow: true,
|
|
76
|
+
inCreate: true,
|
|
77
|
+
fieldOptions: { required: true }
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
tab: "Datos del usuario",
|
|
81
|
+
attribute: "phone",
|
|
82
|
+
label: "Telefono",
|
|
83
|
+
type: String,
|
|
84
|
+
sortable: true,
|
|
85
|
+
inEdit: true,
|
|
86
|
+
inCreate: true,
|
|
87
|
+
inShow: true,
|
|
88
|
+
inList: false
|
|
89
|
+
},
|
|
90
|
+
/*{
|
|
91
|
+
tab: 'Configuración',
|
|
92
|
+
attribute: 'active',
|
|
93
|
+
type: Boolean,
|
|
94
|
+
inList: true,
|
|
95
|
+
inCreate: false,
|
|
96
|
+
label: 'Activo',
|
|
97
|
+
showLabel: false,
|
|
98
|
+
processor: 'Boolean',
|
|
99
|
+
},*/
|
|
100
|
+
{
|
|
101
|
+
tab: "Credenciales",
|
|
102
|
+
attribute: "password",
|
|
103
|
+
label: "Contrase\xF1a",
|
|
104
|
+
type: String,
|
|
105
|
+
sortable: true,
|
|
106
|
+
inEdit: false,
|
|
107
|
+
inCreate: false,
|
|
108
|
+
inShow: false,
|
|
109
|
+
inList: false
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
tab: "Credenciales",
|
|
113
|
+
attribute: "password_confirmation",
|
|
114
|
+
label: "Confirma Contrase\xF1a",
|
|
115
|
+
type: String,
|
|
116
|
+
sortable: true,
|
|
117
|
+
inEdit: false,
|
|
118
|
+
inCreate: false,
|
|
119
|
+
inShow: false,
|
|
120
|
+
inList: false
|
|
121
|
+
},
|
|
122
|
+
/*{
|
|
123
|
+
tab: 'Credenciales',
|
|
124
|
+
attribute: 'role_id',
|
|
125
|
+
type: 'system/role/forSelect.name',
|
|
126
|
+
label: 'Rol de usuario',
|
|
127
|
+
componentProps: {
|
|
128
|
+
filter: { substitutable: true } // Shows only substituable roles for current user, backend logic.
|
|
129
|
+
},
|
|
130
|
+
sortable: true,
|
|
131
|
+
inEdit: true,
|
|
132
|
+
inCreate: true,
|
|
133
|
+
inShow: true,
|
|
134
|
+
inList: false,
|
|
135
|
+
multiple: false,
|
|
136
|
+
},*/
|
|
137
|
+
{
|
|
138
|
+
tab: "Credenciales",
|
|
139
|
+
label: "Roles",
|
|
140
|
+
attribute: "role_ids",
|
|
141
|
+
//listAttribute: 'name',
|
|
142
|
+
// system/role is core-owned and works for every domain (kitchntabs-*, vanexa-*),
|
|
143
|
+
// unlike tenant/role which only exists in kitchntabs-backend-domain
|
|
144
|
+
// (Domain\App\Http\Controllers\API\ECommerce\RoleController — an empty
|
|
145
|
+
// Domain\App\Models\ECommerce\Role subclass of the same core Role/roles table,
|
|
146
|
+
// with equivalent privilege-level-based visibility filtering).
|
|
147
|
+
type: "system/role/forSelect.name",
|
|
148
|
+
//type: Object,
|
|
149
|
+
// TODO Agregar un filtro, solo para traer los roles de cliente.
|
|
150
|
+
pagination: false,
|
|
151
|
+
multiple: true,
|
|
152
|
+
//custom: true,
|
|
153
|
+
//componentProps:{ options: {fullwidth: true} },
|
|
154
|
+
component: SelectArrayInput
|
|
155
|
+
//searchField: "subdomain"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
// @TODO Solo mostrar cuando se está creando:
|
|
159
|
+
label: "Genear Contrase\xF1a Aleatorea Autom\xE1ticamente",
|
|
160
|
+
attribute: "generate_password",
|
|
161
|
+
type: Boolean,
|
|
162
|
+
inList: false,
|
|
163
|
+
inEdit: false,
|
|
164
|
+
tab: "Configuraci\xF3n"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
attribute: "active",
|
|
168
|
+
type: Boolean,
|
|
169
|
+
inList: true,
|
|
170
|
+
label: "Activo",
|
|
171
|
+
tab: "Configuraci\xF3n",
|
|
172
|
+
processor: "Boolean"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
tab: "Avatar",
|
|
176
|
+
attribute: "avatar",
|
|
177
|
+
listAttribute: "image_url",
|
|
178
|
+
label: "Foto Usuario",
|
|
179
|
+
type: String,
|
|
180
|
+
sortable: true,
|
|
181
|
+
inEdit: true,
|
|
182
|
+
inCreate: true,
|
|
183
|
+
inShow: true,
|
|
184
|
+
inList: false,
|
|
185
|
+
custom: true,
|
|
186
|
+
component: AvatarUploadField,
|
|
187
|
+
processor: "File"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
tab: "Credenciales",
|
|
191
|
+
attribute: "password",
|
|
192
|
+
label: "Contrase\xF1a",
|
|
193
|
+
type: String,
|
|
194
|
+
sortable: true,
|
|
195
|
+
inList: false,
|
|
196
|
+
inEdit: true,
|
|
197
|
+
inCreate: true,
|
|
198
|
+
custom: true,
|
|
199
|
+
inShow: false,
|
|
200
|
+
component: PasswordFields
|
|
201
|
+
}
|
|
202
|
+
];
|
|
203
|
+
var userSchema_default = userSchema;
|
|
204
|
+
export {
|
|
205
|
+
userSchema_default as default
|
|
206
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const usersReferenceFilters = [
|
|
2
|
+
{
|
|
3
|
+
id: "q",
|
|
4
|
+
label: "Nombres/Email/Busqueda General",
|
|
5
|
+
source: "q",
|
|
6
|
+
alwaysOn: true,
|
|
7
|
+
reference: null,
|
|
8
|
+
optionText: null
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
id: "email",
|
|
12
|
+
label: "Email",
|
|
13
|
+
source: "email",
|
|
14
|
+
alwaysOn: true,
|
|
15
|
+
reference: null,
|
|
16
|
+
optionText: null
|
|
17
|
+
}
|
|
18
|
+
];
|
|
19
|
+
var usersFilters_default = usersReferenceFilters;
|
|
20
|
+
export {
|
|
21
|
+
usersFilters_default as default
|
|
22
|
+
};
|
package/dist/systemResources.js
CHANGED
|
@@ -29,6 +29,8 @@ import Avatar from "./components/avatar/Avatar";
|
|
|
29
29
|
import SystemUpdateAlt from "@mui/icons-material/SystemUpdateAlt";
|
|
30
30
|
import Person from "@mui/icons-material/Person";
|
|
31
31
|
import CardMembershipIcon from "@mui/icons-material/CardMembership";
|
|
32
|
+
import PaidIcon from "@mui/icons-material/Paid";
|
|
33
|
+
import TranslateIcon from "@mui/icons-material/Translate";
|
|
32
34
|
import { lazy } from "react";
|
|
33
35
|
import BusinessIcon from "@mui/icons-material/Business";
|
|
34
36
|
import Chip from "@mui/material/Chip";
|
|
@@ -878,12 +880,19 @@ const systemResources = [
|
|
|
878
880
|
redirectAfterUpdate: false,
|
|
879
881
|
redirectAfterCreate: true
|
|
880
882
|
}, drawerSettings),
|
|
883
|
+
// ============ Currency Management (core shared master data) ============
|
|
884
|
+
// Backed by dash-backend core's system/currency route (App\Http\Controllers\
|
|
885
|
+
// API\System\CurrencyController). Previously pointed at the domain's
|
|
886
|
+
// ecommerce/currency route — currencies moved to core as "shared master
|
|
887
|
+
// data" (see CLAUDE.md's core/domain split), so every app using this
|
|
888
|
+
// shared systemResources manifest (kitchntabs-*, vanexa-*) now gets a
|
|
889
|
+
// working Currencies page with no domain layer required.
|
|
881
890
|
{
|
|
882
891
|
roles: [DASHAppConstants.system.SYSTEM_ROLE],
|
|
883
892
|
component: ResourceTemplate,
|
|
884
893
|
trash: true,
|
|
885
|
-
model: "
|
|
886
|
-
label: "resource.
|
|
894
|
+
model: "system/currency",
|
|
895
|
+
label: "resource.system.currencies.label",
|
|
887
896
|
schema: [
|
|
888
897
|
{
|
|
889
898
|
label: "C\xF3digo",
|
|
@@ -920,23 +929,20 @@ const systemResources = [
|
|
|
920
929
|
component: FormatCurrency
|
|
921
930
|
}
|
|
922
931
|
],
|
|
923
|
-
|
|
924
|
-
//references: [{ reference: 'roles', target: 'id', schema: roleSchema }],
|
|
925
|
-
icon: /* @__PURE__ */ jsx(Person, {}),
|
|
926
|
-
// group: "resource.groups.system_resources",
|
|
932
|
+
icon: /* @__PURE__ */ jsx(PaidIcon, {}),
|
|
927
933
|
group: "System",
|
|
928
934
|
menu: [
|
|
929
935
|
{
|
|
930
|
-
title: "resource.
|
|
931
|
-
redirect: "/
|
|
936
|
+
title: "resource.system.currencies.menu_list",
|
|
937
|
+
redirect: "/system/currency"
|
|
932
938
|
},
|
|
933
939
|
{
|
|
934
940
|
title: "\u{1F5D1}",
|
|
935
|
-
redirect: "/
|
|
941
|
+
redirect: "/system/currency/trash"
|
|
936
942
|
}
|
|
937
943
|
],
|
|
938
944
|
mainAction: {
|
|
939
|
-
title: "resource.
|
|
945
|
+
title: "resource.system.currencies.main_action",
|
|
940
946
|
mode: "create",
|
|
941
947
|
fn: "virtualhash",
|
|
942
948
|
redirect: "inline/create"
|
|
@@ -950,16 +956,21 @@ const systemResources = [
|
|
|
950
956
|
mutationMode: "pessimistic",
|
|
951
957
|
saveButtonAlwaysEnabled: true,
|
|
952
958
|
listProps: { storeKey: false, filterDefaultValues: { show_disabled: true } },
|
|
953
|
-
// deshabilita persistencia deel estado, cache de los valores seleccionados sort, page, etc.
|
|
954
959
|
resetSelectedIdsOnLoad: true
|
|
955
960
|
},
|
|
956
|
-
// ============ Language Management ============
|
|
961
|
+
// ============ Language Management (core shared master data) ============
|
|
962
|
+
// Backed by dash-backend core's system/language route (App\Http\Controllers\
|
|
963
|
+
// API\System\LanguageController). Previously pointed at the domain's
|
|
964
|
+
// common/language route — languages moved to core as "shared master data"
|
|
965
|
+
// (see CLAUDE.md's core/domain split), so every app using this shared
|
|
966
|
+
// systemResources manifest (kitchntabs-*, vanexa-*) now gets a working
|
|
967
|
+
// Languages page with no domain layer required.
|
|
957
968
|
{
|
|
958
969
|
roles: [DASHAppConstants.system.SYSTEM_ROLE],
|
|
959
970
|
component: ResourceTemplate,
|
|
960
971
|
trash: true,
|
|
961
|
-
model: "
|
|
962
|
-
label: "resource.
|
|
972
|
+
model: "system/language",
|
|
973
|
+
label: "resource.system.languages.label",
|
|
963
974
|
schema: [
|
|
964
975
|
{
|
|
965
976
|
label: "Code",
|
|
@@ -1003,20 +1014,20 @@ const systemResources = [
|
|
|
1003
1014
|
}
|
|
1004
1015
|
}
|
|
1005
1016
|
],
|
|
1006
|
-
icon: /* @__PURE__ */ jsx(
|
|
1017
|
+
icon: /* @__PURE__ */ jsx(TranslateIcon, {}),
|
|
1007
1018
|
group: "System",
|
|
1008
1019
|
menu: [
|
|
1009
1020
|
{
|
|
1010
|
-
title: "resource.
|
|
1011
|
-
redirect: "/
|
|
1021
|
+
title: "resource.system.languages.menu_list",
|
|
1022
|
+
redirect: "/system/language"
|
|
1012
1023
|
},
|
|
1013
1024
|
{
|
|
1014
1025
|
title: "\u{1F5D1}",
|
|
1015
|
-
redirect: "/
|
|
1026
|
+
redirect: "/system/language/trash"
|
|
1016
1027
|
}
|
|
1017
1028
|
],
|
|
1018
1029
|
mainAction: {
|
|
1019
|
-
title: "resource.
|
|
1030
|
+
title: "resource.system.languages.main_action",
|
|
1020
1031
|
mode: "create",
|
|
1021
1032
|
fn: "virtualhash",
|
|
1022
1033
|
redirect: "inline/create"
|
package/package.json
CHANGED
|
@@ -111,8 +111,7 @@ const BridgedLocalesMenuButton: React.FC<BridgedLocalesMenuButtonProps> = ({
|
|
|
111
111
|
<Tooltip title={`Language: ${currentLocaleName}`}>
|
|
112
112
|
<IconButton
|
|
113
113
|
onClick={handleClick}
|
|
114
|
-
|
|
115
|
-
size="small"
|
|
114
|
+
className="dash-icon-button-color dash-icon-button-bg"
|
|
116
115
|
aria-label="change language"
|
|
117
116
|
aria-controls={open ? 'locale-menu' : undefined}
|
|
118
117
|
aria-haspopup="true"
|
|
@@ -53,7 +53,7 @@ const PlanPricesView: React.FC<IDashAutoAdminCustomFieldComponent> = () => {
|
|
|
53
53
|
const prices = plan?.prices;
|
|
54
54
|
|
|
55
55
|
const { data: currencies, isLoading } = useGetList<Currency>(
|
|
56
|
-
'
|
|
56
|
+
'system/currency', // core "shared master data" — works for every domain, unlike ecommerce/currency (kitchntabs-backend-domain only)
|
|
57
57
|
{
|
|
58
58
|
pagination: { page: 1, perPage: 100 },
|
|
59
59
|
sort: { field: 'code', order: 'ASC' },
|
|
@@ -161,7 +161,7 @@ const PlanPricesEdit: React.FC<IDashAutoAdminCustomFieldComponent> = ({ method }
|
|
|
161
161
|
|
|
162
162
|
// Fetch available currencies
|
|
163
163
|
const { data: currencies, isLoading, error } = useGetList<Currency>(
|
|
164
|
-
'
|
|
164
|
+
'system/currency', // core "shared master data" — works for every domain, unlike ecommerce/currency (kitchntabs-backend-domain only)
|
|
165
165
|
{
|
|
166
166
|
pagination: { page: 1, perPage: 100 },
|
|
167
167
|
sort: { field: 'code', order: 'ASC' },
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GlobalTenantWrapper
|
|
3
|
+
*
|
|
4
|
+
* Tenant Data Fetcher Component that runs inside DashThemeProvider — takes
|
|
5
|
+
* tenant data (fetched by a mall/self-service session flow, before any user
|
|
6
|
+
* authentication exists) and:
|
|
7
|
+
* - Sets panel-settings logos in Redux from the tenant's images
|
|
8
|
+
* - Recreates the MUI theme from the tenant's theme settings
|
|
9
|
+
* - Persists a "public" auth shape (tenant only, no user) via
|
|
10
|
+
* AuthPersistenceService, so the rest of the app can read tenant context
|
|
11
|
+
*
|
|
12
|
+
* Consolidated 2026-08-03 from seven byte-identical app-level copies. Two of
|
|
13
|
+
* its five real consumers (kitchntabs-app's and vanexa-app's
|
|
14
|
+
* kt-kiosk/components/MallClientWrapper.tsx) had a stale, commented-out
|
|
15
|
+
* import with a wrong path — GlobalTenantWrapper was referenced in JSX but
|
|
16
|
+
* never actually imported, a pre-existing bug fixed as part of repointing
|
|
17
|
+
* those call sites here.
|
|
18
|
+
*/
|
|
19
|
+
import { AuthPersistenceService } from "dash-auth";
|
|
20
|
+
import { DASH_REDUX_ACTIONS } from "dash-admin-state";
|
|
21
|
+
import { useDispatch } from "react-redux";
|
|
22
|
+
import DashThemeContext from '../../default-theme/DashThemeContext';
|
|
23
|
+
import React, { PropsWithChildren, useEffect } from "react";
|
|
24
|
+
|
|
25
|
+
export interface IGlobalTenantWrapper extends PropsWithChildren {
|
|
26
|
+
tenantData?: any;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Tenant Data Fetcher Component that runs inside DashThemeProvider
|
|
30
|
+
const GlobalTenantWrapper: React.FC<IGlobalTenantWrapper> = (props) => {
|
|
31
|
+
const {
|
|
32
|
+
tenantData = null,
|
|
33
|
+
children
|
|
34
|
+
} = props;
|
|
35
|
+
|
|
36
|
+
const dispatch = useDispatch();
|
|
37
|
+
const themeContext = React.useContext(DashThemeContext);
|
|
38
|
+
const recreateTheme = themeContext?.recreateTheme;
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (!tenantData) {
|
|
42
|
+
// No data to process
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Process tenant images for panel settings
|
|
47
|
+
if (tenantData.tenantImages) {
|
|
48
|
+
const logos = {
|
|
49
|
+
...(tenantData.tenantImages.horizontal_logo?.original && {
|
|
50
|
+
horizontalLogo: tenantData.tenantImages.horizontal_logo.original
|
|
51
|
+
}),
|
|
52
|
+
...(tenantData.tenantImages.squared_logo?.original && {
|
|
53
|
+
squaredLogo: tenantData.tenantImages.squared_logo.original
|
|
54
|
+
}),
|
|
55
|
+
...(tenantData.tenantImages.banner?.original && {
|
|
56
|
+
loginBackground: tenantData.tenantImages.banner.original
|
|
57
|
+
})
|
|
58
|
+
};
|
|
59
|
+
dispatch(DASH_REDUX_ACTIONS.setPanelSettings(logos));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Process tenant settings for theme
|
|
63
|
+
if (tenantData.tenantSettings && recreateTheme) {
|
|
64
|
+
recreateTheme(tenantData.tenantSettings);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Store tenant data for persistence (without user authentication)
|
|
68
|
+
const publicAuthData = {
|
|
69
|
+
auth: {
|
|
70
|
+
tenantImages: tenantData.tenantImages,
|
|
71
|
+
tenantSettings: tenantData.tenantSettings,
|
|
72
|
+
tenant: tenantData.tenant,
|
|
73
|
+
},
|
|
74
|
+
systemValues: tenantData.systemValues
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
AuthPersistenceService.saveAuth(publicAuthData);
|
|
78
|
+
|
|
79
|
+
}, [tenantData]);
|
|
80
|
+
|
|
81
|
+
return <></>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export default GlobalTenantWrapper;
|