valtech-components 4.0.21 → 4.0.22

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.
@@ -56,7 +56,7 @@ import { BrowserMultiFormatReader } from '@zxing/browser';
56
56
  * Current version of valtech-components.
57
57
  * This is automatically updated during the publish process.
58
58
  */
59
- const VERSION = '4.0.21';
59
+ const VERSION = '4.0.22';
60
60
 
61
61
  // Control de estado de refresco (singleton a nivel de módulo)
62
62
  let isRefreshing = false;
@@ -48472,6 +48472,76 @@ function provideValtechAccountRoutes(opts) {
48472
48472
  ];
48473
48473
  }
48474
48474
 
48475
+ /**
48476
+ * Resuelve el label legible de un rol para el idioma dado.
48477
+ * Fallback: displayName en otro idioma → role.name (snake_case).
48478
+ */
48479
+ function resolveRoleLabel(role, lang) {
48480
+ const label = role.displayName?.[lang] ?? role.displayName?.['es'] ?? role.displayName?.['en'];
48481
+ return label ?? role.name;
48482
+ }
48483
+ /**
48484
+ * Resuelve el label de un rol a partir de una lista de roles disponibles.
48485
+ * Busca por id o name → usa resolveRoleLabel → fallback: humaniza el name.
48486
+ *
48487
+ * Función canónica de resolución. Reemplaza los keyMaps manuales en org-view y
48488
+ * member-detail-modal. Cubre roles del sistema Y roles custom de app.
48489
+ */
48490
+ function resolveRoleLabelFromList(roleIdOrName, roles, lang) {
48491
+ const found = roles.find(r => r.id === roleIdOrName || r.name === roleIdOrName);
48492
+ if (found)
48493
+ return resolveRoleLabel(found, lang);
48494
+ // Humaniza el nombre técnico como último recurso (ej. "bingo_taquilla" → "Bingo Taquilla")
48495
+ return roleIdOrName
48496
+ .split(/[_-]/)
48497
+ .filter(Boolean)
48498
+ .map(w => w.charAt(0).toUpperCase() + w.slice(1))
48499
+ .join(' ');
48500
+ }
48501
+ /**
48502
+ * Roles del sistema con displayName (es/en). Espejo de SystemRoleLabels (backend Go).
48503
+ * Backend es autoritativo — esto es un seed para renders previos a la carga de la API.
48504
+ */
48505
+ const SYSTEM_ROLE_DEFAULTS = [
48506
+ {
48507
+ id: 'viewer',
48508
+ name: 'viewer',
48509
+ isSystem: true,
48510
+ displayName: { es: 'Visualizador', en: 'Viewer' },
48511
+ },
48512
+ { id: 'editor', name: 'editor', isSystem: true, displayName: { es: 'Editor', en: 'Editor' } },
48513
+ {
48514
+ id: 'admin',
48515
+ name: 'admin',
48516
+ isSystem: true,
48517
+ displayName: { es: 'Administrador', en: 'Administrator' },
48518
+ },
48519
+ {
48520
+ id: 'bingo_admin',
48521
+ name: 'bingo_admin',
48522
+ isSystem: true,
48523
+ displayName: { es: 'Admin Bingo', en: 'Bingo Admin' },
48524
+ },
48525
+ {
48526
+ id: 'bingo_tesorero',
48527
+ name: 'bingo_tesorero',
48528
+ isSystem: true,
48529
+ displayName: { es: 'Tesorero', en: 'Treasurer' },
48530
+ },
48531
+ {
48532
+ id: 'bingo_taquilla',
48533
+ name: 'bingo_taquilla',
48534
+ isSystem: true,
48535
+ displayName: { es: 'Taquilla', en: 'Box Office' },
48536
+ },
48537
+ {
48538
+ id: 'bingo_operator',
48539
+ name: 'bingo_operator',
48540
+ isSystem: true,
48541
+ displayName: { es: 'Operador', en: 'Operator' },
48542
+ },
48543
+ ];
48544
+
48475
48545
  /**
48476
48546
  * Defaults i18n (es/en) embebidos en `val-edit-org-modal`. Auto-registrados en
48477
48547
  * el constructor del componente si el consumer no proveyó el namespace
@@ -48724,15 +48794,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
48724
48794
  type: Input
48725
48795
  }] } });
48726
48796
 
48727
- /**
48728
- * Resuelve el label legible de un rol para el idioma dado.
48729
- * Fallback: displayName en otro idioma → role.name (snake_case).
48730
- */
48731
- function resolveRoleLabel(role, lang) {
48732
- const label = role.displayName?.[lang] ?? role.displayName?.['es'] ?? role.displayName?.['en'];
48733
- return label ?? role.name;
48734
- }
48735
-
48736
48797
  /**
48737
48798
  * Defaults i18n (es/en) embebidos en `val-invite-member-modal`. Auto-registrados
48738
48799
  * en el constructor del componente si el consumer no proveyó el namespace
@@ -48825,11 +48886,7 @@ class InviteMemberModalComponent {
48825
48886
  this.selectedUsers = signal([]);
48826
48887
  this.sending = signal(false);
48827
48888
  this.selectedRole = signal('viewer');
48828
- this.availableRoles = signal([
48829
- { id: 'viewer', name: 'viewer' },
48830
- { id: 'editor', name: 'editor' },
48831
- { id: 'admin', name: 'admin' },
48832
- ]);
48889
+ this.availableRoles = signal(SYSTEM_ROLE_DEFAULTS);
48833
48890
  this.roleControl = new FormControl('viewer');
48834
48891
  this.roleSelectProps = computed(() => ({
48835
48892
  control: this.roleControl,
@@ -48868,7 +48925,6 @@ class InviteMemberModalComponent {
48868
48925
  if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$b)) {
48869
48926
  this.i18n.registerContent(DEFAULT_NAMESPACE$b, INVITE_MEMBER_MODAL_I18N);
48870
48927
  }
48871
- this.loadRoles();
48872
48928
  this.roleSub = this.roleControl.valueChanges.subscribe(v => {
48873
48929
  if (v)
48874
48930
  this.selectedRole.set(v);
@@ -49015,6 +49071,11 @@ class InviteMemberModalComponent {
49015
49071
  this.sending.set(false);
49016
49072
  }
49017
49073
  }
49074
+ ngOnInit() {
49075
+ // loadRoles aquí (no en constructor) para que @Input() orgId ya esté asignado
49076
+ // por ModalController antes de que corra el hook de inicialización.
49077
+ this.loadRoles();
49078
+ }
49018
49079
  ngOnDestroy() {
49019
49080
  this.roleSub?.unsubscribe();
49020
49081
  }
@@ -49651,18 +49712,7 @@ class MemberDetailModalComponent {
49651
49712
  }
49652
49713
  }
49653
49714
  roleLabel(roleIdOrName) {
49654
- // Try to find by id first (post-change, UUID stored), then by name (initial load)
49655
- const found = this.availableRoles.find(r => r.id === roleIdOrName || r.name === roleIdOrName);
49656
- const name = found?.name ?? roleIdOrName;
49657
- const keyMap = {
49658
- viewer: 'roleViewer',
49659
- editor: 'roleEditor',
49660
- admin: 'roleAdmin',
49661
- super_admin: 'roleSuperAdmin',
49662
- };
49663
- const key = keyMap[name] ?? name;
49664
- const label = this.t(key);
49665
- return label && !label.startsWith('[') ? label : name;
49715
+ return resolveRoleLabelFromList(roleIdOrName, this.availableRoles, this.i18n.lang());
49666
49716
  }
49667
49717
  ngOnDestroy() {
49668
49718
  this.roleSub?.unsubscribe();
@@ -50929,11 +50979,7 @@ class OrganizationViewComponent {
50929
50979
  this.showAllMembers = signal(false);
50930
50980
  this.visibleMembers = computed(() => (this.showAllMembers() ? this.members() : this.members().slice(0, 3)));
50931
50981
  this.transferring = signal(false);
50932
- this.availableRoles = signal([
50933
- { id: 'viewer', name: 'viewer' },
50934
- { id: 'editor', name: 'editor' },
50935
- { id: 'admin', name: 'admin' },
50936
- ]);
50982
+ this.availableRoles = signal(SYSTEM_ROLE_DEFAULTS);
50937
50983
  this.activeOrgId = computed(() => {
50938
50984
  const u = this.auth.user();
50939
50985
  return u?.activeOrgId ?? u?.activeOrg ?? '';
@@ -51332,31 +51378,7 @@ class OrganizationViewComponent {
51332
51378
  });
51333
51379
  }
51334
51380
  roleLabel(roleIdOrName) {
51335
- // Try to find by id first (UUID), then by name
51336
- const found = this.availableRoles().find(r => r.id === roleIdOrName || r.name === roleIdOrName);
51337
- const name = found?.name ?? roleIdOrName;
51338
- const keyMap = {
51339
- viewer: 'roleViewer',
51340
- editor: 'roleEditor',
51341
- admin: 'roleAdmin',
51342
- super_admin: 'roleSuperAdmin',
51343
- };
51344
- // 1) Rol genérico conocido → label i18n. 2) displayName/descripción del backend.
51345
- // 3) Fallback: humanizar el nombre crudo (ej. "bingo_admin" → "Bingo Admin")
51346
- // para no mostrar el código técnico a app-specific roles.
51347
- const mapped = keyMap[name];
51348
- if (mapped) {
51349
- const label = this.tt(mapped);
51350
- if (label && !label.startsWith('['))
51351
- return label;
51352
- }
51353
- if (found?.description)
51354
- return found.description;
51355
- return name
51356
- .split(/[_-]/)
51357
- .filter(Boolean)
51358
- .map(w => w.charAt(0).toUpperCase() + w.slice(1))
51359
- .join(' ');
51381
+ return resolveRoleLabelFromList(roleIdOrName, this.availableRoles(), this.i18n.lang());
51360
51382
  }
51361
51383
  onViewMember(member) {
51362
51384
  void this.modalService.openAdaptive({