valtech-components 4.0.937 → 4.0.939

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 (60) hide show
  1. package/esm2022/lib/components/molecules/group-picker/group-picker.component.mjs +97 -0
  2. package/esm2022/lib/components/organisms/group-members/group-members.component.mjs +178 -0
  3. package/esm2022/lib/components/organisms/mini-games/mini-games.i18n.mjs +1 -381
  4. package/esm2022/lib/components/organisms/mini-games/types.mjs +1 -1
  5. package/esm2022/lib/services/groups/groups.service.mjs +92 -0
  6. package/esm2022/lib/services/groups/types.mjs +2 -0
  7. package/esm2022/lib/version.mjs +2 -2
  8. package/esm2022/public-api.mjs +4 -3
  9. package/fesm2022/valtech-components.mjs +641 -7612
  10. package/fesm2022/valtech-components.mjs.map +1 -1
  11. package/lib/components/molecules/group-picker/group-picker.component.d.ts +28 -0
  12. package/lib/components/organisms/group-members/group-members.component.d.ts +43 -0
  13. package/lib/components/organisms/mini-games/types.d.ts +0 -182
  14. package/lib/services/groups/groups.service.d.ts +39 -0
  15. package/lib/services/groups/types.d.ts +69 -0
  16. package/lib/version.d.ts +1 -1
  17. package/package.json +1 -1
  18. package/public-api.d.ts +4 -2
  19. package/src/lib/assets/games/README.md +8 -0
  20. package/esm2022/lib/components/organisms/mini-games/christianity-bot.mjs +0 -94
  21. package/esm2022/lib/components/organisms/mini-games/christianity-card.component.mjs +0 -503
  22. package/esm2022/lib/components/organisms/mini-games/christianity-catalog.mjs +0 -247
  23. package/esm2022/lib/components/organisms/mini-games/christianity-game.component.mjs +0 -4580
  24. package/esm2022/lib/components/organisms/mini-games/christianity-rules.mjs +0 -1383
  25. package/esm2022/lib/components/organisms/mini-games/christianity-tutorial.mjs +0 -152
  26. package/lib/components/organisms/mini-games/christianity-bot.d.ts +0 -15
  27. package/lib/components/organisms/mini-games/christianity-card.component.d.ts +0 -55
  28. package/lib/components/organisms/mini-games/christianity-catalog.d.ts +0 -18
  29. package/lib/components/organisms/mini-games/christianity-game.component.d.ts +0 -395
  30. package/lib/components/organisms/mini-games/christianity-rules.d.ts +0 -57
  31. package/lib/components/organisms/mini-games/christianity-tutorial.d.ts +0 -38
  32. package/src/lib/assets/games/christianity/card-symbol.svg +0 -51
  33. package/src/lib/assets/games/christianity/card-template-reference/front.html +0 -114
  34. package/src/lib/assets/games/christianity/card-template-reference/front.style.css +0 -352
  35. package/src/lib/assets/games/christianity/data/01-genesis.bible-reference-suggestions.csv +0 -191
  36. package/src/lib/assets/games/christianity/data/01-genesis.bible-verses.nbv-open.csv +0 -170
  37. package/src/lib/assets/games/christianity/data/01-genesis.cards.csv +0 -281
  38. package/src/lib/assets/games/christianity/data/01-genesis.cards.i18n.csv +0 -281
  39. package/src/lib/assets/games/christianity/data/01-genesis.cards.json +0 -16453
  40. package/src/lib/assets/games/christianity/data/01-genesis.unassigned-effects.csv +0 -49
  41. package/src/lib/assets/games/christianity/data/README.md +0 -40
  42. package/src/lib/assets/games/christianity/data/data-con-habilides.csv +0 -273
  43. package/src/lib/assets/games/christianity/data/habilidades-por-tipo.xlsx +0 -0
  44. package/src/lib/assets/games/christianity/data/listado-edicion.csv +0 -281
  45. package/src/lib/assets/games/christianity/editions/1/cards/.gitkeep +0 -1
  46. package/src/lib/assets/games/christianity/editions/1/cards/PLACEHOLDER.png +0 -0
  47. package/src/lib/assets/games/christianity/editions/README.md +0 -34
  48. package/src/lib/assets/games/christianity/icons/1-icon.png +0 -0
  49. package/src/lib/assets/games/christianity/icons/action.png +0 -0
  50. package/src/lib/assets/games/christianity/icons/character.png +0 -0
  51. package/src/lib/assets/games/christianity/icons/event.png +0 -0
  52. package/src/lib/assets/games/christianity/icons/leader.png +0 -0
  53. package/src/lib/assets/games/christianity/icons/offering.png +0 -0
  54. package/src/lib/assets/games/christianity/icons/place.png +0 -0
  55. package/src/lib/assets/games/christianity/icons/tool.png +0 -0
  56. package/src/lib/assets/games/christianity/icons/wisdom.png +0 -0
  57. package/src/lib/assets/games/christianity/sources/README.md +0 -16
  58. package/src/lib/assets/games/christianity/sources/spaonbv_vpl.txt +0 -29102
  59. package/src/lib/assets/games/christianity/sources/spaonbv_vpl.xml +0 -29104
  60. package/src/lib/assets/games/christianity/spaonbv.txt +0 -52
@@ -0,0 +1,97 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, EventEmitter, Input, Output, inject } from '@angular/core';
3
+ import { IonSelect, IonSelectOption } from '@ionic/angular/standalone';
4
+ import { GroupsService } from '../../../services/groups/groups.service';
5
+ import * as i0 from "@angular/core";
6
+ /**
7
+ * val-group-picker — elegir el grupo dueño de un recurso (ADR-083).
8
+ *
9
+ * Se auto-carga: pide sus propios grupos a `GroupsService` en vez de esperar
10
+ * que el consumer se los pase. Es la razón por la que existe como componente y
11
+ * no como un `<select>` armado a mano en cada app — "una línea, una etiqueta
12
+ * i18n" (ver ADR-083 §"Qué se construye una sola vez").
13
+ *
14
+ * Sin texto hardcodeado: los labels llegan por `@Input` (lib i18n-agnostic).
15
+ * Cada app pone su palabra ("Equipo", "Sucursal", "Refugio").
16
+ */
17
+ export class GroupPickerComponent {
18
+ constructor() {
19
+ this.label = '';
20
+ this.placeholder = '';
21
+ this.noGroupLabel = '';
22
+ this.value = null;
23
+ this.disabled = false;
24
+ this.valueChange = new EventEmitter();
25
+ this.groupsSvc = inject(GroupsService);
26
+ this.groups = [];
27
+ }
28
+ ngOnInit() {
29
+ this.groupsSvc.listGroups().subscribe({
30
+ next: (g) => (this.groups = g),
31
+ // Best-effort: si la lectura falla, el picker queda con la opción "sin
32
+ // grupo" únicamente. No es un error bloqueante — crear el recurso sin
33
+ // asignar sigue siendo válido.
34
+ error: () => (this.groups = []),
35
+ });
36
+ }
37
+ onChange(v) {
38
+ this.value = v || null;
39
+ this.valueChange.emit(this.value);
40
+ }
41
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GroupPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
42
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: GroupPickerComponent, isStandalone: true, selector: "val-group-picker", inputs: { label: "label", placeholder: "placeholder", noGroupLabel: "noGroupLabel", value: "value", disabled: "disabled" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `
43
+ <ion-select
44
+ [label]="label"
45
+ [placeholder]="placeholder"
46
+ [value]="value ?? ''"
47
+ [disabled]="disabled"
48
+ interface="popover"
49
+ (ionChange)="onChange($event.detail.value)"
50
+ >
51
+ <!-- Opción vacía SIEMPRE disponible: un recurso sin grupo es visible para
52
+ toda la organización (ADR-083, decisión 3), no un estado inválido. -->
53
+ <ion-select-option value="">{{ noGroupLabel }}</ion-select-option>
54
+ @for (g of groups; track g.id) {
55
+ <ion-select-option [value]="g.id">{{ g.name }}</ion-select-option>
56
+ }
57
+ </ion-select>
58
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }] }); }
59
+ }
60
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GroupPickerComponent, decorators: [{
61
+ type: Component,
62
+ args: [{
63
+ selector: 'val-group-picker',
64
+ standalone: true,
65
+ imports: [CommonModule, IonSelect, IonSelectOption],
66
+ template: `
67
+ <ion-select
68
+ [label]="label"
69
+ [placeholder]="placeholder"
70
+ [value]="value ?? ''"
71
+ [disabled]="disabled"
72
+ interface="popover"
73
+ (ionChange)="onChange($event.detail.value)"
74
+ >
75
+ <!-- Opción vacía SIEMPRE disponible: un recurso sin grupo es visible para
76
+ toda la organización (ADR-083, decisión 3), no un estado inválido. -->
77
+ <ion-select-option value="">{{ noGroupLabel }}</ion-select-option>
78
+ @for (g of groups; track g.id) {
79
+ <ion-select-option [value]="g.id">{{ g.name }}</ion-select-option>
80
+ }
81
+ </ion-select>
82
+ `,
83
+ }]
84
+ }], propDecorators: { label: [{
85
+ type: Input
86
+ }], placeholder: [{
87
+ type: Input
88
+ }], noGroupLabel: [{
89
+ type: Input
90
+ }], value: [{
91
+ type: Input
92
+ }], disabled: [{
93
+ type: Input
94
+ }], valueChange: [{
95
+ type: Output
96
+ }] } });
97
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JvdXAtcGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9tb2xlY3VsZXMvZ3JvdXAtcGlja2VyL2dyb3VwLXBpY2tlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZGLE9BQU8sRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdkUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHlDQUF5QyxDQUFDOztBQUd4RTs7Ozs7Ozs7OztHQVVHO0FBdUJILE1BQU0sT0FBTyxvQkFBb0I7SUF0QmpDO1FBdUJXLFVBQUssR0FBRyxFQUFFLENBQUM7UUFDWCxnQkFBVyxHQUFHLEVBQUUsQ0FBQztRQUNqQixpQkFBWSxHQUFHLEVBQUUsQ0FBQztRQUNsQixVQUFLLEdBQWtCLElBQUksQ0FBQztRQUM1QixhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ2hCLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQWlCLENBQUM7UUFFekMsY0FBUyxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNuRCxXQUFNLEdBQWUsRUFBRSxDQUFDO0tBZ0J6QjtJQWRDLFFBQVE7UUFDTixJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxDQUFDLFNBQVMsQ0FBQztZQUNwQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7WUFDOUIsdUVBQXVFO1lBQ3ZFLHNFQUFzRTtZQUN0RSwrQkFBK0I7WUFDL0IsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxFQUFFLENBQUM7U0FDaEMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFFBQVEsQ0FBQyxDQUFTO1FBQ2hCLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQztRQUN2QixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDcEMsQ0FBQzsrR0F4QlUsb0JBQW9CO21HQUFwQixvQkFBb0IsaVBBbEJyQjs7Ozs7Ozs7Ozs7Ozs7OztHQWdCVCwyREFqQlMsWUFBWSwrQkFBRSxTQUFTLGtWQUFFLGVBQWU7OzRGQW1CdkMsb0JBQW9CO2tCQXRCaEMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsa0JBQWtCO29CQUM1QixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsT0FBTyxFQUFFLENBQUMsWUFBWSxFQUFFLFNBQVMsRUFBRSxlQUFlLENBQUM7b0JBQ25ELFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7OztHQWdCVDtpQkFDRjs4QkFFVSxLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csV0FBVztzQkFBbkIsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLEtBQUs7c0JBQWIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNJLFdBQVc7c0JBQXBCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgQ29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIElucHV0LCBPbkluaXQsIE91dHB1dCwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBJb25TZWxlY3QsIElvblNlbGVjdE9wdGlvbiB9IGZyb20gJ0Bpb25pYy9hbmd1bGFyL3N0YW5kYWxvbmUnO1xuaW1wb3J0IHsgR3JvdXBzU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2dyb3Vwcy9ncm91cHMuc2VydmljZSc7XG5pbXBvcnQgeyBWYWxHcm91cCB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2dyb3Vwcy90eXBlcyc7XG5cbi8qKlxuICogdmFsLWdyb3VwLXBpY2tlciDigJQgZWxlZ2lyIGVsIGdydXBvIGR1ZcOxbyBkZSB1biByZWN1cnNvIChBRFItMDgzKS5cbiAqXG4gKiBTZSBhdXRvLWNhcmdhOiBwaWRlIHN1cyBwcm9waW9zIGdydXBvcyBhIGBHcm91cHNTZXJ2aWNlYCBlbiB2ZXogZGUgZXNwZXJhclxuICogcXVlIGVsIGNvbnN1bWVyIHNlIGxvcyBwYXNlLiBFcyBsYSByYXrDs24gcG9yIGxhIHF1ZSBleGlzdGUgY29tbyBjb21wb25lbnRlIHlcbiAqIG5vIGNvbW8gdW4gYDxzZWxlY3Q+YCBhcm1hZG8gYSBtYW5vIGVuIGNhZGEgYXBwIOKAlCBcInVuYSBsw61uZWEsIHVuYSBldGlxdWV0YVxuICogaTE4blwiICh2ZXIgQURSLTA4MyDCp1wiUXXDqSBzZSBjb25zdHJ1eWUgdW5hIHNvbGEgdmV6XCIpLlxuICpcbiAqIFNpbiB0ZXh0byBoYXJkY29kZWFkbzogbG9zIGxhYmVscyBsbGVnYW4gcG9yIGBASW5wdXRgIChsaWIgaTE4bi1hZ25vc3RpYykuXG4gKiBDYWRhIGFwcCBwb25lIHN1IHBhbGFicmEgKFwiRXF1aXBvXCIsIFwiU3VjdXJzYWxcIiwgXCJSZWZ1Z2lvXCIpLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd2YWwtZ3JvdXAtcGlja2VyJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgSW9uU2VsZWN0LCBJb25TZWxlY3RPcHRpb25dLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxpb24tc2VsZWN0XG4gICAgICBbbGFiZWxdPVwibGFiZWxcIlxuICAgICAgW3BsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyXCJcbiAgICAgIFt2YWx1ZV09XCJ2YWx1ZSA/PyAnJ1wiXG4gICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgaW50ZXJmYWNlPVwicG9wb3ZlclwiXG4gICAgICAoaW9uQ2hhbmdlKT1cIm9uQ2hhbmdlKCRldmVudC5kZXRhaWwudmFsdWUpXCJcbiAgICA+XG4gICAgICA8IS0tIE9wY2nDs24gdmFjw61hIFNJRU1QUkUgZGlzcG9uaWJsZTogdW4gcmVjdXJzbyBzaW4gZ3J1cG8gZXMgdmlzaWJsZSBwYXJhXG4gICAgICAgICAgIHRvZGEgbGEgb3JnYW5pemFjacOzbiAoQURSLTA4MywgZGVjaXNpw7NuIDMpLCBubyB1biBlc3RhZG8gaW52w6FsaWRvLiAtLT5cbiAgICAgIDxpb24tc2VsZWN0LW9wdGlvbiB2YWx1ZT1cIlwiPnt7IG5vR3JvdXBMYWJlbCB9fTwvaW9uLXNlbGVjdC1vcHRpb24+XG4gICAgICBAZm9yIChnIG9mIGdyb3VwczsgdHJhY2sgZy5pZCkge1xuICAgICAgICA8aW9uLXNlbGVjdC1vcHRpb24gW3ZhbHVlXT1cImcuaWRcIj57eyBnLm5hbWUgfX08L2lvbi1zZWxlY3Qtb3B0aW9uPlxuICAgICAgfVxuICAgIDwvaW9uLXNlbGVjdD5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgR3JvdXBQaWNrZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBASW5wdXQoKSBsYWJlbCA9ICcnO1xuICBASW5wdXQoKSBwbGFjZWhvbGRlciA9ICcnO1xuICBASW5wdXQoKSBub0dyb3VwTGFiZWwgPSAnJztcbiAgQElucHV0KCkgdmFsdWU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xuICBAT3V0cHV0KCkgdmFsdWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZyB8IG51bGw+KCk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBncm91cHNTdmMgPSBpbmplY3QoR3JvdXBzU2VydmljZSk7XG4gIGdyb3VwczogVmFsR3JvdXBbXSA9IFtdO1xuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuZ3JvdXBzU3ZjLmxpc3RHcm91cHMoKS5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKGcpID0+ICh0aGlzLmdyb3VwcyA9IGcpLFxuICAgICAgLy8gQmVzdC1lZmZvcnQ6IHNpIGxhIGxlY3R1cmEgZmFsbGEsIGVsIHBpY2tlciBxdWVkYSBjb24gbGEgb3BjacOzbiBcInNpblxuICAgICAgLy8gZ3J1cG9cIiDDum5pY2FtZW50ZS4gTm8gZXMgdW4gZXJyb3IgYmxvcXVlYW50ZSDigJQgY3JlYXIgZWwgcmVjdXJzbyBzaW5cbiAgICAgIC8vIGFzaWduYXIgc2lndWUgc2llbmRvIHbDoWxpZG8uXG4gICAgICBlcnJvcjogKCkgPT4gKHRoaXMuZ3JvdXBzID0gW10pLFxuICAgIH0pO1xuICB9XG5cbiAgb25DaGFuZ2Uodjogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy52YWx1ZSA9IHYgfHwgbnVsbDtcbiAgICB0aGlzLnZhbHVlQ2hhbmdlLmVtaXQodGhpcy52YWx1ZSk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,178 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, EventEmitter, Input, Output, inject } from '@angular/core';
3
+ import { IonIcon, IonSelect, IonSelectOption } from '@ionic/angular/standalone';
4
+ import { ButtonComponent } from '../../atoms/button/button.component';
5
+ import { ComponentStates } from '../../types';
6
+ import { GroupsService } from '../../../services/groups/groups.service';
7
+ import * as i0 from "@angular/core";
8
+ /**
9
+ * val-group-members — administrar la membresía de UN grupo (ADR-083).
10
+ *
11
+ * Deliberadamente NO trae su propio selector de personas: la fuente de
12
+ * "quiénes son los miembros elegibles de la organización" varía por app (org
13
+ * members, invitados, etc.), así que se recibe por `@Input candidates` en vez
14
+ * de que este organismo importe un servicio de organización que no le
15
+ * corresponde. Sin candidatos, igual funciona: solo lista y quita.
16
+ *
17
+ * Sin texto hardcodeado (lib i18n-agnostic): los labels llegan por `@Input`.
18
+ */
19
+ export class GroupMembersComponent {
20
+ constructor() {
21
+ /** Personas elegibles para agregar. Vacío = el organismo solo lista/quita. */
22
+ this.candidates = [];
23
+ this.addPlaceholder = '';
24
+ this.emptyLabel = '';
25
+ this.removeLabel = '';
26
+ this.membersChange = new EventEmitter();
27
+ this.groupsSvc = inject(GroupsService);
28
+ this.members = [];
29
+ this.busy = false;
30
+ }
31
+ get removeButtonProps() {
32
+ return {
33
+ text: this.removeLabel,
34
+ color: 'dark',
35
+ fill: 'clear',
36
+ size: 'small',
37
+ shape: 'round',
38
+ type: 'button',
39
+ state: this.busy ? ComponentStates.DISABLED : ComponentStates.ENABLED,
40
+ };
41
+ }
42
+ ngOnChanges(changes) {
43
+ if (changes['groupId'] && this.groupId) {
44
+ this.reload();
45
+ }
46
+ }
47
+ reload() {
48
+ this.groupsSvc.listMembers(this.groupId).subscribe({
49
+ next: (m) => (this.members = m),
50
+ error: () => (this.members = []),
51
+ });
52
+ }
53
+ /** Candidatos que todavía no están en el grupo — evita ofrecer un alta duplicada. */
54
+ eligible() {
55
+ const current = new Set(this.members.map((m) => m.userId));
56
+ return this.candidates.filter((c) => !current.has(c.userId));
57
+ }
58
+ nameFor(userId) {
59
+ const c = this.candidates.find((x) => x.userId === userId);
60
+ return c?.name || c?.email || userId;
61
+ }
62
+ add(userId) {
63
+ if (!userId || this.busy)
64
+ return;
65
+ this.busy = true;
66
+ this.groupsSvc.addMember(this.groupId, { userId }).subscribe({
67
+ next: (members) => {
68
+ this.members = members;
69
+ this.busy = false;
70
+ this.membersChange.emit(members);
71
+ },
72
+ error: () => (this.busy = false),
73
+ });
74
+ }
75
+ remove(userId) {
76
+ if (this.busy)
77
+ return;
78
+ this.busy = true;
79
+ this.groupsSvc.removeMember(this.groupId, userId).subscribe({
80
+ next: (members) => {
81
+ this.members = members;
82
+ this.busy = false;
83
+ this.membersChange.emit(members);
84
+ },
85
+ error: () => (this.busy = false),
86
+ });
87
+ }
88
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GroupMembersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
89
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: GroupMembersComponent, isStandalone: true, selector: "val-group-members", inputs: { groupId: "groupId", candidates: "candidates", addPlaceholder: "addPlaceholder", emptyLabel: "emptyLabel", removeLabel: "removeLabel" }, outputs: { membersChange: "membersChange" }, usesOnChanges: true, ngImport: i0, template: `
90
+ <div class="group-members">
91
+ @if (candidates.length > 0) {
92
+ <div class="group-members__add">
93
+ <ion-select
94
+ [placeholder]="addPlaceholder"
95
+ interface="popover"
96
+ [disabled]="busy"
97
+ (ionChange)="add($event.detail.value)"
98
+ >
99
+ @for (c of eligible(); track c.userId) {
100
+ <ion-select-option [value]="c.userId">
101
+ {{ c.name || c.email || c.userId }}
102
+ </ion-select-option>
103
+ }
104
+ </ion-select>
105
+ </div>
106
+ }
107
+
108
+ @if (members.length === 0) {
109
+ <p class="group-members__empty">{{ emptyLabel }}</p>
110
+ } @else {
111
+ <ul class="group-members__list">
112
+ @for (m of members; track m.userId) {
113
+ <li class="group-members__row">
114
+ <span class="group-members__name">{{ nameFor(m.userId) }}</span>
115
+ <val-button
116
+ [props]="removeButtonProps"
117
+ (onClick)="remove(m.userId)"
118
+ />
119
+ </li>
120
+ }
121
+ </ul>
122
+ }
123
+ </div>
124
+ `, isInline: true, styles: [".group-members{display:flex;flex-direction:column;gap:12px}.group-members__empty{font-size:.875rem;color:var(--ion-color-medium, #92949c);margin:0}.group-members__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px}.group-members__row{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-radius:10px;background:var(--ion-color-light, #f4f5f8)}.group-members__name{font-size:.9375rem;color:var(--ion-text-color, #000)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }] }); }
125
+ }
126
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GroupMembersComponent, decorators: [{
127
+ type: Component,
128
+ args: [{ selector: 'val-group-members', standalone: true, imports: [CommonModule, IonIcon, IonSelect, IonSelectOption, ButtonComponent], template: `
129
+ <div class="group-members">
130
+ @if (candidates.length > 0) {
131
+ <div class="group-members__add">
132
+ <ion-select
133
+ [placeholder]="addPlaceholder"
134
+ interface="popover"
135
+ [disabled]="busy"
136
+ (ionChange)="add($event.detail.value)"
137
+ >
138
+ @for (c of eligible(); track c.userId) {
139
+ <ion-select-option [value]="c.userId">
140
+ {{ c.name || c.email || c.userId }}
141
+ </ion-select-option>
142
+ }
143
+ </ion-select>
144
+ </div>
145
+ }
146
+
147
+ @if (members.length === 0) {
148
+ <p class="group-members__empty">{{ emptyLabel }}</p>
149
+ } @else {
150
+ <ul class="group-members__list">
151
+ @for (m of members; track m.userId) {
152
+ <li class="group-members__row">
153
+ <span class="group-members__name">{{ nameFor(m.userId) }}</span>
154
+ <val-button
155
+ [props]="removeButtonProps"
156
+ (onClick)="remove(m.userId)"
157
+ />
158
+ </li>
159
+ }
160
+ </ul>
161
+ }
162
+ </div>
163
+ `, styles: [".group-members{display:flex;flex-direction:column;gap:12px}.group-members__empty{font-size:.875rem;color:var(--ion-color-medium, #92949c);margin:0}.group-members__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px}.group-members__row{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-radius:10px;background:var(--ion-color-light, #f4f5f8)}.group-members__name{font-size:.9375rem;color:var(--ion-text-color, #000)}\n"] }]
164
+ }], propDecorators: { groupId: [{
165
+ type: Input,
166
+ args: [{ required: true }]
167
+ }], candidates: [{
168
+ type: Input
169
+ }], addPlaceholder: [{
170
+ type: Input
171
+ }], emptyLabel: [{
172
+ type: Input
173
+ }], removeLabel: [{
174
+ type: Input
175
+ }], membersChange: [{
176
+ type: Output
177
+ }] } });
178
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JvdXAtbWVtYmVycy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL2NvbXBvbmVudHMvb3JnYW5pc21zL2dyb3VwLW1lbWJlcnMvZ3JvdXAtbWVtYmVycy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBYSxNQUFNLEVBQWlCLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN6RyxPQUFPLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNoRixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDdEUsT0FBTyxFQUFFLGVBQWUsRUFBa0IsTUFBTSxhQUFhLENBQUM7QUFDOUQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHlDQUF5QyxDQUFDOztBQVV4RTs7Ozs7Ozs7OztHQVVHO0FBMkNILE1BQU0sT0FBTyxxQkFBcUI7SUExQ2xDO1FBNENFLDhFQUE4RTtRQUNyRSxlQUFVLEdBQTJCLEVBQUUsQ0FBQztRQUN4QyxtQkFBYyxHQUFHLEVBQUUsQ0FBQztRQUNwQixlQUFVLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLGdCQUFXLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLGtCQUFhLEdBQUcsSUFBSSxZQUFZLEVBQW9CLENBQUM7UUFFOUMsY0FBUyxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNuRCxZQUFPLEdBQXFCLEVBQUUsQ0FBQztRQUMvQixTQUFJLEdBQUcsS0FBSyxDQUFDO0tBK0RkO0lBN0RDLElBQUksaUJBQWlCO1FBQ25CLE9BQU87WUFDTCxJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVc7WUFDdEIsS0FBSyxFQUFFLE1BQU07WUFD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SUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbkMsQ0FBQztZQUNELEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDO1NBQ2pDLENBQUMsQ0FBQztJQUNMLENBQUM7K0dBekVVLHFCQUFxQjttR0FBckIscUJBQXFCLGlTQXRDdEI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUNULDRpQkFwQ1MsWUFBWSwrQkFBVyxTQUFTLGtWQUFFLGVBQWUsNkZBQUUsZUFBZTs7NEZBdUNqRSxxQkFBcUI7a0JBMUNqQyxTQUFTOytCQUNFLG1CQUFtQixjQUNqQixJQUFJLFdBQ1AsQ0FBQyxZQUFZLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsZUFBZSxDQUFDLFlBQ25FOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1DVDs4QkFJMEIsT0FBTztzQkFBakMsS0FBSzt1QkFBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7Z0JBRWhCLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csY0FBYztzQkFBdEIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0ksYUFBYTtzQkFBdEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uQ2hhbmdlcywgT3V0cHV0LCBTaW1wbGVDaGFuZ2VzLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IElvbkljb24sIElvblNlbGVjdCwgSW9uU2VsZWN0T3B0aW9uIH0gZnJvbSAnQGlvbmljL2FuZ3VsYXIvc3RhbmRhbG9uZSc7XG5pbXBvcnQgeyBCdXR0b25Db21wb25lbnQgfSBmcm9tICcuLi8uLi9hdG9tcy9idXR0b24vYnV0dG9uLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBDb21wb25lbnRTdGF0ZXMsIEJ1dHRvbk1ldGFkYXRhIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuaW1wb3J0IHsgR3JvdXBzU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2dyb3Vwcy9ncm91cHMuc2VydmljZSc7XG5pbXBvcnQgeyBWYWxHcm91cE1lbWJlciB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2dyb3Vwcy90eXBlcyc7XG5cbi8qKiBQZXJzb25hIGVsZWdpYmxlIHBhcmEgYWdyZWdhciBhbCBncnVwbyAodMOtcGljYW1lbnRlIHVuIGBPcmdNZW1iZXJgKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR3JvdXBNZW1iZXJDYW5kaWRhdGUge1xuICB1c2VySWQ6IHN0cmluZztcbiAgbmFtZT86IHN0cmluZztcbiAgZW1haWw/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogdmFsLWdyb3VwLW1lbWJlcnMg4oCUIGFkbWluaXN0cmFyIGxhIG1lbWJyZXPDrWEgZGUgVU4gZ3J1cG8gKEFEUi0wODMpLlxuICpcbiAqIERlbGliZXJhZGFtZW50ZSBOTyB0cmFlIHN1IHByb3BpbyBzZWxlY3RvciBkZSBwZXJzb25hczogbGEgZnVlbnRlIGRlXG4gKiBcInF1acOpbmVzIHNvbiBsb3MgbWllbWJyb3MgZWxlZ2libGVzIGRlIGxhIG9yZ2FuaXphY2nDs25cIiB2YXLDrWEgcG9yIGFwcCAob3JnXG4gKiBtZW1iZXJzLCBpbnZpdGFkb3MsIGV0Yy4pLCBhc8OtIHF1ZSBzZSByZWNpYmUgcG9yIGBASW5wdXQgY2FuZGlkYXRlc2AgZW4gdmV6XG4gKiBkZSBxdWUgZXN0ZSBvcmdhbmlzbW8gaW1wb3J0ZSB1biBzZXJ2aWNpbyBkZSBvcmdhbml6YWNpw7NuIHF1ZSBubyBsZVxuICogY29ycmVzcG9uZGUuIFNpbiBjYW5kaWRhdG9zLCBpZ3VhbCBmdW5jaW9uYTogc29sbyBsaXN0YSB5IHF1aXRhLlxuICpcbiAqIFNpbiB0ZXh0byBoYXJkY29kZWFkbyAobGliIGkxOG4tYWdub3N0aWMpOiBsb3MgbGFiZWxzIGxsZWdhbiBwb3IgYEBJbnB1dGAuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3ZhbC1ncm91cC1tZW1iZXJzJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgSW9uSWNvbiwgSW9uU2VsZWN0LCBJb25TZWxlY3RPcHRpb24sIEJ1dHRvbkNvbXBvbmVudF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImdyb3VwLW1lbWJlcnNcIj5cbiAgICAgIEBpZiAoY2FuZGlkYXRlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJncm91cC1tZW1iZXJzX19hZGRcIj5cbiAgICAgICAgICA8aW9uLXNlbGVjdFxuICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cImFkZFBsYWNlaG9sZGVyXCJcbiAgICAgICAgICAgIGludGVyZmFjZT1cInBvcG92ZXJcIlxuICAgICAgICAgICAgW2Rpc2FibGVkXT1cImJ1c3lcIlxuICAgICAgICAgICAgKGlvbkNoYW5nZSk9XCJhZGQoJGV2ZW50LmRldGFpbC52YWx1ZSlcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIEBmb3IgKGMgb2YgZWxpZ2libGUoKTsgdHJhY2sgYy51c2VySWQpIHtcbiAgICAgICAgICAgICAgPGlvbi1zZWxlY3Qtb3B0aW9uIFt2YWx1ZV09XCJjLnVzZXJJZFwiPlxuICAgICAgICAgICAgICAgIHt7IGMubmFtZSB8fCBjLmVtYWlsIHx8IGMudXNlcklkIH19XG4gICAgICAgICAgICAgIDwvaW9uLXNlbGVjdC1vcHRpb24+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9pb24tc2VsZWN0PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIH1cblxuICAgICAgQGlmIChtZW1iZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICA8cCBjbGFzcz1cImdyb3VwLW1lbWJlcnNfX2VtcHR5XCI+e3sgZW1wdHlMYWJlbCB9fTwvcD5cbiAgICAgIH0gQGVsc2Uge1xuICAgICAgICA8dWwgY2xhc3M9XCJncm91cC1tZW1iZXJzX19saXN0XCI+XG4gICAgICAgICAgQGZvciAobSBvZiBtZW1iZXJzOyB0cmFjayBtLnVzZXJJZCkge1xuICAgICAgICAgICAgPGxpIGNsYXNzPVwiZ3JvdXAtbWVtYmVyc19fcm93XCI+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZ3JvdXAtbWVtYmVyc19fbmFtZVwiPnt7IG5hbWVGb3IobS51c2VySWQpIH19PC9zcGFuPlxuICAgICAgICAgICAgICA8dmFsLWJ1dHRvblxuICAgICAgICAgICAgICAgIFtwcm9wc109XCJyZW1vdmVCdXR0b25Qcm9wc1wiXG4gICAgICAgICAgICAgICAgKG9uQ2xpY2spPVwicmVtb3ZlKG0udXNlcklkKVwiXG4gICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8L2xpPlxuICAgICAgICAgIH1cbiAgICAgICAgPC91bD5cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVVcmxzOiBbJy4vZ3JvdXAtbWVtYmVycy5jb21wb25lbnQuc2NzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBHcm91cE1lbWJlcnNDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KSBncm91cElkITogc3RyaW5nO1xuICAvKiogUGVyc29uYXMgZWxlZ2libGVzIHBhcmEgYWdyZWdhci4gVmFjw61vID0gZWwgb3JnYW5pc21vIHNvbG8gbGlzdGEvcXVpdGEuICovXG4gIEBJbnB1dCgpIGNhbmRpZGF0ZXM6IEdyb3VwTWVtYmVyQ2FuZGlkYXRlW10gPSBbXTtcbiAgQElucHV0KCkgYWRkUGxhY2Vob2xkZXIgPSAnJztcbiAgQElucHV0KCkgZW1wdHlMYWJlbCA9ICcnO1xuICBASW5wdXQoKSByZW1vdmVMYWJlbCA9ICcnO1xuICBAT3V0cHV0KCkgbWVtYmVyc0NoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8VmFsR3JvdXBNZW1iZXJbXT4oKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGdyb3Vwc1N2YyA9IGluamVjdChHcm91cHNTZXJ2aWNlKTtcbiAgbWVtYmVyczogVmFsR3JvdXBNZW1iZXJbXSA9IFtdO1xuICBidXN5ID0gZmFsc2U7XG5cbiAgZ2V0IHJlbW92ZUJ1dHRvblByb3BzKCk6IEJ1dHRvbk1ldGFkYXRhIHtcbiAgICByZXR1cm4ge1xuICAgICAgdGV4dDogdGhpcy5yZW1vdmVMYWJlbCxcbiAgICAgIGNvbG9yOiAnZGFyaycsXG4gICAgICBmaWxsOiAnY2xlYXInLFxuICAgICAgc2l6ZTogJ3NtYWxsJyxcbiAgICAgIHNoYXBlOiAncm91bmQnLFxuICAgICAgdHlwZTogJ2J1dHRvbicsXG4gICAgICBzdGF0ZTogdGhpcy5idXN5ID8gQ29tcG9uZW50U3RhdGVzLkRJU0FCTEVEIDogQ29tcG9uZW50U3RhdGVzLkVOQUJMRUQsXG4gICAgfTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBpZiAoY2hhbmdlc1snZ3JvdXBJZCddICYmIHRoaXMuZ3JvdXBJZCkge1xuICAgICAgdGhpcy5yZWxvYWQoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlbG9hZCgpOiB2b2lkIHtcbiAgICB0aGlzLmdyb3Vwc1N2Yy5saXN0TWVtYmVycyh0aGlzLmdyb3VwSWQpLnN1YnNjcmliZSh7XG4gICAgICBuZXh0OiAobSkgPT4gKHRoaXMubWVtYmVycyA9IG0pLFxuICAgICAgZXJyb3I6ICgpID0+ICh0aGlzLm1lbWJlcnMgPSBbXSksXG4gICAgfSk7XG4gIH1cblxuICAvKiogQ2FuZGlkYXRvcyBxdWUgdG9kYXbDrWEgbm8gZXN0w6FuIGVuIGVsIGdydXBvIOKAlCBldml0YSBvZnJlY2VyIHVuIGFsdGEgZHVwbGljYWRhLiAqL1xuICBlbGlnaWJsZSgpOiBHcm91cE1lbWJlckNhbmRpZGF0ZVtdIHtcbiAgICBjb25zdCBjdXJyZW50ID0gbmV3IFNldCh0aGlzLm1lbWJlcnMubWFwKChtKSA9PiBtLnVzZXJJZCkpO1xuICAgIHJldHVybiB0aGlzLmNhbmRpZGF0ZXMuZmlsdGVyKChjKSA9PiAhY3VycmVudC5oYXMoYy51c2VySWQpKTtcbiAgfVxuXG4gIG5hbWVGb3IodXNlcklkOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGMgPSB0aGlzLmNhbmRpZGF0ZXMuZmluZCgoeCkgPT4geC51c2VySWQgPT09IHVzZXJJZCk7XG4gICAgcmV0dXJuIGM/Lm5hbWUgfHwgYz8uZW1haWwgfHwgdXNlcklkO1xuICB9XG5cbiAgYWRkKHVzZXJJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCF1c2VySWQgfHwgdGhpcy5idXN5KSByZXR1cm47XG4gICAgdGhpcy5idXN5ID0gdHJ1ZTtcbiAgICB0aGlzLmdyb3Vwc1N2Yy5hZGRNZW1iZXIodGhpcy5ncm91cElkLCB7IHVzZXJJZCB9KS5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKG1lbWJlcnMpID0+IHtcbiAgICAgICAgdGhpcy5tZW1iZXJzID0gbWVtYmVycztcbiAgICAgICAgdGhpcy5idXN5ID0gZmFsc2U7XG4gICAgICAgIHRoaXMubWVtYmVyc0NoYW5nZS5lbWl0KG1lbWJlcnMpO1xuICAgICAgfSxcbiAgICAgIGVycm9yOiAoKSA9PiAodGhpcy5idXN5ID0gZmFsc2UpLFxuICAgIH0pO1xuICB9XG5cbiAgcmVtb3ZlKHVzZXJJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuYnVzeSkgcmV0dXJuO1xuICAgIHRoaXMuYnVzeSA9IHRydWU7XG4gICAgdGhpcy5ncm91cHNTdmMucmVtb3ZlTWVtYmVyKHRoaXMuZ3JvdXBJZCwgdXNlcklkKS5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKG1lbWJlcnMpID0+IHtcbiAgICAgICAgdGhpcy5tZW1iZXJzID0gbWVtYmVycztcbiAgICAgICAgdGhpcy5idXN5ID0gZmFsc2U7XG4gICAgICAgIHRoaXMubWVtYmVyc0NoYW5nZS5lbWl0KG1lbWJlcnMpO1xuICAgICAgfSxcbiAgICAgIGVycm9yOiAoKSA9PiAodGhpcy5idXN5ID0gZmFsc2UpLFxuICAgIH0pO1xuICB9XG59XG4iXX0=