@cqa-lib/cqa-ui 1.1.522 → 1.1.524

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 (26) hide show
  1. package/esm2020/lib/assign-environments-dialog/assign-environments-dialog.component.mjs +155 -0
  2. package/esm2020/lib/assign-environments-dialog/assign-environments-dialog.models.mjs +2 -0
  3. package/esm2020/lib/new-environment-dialog/new-environment-dialog.component.mjs +123 -0
  4. package/esm2020/lib/new-environment-dialog/new-environment-dialog.models.mjs +9 -0
  5. package/esm2020/lib/new-environment-variable-dialog/new-environment-variable-dialog.component.mjs +190 -0
  6. package/esm2020/lib/new-environment-variable-dialog/new-environment-variable-dialog.models.mjs +2 -0
  7. package/esm2020/lib/new-test-data-profile-dialog/new-test-data-profile-dialog.component.mjs +188 -0
  8. package/esm2020/lib/new-test-data-profile-dialog/new-test-data-profile-dialog.models.mjs +2 -0
  9. package/esm2020/lib/ui-kit.module.mjs +21 -1
  10. package/esm2020/public-api.mjs +9 -1
  11. package/fesm2015/cqa-lib-cqa-ui.mjs +669 -1
  12. package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
  13. package/fesm2020/cqa-lib-cqa-ui.mjs +657 -1
  14. package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
  15. package/lib/assign-environments-dialog/assign-environments-dialog.component.d.ts +36 -0
  16. package/lib/assign-environments-dialog/assign-environments-dialog.models.d.ts +19 -0
  17. package/lib/new-environment-dialog/new-environment-dialog.component.d.ts +37 -0
  18. package/lib/new-environment-dialog/new-environment-dialog.models.d.ts +14 -0
  19. package/lib/new-environment-variable-dialog/new-environment-variable-dialog.component.d.ts +54 -0
  20. package/lib/new-environment-variable-dialog/new-environment-variable-dialog.models.d.ts +14 -0
  21. package/lib/new-test-data-profile-dialog/new-test-data-profile-dialog.component.d.ts +43 -0
  22. package/lib/new-test-data-profile-dialog/new-test-data-profile-dialog.models.d.ts +20 -0
  23. package/lib/ui-kit.module.d.ts +92 -88
  24. package/package.json +1 -1
  25. package/public-api.d.ts +8 -0
  26. package/styles.css +1 -1
@@ -0,0 +1,155 @@
1
+ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
2
+ import { FormControl, FormGroup } from '@angular/forms';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "../dynamic-select/dynamic-select-field.component";
5
+ import * as i2 from "@angular/common";
6
+ export class AssignEnvironmentsDialogComponent {
7
+ constructor(cdr) {
8
+ this.cdr = cdr;
9
+ this.mode = 'assign';
10
+ this.profileName = '';
11
+ this.environments = [];
12
+ this.assignedEnvironments = [];
13
+ this.selected = new Set();
14
+ this.sourceForm = new FormGroup({
15
+ sourceEnvId: new FormControl(null),
16
+ });
17
+ this.sourceConfig = this.buildSourceConfig([]);
18
+ this.sourceError = null;
19
+ }
20
+ ngOnInit() {
21
+ // Source picker appears in both modes when there are already-attached envs
22
+ // to copy from. In clone mode it's required; in assign mode it's optional
23
+ // (falling back to the base profile rows when no source is picked).
24
+ if (this.showSourcePicker) {
25
+ const initial = this.defaultSourceEnvId != null
26
+ ? this.defaultSourceEnvId
27
+ : (this.mode === 'clone' && this.assignedEnvironments && this.assignedEnvironments.length
28
+ ? this.assignedEnvironments[0].id
29
+ : null);
30
+ this.sourceForm.get('sourceEnvId').setValue(initial);
31
+ this.sourceConfig = this.buildSourceConfig(this.assignedEnvironments ?? []);
32
+ }
33
+ }
34
+ get showSourcePicker() {
35
+ return (this.assignedEnvironments && this.assignedEnvironments.length > 0);
36
+ }
37
+ get sourceLabel() {
38
+ return this.mode === 'clone' ? 'Copy from which environment' : 'Copy rows from (optional)';
39
+ }
40
+ get sourceHelper() {
41
+ if (this.sourceError) {
42
+ return this.sourceError;
43
+ }
44
+ return this.mode === 'clone'
45
+ ? "The selected environment's rows will be copied into each target environment below."
46
+ : 'Pick an environment to copy its rows into the new ones. Leave blank to seed with the base profile rows.';
47
+ }
48
+ get title() {
49
+ return this.mode === 'clone' ? 'Clone to other environments' : 'Assign to environments';
50
+ }
51
+ get subtitle() {
52
+ const name = this.profileName ? `"${this.profileName}"` : 'this profile';
53
+ return this.mode === 'clone'
54
+ ? `Duplicate ${name} into other environments. Column structure is shared; row values are independent per environment.`
55
+ : `Make ${name} available in the selected environments. Columns are shared — each environment gets an independent row set.`;
56
+ }
57
+ get primaryButtonLabel() {
58
+ const count = this.selected.size;
59
+ const verb = this.mode === 'clone' ? 'Clone to' : 'Assign to';
60
+ return `${verb} ${count} environment${count === 1 ? '' : 's'}`;
61
+ }
62
+ get primaryDisabled() {
63
+ if (this.selected.size === 0) {
64
+ return true;
65
+ }
66
+ if (this.mode === 'clone' && this.sourceForm.get('sourceEnvId').value == null) {
67
+ return true;
68
+ }
69
+ return false;
70
+ }
71
+ get selectableEnvironments() {
72
+ return this.environments ?? [];
73
+ }
74
+ get hasAnySelectable() {
75
+ return (this.environments ?? []).some(e => !e.alreadyAssigned);
76
+ }
77
+ get sourceValue() {
78
+ return this.sourceForm.get('sourceEnvId').value ?? null;
79
+ }
80
+ isSelected(id) {
81
+ return this.selected.has(id);
82
+ }
83
+ toggle(env) {
84
+ if (env.alreadyAssigned) {
85
+ return;
86
+ }
87
+ if (this.selected.has(env.id)) {
88
+ this.selected.delete(env.id);
89
+ }
90
+ else {
91
+ this.selected.add(env.id);
92
+ }
93
+ this.cdr.markForCheck();
94
+ }
95
+ helperFor(env) {
96
+ if (env.alreadyAssigned) {
97
+ return 'Already assigned to this environment';
98
+ }
99
+ return env.description || '';
100
+ }
101
+ getValue() {
102
+ if (this.selected.size === 0) {
103
+ return null;
104
+ }
105
+ const src = this.sourceValue;
106
+ if (this.mode === 'clone') {
107
+ if (src == null) {
108
+ this.sourceError = 'Pick the environment whose rows should be copied.';
109
+ this.cdr.markForCheck();
110
+ return null;
111
+ }
112
+ this.sourceError = null;
113
+ return { selectedIds: Array.from(this.selected), sourceEnvId: Number(src) };
114
+ }
115
+ // Assign mode: source is optional — include it when the user picked one.
116
+ this.sourceError = null;
117
+ return src != null
118
+ ? { selectedIds: Array.from(this.selected), sourceEnvId: Number(src) }
119
+ : { selectedIds: Array.from(this.selected) };
120
+ }
121
+ buildSourceConfig(envs) {
122
+ const options = (envs || []).map(e => ({
123
+ id: e.id,
124
+ value: e.id,
125
+ name: e.name,
126
+ label: e.name,
127
+ statusColor: e.color,
128
+ }));
129
+ return {
130
+ key: 'sourceEnvId',
131
+ label: '',
132
+ placeholder: 'Select source environment…',
133
+ multiple: false,
134
+ searchable: true,
135
+ options,
136
+ };
137
+ }
138
+ }
139
+ AssignEnvironmentsDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: AssignEnvironmentsDialogComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
140
+ AssignEnvironmentsDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: AssignEnvironmentsDialogComponent, selector: "cqa-assign-environments-dialog", inputs: { mode: "mode", profileName: "profileName", environments: "environments", assignedEnvironments: "assignedEnvironments", defaultSourceEnvId: "defaultSourceEnvId" }, host: { styleAttribute: "display:block;width:100%;", classAttribute: "cqa-ui-root" }, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-w-full\">\n\n <!-- Source env picker: required in clone mode, optional in assign mode -->\n <div *ngIf=\"showSourcePicker\" class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700\">{{ sourceLabel }}</label>\n <cqa-dynamic-select\n [form]=\"sourceForm\"\n [config]=\"sourceConfig\">\n </cqa-dynamic-select>\n <span [class.cqa-text-red-600]=\"sourceError\" [class.cqa-text-gray-500]=\"!sourceError\" class=\"cqa-text-xs\">\n {{ sourceHelper }}\n </span>\n </div>\n\n <!-- Selectable envs -->\n <div\n *ngIf=\"hasAnySelectable || (environments?.length || 0) > 0\"\n class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-max-h-[340px] cqa-overflow-y-auto\">\n <label\n *ngFor=\"let env of selectableEnvironments\"\n class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-px-3 cqa-py-2.5 cqa-border cqa-rounded-[10px] cqa-bg-white cqa-transition-colors\"\n [class.cqa-border-gray-200]=\"!isSelected(env.id) && !env.alreadyAssigned\"\n [class.hover:cqa-border-indigo-200]=\"!env.alreadyAssigned && !isSelected(env.id)\"\n [class.cqa-border-indigo-400]=\"isSelected(env.id)\"\n [class.cqa-bg-indigo-50]=\"isSelected(env.id)\"\n [class.cqa-opacity-50]=\"env.alreadyAssigned\"\n [class.cqa-cursor-pointer]=\"!env.alreadyAssigned\"\n [class.cqa-cursor-not-allowed]=\"env.alreadyAssigned\"\n (click)=\"toggle(env)\">\n <input\n type=\"checkbox\"\n class=\"cqa-w-4 cqa-h-4 cqa-cursor-pointer\"\n [checked]=\"isSelected(env.id)\"\n [disabled]=\"!!env.alreadyAssigned\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggle(env)\" />\n\n <span\n class=\"cqa-inline-block cqa-w-2 cqa-h-2 cqa-rounded-full cqa-flex-none\"\n [style.background]=\"env.color || '#3F43EE'\"></span>\n\n <div class=\"cqa-flex cqa-flex-col cqa-min-w-0 cqa-flex-1\">\n <div class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">{{ env.name }}</div>\n <div *ngIf=\"helperFor(env)\" class=\"cqa-text-xs cqa-text-gray-500 cqa-leading-[1.4]\">{{ helperFor(env) }}</div>\n </div>\n </label>\n </div>\n\n <div\n *ngIf=\"(environments?.length || 0) === 0\"\n class=\"cqa-py-8 cqa-px-4 cqa-text-center cqa-text-sm cqa-text-gray-500\">\n All environments are already assigned to this profile.\n </div>\n</div>\n", components: [{ type: i1.DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore", "addCustomValue"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
141
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: AssignEnvironmentsDialogComponent, decorators: [{
142
+ type: Component,
143
+ args: [{ selector: 'cqa-assign-environments-dialog', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'cqa-ui-root', style: 'display:block;width:100%;' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-w-full\">\n\n <!-- Source env picker: required in clone mode, optional in assign mode -->\n <div *ngIf=\"showSourcePicker\" class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700\">{{ sourceLabel }}</label>\n <cqa-dynamic-select\n [form]=\"sourceForm\"\n [config]=\"sourceConfig\">\n </cqa-dynamic-select>\n <span [class.cqa-text-red-600]=\"sourceError\" [class.cqa-text-gray-500]=\"!sourceError\" class=\"cqa-text-xs\">\n {{ sourceHelper }}\n </span>\n </div>\n\n <!-- Selectable envs -->\n <div\n *ngIf=\"hasAnySelectable || (environments?.length || 0) > 0\"\n class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-max-h-[340px] cqa-overflow-y-auto\">\n <label\n *ngFor=\"let env of selectableEnvironments\"\n class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-px-3 cqa-py-2.5 cqa-border cqa-rounded-[10px] cqa-bg-white cqa-transition-colors\"\n [class.cqa-border-gray-200]=\"!isSelected(env.id) && !env.alreadyAssigned\"\n [class.hover:cqa-border-indigo-200]=\"!env.alreadyAssigned && !isSelected(env.id)\"\n [class.cqa-border-indigo-400]=\"isSelected(env.id)\"\n [class.cqa-bg-indigo-50]=\"isSelected(env.id)\"\n [class.cqa-opacity-50]=\"env.alreadyAssigned\"\n [class.cqa-cursor-pointer]=\"!env.alreadyAssigned\"\n [class.cqa-cursor-not-allowed]=\"env.alreadyAssigned\"\n (click)=\"toggle(env)\">\n <input\n type=\"checkbox\"\n class=\"cqa-w-4 cqa-h-4 cqa-cursor-pointer\"\n [checked]=\"isSelected(env.id)\"\n [disabled]=\"!!env.alreadyAssigned\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggle(env)\" />\n\n <span\n class=\"cqa-inline-block cqa-w-2 cqa-h-2 cqa-rounded-full cqa-flex-none\"\n [style.background]=\"env.color || '#3F43EE'\"></span>\n\n <div class=\"cqa-flex cqa-flex-col cqa-min-w-0 cqa-flex-1\">\n <div class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">{{ env.name }}</div>\n <div *ngIf=\"helperFor(env)\" class=\"cqa-text-xs cqa-text-gray-500 cqa-leading-[1.4]\">{{ helperFor(env) }}</div>\n </div>\n </label>\n </div>\n\n <div\n *ngIf=\"(environments?.length || 0) === 0\"\n class=\"cqa-py-8 cqa-px-4 cqa-text-center cqa-text-sm cqa-text-gray-500\">\n All environments are already assigned to this profile.\n </div>\n</div>\n" }]
144
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { mode: [{
145
+ type: Input
146
+ }], profileName: [{
147
+ type: Input
148
+ }], environments: [{
149
+ type: Input
150
+ }], assignedEnvironments: [{
151
+ type: Input
152
+ }], defaultSourceEnvId: [{
153
+ type: Input
154
+ }] } });
155
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzaWduLWVudmlyb25tZW50cy1kaWFsb2cuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9hc3NpZ24tZW52aXJvbm1lbnRzLWRpYWxvZy9hc3NpZ24tZW52aXJvbm1lbnRzLWRpYWxvZy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2Fzc2lnbi1lbnZpcm9ubWVudHMtZGlhbG9nL2Fzc2lnbi1lbnZpcm9ubWVudHMtZGlhbG9nLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBcUIsU0FBUyxFQUFFLEtBQUssRUFBVSxNQUFNLGVBQWUsQ0FBQztBQUNyRyxPQUFPLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7O0FBa0J4RCxNQUFNLE9BQU8saUNBQWlDO0lBZ0I1QyxZQUE2QixHQUFzQjtRQUF0QixRQUFHLEdBQUgsR0FBRyxDQUFtQjtRQWYxQyxTQUFJLEdBQTJCLFFBQVEsQ0FBQztRQUN4QyxnQkFBVyxHQUFXLEVBQUUsQ0FBQztRQUN6QixpQkFBWSxHQUE4QixFQUFFLENBQUM7UUFDN0MseUJBQW9CLEdBQThCLEVBQUUsQ0FBQztRQUc5QyxhQUFRLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUU3QixlQUFVLEdBQUcsSUFBSSxTQUFTLENBQUM7WUFDekMsV0FBVyxFQUFFLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQztTQUNuQyxDQUFDLENBQUM7UUFDSSxpQkFBWSxHQUE2QixJQUFJLENBQUMsaUJBQWlCLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFcEUsZ0JBQVcsR0FBa0IsSUFBSSxDQUFDO0lBRWEsQ0FBQztJQUV2RCxRQUFRO1FBQ04sMkVBQTJFO1FBQzNFLDBFQUEwRTtRQUMxRSxvRUFBb0U7UUFDcEUsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7WUFD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QUFHLEVBQUUsYUFBYTtZQUNsQixLQUFLLEVBQUUsRUFBRTtZQUNULFdBQVcsRUFBRSw0QkFBNEI7WUFDekMsUUFBUSxFQUFFLEtBQUs7WUFDZixVQUFVLEVBQUUsSUFBSTtZQUNoQixPQUFPO1NBQ1IsQ0FBQztJQUNKLENBQUM7OzhIQXpJVSxpQ0FBaUM7a0hBQWpDLGlDQUFpQyx3VUNuQjlDLHE1RUFzREE7MkZEbkNhLGlDQUFpQztrQkFON0MsU0FBUzsrQkFDRSxnQ0FBZ0MsbUJBRXpCLHVCQUF1QixDQUFDLE1BQU0sUUFDekMsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSwyQkFBMkIsRUFBRTt3R0FHekQsSUFBSTtzQkFBWixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBQ0csa0JBQWtCO3NCQUExQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIElucHV0LCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Db250cm9sLCBGb3JtR3JvdXAgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7XG4gIER5bmFtaWNTZWxlY3RGaWVsZENvbmZpZyxcbiAgU2VsZWN0T3B0aW9uLFxufSBmcm9tICcuLi9keW5hbWljLXNlbGVjdC9keW5hbWljLXNlbGVjdC1maWVsZC5jb21wb25lbnQnO1xuaW1wb3J0IHtcbiAgQXNzaWduRW52aXJvbm1lbnRPcHRpb24sXG4gIEFzc2lnbkVudmlyb25tZW50c0RpYWxvZ1ZhbHVlLFxuICBBc3NpZ25FbnZpcm9ubWVudHNNb2RlLFxufSBmcm9tICcuL2Fzc2lnbi1lbnZpcm9ubWVudHMtZGlhbG9nLm1vZGVscyc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2NxYS1hc3NpZ24tZW52aXJvbm1lbnRzLWRpYWxvZycsXG4gIHRlbXBsYXRlVXJsOiAnLi9hc3NpZ24tZW52aXJvbm1lbnRzLWRpYWxvZy5jb21wb25lbnQuaHRtbCcsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBob3N0OiB7IGNsYXNzOiAnY3FhLXVpLXJvb3QnLCBzdHlsZTogJ2Rpc3BsYXk6YmxvY2s7d2lkdGg6MTAwJTsnIH0sXG59KVxuZXhwb3J0IGNsYXNzIEFzc2lnbkVudmlyb25tZW50c0RpYWxvZ0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIEBJbnB1dCgpIG1vZGU6IEFzc2lnbkVudmlyb25tZW50c01vZGUgPSAnYXNzaWduJztcbiAgQElucHV0KCkgcHJvZmlsZU5hbWU6IHN0cmluZyA9ICcnO1xuICBASW5wdXQoKSBlbnZpcm9ubWVudHM6IEFzc2lnbkVudmlyb25tZW50T3B0aW9uW10gPSBbXTtcbiAgQElucHV0KCkgYXNzaWduZWRFbnZpcm9ubWVudHM6IEFzc2lnbkVudmlyb25tZW50T3B0aW9uW10gPSBbXTtcbiAgQElucHV0KCkgZGVmYXVsdFNvdXJjZUVudklkPzogbnVtYmVyO1xuXG4gIHB1YmxpYyByZWFkb25seSBzZWxlY3RlZCA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuXG4gIHB1YmxpYyByZWFkb25seSBzb3VyY2VGb3JtID0gbmV3IEZvcm1Hcm91cCh7XG4gICAgc291cmNlRW52SWQ6IG5ldyBGb3JtQ29udHJvbChudWxsKSxcbiAgfSk7XG4gIHB1YmxpYyBzb3VyY2VDb25maWc6IER5bmFtaWNTZWxlY3RGaWVsZENvbmZpZyA9IHRoaXMuYnVpbGRTb3VyY2VDb25maWcoW10pO1xuXG4gIHB1YmxpYyBzb3VyY2VFcnJvcjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBjZHI6IENoYW5nZURldGVjdG9yUmVmKSB7fVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIC8vIFNvdXJjZSBwaWNrZXIgYXBwZWFycyBpbiBib3RoIG1vZGVzIHdoZW4gdGhlcmUgYXJlIGFscmVhZHktYXR0YWNoZWQgZW52c1xuICAgIC8vIHRvIGNvcHkgZnJvbS4gSW4gY2xvbmUgbW9kZSBpdCdzIHJlcXVpcmVkOyBpbiBhc3NpZ24gbW9kZSBpdCdzIG9wdGlvbmFsXG4gICAgLy8gKGZhbGxpbmcgYmFjayB0byB0aGUgYmFzZSBwcm9maWxlIHJvd3Mgd2hlbiBubyBzb3VyY2UgaXMgcGlja2VkKS5cbiAgICBpZiAodGhpcy5zaG93U291cmNlUGlja2VyKSB7XG4gICAgICBjb25zdCBpbml0aWFsID0gdGhpcy5kZWZhdWx0U291cmNlRW52SWQgIT0gbnVsbFxuICAgICAgICA/IHRoaXMuZGVmYXVsdFNvdXJjZUVudklkXG4gICAgICAgIDogKHRoaXMubW9kZSA9PT0gJ2Nsb25lJyAmJiB0aGlzLmFzc2lnbmVkRW52aXJvbm1lbnRzICYmIHRoaXMuYXNzaWduZWRFbnZpcm9ubWVudHMubGVuZ3RoXG4gICAgICAgICAgPyB0aGlzLmFzc2lnbmVkRW52aXJvbm1lbnRzWzBdLmlkXG4gICAgICAgICAgOiBudWxsKTtcbiAgICAgIHRoaXMuc291cmNlRm9ybS5nZXQoJ3NvdXJjZUVudklkJykhLnNldFZhbHVlKGluaXRpYWwpO1xuICAgICAgdGhpcy5zb3VyY2VDb25maWcgPSB0aGlzLmJ1aWxkU291cmNlQ29uZmlnKHRoaXMuYXNzaWduZWRFbnZpcm9ubWVudHMgPz8gW10pO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXQgc2hvd1NvdXJjZVBpY2tlcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKHRoaXMuYXNzaWduZWRFbnZpcm9ubWVudHMgJiYgdGhpcy5hc3NpZ25lZEVudmlyb25tZW50cy5sZW5ndGggPiAwKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgc291cmNlTGFiZWwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5tb2RlID09PSAnY2xvbmUnID8gJ0NvcHkgZnJvbSB3aGljaCBlbnZpcm9ubWVudCcgOiAnQ29weSByb3dzIGZyb20gKG9wdGlvbmFsKSc7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHNvdXJjZUhlbHBlcigpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLnNvdXJjZUVycm9yKSB7IHJldHVybiB0aGlzLnNvdXJjZUVycm9yOyB9XG4gICAgcmV0dXJuIHRoaXMubW9kZSA9PT0gJ2Nsb25lJ1xuICAgICAgPyBcIlRoZSBzZWxlY3RlZCBlbnZpcm9ubWVudCdzIHJvd3Mgd2lsbCBiZSBjb3BpZWQgaW50byBlYWNoIHRhcmdldCBlbnZpcm9ubWVudCBiZWxvdy5cIlxuICAgICAgOiAnUGljayBhbiBlbnZpcm9ubWVudCB0byBjb3B5IGl0cyByb3dzIGludG8gdGhlIG5ldyBvbmVzLiBMZWF2ZSBibGFuayB0byBzZWVkIHdpdGggdGhlIGJhc2UgcHJvZmlsZSByb3dzLic7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHRpdGxlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMubW9kZSA9PT0gJ2Nsb25lJyA/ICdDbG9uZSB0byBvdGhlciBlbnZpcm9ubWVudHMnIDogJ0Fzc2lnbiB0byBlbnZpcm9ubWVudHMnO1xuICB9XG5cbiAgcHVibGljIGdldCBzdWJ0aXRsZSgpOiBzdHJpbmcge1xuICAgIGNvbnN0IG5hbWUgPSB0aGlzLnByb2ZpbGVOYW1lID8gYFwiJHt0aGlzLnByb2ZpbGVOYW1lfVwiYCA6ICd0aGlzIHByb2ZpbGUnO1xuICAgIHJldHVybiB0aGlzLm1vZGUgPT09ICdjbG9uZSdcbiAgICAgID8gYER1cGxpY2F0ZSAke25hbWV9IGludG8gb3RoZXIgZW52aXJvbm1lbnRzLiBDb2x1bW4gc3RydWN0dXJlIGlzIHNoYXJlZDsgcm93IHZhbHVlcyBhcmUgaW5kZXBlbmRlbnQgcGVyIGVudmlyb25tZW50LmBcbiAgICAgIDogYE1ha2UgJHtuYW1lfSBhdmFpbGFibGUgaW4gdGhlIHNlbGVjdGVkIGVudmlyb25tZW50cy4gQ29sdW1ucyBhcmUgc2hhcmVkIOKAlCBlYWNoIGVudmlyb25tZW50IGdldHMgYW4gaW5kZXBlbmRlbnQgcm93IHNldC5gO1xuICB9XG5cbiAgcHVibGljIGdldCBwcmltYXJ5QnV0dG9uTGFiZWwoKTogc3RyaW5nIHtcbiAgICBjb25zdCBjb3VudCA9IHRoaXMuc2VsZWN0ZWQuc2l6ZTtcbiAgICBjb25zdCB2ZXJiID0gdGhpcy5tb2RlID09PSAnY2xvbmUnID8gJ0Nsb25lIHRvJyA6ICdBc3NpZ24gdG8nO1xuICAgIHJldHVybiBgJHt2ZXJifSAke2NvdW50fSBlbnZpcm9ubWVudCR7Y291bnQgPT09IDEgPyAnJyA6ICdzJ31gO1xuICB9XG5cbiAgcHVibGljIGdldCBwcmltYXJ5RGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuc2VsZWN0ZWQuc2l6ZSA9PT0gMCkgeyByZXR1cm4gdHJ1ZTsgfVxuICAgIGlmICh0aGlzLm1vZGUgPT09ICdjbG9uZScgJiYgdGhpcy5zb3VyY2VGb3JtLmdldCgnc291cmNlRW52SWQnKSEudmFsdWUgPT0gbnVsbCkgeyByZXR1cm4gdHJ1ZTsgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgc2VsZWN0YWJsZUVudmlyb25tZW50cygpOiBBc3NpZ25FbnZpcm9ubWVudE9wdGlvbltdIHtcbiAgICByZXR1cm4gdGhpcy5lbnZpcm9ubWVudHMgPz8gW107XG4gIH1cblxuICBwdWJsaWMgZ2V0IGhhc0FueVNlbGVjdGFibGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICh0aGlzLmVudmlyb25tZW50cyA/PyBbXSkuc29tZShlID0+ICFlLmFscmVhZHlBc3NpZ25lZCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHNvdXJjZVZhbHVlKCk6IG51bWJlciB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnNvdXJjZUZvcm0uZ2V0KCdzb3VyY2VFbnZJZCcpIS52YWx1ZSA/PyBudWxsO1xuICB9XG5cbiAgcHVibGljIGlzU2VsZWN0ZWQoaWQ6IG51bWJlcik6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdGVkLmhhcyhpZCk7XG4gIH1cblxuICBwdWJsaWMgdG9nZ2xlKGVudjogQXNzaWduRW52aXJvbm1lbnRPcHRpb24pOiB2b2lkIHtcbiAgICBpZiAoZW52LmFscmVhZHlBc3NpZ25lZCkgeyByZXR1cm47IH1cbiAgICBpZiAodGhpcy5zZWxlY3RlZC5oYXMoZW52LmlkKSkge1xuICAgICAgdGhpcy5zZWxlY3RlZC5kZWxldGUoZW52LmlkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zZWxlY3RlZC5hZGQoZW52LmlkKTtcbiAgICB9XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBwdWJsaWMgaGVscGVyRm9yKGVudjogQXNzaWduRW52aXJvbm1lbnRPcHRpb24pOiBzdHJpbmcge1xuICAgIGlmIChlbnYuYWxyZWFkeUFzc2lnbmVkKSB7IHJldHVybiAnQWxyZWFkeSBhc3NpZ25lZCB0byB0aGlzIGVudmlyb25tZW50JzsgfVxuICAgIHJldHVybiBlbnYuZGVzY3JpcHRpb24gfHwgJyc7XG4gIH1cblxuICBwdWJsaWMgZ2V0VmFsdWUoKTogQXNzaWduRW52aXJvbm1lbnRzRGlhbG9nVmFsdWUgfCBudWxsIHtcbiAgICBpZiAodGhpcy5zZWxlY3RlZC5zaXplID09PSAwKSB7IHJldHVybiBudWxsOyB9XG4gICAgY29uc3Qgc3JjID0gdGhpcy5zb3VyY2VWYWx1ZTtcbiAgICBpZiAodGhpcy5tb2RlID09PSAnY2xvbmUnKSB7XG4gICAgICBpZiAoc3JjID09IG51bGwpIHtcbiAgICAgICAgdGhpcy5zb3VyY2VFcnJvciA9ICdQaWNrIHRoZSBlbnZpcm9ubWVudCB3aG9zZSByb3dzIHNob3VsZCBiZSBjb3BpZWQuJztcbiAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgdGhpcy5zb3VyY2VFcnJvciA9IG51bGw7XG4gICAgICByZXR1cm4geyBzZWxlY3RlZElkczogQXJyYXkuZnJvbSh0aGlzLnNlbGVjdGVkKSwgc291cmNlRW52SWQ6IE51bWJlcihzcmMpIH07XG4gICAgfVxuICAgIC8vIEFzc2lnbiBtb2RlOiBzb3VyY2UgaXMgb3B0aW9uYWwg4oCUIGluY2x1ZGUgaXQgd2hlbiB0aGUgdXNlciBwaWNrZWQgb25lLlxuICAgIHRoaXMuc291cmNlRXJyb3IgPSBudWxsO1xuICAgIHJldHVybiBzcmMgIT0gbnVsbFxuICAgICAgPyB7IHNlbGVjdGVkSWRzOiBBcnJheS5mcm9tKHRoaXMuc2VsZWN0ZWQpLCBzb3VyY2VFbnZJZDogTnVtYmVyKHNyYykgfVxuICAgICAgOiB7IHNlbGVjdGVkSWRzOiBBcnJheS5mcm9tKHRoaXMuc2VsZWN0ZWQpIH07XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkU291cmNlQ29uZmlnKGVudnM6IEFzc2lnbkVudmlyb25tZW50T3B0aW9uW10pOiBEeW5hbWljU2VsZWN0RmllbGRDb25maWcge1xuICAgIGNvbnN0IG9wdGlvbnM6IFNlbGVjdE9wdGlvbltdID0gKGVudnMgfHwgW10pLm1hcChlID0+ICh7XG4gICAgICBpZDogZS5pZCxcbiAgICAgIHZhbHVlOiBlLmlkLFxuICAgICAgbmFtZTogZS5uYW1lLFxuICAgICAgbGFiZWw6IGUubmFtZSxcbiAgICAgIHN0YXR1c0NvbG9yOiBlLmNvbG9yLFxuICAgIH0pKTtcbiAgICByZXR1cm4ge1xuICAgICAga2V5OiAnc291cmNlRW52SWQnLFxuICAgICAgbGFiZWw6ICcnLFxuICAgICAgcGxhY2Vob2xkZXI6ICdTZWxlY3Qgc291cmNlIGVudmlyb25tZW504oCmJyxcbiAgICAgIG11bHRpcGxlOiBmYWxzZSxcbiAgICAgIHNlYXJjaGFibGU6IHRydWUsXG4gICAgICBvcHRpb25zLFxuICAgIH07XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtZmxleC1jb2wgY3FhLWdhcC00IGNxYS13LWZ1bGxcIj5cblxuICA8IS0tIFNvdXJjZSBlbnYgcGlja2VyOiByZXF1aXJlZCBpbiBjbG9uZSBtb2RlLCBvcHRpb25hbCBpbiBhc3NpZ24gbW9kZSAtLT5cbiAgPGRpdiAqbmdJZj1cInNob3dTb3VyY2VQaWNrZXJcIiBjbGFzcz1cImNxYS1mbGV4IGNxYS1mbGV4LWNvbCBjcWEtZ2FwLTJcIj5cbiAgICA8bGFiZWwgY2xhc3M9XCJjcWEtdGV4dC1zbSBjcWEtZm9udC1tZWRpdW0gY3FhLXRleHQtZ3JheS03MDBcIj57eyBzb3VyY2VMYWJlbCB9fTwvbGFiZWw+XG4gICAgPGNxYS1keW5hbWljLXNlbGVjdFxuICAgICAgW2Zvcm1dPVwic291cmNlRm9ybVwiXG4gICAgICBbY29uZmlnXT1cInNvdXJjZUNvbmZpZ1wiPlxuICAgIDwvY3FhLWR5bmFtaWMtc2VsZWN0PlxuICAgIDxzcGFuIFtjbGFzcy5jcWEtdGV4dC1yZWQtNjAwXT1cInNvdXJjZUVycm9yXCIgW2NsYXNzLmNxYS10ZXh0LWdyYXktNTAwXT1cIiFzb3VyY2VFcnJvclwiIGNsYXNzPVwiY3FhLXRleHQteHNcIj5cbiAgICAgIHt7IHNvdXJjZUhlbHBlciB9fVxuICAgIDwvc3Bhbj5cbiAgPC9kaXY+XG5cbiAgPCEtLSBTZWxlY3RhYmxlIGVudnMgLS0+XG4gIDxkaXZcbiAgICAqbmdJZj1cImhhc0FueVNlbGVjdGFibGUgfHwgKGVudmlyb25tZW50cz8ubGVuZ3RoIHx8IDApID4gMFwiXG4gICAgY2xhc3M9XCJjcWEtZmxleCBjcWEtZmxleC1jb2wgY3FhLWdhcC0yIGNxYS1tYXgtaC1bMzQwcHhdIGNxYS1vdmVyZmxvdy15LWF1dG9cIj5cbiAgICA8bGFiZWxcbiAgICAgICpuZ0Zvcj1cImxldCBlbnYgb2Ygc2VsZWN0YWJsZUVudmlyb25tZW50c1wiXG4gICAgICBjbGFzcz1cImNxYS1mbGV4IGNxYS1pdGVtcy1jZW50ZXIgY3FhLWdhcC0zIGNxYS1weC0zIGNxYS1weS0yLjUgY3FhLWJvcmRlciBjcWEtcm91bmRlZC1bMTBweF0gY3FhLWJnLXdoaXRlIGNxYS10cmFuc2l0aW9uLWNvbG9yc1wiXG4gICAgICBbY2xhc3MuY3FhLWJvcmRlci1ncmF5LTIwMF09XCIhaXNTZWxlY3RlZChlbnYuaWQpICYmICFlbnYuYWxyZWFkeUFzc2lnbmVkXCJcbiAgICAgIFtjbGFzcy5ob3ZlcjpjcWEtYm9yZGVyLWluZGlnby0yMDBdPVwiIWVudi5hbHJlYWR5QXNzaWduZWQgJiYgIWlzU2VsZWN0ZWQoZW52LmlkKVwiXG4gICAgICBbY2xhc3MuY3FhLWJvcmRlci1pbmRpZ28tNDAwXT1cImlzU2VsZWN0ZWQoZW52LmlkKVwiXG4gICAgICBbY2xhc3MuY3FhLWJnLWluZGlnby01MF09XCJpc1NlbGVjdGVkKGVudi5pZClcIlxuICAgICAgW2NsYXNzLmNxYS1vcGFjaXR5LTUwXT1cImVudi5hbHJlYWR5QXNzaWduZWRcIlxuICAgICAgW2NsYXNzLmNxYS1jdXJzb3ItcG9pbnRlcl09XCIhZW52LmFscmVhZHlBc3NpZ25lZFwiXG4gICAgICBbY2xhc3MuY3FhLWN1cnNvci1ub3QtYWxsb3dlZF09XCJlbnYuYWxyZWFkeUFzc2lnbmVkXCJcbiAgICAgIChjbGljayk9XCJ0b2dnbGUoZW52KVwiPlxuICAgICAgPGlucHV0XG4gICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgIGNsYXNzPVwiY3FhLXctNCBjcWEtaC00IGNxYS1jdXJzb3ItcG9pbnRlclwiXG4gICAgICAgIFtjaGVja2VkXT1cImlzU2VsZWN0ZWQoZW52LmlkKVwiXG4gICAgICAgIFtkaXNhYmxlZF09XCIhIWVudi5hbHJlYWR5QXNzaWduZWRcIlxuICAgICAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcbiAgICAgICAgKGNoYW5nZSk9XCJ0b2dnbGUoZW52KVwiIC8+XG5cbiAgICAgIDxzcGFuXG4gICAgICAgIGNsYXNzPVwiY3FhLWlubGluZS1ibG9jayBjcWEtdy0yIGNxYS1oLTIgY3FhLXJvdW5kZWQtZnVsbCBjcWEtZmxleC1ub25lXCJcbiAgICAgICAgW3N0eWxlLmJhY2tncm91bmRdPVwiZW52LmNvbG9yIHx8ICcjM0Y0M0VFJ1wiPjwvc3Bhbj5cblxuICAgICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1mbGV4LWNvbCBjcWEtbWluLXctMCBjcWEtZmxleC0xXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtdGV4dC1zbSBjcWEtZm9udC1tZWRpdW0gY3FhLXRleHQtZ3JheS05MDBcIj57eyBlbnYubmFtZSB9fTwvZGl2PlxuICAgICAgICA8ZGl2ICpuZ0lmPVwiaGVscGVyRm9yKGVudilcIiBjbGFzcz1cImNxYS10ZXh0LXhzIGNxYS10ZXh0LWdyYXktNTAwIGNxYS1sZWFkaW5nLVsxLjRdXCI+e3sgaGVscGVyRm9yKGVudikgfX08L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvbGFiZWw+XG4gIDwvZGl2PlxuXG4gIDxkaXZcbiAgICAqbmdJZj1cIihlbnZpcm9ubWVudHM/Lmxlbmd0aCB8fCAwKSA9PT0gMFwiXG4gICAgY2xhc3M9XCJjcWEtcHktOCBjcWEtcHgtNCBjcWEtdGV4dC1jZW50ZXIgY3FhLXRleHQtc20gY3FhLXRleHQtZ3JheS01MDBcIj5cbiAgICBBbGwgZW52aXJvbm1lbnRzIGFyZSBhbHJlYWR5IGFzc2lnbmVkIHRvIHRoaXMgcHJvZmlsZS5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzaWduLWVudmlyb25tZW50cy1kaWFsb2cubW9kZWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9hc3NpZ24tZW52aXJvbm1lbnRzLWRpYWxvZy9hc3NpZ24tZW52aXJvbm1lbnRzLWRpYWxvZy5tb2RlbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCB0eXBlIEFzc2lnbkVudmlyb25tZW50c01vZGUgPSAnYXNzaWduJyB8ICdjbG9uZSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXNzaWduRW52aXJvbm1lbnRPcHRpb24ge1xuICBpZDogbnVtYmVyO1xuICBuYW1lOiBzdHJpbmc7XG4gIGNvbG9yPzogc3RyaW5nO1xuICBkZXNjcmlwdGlvbj86IHN0cmluZztcbiAgYWxyZWFkeUFzc2lnbmVkPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBc3NpZ25FbnZpcm9ubWVudHNEaWFsb2dWYWx1ZSB7XG4gIHNlbGVjdGVkSWRzOiBudW1iZXJbXTtcbiAgc291cmNlRW52SWQ/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXNzaWduRW52aXJvbm1lbnRzRGlhbG9nSW5wdXRzIHtcbiAgbW9kZT86IEFzc2lnbkVudmlyb25tZW50c01vZGU7XG4gIHByb2ZpbGVOYW1lPzogc3RyaW5nO1xuICBlbnZpcm9ubWVudHM/OiBBc3NpZ25FbnZpcm9ubWVudE9wdGlvbltdO1xuICBhc3NpZ25lZEVudmlyb25tZW50cz86IEFzc2lnbkVudmlyb25tZW50T3B0aW9uW107XG4gIGRlZmF1bHRTb3VyY2VFbnZJZD86IG51bWJlcjtcbn1cbiJdfQ==
@@ -0,0 +1,123 @@
1
+ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
2
+ import { ENVIRONMENT_ACCENT_COLORS, } from './new-environment-dialog.models';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "../custom-input/custom-input.component";
5
+ import * as i2 from "../custom-toggle/custom-toggle.component";
6
+ import * as i3 from "@angular/common";
7
+ export class NewEnvironmentDialogComponent {
8
+ constructor(cdr) {
9
+ this.cdr = cdr;
10
+ this.mode = 'create';
11
+ this.existingNames = [];
12
+ this.allowDefaultToggle = true;
13
+ this.defaultAlreadySet = false;
14
+ this.colors = ENVIRONMENT_ACCENT_COLORS;
15
+ this.name = '';
16
+ this.description = '';
17
+ this.color = ENVIRONMENT_ACCENT_COLORS[0];
18
+ this.isDefault = false;
19
+ this.nameError = null;
20
+ }
21
+ ngOnInit() {
22
+ if (this.initialValue) {
23
+ this.name = this.initialValue.name ?? '';
24
+ this.description = this.initialValue.description ?? '';
25
+ this.color = this.initialValue.color || ENVIRONMENT_ACCENT_COLORS[0];
26
+ this.isDefault = this.initialValue.isDefault ?? false;
27
+ }
28
+ }
29
+ get title() {
30
+ return this.mode === 'edit' ? 'Edit environment' : 'New environment';
31
+ }
32
+ get subtitle() {
33
+ return 'Create an environment to scope variables, DB configs, and data profiles.';
34
+ }
35
+ get primaryButtonLabel() {
36
+ return this.mode === 'edit' ? 'Save changes' : 'Create environment';
37
+ }
38
+ get nameErrorsArray() {
39
+ return this.nameError ? [this.nameError] : [];
40
+ }
41
+ get defaultHelperText() {
42
+ if (!this.allowDefaultToggle) {
43
+ return 'Default promotion is handled from the environment detail page.';
44
+ }
45
+ if (this.defaultAlreadySet && !this.isDefault) {
46
+ return 'Another environment is currently the default. Toggling this on will demote it.';
47
+ }
48
+ return 'Test cases without an explicit env selected will resolve against this one.';
49
+ }
50
+ onNameChange(next) {
51
+ this.name = next;
52
+ this.nameError = null;
53
+ this.cdr.markForCheck();
54
+ }
55
+ onDescriptionChange(next) {
56
+ this.description = next;
57
+ this.cdr.markForCheck();
58
+ }
59
+ onColorSelect(next) {
60
+ this.color = next;
61
+ this.cdr.markForCheck();
62
+ }
63
+ onDefaultChange(next) {
64
+ this.isDefault = next;
65
+ this.cdr.markForCheck();
66
+ }
67
+ /**
68
+ * Called by the host (via DialogRef.getComponentInstance()) when the primary
69
+ * button is clicked. Returns the captured value when valid, or null when the
70
+ * form has errors — host should leave the dialog open.
71
+ */
72
+ getValue() {
73
+ const trimmedName = this.name.trim();
74
+ if (!trimmedName) {
75
+ this.nameError = 'Name is required.';
76
+ }
77
+ else if (trimmedName.length < 2) {
78
+ this.nameError = 'Name must be at least 2 characters.';
79
+ }
80
+ else if (this.isDuplicateName(trimmedName)) {
81
+ this.nameError = 'An environment with this name already exists — names must be unique.';
82
+ }
83
+ else {
84
+ this.nameError = null;
85
+ }
86
+ if (this.nameError) {
87
+ this.cdr.markForCheck();
88
+ return null;
89
+ }
90
+ return {
91
+ name: trimmedName,
92
+ description: this.description ? this.description.trim() : null,
93
+ color: this.color,
94
+ isDefault: this.allowDefaultToggle ? this.isDefault : false,
95
+ };
96
+ }
97
+ isDuplicateName(candidate) {
98
+ const existing = (this.existingNames ?? []).map(n => (n ?? '').trim().toLowerCase());
99
+ const lowered = candidate.toLowerCase();
100
+ if (this.mode === 'edit') {
101
+ const original = (this.initialValue?.name ?? '').trim().toLowerCase();
102
+ return lowered !== original && existing.includes(lowered);
103
+ }
104
+ return existing.includes(lowered);
105
+ }
106
+ }
107
+ NewEnvironmentDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: NewEnvironmentDialogComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
108
+ NewEnvironmentDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: NewEnvironmentDialogComponent, selector: "cqa-new-environment-dialog", inputs: { mode: "mode", initialValue: "initialValue", existingNames: "existingNames", allowDefaultToggle: "allowDefaultToggle", defaultAlreadySet: "defaultAlreadySet" }, host: { styleAttribute: "display:block;width:100%;", classAttribute: "cqa-ui-root" }, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-w-full\">\n\n <!-- Name -->\n <div class=\"cqa-flex cqa-flex-col\">\n <cqa-custom-input\n label=\"Environment name\"\n placeholder=\"e.g. QA, SIT, UAT, Prod, Demo\"\n type=\"text\"\n [value]=\"name\"\n [required]=\"true\"\n [fullWidth]=\"true\"\n [errors]=\"nameErrorsArray\"\n (valueChange)=\"onNameChange($event)\">\n </cqa-custom-input>\n <span *ngIf=\"!nameError\"\n class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Names are user-defined. Be concise \u2014 you'll see this on every test run.\n </span>\n </div>\n\n <!-- Description -->\n <div class=\"cqa-flex cqa-flex-col\">\n <cqa-custom-input\n label=\"Description\"\n placeholder=\"What is this environment for?\"\n type=\"text\"\n [value]=\"description\"\n [fullWidth]=\"true\"\n (valueChange)=\"onDescriptionChange($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Accent color -->\n <div class=\"cqa-flex cqa-flex-col\">\n <label class=\"cqa-text-sm cqa-mb-2 cqa-font-medium cqa-text-gray-700\">Accent color</label>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button\n *ngFor=\"let swatch of colors\"\n type=\"button\"\n class=\"cqa-w-7 cqa-h-7 cqa-rounded-lg cqa-cursor-pointer cqa-transition-all\"\n [attr.aria-label]=\"'Select ' + swatch\"\n [attr.aria-pressed]=\"color === swatch\"\n [style.background]=\"swatch\"\n [style.border]=\"color === swatch ? '2px solid #0F172A' : '2px solid transparent'\"\n [style.boxShadow]=\"color === swatch ? '0 0 0 2px rgba(15,23,42,0.12)' : '0 0 0 1px rgba(0,0,0,0.05)'\"\n (click)=\"onColorSelect(swatch)\">\n </button>\n </div>\n </div>\n\n <!-- Make default -->\n <div\n *ngIf=\"allowDefaultToggle\"\n class=\"cqa-flex cqa-items-start cqa-gap-3 cqa-p-3 cqa-rounded-lg cqa-border cqa-border-indigo-100 cqa-bg-indigo-50\">\n <cqa-custom-toggle\n [checked]=\"isDefault\"\n ariaLabel=\"Make default environment\"\n (checkedChange)=\"onDefaultChange($event)\">\n </cqa-custom-toggle>\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\">\n <span class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">\n Make this the default environment\n </span>\n <span class=\"cqa-text-xs cqa-text-gray-600 cqa-mt-0.5\">\n {{ defaultHelperText }}\n </span>\n </div>\n </div>\n\n</div>\n", components: [{ type: i1.CustomInputComponent, selector: "cqa-custom-input", inputs: ["inputId", "label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: i2.CustomToggleComponent, selector: "cqa-custom-toggle", inputs: ["checked", "disabled", "ariaLabel"], outputs: ["checkedChange", "change"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
109
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: NewEnvironmentDialogComponent, decorators: [{
110
+ type: Component,
111
+ args: [{ selector: 'cqa-new-environment-dialog', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'cqa-ui-root', style: 'display:block;width:100%;' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-w-full\">\n\n <!-- Name -->\n <div class=\"cqa-flex cqa-flex-col\">\n <cqa-custom-input\n label=\"Environment name\"\n placeholder=\"e.g. QA, SIT, UAT, Prod, Demo\"\n type=\"text\"\n [value]=\"name\"\n [required]=\"true\"\n [fullWidth]=\"true\"\n [errors]=\"nameErrorsArray\"\n (valueChange)=\"onNameChange($event)\">\n </cqa-custom-input>\n <span *ngIf=\"!nameError\"\n class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Names are user-defined. Be concise \u2014 you'll see this on every test run.\n </span>\n </div>\n\n <!-- Description -->\n <div class=\"cqa-flex cqa-flex-col\">\n <cqa-custom-input\n label=\"Description\"\n placeholder=\"What is this environment for?\"\n type=\"text\"\n [value]=\"description\"\n [fullWidth]=\"true\"\n (valueChange)=\"onDescriptionChange($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Accent color -->\n <div class=\"cqa-flex cqa-flex-col\">\n <label class=\"cqa-text-sm cqa-mb-2 cqa-font-medium cqa-text-gray-700\">Accent color</label>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button\n *ngFor=\"let swatch of colors\"\n type=\"button\"\n class=\"cqa-w-7 cqa-h-7 cqa-rounded-lg cqa-cursor-pointer cqa-transition-all\"\n [attr.aria-label]=\"'Select ' + swatch\"\n [attr.aria-pressed]=\"color === swatch\"\n [style.background]=\"swatch\"\n [style.border]=\"color === swatch ? '2px solid #0F172A' : '2px solid transparent'\"\n [style.boxShadow]=\"color === swatch ? '0 0 0 2px rgba(15,23,42,0.12)' : '0 0 0 1px rgba(0,0,0,0.05)'\"\n (click)=\"onColorSelect(swatch)\">\n </button>\n </div>\n </div>\n\n <!-- Make default -->\n <div\n *ngIf=\"allowDefaultToggle\"\n class=\"cqa-flex cqa-items-start cqa-gap-3 cqa-p-3 cqa-rounded-lg cqa-border cqa-border-indigo-100 cqa-bg-indigo-50\">\n <cqa-custom-toggle\n [checked]=\"isDefault\"\n ariaLabel=\"Make default environment\"\n (checkedChange)=\"onDefaultChange($event)\">\n </cqa-custom-toggle>\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1\">\n <span class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">\n Make this the default environment\n </span>\n <span class=\"cqa-text-xs cqa-text-gray-600 cqa-mt-0.5\">\n {{ defaultHelperText }}\n </span>\n </div>\n </div>\n\n</div>\n" }]
112
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { mode: [{
113
+ type: Input
114
+ }], initialValue: [{
115
+ type: Input
116
+ }], existingNames: [{
117
+ type: Input
118
+ }], allowDefaultToggle: [{
119
+ type: Input
120
+ }], defaultAlreadySet: [{
121
+ type: Input
122
+ }] } });
123
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV3LWVudmlyb25tZW50LWRpYWxvZy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL25ldy1lbnZpcm9ubWVudC1kaWFsb2cvbmV3LWVudmlyb25tZW50LWRpYWxvZy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL25ldy1lbnZpcm9ubWVudC1kaWFsb2cvbmV3LWVudmlyb25tZW50LWRpYWxvZy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQXFCLFNBQVMsRUFBRSxLQUFLLEVBQVUsTUFBTSxlQUFlLENBQUM7QUFDckcsT0FBTyxFQUNMLHlCQUF5QixHQUUxQixNQUFNLGlDQUFpQyxDQUFDOzs7OztBQVF6QyxNQUFNLE9BQU8sNkJBQTZCO0lBZ0J4QyxZQUE2QixHQUFzQjtRQUF0QixRQUFHLEdBQUgsR0FBRyxDQUFtQjtRQWYxQyxTQUFJLEdBQXNCLFFBQVEsQ0FBQztRQUVuQyxrQkFBYSxHQUFhLEVBQUUsQ0FBQztRQUM3Qix1QkFBa0IsR0FBWSxJQUFJLENBQUM7UUFDbkMsc0JBQWlCLEdBQVksS0FBSyxDQUFDO1FBRW5DLFdBQU0sR0FBc0IseUJBQXlCLENBQUM7UUFFL0QsU0FBSSxHQUFHLEVBQUUsQ0FBQztRQUNWLGdCQUFXLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLFVBQUssR0FBVyx5QkFBeUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3QyxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBRWxCLGNBQVMsR0FBa0IsSUFBSSxDQUFDO0lBRXNCLENBQUM7SUFFdkQsUUFBUTtRQUNOLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNyQixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUN6QyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxJQUFJLEVBQUUsQ0FBQztZQUN2RCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxJQUFJLHlCQUF5QixDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3JFLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLElBQUksS0FBSyxDQUFDO1NBQ3ZEO0lBQ0gsQ0FBQztJQUVELElBQUksS0FBSztRQUNQLE9BQU8sSUFBSSxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQztJQUN2RSxDQUFDO0lBRUQsSUFBSSxRQUFRO1FBQ1YsT0FBTywwRUFBMEUsQ0FBQztJQUNwRixDQUFDO0lBRUQsSUFBSSxrQkFBa0I7UUFDcEIsT0FBTyxJQUFJLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQztJQUN0RSxDQUFDO0lBRUQsSUFBSSxlQUFlO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNoRCxDQUFDO0lBRUQsSUFBSSxpQkFBaUI7UUFDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRTtZQUM1QixPQUFPLGdFQUFnRSxDQUFDO1NBQ3pFO1FBQ0QsSUFBSSxJQUFJLENBQUMsaUJBQWlCLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQzdDLE9BQU8sZ0ZBQWdGLENBQUM7U0FDekY7UUFDRCxPQUFPLDRFQUE0RSxDQUFDO0lBQ3RGLENBQUM7SUFFRCxZQUFZLENBQUMsSUFBWTtRQUN2QixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN0QixJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFRCxtQkFBbUIsQ0FBQyxJQUFZO1FBQzlCLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVELGFBQWEsQ0FBQyxJQUFZO1FBQ3hCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBQ2xCLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVELGVBQWUsQ0FBQyxJQUFhO1FBQzNCLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxRQUFRO1FBQ04sTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUVyQyxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ2hCLElBQUksQ0FBQyxTQUFTLEdBQUcsbUJBQW1CLENBQUM7U0FDdEM7YUFBTSxJQUFJLFdBQVcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQ2pDLElBQUksQ0FBQyxTQUFTLEdBQUcscUNBQXFDLENBQUM7U0FDeEQ7YUFBTSxJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLEVBQUU7WUFDNUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxzRUFBc0UsQ0FBQztTQUN6RjthQUFNO1lBQ0wsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7U0FDdkI7UUFFRCxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDbEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN4QixPQUFPLElBQUksQ0FBQztTQUNiO1FBRUQsT0FBTztZQUNMLElBQUksRUFBRSxXQUFXO1lBQ2pCLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJO1lBQzlELEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztZQUNqQixTQUFTLEVBQUUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLO1NBQzVELENBQUM7SUFDSixDQUFDO0lBRU8sZUFBZSxDQUFDLFNBQWlCO1FBQ3ZDLE1BQU0sUUFBUSxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsSUFBSSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ3JGLE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN4QyxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssTUFBTSxFQUFFO1lBQ3hCLE1BQU0sUUFBUSxHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDdEUsT0FBTyxPQUFPLEtBQUssUUFBUSxJQUFJLFFBQVEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDM0Q7UUFDRCxPQUFPLFFBQVEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDcEMsQ0FBQzs7MEhBakhVLDZCQUE2Qjs4R0FBN0IsNkJBQTZCLGtVQ1oxQyxnOEVBc0VBOzJGRDFEYSw2QkFBNkI7a0JBTnpDLFNBQVM7K0JBQ0UsNEJBQTRCLG1CQUVyQix1QkFBdUIsQ0FBQyxNQUFNLFFBQ3pDLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsMkJBQTJCLEVBQUU7d0dBR3pELElBQUk7c0JBQVosS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csa0JBQWtCO3NCQUExQixLQUFLO2dCQUNHLGlCQUFpQjtzQkFBekIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBJbnB1dCwgT25Jbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBFTlZJUk9OTUVOVF9BQ0NFTlRfQ09MT1JTLFxuICBFbnZpcm9ubWVudERpYWxvZ1ZhbHVlLFxufSBmcm9tICcuL25ldy1lbnZpcm9ubWVudC1kaWFsb2cubW9kZWxzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnY3FhLW5ldy1lbnZpcm9ubWVudC1kaWFsb2cnLFxuICB0ZW1wbGF0ZVVybDogJy4vbmV3LWVudmlyb25tZW50LWRpYWxvZy5jb21wb25lbnQuaHRtbCcsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBob3N0OiB7IGNsYXNzOiAnY3FhLXVpLXJvb3QnLCBzdHlsZTogJ2Rpc3BsYXk6YmxvY2s7d2lkdGg6MTAwJTsnIH0sXG59KVxuZXhwb3J0IGNsYXNzIE5ld0Vudmlyb25tZW50RGlhbG9nQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgQElucHV0KCkgbW9kZTogJ2NyZWF0ZScgfCAnZWRpdCcgPSAnY3JlYXRlJztcbiAgQElucHV0KCkgaW5pdGlhbFZhbHVlPzogUGFydGlhbDxFbnZpcm9ubWVudERpYWxvZ1ZhbHVlPjtcbiAgQElucHV0KCkgZXhpc3RpbmdOYW1lczogc3RyaW5nW10gPSBbXTtcbiAgQElucHV0KCkgYWxsb3dEZWZhdWx0VG9nZ2xlOiBib29sZWFuID0gdHJ1ZTtcbiAgQElucHV0KCkgZGVmYXVsdEFscmVhZHlTZXQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICByZWFkb25seSBjb2xvcnM6IHJlYWRvbmx5IHN0cmluZ1tdID0gRU5WSVJPTk1FTlRfQUNDRU5UX0NPTE9SUztcblxuICBuYW1lID0gJyc7XG4gIGRlc2NyaXB0aW9uID0gJyc7XG4gIGNvbG9yOiBzdHJpbmcgPSBFTlZJUk9OTUVOVF9BQ0NFTlRfQ09MT1JTWzBdO1xuICBpc0RlZmF1bHQgPSBmYWxzZTtcblxuICBuYW1lRXJyb3I6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZikge31cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pbml0aWFsVmFsdWUpIHtcbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuaW5pdGlhbFZhbHVlLm5hbWUgPz8gJyc7XG4gICAgICB0aGlzLmRlc2NyaXB0aW9uID0gdGhpcy5pbml0aWFsVmFsdWUuZGVzY3JpcHRpb24gPz8gJyc7XG4gICAgICB0aGlzLmNvbG9yID0gdGhpcy5pbml0aWFsVmFsdWUuY29sb3IgfHwgRU5WSVJPTk1FTlRfQUNDRU5UX0NPTE9SU1swXTtcbiAgICAgIHRoaXMuaXNEZWZhdWx0ID0gdGhpcy5pbml0aWFsVmFsdWUuaXNEZWZhdWx0ID8/IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIGdldCB0aXRsZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm1vZGUgPT09ICdlZGl0JyA/ICdFZGl0IGVudmlyb25tZW50JyA6ICdOZXcgZW52aXJvbm1lbnQnO1xuICB9XG5cbiAgZ2V0IHN1YnRpdGxlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICdDcmVhdGUgYW4gZW52aXJvbm1lbnQgdG8gc2NvcGUgdmFyaWFibGVzLCBEQiBjb25maWdzLCBhbmQgZGF0YSBwcm9maWxlcy4nO1xuICB9XG5cbiAgZ2V0IHByaW1hcnlCdXR0b25MYWJlbCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm1vZGUgPT09ICdlZGl0JyA/ICdTYXZlIGNoYW5nZXMnIDogJ0NyZWF0ZSBlbnZpcm9ubWVudCc7XG4gIH1cblxuICBnZXQgbmFtZUVycm9yc0FycmF5KCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lRXJyb3IgPyBbdGhpcy5uYW1lRXJyb3JdIDogW107XG4gIH1cblxuICBnZXQgZGVmYXVsdEhlbHBlclRleHQoKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMuYWxsb3dEZWZhdWx0VG9nZ2xlKSB7XG4gICAgICByZXR1cm4gJ0RlZmF1bHQgcHJvbW90aW9uIGlzIGhhbmRsZWQgZnJvbSB0aGUgZW52aXJvbm1lbnQgZGV0YWlsIHBhZ2UuJztcbiAgICB9XG4gICAgaWYgKHRoaXMuZGVmYXVsdEFscmVhZHlTZXQgJiYgIXRoaXMuaXNEZWZhdWx0KSB7XG4gICAgICByZXR1cm4gJ0Fub3RoZXIgZW52aXJvbm1lbnQgaXMgY3VycmVudGx5IHRoZSBkZWZhdWx0LiBUb2dnbGluZyB0aGlzIG9uIHdpbGwgZGVtb3RlIGl0Lic7XG4gICAgfVxuICAgIHJldHVybiAnVGVzdCBjYXNlcyB3aXRob3V0IGFuIGV4cGxpY2l0IGVudiBzZWxlY3RlZCB3aWxsIHJlc29sdmUgYWdhaW5zdCB0aGlzIG9uZS4nO1xuICB9XG5cbiAgb25OYW1lQ2hhbmdlKG5leHQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMubmFtZSA9IG5leHQ7XG4gICAgdGhpcy5uYW1lRXJyb3IgPSBudWxsO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgb25EZXNjcmlwdGlvbkNoYW5nZShuZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmRlc2NyaXB0aW9uID0gbmV4dDtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIG9uQ29sb3JTZWxlY3QobmV4dDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5jb2xvciA9IG5leHQ7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBvbkRlZmF1bHRDaGFuZ2UobmV4dDogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuaXNEZWZhdWx0ID0gbmV4dDtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsZWQgYnkgdGhlIGhvc3QgKHZpYSBEaWFsb2dSZWYuZ2V0Q29tcG9uZW50SW5zdGFuY2UoKSkgd2hlbiB0aGUgcHJpbWFyeVxuICAgKiBidXR0b24gaXMgY2xpY2tlZC4gUmV0dXJucyB0aGUgY2FwdHVyZWQgdmFsdWUgd2hlbiB2YWxpZCwgb3IgbnVsbCB3aGVuIHRoZVxuICAgKiBmb3JtIGhhcyBlcnJvcnMg4oCUIGhvc3Qgc2hvdWxkIGxlYXZlIHRoZSBkaWFsb2cgb3Blbi5cbiAgICovXG4gIGdldFZhbHVlKCk6IEVudmlyb25tZW50RGlhbG9nVmFsdWUgfCBudWxsIHtcbiAgICBjb25zdCB0cmltbWVkTmFtZSA9IHRoaXMubmFtZS50cmltKCk7XG5cbiAgICBpZiAoIXRyaW1tZWROYW1lKSB7XG4gICAgICB0aGlzLm5hbWVFcnJvciA9ICdOYW1lIGlzIHJlcXVpcmVkLic7XG4gICAgfSBlbHNlIGlmICh0cmltbWVkTmFtZS5sZW5ndGggPCAyKSB7XG4gICAgICB0aGlzLm5hbWVFcnJvciA9ICdOYW1lIG11c3QgYmUgYXQgbGVhc3QgMiBjaGFyYWN0ZXJzLic7XG4gICAgfSBlbHNlIGlmICh0aGlzLmlzRHVwbGljYXRlTmFtZSh0cmltbWVkTmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZUVycm9yID0gJ0FuIGVudmlyb25tZW50IHdpdGggdGhpcyBuYW1lIGFscmVhZHkgZXhpc3RzIOKAlCBuYW1lcyBtdXN0IGJlIHVuaXF1ZS4nO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm5hbWVFcnJvciA9IG51bGw7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMubmFtZUVycm9yKSB7XG4gICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiB0cmltbWVkTmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiB0aGlzLmRlc2NyaXB0aW9uID8gdGhpcy5kZXNjcmlwdGlvbi50cmltKCkgOiBudWxsLFxuICAgICAgY29sb3I6IHRoaXMuY29sb3IsXG4gICAgICBpc0RlZmF1bHQ6IHRoaXMuYWxsb3dEZWZhdWx0VG9nZ2xlID8gdGhpcy5pc0RlZmF1bHQgOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBpc0R1cGxpY2F0ZU5hbWUoY2FuZGlkYXRlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBleGlzdGluZyA9ICh0aGlzLmV4aXN0aW5nTmFtZXMgPz8gW10pLm1hcChuID0+IChuID8/ICcnKS50cmltKCkudG9Mb3dlckNhc2UoKSk7XG4gICAgY29uc3QgbG93ZXJlZCA9IGNhbmRpZGF0ZS50b0xvd2VyQ2FzZSgpO1xuICAgIGlmICh0aGlzLm1vZGUgPT09ICdlZGl0Jykge1xuICAgICAgY29uc3Qgb3JpZ2luYWwgPSAodGhpcy5pbml0aWFsVmFsdWU/Lm5hbWUgPz8gJycpLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgcmV0dXJuIGxvd2VyZWQgIT09IG9yaWdpbmFsICYmIGV4aXN0aW5nLmluY2x1ZGVzKGxvd2VyZWQpO1xuICAgIH1cbiAgICByZXR1cm4gZXhpc3RpbmcuaW5jbHVkZXMobG93ZXJlZCk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtZmxleC1jb2wgY3FhLWdhcC00IGNxYS13LWZ1bGxcIj5cblxuICA8IS0tIE5hbWUgLS0+XG4gIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtZmxleC1jb2xcIj5cbiAgICA8Y3FhLWN1c3RvbS1pbnB1dFxuICAgICAgbGFiZWw9XCJFbnZpcm9ubWVudCBuYW1lXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwiZS5nLiBRQSwgU0lULCBVQVQsIFByb2QsIERlbW9cIlxuICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgW3ZhbHVlXT1cIm5hbWVcIlxuICAgICAgW3JlcXVpcmVkXT1cInRydWVcIlxuICAgICAgW2Z1bGxXaWR0aF09XCJ0cnVlXCJcbiAgICAgIFtlcnJvcnNdPVwibmFtZUVycm9yc0FycmF5XCJcbiAgICAgICh2YWx1ZUNoYW5nZSk9XCJvbk5hbWVDaGFuZ2UoJGV2ZW50KVwiPlxuICAgIDwvY3FhLWN1c3RvbS1pbnB1dD5cbiAgICA8c3BhbiAqbmdJZj1cIiFuYW1lRXJyb3JcIlxuICAgICAgY2xhc3M9XCJjcWEtdGV4dC14cyBjcWEtdGV4dC1ncmF5LTUwMCBjcWEtbXQtMVwiPlxuICAgICAgTmFtZXMgYXJlIHVzZXItZGVmaW5lZC4gQmUgY29uY2lzZSDigJQgeW91J2xsIHNlZSB0aGlzIG9uIGV2ZXJ5IHRlc3QgcnVuLlxuICAgIDwvc3Bhbj5cbiAgPC9kaXY+XG5cbiAgPCEtLSBEZXNjcmlwdGlvbiAtLT5cbiAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1mbGV4LWNvbFwiPlxuICAgIDxjcWEtY3VzdG9tLWlucHV0XG4gICAgICBsYWJlbD1cIkRlc2NyaXB0aW9uXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwiV2hhdCBpcyB0aGlzIGVudmlyb25tZW50IGZvcj9cIlxuICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgW3ZhbHVlXT1cImRlc2NyaXB0aW9uXCJcbiAgICAgIFtmdWxsV2lkdGhdPVwidHJ1ZVwiXG4gICAgICAodmFsdWVDaGFuZ2UpPVwib25EZXNjcmlwdGlvbkNoYW5nZSgkZXZlbnQpXCI+XG4gICAgPC9jcWEtY3VzdG9tLWlucHV0PlxuICA8L2Rpdj5cblxuICA8IS0tIEFjY2VudCBjb2xvciAtLT5cbiAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1mbGV4LWNvbFwiPlxuICAgIDxsYWJlbCBjbGFzcz1cImNxYS10ZXh0LXNtIGNxYS1tYi0yIGNxYS1mb250LW1lZGl1bSBjcWEtdGV4dC1ncmF5LTcwMFwiPkFjY2VudCBjb2xvcjwvbGFiZWw+XG4gICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1pdGVtcy1jZW50ZXIgY3FhLWdhcC0yXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgICpuZ0Zvcj1cImxldCBzd2F0Y2ggb2YgY29sb3JzXCJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIGNsYXNzPVwiY3FhLXctNyBjcWEtaC03IGNxYS1yb3VuZGVkLWxnIGNxYS1jdXJzb3ItcG9pbnRlciBjcWEtdHJhbnNpdGlvbi1hbGxcIlxuICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidTZWxlY3QgJyArIHN3YXRjaFwiXG4gICAgICAgIFthdHRyLmFyaWEtcHJlc3NlZF09XCJjb2xvciA9PT0gc3dhdGNoXCJcbiAgICAgICAgW3N0eWxlLmJhY2tncm91bmRdPVwic3dhdGNoXCJcbiAgICAgICAgW3N0eWxlLmJvcmRlcl09XCJjb2xvciA9PT0gc3dhdGNoID8gJzJweCBzb2xpZCAjMEYxNzJBJyA6ICcycHggc29saWQgdHJhbnNwYXJlbnQnXCJcbiAgICAgICAgW3N0eWxlLmJveFNoYWRvd109XCJjb2xvciA9PT0gc3dhdGNoID8gJzAgMCAwIDJweCByZ2JhKDE1LDIzLDQyLDAuMTIpJyA6ICcwIDAgMCAxcHggcmdiYSgwLDAsMCwwLjA1KSdcIlxuICAgICAgICAoY2xpY2spPVwib25Db2xvclNlbGVjdChzd2F0Y2gpXCI+XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG5cbiAgPCEtLSBNYWtlIGRlZmF1bHQgLS0+XG4gIDxkaXZcbiAgICAqbmdJZj1cImFsbG93RGVmYXVsdFRvZ2dsZVwiXG4gICAgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtc3RhcnQgY3FhLWdhcC0zIGNxYS1wLTMgY3FhLXJvdW5kZWQtbGcgY3FhLWJvcmRlciBjcWEtYm9yZGVyLWluZGlnby0xMDAgY3FhLWJnLWluZGlnby01MFwiPlxuICAgIDxjcWEtY3VzdG9tLXRvZ2dsZVxuICAgICAgW2NoZWNrZWRdPVwiaXNEZWZhdWx0XCJcbiAgICAgIGFyaWFMYWJlbD1cIk1ha2UgZGVmYXVsdCBlbnZpcm9ubWVudFwiXG4gICAgICAoY2hlY2tlZENoYW5nZSk9XCJvbkRlZmF1bHRDaGFuZ2UoJGV2ZW50KVwiPlxuICAgIDwvY3FhLWN1c3RvbS10b2dnbGU+XG4gICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1mbGV4LWNvbCBjcWEtZmxleC0xXCI+XG4gICAgICA8c3BhbiBjbGFzcz1cImNxYS10ZXh0LXNtIGNxYS1mb250LW1lZGl1bSBjcWEtdGV4dC1ncmF5LTkwMFwiPlxuICAgICAgICBNYWtlIHRoaXMgdGhlIGRlZmF1bHQgZW52aXJvbm1lbnRcbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxzcGFuIGNsYXNzPVwiY3FhLXRleHQteHMgY3FhLXRleHQtZ3JheS02MDAgY3FhLW10LTAuNVwiPlxuICAgICAgICB7eyBkZWZhdWx0SGVscGVyVGV4dCB9fVxuICAgICAgPC9zcGFuPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cblxuPC9kaXY+XG4iXX0=
@@ -0,0 +1,9 @@
1
+ export const ENVIRONMENT_ACCENT_COLORS = [
2
+ '#3F43EE',
3
+ '#A855F7',
4
+ '#00A63E',
5
+ '#F59E0B',
6
+ '#0EA5E9',
7
+ '#EC4899',
8
+ ];
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV3LWVudmlyb25tZW50LWRpYWxvZy5tb2RlbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL25ldy1lbnZpcm9ubWVudC1kaWFsb2cvbmV3LWVudmlyb25tZW50LWRpYWxvZy5tb2RlbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBZUEsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQXNCO0lBQzFELFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztDQUNWLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgaW50ZXJmYWNlIEVudmlyb25tZW50RGlhbG9nVmFsdWUge1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmcgfCBudWxsO1xuICBjb2xvcjogc3RyaW5nO1xuICBpc0RlZmF1bHQ6IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmV3RW52aXJvbm1lbnREaWFsb2dJbnB1dHMge1xuICBtb2RlPzogJ2NyZWF0ZScgfCAnZWRpdCc7XG4gIGluaXRpYWxWYWx1ZT86IFBhcnRpYWw8RW52aXJvbm1lbnREaWFsb2dWYWx1ZT47XG4gIGV4aXN0aW5nTmFtZXM/OiBzdHJpbmdbXTtcbiAgYWxsb3dEZWZhdWx0VG9nZ2xlPzogYm9vbGVhbjtcbiAgZGVmYXVsdEFscmVhZHlTZXQ/OiBib29sZWFuO1xufVxuXG5leHBvcnQgY29uc3QgRU5WSVJPTk1FTlRfQUNDRU5UX0NPTE9SUzogcmVhZG9ubHkgc3RyaW5nW10gPSBbXG4gICcjM0Y0M0VFJyxcbiAgJyNBODU1RjcnLFxuICAnIzAwQTYzRScsXG4gICcjRjU5RTBCJyxcbiAgJyMwRUE1RTknLFxuICAnI0VDNDg5OScsXG5dO1xuIl19
@@ -0,0 +1,190 @@
1
+ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ import * as i1 from "../custom-input/custom-input.component";
4
+ import * as i2 from "../dropdown-button/dropdown-button.component";
5
+ import * as i3 from "../permission-toggle/permission-toggle.component";
6
+ import * as i4 from "@angular/common";
7
+ export class NewEnvironmentVariableDialogComponent {
8
+ constructor(cdr) {
9
+ this.cdr = cdr;
10
+ this.mode = 'create';
11
+ this.existingNames = [];
12
+ this.envName = '';
13
+ this.typeDropdownOptions = [
14
+ { label: 'String', value: 'String' },
15
+ { label: 'Number', value: 'Number' },
16
+ { label: 'Boolean', value: 'Boolean' },
17
+ { label: 'Password', value: 'Password' },
18
+ ];
19
+ this.name = '';
20
+ this.type = 'String';
21
+ this.value = '';
22
+ this.readWriteMode = 'RW';
23
+ this.passwordTouched = false;
24
+ this.nameError = null;
25
+ this.valueError = null;
26
+ }
27
+ ngOnInit() {
28
+ if (this.initialValue) {
29
+ this.name = this.initialValue.name ?? '';
30
+ this.type = this.initialValue.type ?? 'String';
31
+ this.value = this.initialValue.value ?? '';
32
+ this.readWriteMode = this.initialValue.readWriteMode ?? 'RW';
33
+ }
34
+ if (this.type === 'Boolean' && this.value !== 'true' && this.value !== 'false') {
35
+ this.value = 'false';
36
+ }
37
+ if (this.mode === 'edit' && this.type === 'Password') {
38
+ this.value = '';
39
+ }
40
+ }
41
+ get title() {
42
+ return this.mode === 'edit' ? 'Edit variable' : 'New variable';
43
+ }
44
+ get subtitle() {
45
+ return this.envName ? `Scoped to the ${this.envName} environment.` : 'Scoped to this environment.';
46
+ }
47
+ get primaryButtonLabel() {
48
+ return this.mode === 'edit' ? 'Save changes' : 'Add variable';
49
+ }
50
+ get isBoolean() { return this.type === 'Boolean'; }
51
+ get isPassword() { return this.type === 'Password'; }
52
+ get isNumber() { return this.type === 'Number'; }
53
+ get valuePlaceholder() {
54
+ if (this.isPassword && this.mode === 'edit') {
55
+ return '•••••• (leave blank to keep existing)';
56
+ }
57
+ if (this.readWriteMode === 'RW') {
58
+ return 'Leave blank to populate during test execution';
59
+ }
60
+ return 'Enter a value';
61
+ }
62
+ get nameHelperText() {
63
+ if (this.nameError) {
64
+ return this.nameError;
65
+ }
66
+ return 'Variable names must be unique within the environment.';
67
+ }
68
+ get permissionHelperText() {
69
+ return this.readWriteMode === 'RO'
70
+ ? 'Read only — test steps can read but not overwrite.'
71
+ : 'Read/write — test cases can capture values here.';
72
+ }
73
+ get nameErrorsArray() { return this.nameError ? [this.nameError] : []; }
74
+ get valueErrorsArray() { return this.valueError ? [this.valueError] : []; }
75
+ get booleanDropdownOptions() {
76
+ return [
77
+ { label: 'true', value: 'true' },
78
+ { label: 'false', value: 'false' },
79
+ ];
80
+ }
81
+ onNameChange(next) {
82
+ this.name = next;
83
+ this.nameError = null;
84
+ this.cdr.markForCheck();
85
+ }
86
+ onTypeChange(next) {
87
+ if (!next) {
88
+ return;
89
+ }
90
+ this.type = next;
91
+ if (this.type === 'Boolean' && this.value !== 'true' && this.value !== 'false') {
92
+ this.value = 'false';
93
+ }
94
+ if (this.type === 'Password') {
95
+ this.passwordTouched = false;
96
+ if (this.mode === 'edit') {
97
+ this.value = '';
98
+ }
99
+ }
100
+ this.valueError = null;
101
+ this.cdr.markForCheck();
102
+ }
103
+ onPermissionChange(next) {
104
+ this.readWriteMode = next === 'RO' ? 'RO' : 'RW';
105
+ this.cdr.markForCheck();
106
+ }
107
+ onValueChange(next) {
108
+ this.value = next;
109
+ if (this.isPassword) {
110
+ this.passwordTouched = true;
111
+ }
112
+ this.valueError = null;
113
+ this.cdr.markForCheck();
114
+ }
115
+ onBooleanValueChange(next) {
116
+ this.value = next;
117
+ this.cdr.markForCheck();
118
+ }
119
+ /**
120
+ * Host reads via DialogRef.getComponentInstance(). Returns null on validation
121
+ * failure — host keeps the dialog open and surfaces the inline error already
122
+ * written onto nameError / valueError.
123
+ */
124
+ getValue() {
125
+ const trimmedName = this.name.trim();
126
+ if (!trimmedName) {
127
+ this.nameError = 'Name is required.';
128
+ }
129
+ else if (this.isDuplicateName(trimmedName)) {
130
+ this.nameError = 'A variable with this name already exists in this environment.';
131
+ }
132
+ else {
133
+ this.nameError = null;
134
+ }
135
+ if (this.isNumber && this.value && !this.isValidNumber(this.value)) {
136
+ this.valueError = 'Value must be a number.';
137
+ }
138
+ else {
139
+ this.valueError = null;
140
+ }
141
+ if (this.nameError || this.valueError) {
142
+ this.cdr.markForCheck();
143
+ return null;
144
+ }
145
+ const omitPasswordValue = this.isPassword && this.mode === 'edit' && !this.passwordTouched;
146
+ return {
147
+ name: trimmedName,
148
+ type: this.type,
149
+ value: omitPasswordValue ? null : this.serializeValue(),
150
+ readWriteMode: this.readWriteMode,
151
+ };
152
+ }
153
+ serializeValue() {
154
+ if (this.isBoolean) {
155
+ return this.value === 'true' ? 'true' : 'false';
156
+ }
157
+ return this.value ?? '';
158
+ }
159
+ isDuplicateName(candidate) {
160
+ const existing = (this.existingNames ?? []).map(n => (n ?? '').trim().toLowerCase());
161
+ const lowered = candidate.toLowerCase();
162
+ if (this.mode === 'edit') {
163
+ const original = (this.initialValue?.name ?? '').trim().toLowerCase();
164
+ return lowered !== original && existing.includes(lowered);
165
+ }
166
+ return existing.includes(lowered);
167
+ }
168
+ isValidNumber(raw) {
169
+ const trimmed = raw.trim();
170
+ if (!trimmed) {
171
+ return true;
172
+ }
173
+ return !Number.isNaN(Number(trimmed));
174
+ }
175
+ }
176
+ NewEnvironmentVariableDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: NewEnvironmentVariableDialogComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
177
+ NewEnvironmentVariableDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: NewEnvironmentVariableDialogComponent, selector: "cqa-new-environment-variable-dialog", inputs: { mode: "mode", initialValue: "initialValue", existingNames: "existingNames", envName: "envName" }, host: { styleAttribute: "display:block;width:100%;", classAttribute: "cqa-ui-root" }, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-w-full\">\n\n <!-- Name -->\n <div class=\"cqa-flex cqa-flex-col\">\n <cqa-custom-input\n label=\"Name\"\n placeholder=\"e.g. order_id\"\n type=\"text\"\n [value]=\"name\"\n [required]=\"true\"\n [fullWidth]=\"true\"\n [errors]=\"nameErrorsArray\"\n inputInlineStyle=\"font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace;\"\n (valueChange)=\"onNameChange($event)\">\n </cqa-custom-input>\n <span *ngIf=\"!nameError\"\n class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n {{ nameHelperText }}\n </span>\n </div>\n\n <!-- Type + Permission -->\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4\">\n <div class=\"cqa-flex cqa-flex-col\">\n <label class=\"cqa-text-sm cqa-mb-1.5 cqa-font-medium cqa-text-gray-700\">Type</label>\n <cqa-dropdown-button\n [options]=\"typeDropdownOptions\"\n [selectedValue]=\"type\"\n (selectionChange)=\"onTypeChange($event)\">\n </cqa-dropdown-button>\n </div>\n <div class=\"cqa-flex cqa-flex-col\">\n <label class=\"cqa-text-sm cqa-mb-1.5 cqa-font-medium cqa-text-gray-700\">Permission</label>\n <div class=\"cqa-pt-0.5\">\n <cqa-permission-toggle\n [value]=\"readWriteMode\"\n (valueChange)=\"onPermissionChange($event)\">\n </cqa-permission-toggle>\n </div>\n <span class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">{{ permissionHelperText }}</span>\n </div>\n </div>\n\n <!-- Value -->\n <div class=\"cqa-flex cqa-flex-col\">\n <ng-container *ngIf=\"isBoolean; else nonBooleanValue\">\n <label class=\"cqa-text-sm cqa-mb-1.5 cqa-font-medium cqa-text-gray-700\">Value</label>\n <cqa-dropdown-button\n [options]=\"booleanDropdownOptions\"\n [selectedValue]=\"value\"\n (selectionChange)=\"onBooleanValueChange($event)\">\n </cqa-dropdown-button>\n </ng-container>\n <ng-template #nonBooleanValue>\n <cqa-custom-input\n label=\"Value\"\n [type]=\"isPassword ? 'password' : 'text'\"\n [value]=\"value\"\n [placeholder]=\"valuePlaceholder\"\n [fullWidth]=\"true\"\n [errors]=\"valueErrorsArray\"\n inputInlineStyle=\"font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace;\"\n (valueChange)=\"onValueChange($event)\">\n </cqa-custom-input>\n </ng-template>\n </div>\n\n</div>\n", components: [{ type: i1.CustomInputComponent, selector: "cqa-custom-input", inputs: ["inputId", "label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: i2.DropdownButtonComponent, selector: "cqa-dropdown-button", inputs: ["label", "options", "selectedValue", "disabled", "placeholder"], outputs: ["selectionChange", "opened", "closed"] }, { type: i3.PermissionToggleComponent, selector: "cqa-permission-toggle", inputs: ["value", "disabled", "roTooltip", "rwTooltip"], outputs: ["valueChange"] }], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
178
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: NewEnvironmentVariableDialogComponent, decorators: [{
179
+ type: Component,
180
+ args: [{ selector: 'cqa-new-environment-variable-dialog', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'cqa-ui-root', style: 'display:block;width:100%;' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-w-full\">\n\n <!-- Name -->\n <div class=\"cqa-flex cqa-flex-col\">\n <cqa-custom-input\n label=\"Name\"\n placeholder=\"e.g. order_id\"\n type=\"text\"\n [value]=\"name\"\n [required]=\"true\"\n [fullWidth]=\"true\"\n [errors]=\"nameErrorsArray\"\n inputInlineStyle=\"font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace;\"\n (valueChange)=\"onNameChange($event)\">\n </cqa-custom-input>\n <span *ngIf=\"!nameError\"\n class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n {{ nameHelperText }}\n </span>\n </div>\n\n <!-- Type + Permission -->\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4\">\n <div class=\"cqa-flex cqa-flex-col\">\n <label class=\"cqa-text-sm cqa-mb-1.5 cqa-font-medium cqa-text-gray-700\">Type</label>\n <cqa-dropdown-button\n [options]=\"typeDropdownOptions\"\n [selectedValue]=\"type\"\n (selectionChange)=\"onTypeChange($event)\">\n </cqa-dropdown-button>\n </div>\n <div class=\"cqa-flex cqa-flex-col\">\n <label class=\"cqa-text-sm cqa-mb-1.5 cqa-font-medium cqa-text-gray-700\">Permission</label>\n <div class=\"cqa-pt-0.5\">\n <cqa-permission-toggle\n [value]=\"readWriteMode\"\n (valueChange)=\"onPermissionChange($event)\">\n </cqa-permission-toggle>\n </div>\n <span class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">{{ permissionHelperText }}</span>\n </div>\n </div>\n\n <!-- Value -->\n <div class=\"cqa-flex cqa-flex-col\">\n <ng-container *ngIf=\"isBoolean; else nonBooleanValue\">\n <label class=\"cqa-text-sm cqa-mb-1.5 cqa-font-medium cqa-text-gray-700\">Value</label>\n <cqa-dropdown-button\n [options]=\"booleanDropdownOptions\"\n [selectedValue]=\"value\"\n (selectionChange)=\"onBooleanValueChange($event)\">\n </cqa-dropdown-button>\n </ng-container>\n <ng-template #nonBooleanValue>\n <cqa-custom-input\n label=\"Value\"\n [type]=\"isPassword ? 'password' : 'text'\"\n [value]=\"value\"\n [placeholder]=\"valuePlaceholder\"\n [fullWidth]=\"true\"\n [errors]=\"valueErrorsArray\"\n inputInlineStyle=\"font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace;\"\n (valueChange)=\"onValueChange($event)\">\n </cqa-custom-input>\n </ng-template>\n </div>\n\n</div>\n" }]
181
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { mode: [{
182
+ type: Input
183
+ }], initialValue: [{
184
+ type: Input
185
+ }], existingNames: [{
186
+ type: Input
187
+ }], envName: [{
188
+ type: Input
189
+ }] } });
190
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV3LWVudmlyb25tZW50LXZhcmlhYmxlLWRpYWxvZy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL25ldy1lbnZpcm9ubWVudC12YXJpYWJsZS1kaWFsb2cvbmV3LWVudmlyb25tZW50LXZhcmlhYmxlLWRpYWxvZy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL25ldy1lbnZpcm9ubWVudC12YXJpYWJsZS1kaWFsb2cvbmV3LWVudmlyb25tZW50LXZhcmlhYmxlLWRpYWxvZy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQXFCLFNBQVMsRUFBRSxLQUFLLEVBQVUsTUFBTSxlQUFlLENBQUM7Ozs7OztBQWFyRyxNQUFNLE9BQU8scUNBQXFDO0lBc0JoRCxZQUE2QixHQUFzQjtRQUF0QixRQUFHLEdBQUgsR0FBRyxDQUFtQjtRQXJCMUMsU0FBSSxHQUFzQixRQUFRLENBQUM7UUFFbkMsa0JBQWEsR0FBYSxFQUFFLENBQUM7UUFDN0IsWUFBTyxHQUFXLEVBQUUsQ0FBQztRQUVyQix3QkFBbUIsR0FBa0Q7WUFDNUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUU7WUFDcEMsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUU7WUFDcEMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUU7WUFDdEMsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUU7U0FDekMsQ0FBQztRQUVGLFNBQUksR0FBRyxFQUFFLENBQUM7UUFDVixTQUFJLEdBQXNCLFFBQVEsQ0FBQztRQUNuQyxVQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ1gsa0JBQWEsR0FBNEIsSUFBSSxDQUFDO1FBQzlDLG9CQUFlLEdBQUcsS0FB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QUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN0RSxPQUFPLE9BQU8sS0FBSyxRQUFRLElBQUksUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUMzRDtRQUNELE9BQU8sUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRU8sYUFBYSxDQUFDLEdBQVc7UUFDL0IsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzNCLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFBRSxPQUFPLElBQUksQ0FBQztTQUFFO1FBQzlCLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ3hDLENBQUM7O2tJQXJMVSxxQ0FBcUM7c0hBQXJDLHFDQUFxQyw2UUNibEQscStFQW9FQTsyRkR2RGEscUNBQXFDO2tCQU5qRCxTQUFTOytCQUNFLHFDQUFxQyxtQkFFOUIsdUJBQXVCLENBQUMsTUFBTSxRQUN6QyxFQUFFLEtBQUssRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLDJCQUEyQixFQUFFO3dHQUd6RCxJQUFJO3NCQUFaLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxhQUFhO3NCQUFyQixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBJbnB1dCwgT25Jbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBFbnZWYXJpYWJsZURpYWxvZ1ZhbHVlLFxuICBFbnZWYXJpYWJsZVVJUGVybWlzc2lvbixcbiAgRW52VmFyaWFibGVVSVR5cGUsXG59IGZyb20gJy4vbmV3LWVudmlyb25tZW50LXZhcmlhYmxlLWRpYWxvZy5tb2RlbHMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjcWEtbmV3LWVudmlyb25tZW50LXZhcmlhYmxlLWRpYWxvZycsXG4gIHRlbXBsYXRlVXJsOiAnLi9uZXctZW52aXJvbm1lbnQtdmFyaWFibGUtZGlhbG9nLmNvbXBvbmVudC5odG1sJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGhvc3Q6IHsgY2xhc3M6ICdjcWEtdWktcm9vdCcsIHN0eWxlOiAnZGlzcGxheTpibG9jazt3aWR0aDoxMDAlOycgfSxcbn0pXG5leHBvcnQgY2xhc3MgTmV3RW52aXJvbm1lbnRWYXJpYWJsZURpYWxvZ0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIEBJbnB1dCgpIG1vZGU6ICdjcmVhdGUnIHwgJ2VkaXQnID0gJ2NyZWF0ZSc7XG4gIEBJbnB1dCgpIGluaXRpYWxWYWx1ZT86IFBhcnRpYWw8RW52VmFyaWFibGVEaWFsb2dWYWx1ZT47XG4gIEBJbnB1dCgpIGV4aXN0aW5nTmFtZXM6IHN0cmluZ1tdID0gW107XG4gIEBJbnB1dCgpIGVudk5hbWU6IHN0cmluZyA9ICcnO1xuXG4gIHJlYWRvbmx5IHR5cGVEcm9wZG93bk9wdGlvbnM6IHsgbGFiZWw6IHN0cmluZzsgdmFsdWU6IEVudlZhcmlhYmxlVUlUeXBlIH1bXSA9IFtcbiAgICB7IGxhYmVsOiAnU3RyaW5nJywgdmFsdWU6ICdTdHJpbmcnIH0sXG4gICAgeyBsYWJlbDogJ051bWJlcicsIHZhbHVlOiAnTnVtYmVyJyB9LFxuICAgIHsgbGFiZWw6ICdCb29sZWFuJywgdmFsdWU6ICdCb29sZWFuJyB9LFxuICAgIHsgbGFiZWw6ICdQYXNzd29yZCcsIHZhbHVlOiAnUGFzc3dvcmQnIH0sXG4gIF07XG5cbiAgbmFtZSA9ICcnO1xuICB0eXBlOiBFbnZWYXJpYWJsZVVJVHlwZSA9ICdTdHJpbmcnO1xuICB2YWx1ZSA9ICcnO1xuICByZWFkV3JpdGVNb2RlOiBFbnZWYXJpYWJsZVVJUGVybWlzc2lvbiA9ICdSVyc7XG4gIHBhc3N3b3JkVG91Y2hlZCA9IGZhbHNlO1xuXG4gIG5hbWVFcnJvcjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHZhbHVlRXJyb3I6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZikge31cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pbml0aWFsVmFsdWUpIHtcbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuaW5pdGlhbFZhbHVlLm5hbWUgPz8gJyc7XG4gICAgICB0aGlzLnR5cGUgPSB0aGlzLmluaXRpYWxWYWx1ZS50eXBlID8/ICdTdHJpbmcnO1xuICAgICAgdGhpcy52YWx1ZSA9IHRoaXMuaW5pdGlhbFZhbHVlLnZhbHVlID8/ICcnO1xuICAgICAgdGhpcy5yZWFkV3JpdGVNb2RlID0gdGhpcy5pbml0aWFsVmFsdWUucmVhZFdyaXRlTW9kZSA/PyAnUlcnO1xuICAgIH1cbiAgICBpZiAodGhpcy50eXBlID09PSAnQm9vbGVhbicgJiYgdGhpcy52YWx1ZSAhPT0gJ3RydWUnICYmIHRoaXMudmFsdWUgIT09ICdmYWxzZScpIHtcbiAgICAgIHRoaXMudmFsdWUgPSAnZmFsc2UnO1xuICAgIH1cbiAgICBpZiAodGhpcy5tb2RlID09PSAnZWRpdCcgJiYgdGhpcy50eXBlID09PSAnUGFzc3dvcmQnKSB7XG4gICAgICB0aGlzLnZhbHVlID0gJyc7XG4gICAgfVxuICB9XG5cbiAgZ2V0IHRpdGxlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMubW9kZSA9PT0gJ2VkaXQnID8gJ0VkaXQgdmFyaWFibGUnIDogJ05ldyB2YXJpYWJsZSc7XG4gIH1cblxuICBnZXQgc3VidGl0bGUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5lbnZOYW1lID8gYFNjb3BlZCB0byB0aGUgJHt0aGlzLmVudk5hbWV9IGVudmlyb25tZW50LmAgOiAnU2NvcGVkIHRvIHRoaXMgZW52aXJvbm1lbnQuJztcbiAgfVxuXG4gIGdldCBwcmltYXJ5QnV0dG9uTGFiZWwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5tb2RlID09PSAnZWRpdCcgPyAnU2F2ZSBjaGFuZ2VzJyA6ICdBZGQgdmFyaWFibGUnO1xuICB9XG5cbiAgZ2V0IGlzQm9vbGVhbigpOiBib29sZWFuIHsgcmV0dXJuIHRoaXMudHlwZSA9PT0gJ0Jvb2xlYW4nOyB9XG4gIGdldCBpc1Bhc3N3b3JkKCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy50eXBlID09PSAnUGFzc3dvcmQnOyB9XG4gIGdldCBpc051bWJlcigpOiBib29sZWFuIHsgcmV0dXJuIHRoaXMudHlwZSA9PT0gJ051bWJlcic7IH1cblxuICBnZXQgdmFsdWVQbGFjZWhvbGRlcigpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLmlzUGFzc3dvcmQgJiYgdGhpcy5tb2RlID09PSAnZWRpdCcpIHtcbiAgICAgIHJldHVybiAn4oCi4oCi4oCi4oCi4oCi4oCiIChsZWF2ZSBibGFuayB0byBrZWVwIGV4aXN0aW5nKSc7XG4gICAgfVxuICAgIGlmICh0aGlzLnJlYWRXcml0ZU1vZGUgPT09ICdSVycpIHtcbiAgICAgIHJldHVybiAnTGVhdmUgYmxhbmsgdG8gcG9wdWxhdGUgZHVyaW5nIHRlc3QgZXhlY3V0aW9uJztcbiAgICB9XG4gICAgcmV0dXJuICdFbnRlciBhIHZhbHVlJztcbiAgfVxuXG4gIGdldCBuYW1lSGVscGVyVGV4dCgpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLm5hbWVFcnJvcikgeyByZXR1cm4gdGhpcy5uYW1lRXJyb3I7IH1cbiAgICByZXR1cm4gJ1ZhcmlhYmxlIG5hbWVzIG11c3QgYmUgdW5pcXVlIHdpdGhpbiB0aGUgZW52aXJvbm1lbnQuJztcbiAgfVxuXG4gIGdldCBwZXJtaXNzaW9uSGVscGVyVGV4dCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnJlYWRXcml0ZU1vZGUgPT09ICdSTydcbiAgICAgID8gJ1JlYWQgb25seSDigJQgdGVzdCBzdGVwcyBjYW4gcmVhZCBidXQgbm90IG92ZXJ3cml0ZS4nXG4gICAgICA6ICdSZWFkL3dyaXRlIOKAlCB0ZXN0IGNhc2VzIGNhbiBjYXB0dXJlIHZhbHVlcyBoZXJlLic7XG4gIH1cblxuICBnZXQgbmFtZUVycm9yc0FycmF5KCk6IHN0cmluZ1tdIHsgcmV0dXJuIHRoaXMubmFtZUVycm9yID8gW3RoaXMubmFtZUVycm9yXSA6IFtdOyB9XG4gIGdldCB2YWx1ZUVycm9yc0FycmF5KCk6IHN0cmluZ1tdIHsgcmV0dXJuIHRoaXMudmFsdWVFcnJvciA/IFt0aGlzLnZhbHVlRXJyb3JdIDogW107IH1cblxuICBnZXQgYm9vbGVhbkRyb3Bkb3duT3B0aW9ucygpOiB7IGxhYmVsOiBzdHJpbmc7IHZhbHVlOiBzdHJpbmcgfVtdIHtcbiAgICByZXR1cm4gW1xuICAgICAgeyBsYWJlbDogJ3RydWUnLCB2YWx1ZTogJ3RydWUnIH0sXG4gICAgICB7IGxhYmVsOiAnZmFsc2UnLCB2YWx1ZTogJ2ZhbHNlJyB9LFxuICAgIF07XG4gIH1cblxuICBvbk5hbWVDaGFuZ2UobmV4dDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5uYW1lID0gbmV4dDtcbiAgICB0aGlzLm5hbWVFcnJvciA9IG51bGw7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBvblR5cGVDaGFuZ2UobmV4dDogRW52VmFyaWFibGVVSVR5cGUpOiB2b2lkIHtcbiAgICBpZiAoIW5leHQpIHsgcmV0dXJuOyB9XG4gICAgdGhpcy50eXBlID0gbmV4dDtcbiAgICBpZiAodGhpcy50eXBlID09PSAnQm9vbGVhbicgJiYgdGhpcy52YWx1ZSAhPT0gJ3RydWUnICYmIHRoaXMudmFsdWUgIT09ICdmYWxzZScpIHtcbiAgICAgIHRoaXMudmFsdWUgPSAnZmFsc2UnO1xuICAgIH1cbiAgICBpZiAodGhpcy50eXBlID09PSAnUGFzc3dvcmQnKSB7XG4gICAgICB0aGlzLnBhc3N3b3JkVG91Y2hlZCA9IGZhbHNlO1xuICAgICAgaWYgKHRoaXMubW9kZSA9PT0gJ2VkaXQnKSB7IHRoaXMudmFsdWUgPSAnJzsgfVxuICAgIH1cbiAgICB0aGlzLnZhbHVlRXJyb3IgPSBudWxsO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgb25QZXJtaXNzaW9uQ2hhbmdlKG5leHQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMucmVhZFdyaXRlTW9kZSA9IG5leHQgPT09ICdSTycgPyAnUk8nIDogJ1JXJztcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIG9uVmFsdWVDaGFuZ2UobmV4dDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy52YWx1ZSA9IG5leHQ7XG4gICAgaWYgKHRoaXMuaXNQYXNzd29yZCkgeyB0aGlzLnBhc3N3b3JkVG91Y2hlZCA9IHRydWU7IH1cbiAgICB0aGlzLnZhbHVlRXJyb3IgPSBudWxsO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgb25Cb29sZWFuVmFsdWVDaGFuZ2UobmV4dDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy52YWx1ZSA9IG5leHQ7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvKipcbiAgICogSG9zdCByZWFkcyB2aWEgRGlhbG9nUmVmLmdldENvbXBvbmVudEluc3RhbmNlKCkuIFJldHVybnMgbnVsbCBvbiB2YWxpZGF0aW9uXG4gICAqIGZhaWx1cmUg4oCUIGhvc3Qga2VlcHMgdGhlIGRpYWxvZyBvcGVuIGFuZCBzdXJmYWNlcyB0aGUgaW5saW5lIGVycm9yIGFscmVhZHlcbiAgICogd3JpdHRlbiBvbnRvIG5hbWVFcnJvciAvIHZhbHVlRXJyb3IuXG4gICAqL1xuICBnZXRWYWx1ZSgpOiBFbnZWYXJpYWJsZURpYWxvZ1ZhbHVlIHwgbnVsbCB7XG4gICAgY29uc3QgdHJpbW1lZE5hbWUgPSB0aGlzLm5hbWUudHJpbSgpO1xuXG4gICAgaWYgKCF0cmltbWVkTmFtZSkge1xuICAgICAgdGhpcy5uYW1lRXJyb3IgPSAnTmFtZSBpcyByZXF1aXJlZC4nO1xuICAgIH0gZWxzZSBpZiAodGhpcy5pc0R1cGxpY2F0ZU5hbWUodHJpbW1lZE5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVFcnJvciA9ICdBIHZhcmlhYmxlIHdpdGggdGhpcyBuYW1lIGFscmVhZHkgZXhpc3RzIGluIHRoaXMgZW52aXJvbm1lbnQuJztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5uYW1lRXJyb3IgPSBudWxsO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmlzTnVtYmVyICYmIHRoaXMudmFsdWUgJiYgIXRoaXMuaXNWYWxpZE51bWJlcih0aGlzLnZhbHVlKSkge1xuICAgICAgdGhpcy52YWx1ZUVycm9yID0gJ1ZhbHVlIG11c3QgYmUgYSBudW1iZXIuJztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy52YWx1ZUVycm9yID0gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5uYW1lRXJyb3IgfHwgdGhpcy52YWx1ZUVycm9yKSB7XG4gICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IG9taXRQYXNzd29yZFZhbHVlID0gdGhpcy5pc1Bhc3N3b3JkICYmIHRoaXMubW9kZSA9PT0gJ2VkaXQnICYmICF0aGlzLnBhc3N3b3JkVG91Y2hlZDtcblxuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiB0cmltbWVkTmFtZSxcbiAgICAgIHR5cGU6IHRoaXMudHlwZSxcbiAgICAgIHZhbHVlOiBvbWl0UGFzc3dvcmRWYWx1ZSA/IG51bGwgOiB0aGlzLnNlcmlhbGl6ZVZhbHVlKCksXG4gICAgICByZWFkV3JpdGVNb2RlOiB0aGlzLnJlYWRXcml0ZU1vZGUsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgc2VyaWFsaXplVmFsdWUoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgaWYgKHRoaXMuaXNCb29sZWFuKSB7XG4gICAgICByZXR1cm4gdGhpcy52YWx1ZSA9PT0gJ3RydWUnID8gJ3RydWUnIDogJ2ZhbHNlJztcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudmFsdWUgPz8gJyc7XG4gIH1cblxuICBwcml2YXRlIGlzRHVwbGljYXRlTmFtZShjYW5kaWRhdGU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gKHRoaXMuZXhpc3RpbmdOYW1lcyA/PyBbXSkubWFwKG4gPT4gKG4gPz8gJycpLnRyaW0oKS50b0xvd2VyQ2FzZSgpKTtcbiAgICBjb25zdCBsb3dlcmVkID0gY2FuZGlkYXRlLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYgKHRoaXMubW9kZSA9PT0gJ2VkaXQnKSB7XG4gICAgICBjb25zdCBvcmlnaW5hbCA9ICh0aGlzLmluaXRpYWxWYWx1ZT8ubmFtZSA/PyAnJykudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG4gICAgICByZXR1cm4gbG93ZXJlZCAhPT0gb3JpZ2luYWwgJiYgZXhpc3RpbmcuaW5jbHVkZXMobG93ZXJlZCk7XG4gICAgfVxuICAgIHJldHVybiBleGlzdGluZy5pbmNsdWRlcyhsb3dlcmVkKTtcbiAgfVxuXG4gIHByaXZhdGUgaXNWYWxpZE51bWJlcihyYXc6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHRyaW1tZWQgPSByYXcudHJpbSgpO1xuICAgIGlmICghdHJpbW1lZCkgeyByZXR1cm4gdHJ1ZTsgfVxuICAgIHJldHVybiAhTnVtYmVyLmlzTmFOKE51bWJlcih0cmltbWVkKSk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtZmxleC1jb2wgY3FhLWdhcC00IGNxYS13LWZ1bGxcIj5cblxuICA8IS0tIE5hbWUgLS0+XG4gIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtZmxleC1jb2xcIj5cbiAgICA8Y3FhLWN1c3RvbS1pbnB1dFxuICAgICAgbGFiZWw9XCJOYW1lXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwiZS5nLiBvcmRlcl9pZFwiXG4gICAgICB0eXBlPVwidGV4dFwiXG4gICAgICBbdmFsdWVdPVwibmFtZVwiXG4gICAgICBbcmVxdWlyZWRdPVwidHJ1ZVwiXG4gICAgICBbZnVsbFdpZHRoXT1cInRydWVcIlxuICAgICAgW2Vycm9yc109XCJuYW1lRXJyb3JzQXJyYXlcIlxuICAgICAgaW5wdXRJbmxpbmVTdHlsZT1cImZvbnQtZmFtaWx5OiB1aS1tb25vc3BhY2UsIFNGTW9uby1SZWd1bGFyLCBNZW5sbywgTW9uYWNvLCBDb25zb2xhcywgJ0xpYmVyYXRpb24gTW9ubycsIG1vbm9zcGFjZTtcIlxuICAgICAgKHZhbHVlQ2hhbmdlKT1cIm9uTmFtZUNoYW5nZSgkZXZlbnQpXCI+XG4gICAgPC9jcWEtY3VzdG9tLWlucHV0PlxuICAgIDxzcGFuICpuZ0lmPVwiIW5hbWVFcnJvclwiXG4gICAgICBjbGFzcz1cImNxYS10ZXh0LXhzIGNxYS10ZXh0LWdyYXktNTAwIGNxYS1tdC0xXCI+XG4gICAgICB7eyBuYW1lSGVscGVyVGV4dCB9fVxuICAgIDwvc3Bhbj5cbiAgPC9kaXY+XG5cbiAgPCEtLSBUeXBlICsgUGVybWlzc2lvbiAtLT5cbiAgPGRpdiBjbGFzcz1cImNxYS1ncmlkIGNxYS1ncmlkLWNvbHMtMiBjcWEtZ2FwLTRcIj5cbiAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWZsZXgtY29sXCI+XG4gICAgICA8bGFiZWwgY2xhc3M9XCJjcWEtdGV4dC1zbSBjcWEtbWItMS41IGNxYS1mb250LW1lZGl1bSBjcWEtdGV4dC1ncmF5LTcwMFwiPlR5cGU8L2xhYmVsPlxuICAgICAgPGNxYS1kcm9wZG93bi1idXR0b25cbiAgICAgICAgW29wdGlvbnNdPVwidHlwZURyb3Bkb3duT3B0aW9uc1wiXG4gICAgICAgIFtzZWxlY3RlZFZhbHVlXT1cInR5cGVcIlxuICAgICAgICAoc2VsZWN0aW9uQ2hhbmdlKT1cIm9uVHlwZUNoYW5nZSgkZXZlbnQpXCI+XG4gICAgICA8L2NxYS1kcm9wZG93bi1idXR0b24+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1mbGV4LWNvbFwiPlxuICAgICAgPGxhYmVsIGNsYXNzPVwiY3FhLXRleHQtc20gY3FhLW1iLTEuNSBjcWEtZm9udC1tZWRpdW0gY3FhLXRleHQtZ3JheS03MDBcIj5QZXJtaXNzaW9uPC9sYWJlbD5cbiAgICAgIDxkaXYgY2xhc3M9XCJjcWEtcHQtMC41XCI+XG4gICAgICAgIDxjcWEtcGVybWlzc2lvbi10b2dnbGVcbiAgICAgICAgICBbdmFsdWVdPVwicmVhZFdyaXRlTW9kZVwiXG4gICAgICAgICAgKHZhbHVlQ2hhbmdlKT1cIm9uUGVybWlzc2lvbkNoYW5nZSgkZXZlbnQpXCI+XG4gICAgICAgIDwvY3FhLXBlcm1pc3Npb24tdG9nZ2xlPlxuICAgICAgPC9kaXY+XG4gICAgICA8c3BhbiBjbGFzcz1cImNxYS10ZXh0LXhzIGNxYS10ZXh0LWdyYXktNTAwIGNxYS1tdC0xXCI+e3sgcGVybWlzc2lvbkhlbHBlclRleHQgfX08L3NwYW4+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuXG4gIDwhLS0gVmFsdWUgLS0+XG4gIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtZmxleC1jb2xcIj5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaXNCb29sZWFuOyBlbHNlIG5vbkJvb2xlYW5WYWx1ZVwiPlxuICAgICAgPGxhYmVsIGNsYXNzPVwiY3FhLXRleHQtc20gY3FhLW1iLTEuNSBjcWEtZm9udC1tZWRpdW0gY3FhLXRleHQtZ3JheS03MDBcIj5WYWx1ZTwvbGFiZWw+XG4gICAgICA8Y3FhLWRyb3Bkb3duLWJ1dHRvblxuICAgICAgICBbb3B0aW9uc109XCJib29sZWFuRHJvcGRvd25PcHRpb25zXCJcbiAgICAgICAgW3NlbGVjdGVkVmFsdWVdPVwidmFsdWVcIlxuICAgICAgICAoc2VsZWN0aW9uQ2hhbmdlKT1cIm9uQm9vbGVhblZhbHVlQ2hhbmdlKCRldmVudClcIj5cbiAgICAgIDwvY3FhLWRyb3Bkb3duLWJ1dHRvbj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctdGVtcGxhdGUgI25vbkJvb2xlYW5WYWx1ZT5cbiAgICAgIDxjcWEtY3VzdG9tLWlucHV0XG4gICAgICAgIGxhYmVsPVwiVmFsdWVcIlxuICAgICAgICBbdHlwZV09XCJpc1Bhc3N3b3JkID8gJ3Bhc3N3b3JkJyA6ICd0ZXh0J1wiXG4gICAgICAgIFt2YWx1ZV09XCJ2YWx1ZVwiXG4gICAgICAgIFtwbGFjZWhvbGRlcl09XCJ2YWx1ZVBsYWNlaG9sZGVyXCJcbiAgICAgICAgW2Z1bGxXaWR0aF09XCJ0cnVlXCJcbiAgICAgICAgW2Vycm9yc109XCJ2YWx1ZUVycm9yc0FycmF5XCJcbiAgICAgICAgaW5wdXRJbmxpbmVTdHlsZT1cImZvbnQtZmFtaWx5OiB1aS1tb25vc3BhY2UsIFNGTW9uby1SZWd1bGFyLCBNZW5sbywgTW9uYWNvLCBDb25zb2xhcywgJ0xpYmVyYXRpb24gTW9ubycsIG1vbm9zcGFjZTtcIlxuICAgICAgICAodmFsdWVDaGFuZ2UpPVwib25WYWx1ZUNoYW5nZSgkZXZlbnQpXCI+XG4gICAgICA8L2NxYS1jdXN0b20taW5wdXQ+XG4gICAgPC9uZy10ZW1wbGF0ZT5cbiAgPC9kaXY+XG5cbjwvZGl2PlxuIl19