@dashadmin/dash-admin 1.3.44 → 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.
Files changed (53) hide show
  1. package/dist/components/i18n/BridgedLocalesMenuButton.js +1 -2
  2. package/dist/components/menu/DarkToggleMode.js +1 -1
  3. package/dist/components/serviceAccount/ApiKeyRevealDialog.js +110 -0
  4. package/dist/components/serviceAccount/ServiceAccountStatusSwitch.js +94 -0
  5. package/dist/components/subscription/PlanPricesSettings.js +4 -2
  6. package/dist/components/tenancy/GlobalTenantWrapper.js +64 -0
  7. package/dist/components/tenancy/TenantSwitcher.js +389 -0
  8. package/dist/contexts/com/components/EchoNotificationsCenter.js +40 -0
  9. package/dist/default-theme/menu/AppMenuComponents/expanded/SidebarItem.js +1 -0
  10. package/dist/index.js +60 -40
  11. package/dist/pages/Profile.js +32 -38
  12. package/dist/providers/i18n/en.js +108 -0
  13. package/dist/providers/i18n/es.js +108 -0
  14. package/dist/providers/i18n/languages.js +3 -1
  15. package/dist/providers/i18n/mergeTranslations.js +18 -0
  16. package/dist/resources/User/components/AvatarUploadField.js +61 -0
  17. package/dist/resources/User/components/PasswordFields.js +67 -0
  18. package/dist/resources/User/getProfileMenu.js +36 -0
  19. package/dist/resources/User/profileResource.js +33 -0
  20. package/dist/resources/User/userLayout.js +58 -0
  21. package/dist/resources/User/userResource.js +90 -0
  22. package/dist/resources/User/userSchema.js +206 -0
  23. package/dist/resources/User/usersFilters.js +22 -0
  24. package/dist/systemResources.js +30 -19
  25. package/dist/templates/ResourceTemplateCreate.js +5 -2
  26. package/package.json +4 -1
  27. package/src/components/i18n/BridgedLocalesMenuButton.tsx +1 -2
  28. package/src/components/menu/DarkToggleMode.tsx +1 -1
  29. package/src/components/serviceAccount/ApiKeyRevealDialog.tsx +129 -0
  30. package/src/components/serviceAccount/ServiceAccountStatusSwitch.tsx +99 -0
  31. package/src/components/subscription/PlanPricesSettings.tsx +2 -2
  32. package/src/components/tenancy/GlobalTenantWrapper.tsx +84 -0
  33. package/src/components/tenancy/TenantSwitcher.tsx +485 -0
  34. package/src/contexts/com/components/EchoNotificationsCenter.tsx +65 -0
  35. package/src/default-theme/menu/AppMaterialMenu.tsx +1 -1
  36. package/src/default-theme/menu/AppMenuComponents/expanded/SidebarItem.tsx +1 -0
  37. package/src/default-theme/menu/SidebarActions.tsx +1 -1
  38. package/src/index.tsx +15 -0
  39. package/src/pages/Profile.tsx +69 -107
  40. package/src/providers/i18n/en.ts +113 -0
  41. package/src/providers/i18n/es.ts +113 -0
  42. package/src/providers/i18n/languages.tsx +3 -0
  43. package/src/providers/i18n/mergeTranslations.ts +53 -0
  44. package/src/resources/User/components/AvatarUploadField.tsx +57 -0
  45. package/src/resources/User/components/PasswordFields.tsx +73 -0
  46. package/src/resources/User/getProfileMenu.ts +57 -0
  47. package/src/resources/User/profileResource.tsx +51 -0
  48. package/src/resources/User/userLayout.tsx +62 -0
  49. package/src/resources/User/userResource.tsx +111 -0
  50. package/src/resources/User/userSchema.tsx +213 -0
  51. package/src/resources/User/usersFilters.tsx +21 -0
  52. package/src/systemResources.tsx +31 -20
  53. package/src/templates/ResourceTemplateCreate.tsx +17 -2
@@ -26,12 +26,13 @@ import {
26
26
  useRefresh,
27
27
  Loading,
28
28
  useNotify,
29
+ useTranslate,
29
30
  TextInput
30
31
  } from "react-admin";
31
32
  import { useDispatch } from "react-redux";
32
33
  import { DASH_REDUX_ACTIONS } from "dash-admin-state";
33
- import useAxios from "../hooks/axios";
34
- import SingleImageUploader from "./SingleImageUploader";
34
+ import { useAxios } from "dash-axios-hook";
35
+ import { SingleImageUploader } from "dash-components";
35
36
  import { useAuthContext } from "../contexts/auth";
36
37
  import UserPreferences from "../components/user/UserPreferences";
37
38
  const Profile = (_props) => {
@@ -40,31 +41,35 @@ const Profile = (_props) => {
40
41
  const { user, fetchAuth } = useAuthContext();
41
42
  const [avatar, setAvatar] = useState({ rawFile: null, urlFile: "" });
42
43
  const notify = useNotify();
43
- const { axios } = useAxios();
44
+ const translate = useTranslate();
45
+ const axios = useAxios();
44
46
  const refresh = useRefresh();
47
+ const { showPreferences = false } = _props;
45
48
  const dispatch = useDispatch();
46
49
  useEffect(() => {
47
50
  dispatch(
48
51
  DASH_REDUX_ACTIONS.updatePage({
49
- title: "Perfil",
52
+ title: translate("profile.title", { _: "Perfil" }),
50
53
  //icon:
51
- subTitle: "Configuraci\xF3n de perfil"
54
+ subTitle: translate("profile.subtitle", { _: "Configuraci\xF3n de perfil" })
52
55
  })
53
56
  );
54
- }, []);
57
+ }, [translate]);
55
58
  const validateUserCreation = (values) => {
56
59
  const errors = {};
57
60
  if (currTab === "auth/update/password") {
61
+ const required = translate("profile.validation.required", { _: "El campo es requerido" });
62
+ const mismatch = translate("profile.validation.password_mismatch", { _: "Las contrase\xF1as no coinciden" });
58
63
  if ((values.password || values.password_confirmation) && !values.current_password) {
59
- errors.current_password = "El campo es requerido";
64
+ errors.current_password = required;
60
65
  }
61
66
  if (values.current_password && (!values.password || !values.password_confirmation)) {
62
- errors.password = "El campo es requerido";
63
- errors.password_confirmation = "El campo es requerido";
67
+ errors.password = required;
68
+ errors.password_confirmation = required;
64
69
  }
65
70
  if (values.password_confirmation !== values.password) {
66
- errors.password = "Las contrase\xF1as no coinciden";
67
- errors.password_confirmation = "Las contrase\xF1as no coinciden";
71
+ errors.password = mismatch;
72
+ errors.password_confirmation = mismatch;
68
73
  }
69
74
  }
70
75
  return errors;
@@ -103,17 +108,17 @@ const Profile = (_props) => {
103
108
  yield fetchAuth();
104
109
  console.log("Auth context refreshed after profile update");
105
110
  } catch (authError) {
106
- console.error("Faileds to refresh auth context:", authError);
111
+ console.error("Failed to refresh auth context:", authError);
107
112
  }
108
- notify("Usuario actualizado correctamente", { type: "success" });
113
+ notify(translate("profile.notify.success", { _: "Usuario actualizado correctamente" }), { type: "success" });
109
114
  refresh();
110
115
  } catch (error) {
111
116
  let mainMessage = ((_b = (_a = error == null ? void 0 : error.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message) || ((_c = error == null ? void 0 : error.body) == null ? void 0 : _c.message) || "";
112
117
  let fieldErrors = ((_e = (_d = error == null ? void 0 : error.response) == null ? void 0 : _d.data) == null ? void 0 : _e.errors) || ((_f = error == null ? void 0 : error.body) == null ? void 0 : _f.errors) || error;
113
118
  if (mainMessage) {
114
- notify(`Error al actualizar el usuario, ${mainMessage}`, { type: "error" });
119
+ notify(translate("profile.notify.error_with_message", { message: mainMessage, _: `Error al actualizar el usuario, ${mainMessage}` }), { type: "error" });
115
120
  } else {
116
- notify("Error al actualizar el usuario", { type: "error" });
121
+ notify(translate("profile.notify.error", { _: "Error al actualizar el usuario" }), { type: "error" });
117
122
  }
118
123
  if (fieldErrors && typeof fieldErrors === "object") {
119
124
  const errors = {};
@@ -124,6 +129,7 @@ const Profile = (_props) => {
124
129
  }
125
130
  } finally {
126
131
  setIsLoading(false);
132
+ window.location.reload();
127
133
  }
128
134
  });
129
135
  const handleInfoSubmit = () => {
@@ -165,7 +171,6 @@ const Profile = (_props) => {
165
171
  width: "100%"
166
172
  },
167
173
  children: [
168
- "<!-- F -->",
169
174
  /* @__PURE__ */ jsx(
170
175
  SingleImageUploader,
171
176
  {
@@ -211,7 +216,7 @@ const Profile = (_props) => {
211
216
  CardHeader,
212
217
  {
213
218
  sx: { padding: "16px 25px 0" },
214
- title: "Info"
219
+ title: translate("profile.info.title", { _: "Info" })
215
220
  }
216
221
  ),
217
222
  /* @__PURE__ */ jsx(CardContent, { sx: { padding: "25px" }, children: /* @__PURE__ */ jsxs(Grid, { container: true, spacing: 2, children: [
@@ -219,7 +224,7 @@ const Profile = (_props) => {
219
224
  TextInput,
220
225
  {
221
226
  source: "name",
222
- label: "Nombre",
227
+ label: translate("profile.info.name", { _: "Nombre" }),
223
228
  variant: "outlined",
224
229
  fullWidth: true
225
230
  }
@@ -228,7 +233,7 @@ const Profile = (_props) => {
228
233
  TextInput,
229
234
  {
230
235
  source: "lastname",
231
- label: "Apellido",
236
+ label: translate("profile.info.lastname", { _: "Apellido" }),
232
237
  variant: "outlined",
233
238
  fullWidth: true
234
239
  }
@@ -237,7 +242,7 @@ const Profile = (_props) => {
237
242
  TextInput,
238
243
  {
239
244
  source: "email",
240
- label: "Email",
245
+ label: translate("profile.info.email", { _: "Email" }),
241
246
  variant: "outlined",
242
247
  fullWidth: true
243
248
  }
@@ -258,7 +263,7 @@ const Profile = (_props) => {
258
263
  color: "white"
259
264
  }
260
265
  },
261
- children: isLoading && currTab === "auth/update/info" ? "Guardando..." : "Guardar"
266
+ children: isLoading && currTab === "auth/update/info" ? translate("profile.info.saving", { _: "Guardando..." }) : translate("profile.info.save", { _: "Guardar" })
262
267
  }
263
268
  ) })
264
269
  ] }) })
@@ -268,7 +273,7 @@ const Profile = (_props) => {
268
273
  CardHeader,
269
274
  {
270
275
  sx: { padding: "16px 25px 0" },
271
- title: "Contrase\xF1as"
276
+ title: translate("profile.password.title", { _: "Contrase\xF1as" })
272
277
  }
273
278
  ),
274
279
  /* @__PURE__ */ jsx(CardContent, { sx: { padding: "25px" }, children: /* @__PURE__ */ jsxs(Grid, { container: true, spacing: 2, children: [
@@ -277,7 +282,7 @@ const Profile = (_props) => {
277
282
  {
278
283
  type: "password",
279
284
  source: "current_password",
280
- label: "Contrase\xF1a actual",
285
+ label: translate("profile.password.current", { _: "Contrase\xF1a actual" }),
281
286
  variant: "outlined",
282
287
  fullWidth: true
283
288
  }
@@ -287,7 +292,7 @@ const Profile = (_props) => {
287
292
  {
288
293
  type: "password",
289
294
  source: "password",
290
- label: "Nueva contrase\xF1a",
295
+ label: translate("profile.password.new", { _: "Nueva contrase\xF1a" }),
291
296
  variant: "outlined",
292
297
  fullWidth: true
293
298
  }
@@ -295,7 +300,7 @@ const Profile = (_props) => {
295
300
  /* @__PURE__ */ jsx(Grid, { size: 12, children: /* @__PURE__ */ jsx(
296
301
  TextInput,
297
302
  {
298
- label: "Repita nueva contrase\xF1a",
303
+ label: translate("profile.password.confirm", { _: "Repita nueva contrase\xF1a" }),
299
304
  type: "password",
300
305
  source: "password_confirmation",
301
306
  variant: "outlined",
@@ -318,23 +323,12 @@ const Profile = (_props) => {
318
323
  color: "white"
319
324
  }
320
325
  },
321
- children: isLoading && currTab === "auth/update/password" ? "Guardando Contrase\xF1as..." : "Guardar Contrase\xF1as"
326
+ children: isLoading && currTab === "auth/update/password" ? translate("profile.password.saving", { _: "Guardando Contrase\xF1as..." }) : translate("profile.password.save", { _: "Guardar Contrase\xF1as" })
322
327
  }
323
328
  ) })
324
329
  ] }) })
325
330
  ] }),
326
- /* @__PURE__ */ jsxs(Grid, { size: {
327
- xs: 12
328
- }, children: [
329
- /* @__PURE__ */ jsx(
330
- CardHeader,
331
- {
332
- sx: { padding: "16px 25px 0" },
333
- title: "Preferencias"
334
- }
335
- ),
336
- /* @__PURE__ */ jsx(CardContent, { sx: { padding: "25px" }, children: /* @__PURE__ */ jsx(UserPreferences, {}) })
337
- ] })
331
+ showPreferences && /* @__PURE__ */ jsx(Grid, { size: { xs: 12 }, children: /* @__PURE__ */ jsx(CardContent, { sx: { padding: "25px" }, children: /* @__PURE__ */ jsx(UserPreferences, {}) }) })
338
332
  ]
339
333
  }
340
334
  ) })
@@ -302,8 +302,55 @@ const dashEnglish = {
302
302
  auto_reset_notice: "This screen will automatically reset in 30 seconds",
303
303
  loading: "Loading..."
304
304
  },
305
+ // Service account API keys
306
+ serviceAccount: {
307
+ reveal: {
308
+ title: "Copy your API key now",
309
+ warning: "This is the only time this key will be shown. It cannot be recovered later \u2014 if you lose it, you will have to issue a new one.",
310
+ forKey: "Key",
311
+ copy: "Copy",
312
+ copied: "Copied",
313
+ dismiss: "I have saved it"
314
+ },
315
+ status: {
316
+ active: "Active",
317
+ disabled: "Disabled"
318
+ },
319
+ expiration: {
320
+ "1": "1 day",
321
+ "7": "7 days",
322
+ "30": "30 days",
323
+ never: "Never"
324
+ },
325
+ notify: {
326
+ enabled: "API key enabled",
327
+ disabled: "API key disabled",
328
+ toggle_error: "Could not change the key status"
329
+ },
330
+ action: {
331
+ enable: "Enable",
332
+ disable: "Disable"
333
+ },
334
+ // Shown when a tenancy-level role is selected: such a key reaches every
335
+ // tenant in the account, so the tenant field stops being a boundary.
336
+ tenancy_role_warning: "This role grants access to every tenant in the account. The selected tenant is informational, not a security boundary."
337
+ },
305
338
  // Resource labels for admin panel
306
339
  resource: {
340
+ tenancy: {
341
+ serviceAccounts: {
342
+ label: "Service Accounts",
343
+ name: "Name",
344
+ tenant: "Tenant",
345
+ roles: "Roles",
346
+ expiration: "Expiration",
347
+ status: "Status",
348
+ token: "Key",
349
+ expires_at: "Expires",
350
+ last_used_at: "Last used",
351
+ created_at: "Created"
352
+ }
353
+ },
307
354
  // Groups
308
355
  groups: {
309
356
  system_resources: "System Resources",
@@ -506,6 +553,67 @@ const dashEnglish = {
506
553
  all_products: "All Products",
507
554
  has_modifiers: "Customizable",
508
555
  no_more_products: "No more products"
556
+ },
557
+ // JSON Color Selector - image-based theme extraction
558
+ colorSelector: {
559
+ imageExtractor: {
560
+ title_ai: "AI Theme Generator",
561
+ title_local: "Theme from Image",
562
+ upload_prompt: "Upload an Image to Extract Colors",
563
+ upload_hint: "Select an image file and we'll automatically extract a color palette",
564
+ upload_button: "Choose Image",
565
+ drop_hint: "or drag and drop it here",
566
+ invalid_file_type: "Please select a valid image file",
567
+ file_too_large: "File size must be less than %{limit}MB",
568
+ extracting: "Extracting colors from image...",
569
+ extracted_colors: "Extracted Colors (%{count} colors found)",
570
+ dominant_label: "Dominant",
571
+ uploaded_image_alt: "Uploaded image",
572
+ no_palette_error: "Please extract colors from an image first",
573
+ theme_generation_failed: "Failed to generate theme",
574
+ theme_description_label: "Theme Description (Optional)",
575
+ theme_description_placeholder: "Optional: Describe the theme style you want (e.g., 'modern and minimalist', 'warm and cozy', 'professional corporate')",
576
+ apply_colors_button: "Apply Colors",
577
+ generate_button: "Generate AI Theme",
578
+ generating_button: "Generating...",
579
+ apply_colors_help_label: "Apply Colors:",
580
+ apply_colors_help_desc: "Maps the extracted palette to your base theme colors locally \u2014 no AI involved",
581
+ generate_help_label: "Generate AI Theme:",
582
+ generate_help_desc: "Uses AI to create a complete color scheme based on extracted colors and your description"
583
+ }
584
+ },
585
+ // Profile page
586
+ profile: {
587
+ title: "Profile",
588
+ subtitle: "Profile settings",
589
+ info: {
590
+ title: "Info",
591
+ name: "Name",
592
+ lastname: "Last name",
593
+ email: "Email",
594
+ save: "Save",
595
+ saving: "Saving..."
596
+ },
597
+ password: {
598
+ title: "Passwords",
599
+ current: "Current password",
600
+ new: "New password",
601
+ confirm: "Confirm new password",
602
+ save: "Save Passwords",
603
+ saving: "Saving Passwords..."
604
+ },
605
+ preferences: {
606
+ title: "Preferences"
607
+ },
608
+ validation: {
609
+ required: "This field is required",
610
+ password_mismatch: "Passwords do not match"
611
+ },
612
+ notify: {
613
+ success: "User updated successfully",
614
+ error: "Error updating user",
615
+ error_with_message: "Error updating user, %{message}"
616
+ }
509
617
  }
510
618
  };
511
619
  var en_default = __spreadValues(__spreadValues({}, raEnglish), dashEnglish);
@@ -309,8 +309,55 @@ const dashSpanish = {
309
309
  auto_reset_notice: "Esta pantalla se reiniciar\xE1 autom\xE1ticamente en 30 segundos",
310
310
  loading: "Cargando..."
311
311
  },
312
+ // Service account API keys
313
+ serviceAccount: {
314
+ reveal: {
315
+ title: "Copia tu API Key ahora",
316
+ warning: "Esta es la \xFAnica vez que se mostrar\xE1 esta clave. No se puede recuperar m\xE1s adelante \u2014 si la pierdes, tendr\xE1s que emitir una nueva.",
317
+ forKey: "Clave",
318
+ copy: "Copiar",
319
+ copied: "Copiado",
320
+ dismiss: "La he guardado"
321
+ },
322
+ status: {
323
+ active: "Activa",
324
+ disabled: "Deshabilitada"
325
+ },
326
+ expiration: {
327
+ "1": "1 d\xEDa",
328
+ "7": "7 d\xEDas",
329
+ "30": "30 d\xEDas",
330
+ never: "Nunca"
331
+ },
332
+ notify: {
333
+ enabled: "API Key habilitada",
334
+ disabled: "API Key deshabilitada",
335
+ toggle_error: "No se pudo cambiar el estado de la API Key"
336
+ },
337
+ action: {
338
+ enable: "Habilitar",
339
+ disable: "Deshabilitar"
340
+ },
341
+ // Shown when a tenancy-level role is selected: such a key reaches every
342
+ // tenant in the account, so the tenant field stops being a boundary.
343
+ tenancy_role_warning: "Este rol otorga acceso a todos los locales de la cuenta. El local seleccionado es informativo, no un l\xEDmite de seguridad."
344
+ },
312
345
  // Resource labels for admin panel
313
346
  resource: {
347
+ tenancy: {
348
+ serviceAccounts: {
349
+ label: "Cuentas de Servicio",
350
+ name: "Nombre",
351
+ tenant: "Local",
352
+ roles: "Roles",
353
+ expiration: "Expiraci\xF3n",
354
+ status: "Estado",
355
+ token: "Clave",
356
+ expires_at: "Expira",
357
+ last_used_at: "\xDAltimo uso",
358
+ created_at: "Creado"
359
+ }
360
+ },
314
361
  // Groups
315
362
  groups: {
316
363
  system_resources: "Recursos de Sistema",
@@ -512,6 +559,67 @@ const dashSpanish = {
512
559
  all_products: "Todos los Productos",
513
560
  has_modifiers: "Personalizable",
514
561
  no_more_products: "No hay m\xE1s productos"
562
+ },
563
+ // JSON Color Selector - extracción de tema desde imagen
564
+ colorSelector: {
565
+ imageExtractor: {
566
+ title_ai: "Generador de Tema con IA",
567
+ title_local: "Tema desde Imagen",
568
+ upload_prompt: "Sube una Imagen para Extraer Colores",
569
+ upload_hint: "Selecciona un archivo de imagen y extraeremos autom\xE1ticamente una paleta de colores",
570
+ upload_button: "Elegir Imagen",
571
+ drop_hint: "o arr\xE1strala aqu\xED",
572
+ invalid_file_type: "Por favor selecciona un archivo de imagen v\xE1lido",
573
+ file_too_large: "El archivo debe pesar menos de %{limit}MB",
574
+ extracting: "Extrayendo colores de la imagen...",
575
+ extracted_colors: "Colores Extra\xEDdos (%{count} colores encontrados)",
576
+ dominant_label: "Dominante",
577
+ uploaded_image_alt: "Imagen subida",
578
+ no_palette_error: "Primero extrae los colores de una imagen",
579
+ theme_generation_failed: "No se pudo generar el tema",
580
+ theme_description_label: "Descripci\xF3n del Tema (Opcional)",
581
+ theme_description_placeholder: "Opcional: Describe el estilo de tema que deseas (ej: 'moderno y minimalista', 'c\xE1lido y acogedor', 'corporativo profesional')",
582
+ apply_colors_button: "Aplicar Colores",
583
+ generate_button: "Generar Tema con IA",
584
+ generating_button: "Generando...",
585
+ apply_colors_help_label: "Aplicar Colores:",
586
+ apply_colors_help_desc: "Aplica la paleta extra\xEDda a los colores base de tu tema localmente \u2014 sin usar IA",
587
+ generate_help_label: "Generar Tema con IA:",
588
+ generate_help_desc: "Usa IA para crear un esquema de color completo basado en los colores extra\xEDdos y tu descripci\xF3n"
589
+ }
590
+ },
591
+ // Profile page
592
+ profile: {
593
+ title: "Perfil",
594
+ subtitle: "Configuraci\xF3n de perfil",
595
+ info: {
596
+ title: "Info",
597
+ name: "Nombre",
598
+ lastname: "Apellido",
599
+ email: "Email",
600
+ save: "Guardar",
601
+ saving: "Guardando..."
602
+ },
603
+ password: {
604
+ title: "Contrase\xF1as",
605
+ current: "Contrase\xF1a actual",
606
+ new: "Nueva contrase\xF1a",
607
+ confirm: "Repita nueva contrase\xF1a",
608
+ save: "Guardar Contrase\xF1as",
609
+ saving: "Guardando Contrase\xF1as..."
610
+ },
611
+ preferences: {
612
+ title: "Preferencias"
613
+ },
614
+ validation: {
615
+ required: "El campo es requerido",
616
+ password_mismatch: "Las contrase\xF1as no coinciden"
617
+ },
618
+ notify: {
619
+ success: "Usuario actualizado correctamente",
620
+ error: "Error al actualizar el usuario",
621
+ error_with_message: "Error al actualizar el usuario, %{message}"
622
+ }
515
623
  }
516
624
  };
517
625
  var es_default = __spreadValues(__spreadValues({}, raSpanish), dashSpanish);
@@ -2,7 +2,9 @@ import enMessages from "./en";
2
2
  import esMessages from "./es";
3
3
  const en = enMessages;
4
4
  const es = esMessages;
5
+ import { mergeTranslations } from "./mergeTranslations";
5
6
  export {
6
7
  en,
7
- es
8
+ es,
9
+ mergeTranslations
8
10
  };
@@ -0,0 +1,18 @@
1
+ const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2
+ const mergeTranslations = (...sources) => {
3
+ const result = {};
4
+ for (const source of sources) {
5
+ if (!isPlainObject(source)) continue;
6
+ for (const key of Object.keys(source)) {
7
+ const incoming = source[key];
8
+ const existing = result[key];
9
+ result[key] = isPlainObject(existing) && isPlainObject(incoming) ? mergeTranslations(existing, incoming) : incoming;
10
+ }
11
+ }
12
+ return result;
13
+ };
14
+ var mergeTranslations_default = mergeTranslations;
15
+ export {
16
+ mergeTranslations_default as default,
17
+ mergeTranslations
18
+ };
@@ -0,0 +1,61 @@
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
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
21
+ import { useRecordContext } from "react-admin";
22
+ import { SingleImageUploader } from "dash-components";
23
+ import { useFormContext } from "react-hook-form";
24
+ const AvatarHandler = (props) => {
25
+ var _a, _b;
26
+ const { method, attribute } = props;
27
+ const record = useRecordContext();
28
+ const {
29
+ setValue,
30
+ formState: { errors }
31
+ } = useFormContext();
32
+ const onChange = (file) => {
33
+ setValue(attribute.attribute, file, { shouldDirty: true });
34
+ };
35
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
36
+ /* @__PURE__ */ jsx(
37
+ SingleImageUploader,
38
+ __spreadProps(__spreadValues({
39
+ classNamePrefix: "dash-profile"
40
+ }, method === "edit" && { currentUrl: `${record.image_path}` }), {
41
+ onChange
42
+ })
43
+ ),
44
+ errors[attribute.attribute] && /* @__PURE__ */ jsx("span", { style: { color: "red" }, children: ((_b = (_a = errors[attribute.attribute]) == null ? void 0 : _a.message) == null ? void 0 : _b.toString()) || "Error" })
45
+ ] });
46
+ };
47
+ const AvatarUploadField = ({ method, attribute, resourceConfig }) => {
48
+ switch (method) {
49
+ case "edit":
50
+ return /* @__PURE__ */ jsx(AvatarHandler, { attribute, method, resourceConfig });
51
+ case "create":
52
+ return /* @__PURE__ */ jsx(AvatarHandler, { attribute, method, resourceConfig });
53
+ case "view":
54
+ return /* @__PURE__ */ jsx(Fragment, {});
55
+ }
56
+ };
57
+ var AvatarUploadField_default = AvatarUploadField;
58
+ export {
59
+ AvatarHandler,
60
+ AvatarUploadField_default as default
61
+ };
@@ -0,0 +1,67 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import {
3
+ PasswordInput
4
+ } from "react-admin";
5
+ import { Box } from "@mui/material";
6
+ const PasswordShow = (_props) => {
7
+ return /* @__PURE__ */ jsx(Fragment, {});
8
+ };
9
+ const PasswordEdit = (_props) => {
10
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
11
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
12
+ PasswordInput,
13
+ {
14
+ sx: { width: "100%" },
15
+ autoComplete: "off",
16
+ source: "Contrase\xF1a",
17
+ name: "password"
18
+ }
19
+ ) }),
20
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
21
+ PasswordInput,
22
+ {
23
+ sx: { width: "100%" },
24
+ autoComplete: "off",
25
+ source: "Confirmar Contrase\xF1a",
26
+ name: "password_confirmation"
27
+ }
28
+ ) })
29
+ ] });
30
+ };
31
+ const PasswordCreate = (_props) => {
32
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
33
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
34
+ PasswordInput,
35
+ {
36
+ sx: { width: "100%" },
37
+ source: "Contrase\xF1a",
38
+ name: "password"
39
+ }
40
+ ) }),
41
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
42
+ PasswordInput,
43
+ {
44
+ sx: { width: "100%" },
45
+ source: "Confirmar Contrase\xF1a",
46
+ name: "password_confirmation"
47
+ }
48
+ ) })
49
+ ] });
50
+ };
51
+ const PasswordFields = ({ method, attribute, resourceConfig }) => {
52
+ switch (method) {
53
+ case "edit":
54
+ return /* @__PURE__ */ jsx(PasswordEdit, { attribute, method, resourceConfig });
55
+ case "create":
56
+ return /* @__PURE__ */ jsx(PasswordCreate, { attribute, method, resourceConfig });
57
+ case "view":
58
+ return /* @__PURE__ */ jsx(PasswordShow, { attribute, method, resourceConfig });
59
+ }
60
+ };
61
+ var PasswordFields_default = PasswordFields;
62
+ export {
63
+ PasswordCreate,
64
+ PasswordEdit,
65
+ PasswordShow,
66
+ PasswordFields_default as default
67
+ };
@@ -0,0 +1,36 @@
1
+ import { dashStorage } from "dash-utils";
2
+ const getProfileMenu = (resourceConfig) => {
3
+ const userStr = dashStorage.getItem("user");
4
+ const rolesStr = dashStorage.getItem("roles");
5
+ const user = userStr ? JSON.parse(userStr) : null;
6
+ const roles = rolesStr ? JSON.parse(rolesStr) : [];
7
+ const profileMenu = [
8
+ {
9
+ title: "Perfil",
10
+ redirect: "/profile"
11
+ }
12
+ ];
13
+ const isCliente = roles ? roles.map((role) => role.name).includes("Cliente") : false;
14
+ if (isCliente) {
15
+ profileMenu.push(
16
+ {
17
+ title: "Comunas",
18
+ redirect: "/profile/commune"
19
+ },
20
+ {
21
+ title: "Centros Log\xEDsticos",
22
+ redirect: "/profile/logistic-center"
23
+ },
24
+ {
25
+ title: "Notificaciones",
26
+ redirect: "/profile/notification"
27
+ }
28
+ );
29
+ }
30
+ return profileMenu;
31
+ };
32
+ var getProfileMenu_default = getProfileMenu;
33
+ export {
34
+ getProfileMenu_default as default,
35
+ getProfileMenu
36
+ };
@@ -0,0 +1,33 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import ResourceTemplate from "../../templates/ResourceTemplate";
3
+ import Dashboard from "@mui/icons-material/Dashboard";
4
+ import { DASHAdminSystemConstants } from "dash-constants";
5
+ import getProfileMenu from "./getProfileMenu";
6
+ const profileResource = {
7
+ filterWithSubmit: true,
8
+ roles: [
9
+ "*"
10
+ /*
11
+ DASHAdminSystemConstants.system.DASH_SYSTEM_ROLE,
12
+ DASHAppConstants.system.TENANT_ROLE,
13
+ DASHAppConstants.system.USER_ROLE,
14
+ DASHAppConstants.system.CREATOR_ROLE,
15
+ DASHAppConstants.system.CLOSING_ROLE,
16
+ DASHAppConstants.system.GUNNER_ROLE,
17
+ DASHAppConstants.system.DRIVER_ROLE
18
+ */
19
+ ],
20
+ component: ResourceTemplate,
21
+ hidden: true,
22
+ model: "profile",
23
+ group: "Perfil",
24
+ label: "Perfil",
25
+ icon: /* @__PURE__ */ jsx(Dashboard, {}),
26
+ schema: null,
27
+ menu: getProfileMenu,
28
+ listProps: { perPage: DASHAdminSystemConstants.system.DEFAULT_PER_PAGE || 50 }
29
+ };
30
+ var profileResource_default = profileResource;
31
+ export {
32
+ profileResource_default as default
33
+ };