ng-configcat-publicapi-ui 5.3.10 → 5.3.11

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.
@@ -2742,6 +2742,7 @@ class SettingListComponent {
2742
2742
  this.messagingService.showSuccessSnack("Settings saved successfully.", 5000);
2743
2743
  },
2744
2744
  error: (error) => {
2745
+ this.submitting = false;
2745
2746
  if (error instanceof HttpErrorResponse && error.status === 400 && FormHelper.getHttpErrorResponseMessage(error, "Reason") === "Reason required") {
2746
2747
  const dialogRef = this.dialog.open(ReasonDialogComponent, {
2747
2748
  width: "450px",
@@ -2751,9 +2752,6 @@ class SettingListComponent {
2751
2752
  updateSettingValuesModel.reason = result.reason;
2752
2753
  this.updateSettingValues(updateSettingValuesModel);
2753
2754
  }
2754
- else {
2755
- this.submitting = false;
2756
- }
2757
2755
  });
2758
2756
  return;
2759
2757
  }
@@ -3614,7 +3612,9 @@ class VariationsDialogComponent {
3614
3612
  predefinedVariationId: new FormControl(predefinedVariation.predefinedVariationId),
3615
3613
  name: new FormControl({ value: predefinedVariation.name, disabled: !this.data.manage }, { validators: [Validators.maxLength(255)] }),
3616
3614
  hint: new FormControl({ value: predefinedVariation.hint, disabled: !this.data.manage }, { validators: [Validators.maxLength(1000)] }),
3617
- value: this.createPredefinedVariationValueFormGroup(predefinedVariation.value, !this.data.manage || !!predefinedVariation.usages.length),
3615
+ value: this.createPredefinedVariationValueFormGroup(predefinedVariation.value, !this.data.manage
3616
+ || (predefinedVariation.usages.length > 0)
3617
+ || (predefinedVariation.usagesInOtherEnvironments > 0)),
3618
3618
  valueForComparison: new FormControl({
3619
3619
  value: getPredefinedVariationValueDisplayValue(this.settingType, predefinedVariation.value),
3620
3620
  disabled: true,
@@ -3797,7 +3797,7 @@ class VariationsDialogComponent {
3797
3797
  return getPredefinedVariationColorIndex(this.settingType, getRawPredefinedVariationValue(row.controls.value), index);
3798
3798
  }
3799
3799
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: VariationsDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3800
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: VariationsDialogComponent, isStandalone: true, selector: "app-variations-dialog", ngImport: i0, template: "@if (setting.isLoading()) {\n <div mat-dialog-content class=\"content\">\n <app-loader />\n </div>\n} @else {\n <form [formGroup]=\"formGroup\" (ngSubmit)=\"onSubmit()\">\n <h1 mat-dialog-title>{{ data.manage ? \"Manage predefined variations\" : \"View predefined variations\" }}</h1>\n <div class=\"content\">\n <div class=\"dialog-description\" mat-dialog-content>\n @if (data.manage) {\n <p>\n Add, delete, and update predefined variations of the\n <strong>{{ data.settingName }}</strong>\n setting.\n <br />\n The\n <strong>served value</strong>\n is sent to SDKs and received by your applications. The\n <strong>display name</strong>\n appears in the targeting UI.\n <br />\n You can update a value or delete a variation only if it is not in use. As a help, you can see where each\n variation is used.\n </p>\n } @else {\n <p>\n The\n <strong>served value</strong>\n is sent to SDKs and received by your applications. The\n <strong>display name</strong>\n appears in the targeting UI.\n </p>\n }\n </div>\n\n <div class=\"dialog-table\" mat-dialog-content>\n <table\n mat-table\n cdkDropList\n [dataSource]=\"dataSource\"\n [cdkDropListData]=\"dataSource\"\n [cdkDropListDisabled]=\"!data.manage || settingType === SettingType.Boolean\"\n (cdkDropListDropped)=\"dropTable($event)\">\n <ng-container matColumnDef=\"reorder\">\n <th *matHeaderCellDef mat-header-cell></th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"drag-handle\">\n <div cdkDragHandle matTooltip=\"Drag here to reorder\" matTooltipPosition=\"above\">\n <mat-icon>drag_indicator</mat-icon>\n </div>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"color\">\n <th *matHeaderCellDef mat-header-cell></th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n <span [class]=\"'variation-indicator variation-color-' + getColorIndex(row, i)\"></span>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"value\">\n <th *matHeaderCellDef mat-header-cell>Served value *</th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n @switch (settingType) {\n @case (SettingType.Boolean) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.boolValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingType.String) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.stringValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingType.Int) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.intValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingType.Double) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.doubleValue,\n setFocus: i === focusIndex,\n }\" />\n }\n }\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"name\">\n <th *matHeaderCellDef mat-header-cell>Display name (optional)</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"small-form-field\">\n <input\n matInput\n [formControl]=\"row.controls.name\"\n [placeholder]=\"row.controls.valueForComparison.value\" />\n @if (row.controls.name.invalid) {\n <mat-error class=\"small-error\">\n {{ formHelper.getErrorMessage(row.controls.name) }}\n </mat-error>\n }\n </mat-form-field>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"hint\">\n <th *matHeaderCellDef mat-header-cell>Hint (optional)</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"small-form-field suffixed\">\n <input matInput [formControl]=\"row.controls.hint\" />\n <button\n matSuffix\n class=\"input-suffix-button\"\n type=\"button\"\n mat-icon-button\n matTooltip=\"Advanced editor\"\n (click)=\"expandHint(row.controls.hint)\">\n <mat-icon class=\"icon-transform-rotate\">edit_note</mat-icon>\n </button>\n @if (row.controls.hint.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(row.controls.hint) }}\n </mat-error>\n }\n </mat-form-field>\n </div>\n </td>\n </ng-container>\n <ng-container matColumnDef=\"variationId\">\n <th *matHeaderCellDef mat-header-cell>Variation ID</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <app-copyable-value [value]=\"row.controls.variationId.value\" [small]=\"true\" />\n </td>\n </ng-container>\n <ng-container matColumnDef=\"usages\">\n <th *matHeaderCellDef mat-header-cell>Usages</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <div class=\"usages\">\n <button\n type=\"button\"\n class=\"usage-button\"\n mat-icon-button\n [disabled]=\"!row.controls.usages.controls.length && !row.controls.usagesInOtherEnvironments.value\"\n (click)=\"row.controls.usagesExpanded.setValue(!row.controls.usagesExpanded.value)\">\n @if (row.controls.usagesExpanded.value) {\n <mat-icon>expand_less</mat-icon>\n } @else {\n <mat-icon>expand_more</mat-icon>\n }\n </button>\n <div>\n @if (row.controls.usagesExpanded.value) {\n @for (usage of row.controls.usages.controls; track $index) {\n <div class=\"usage\">\n <a target=\"_blank\" rel=\"noopener noreferrer\" [href]=\"usage.controls.routerLink.value\">\n {{ usage.controls.displayValue.value }}\n </a>\n </div>\n }\n @if (row.controls.usagesInOtherEnvironments.value > 0) {\n {{ row.controls.usagesInOtherEnvironments.value }} usage{{\n row.controls.usagesInOtherEnvironments.value > 1 ? \"s\" : \"\"\n }}\n in environments you don't have access to.\n } @else if (row.controls.usages.controls.length === 0) {\n <div>no usages</div>\n }\n } @else {\n <div>\n @if (row.controls.usages.controls.length + row.controls.usagesInOtherEnvironments.value > 0) {\n {{ row.controls.usages.controls.length + row.controls.usagesInOtherEnvironments.value }}\n usage{{\n row.controls.usages.controls.length + row.controls.usagesInOtherEnvironments.value > 1\n ? \"s\"\n : \"\"\n }}\n } @else {\n <div>no usages</div>\n }\n </div>\n }\n </div>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"actions\">\n <th *matHeaderCellDef mat-header-cell>{{ dataSource.data.length }} / {{ maxPredefinedVariations }}</th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div\n class=\"delete\"\n [matTooltip]=\"\n formGroup.controls.predefinedVariations.controls.length > 2\n ? 'Cannot remove a variation that is already in use.'\n : 'At least 2 predefined variations should be set.'\n \"\n [matTooltipDisabled]=\"\n row.controls.usages.controls.length === 0 &&\n formGroup.controls.predefinedVariations.controls.length > 2\n \">\n <button\n mat-icon-button\n type=\"button\"\n matTooltip=\"Remove variation\"\n [disabled]=\"\n formGroup.controls.predefinedVariations.controls.length <= 2 ||\n row.controls.usages.controls.length > 0\n \"\n (click)=\"removeVariation(i)\">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n <tr *matHeaderRowDef=\"displayedColumns\" mat-header-row></tr>\n <tr *matRowDef=\"let row; columns: displayedColumns\" mat-row cdkDrag [cdkDragData]=\"row\"></tr>\n </table>\n @if (\n formGroup.controls.predefinedVariations.invalid &&\n formHelper.getErrorMessage(formGroup.controls.predefinedVariations)\n ) {\n <mat-error>\n {{ formHelper.getErrorMessage(formGroup.controls.predefinedVariations) }}\n </mat-error>\n }\n </div>\n @if (data.manage && settingType !== SettingType.Boolean) {\n <div class=\"add-variation\" mat-dialog-content>\n <div\n [matTooltip]=\"'Maximum ' + maxPredefinedVariations + ' variations can be added.'\"\n [matTooltipDisabled]=\"dataSource.data.length < maxPredefinedVariations\">\n <button\n type=\"button\"\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"dataSource.data.length >= maxPredefinedVariations\"\n (click)=\"addVariation()\">\n <mat-icon>add</mat-icon>\n Add variation\n </button>\n </div>\n </div>\n }\n </div>\n\n <div mat-dialog-actions>\n @if (data.manage) {\n <button\n type=\"submit\"\n mat-flat-button\n color=\"primary\"\n [disabled]=\"submitting() || !formGroup.dirty || !formGroup.valid\">\n Save\n </button>\n <button type=\"button\" mat-stroked-button [mat-dialog-close]>Cancel</button>\n } @else {\n <button type=\"button\" color=\"primary\" mat-flat-button [mat-dialog-close]>Close</button>\n }\n </div>\n </form>\n}\n\n<ng-template #settingValueTemplate let-formControl=\"formControl\" let-setFocus=\"setFocus\">\n @switch (settingType) {\n @case (SettingType.String) {\n <mat-form-field class=\"small-form-field text suffixed\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <input\n matInput\n type=\"text\"\n placeholder=\"Add text ...\"\n focus\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\"\n [isFocused]=\"setFocus\"\n [formControl]=\"formControl\" />\n <button\n matSuffix\n class=\"input-suffix-button\"\n type=\"button\"\n mat-icon-button\n matTooltip=\"Advanced editor\"\n (click)=\"expandText(formControl)\">\n <mat-icon class=\"icon-transform-rotate\">edit_note</mat-icon>\n </button>\n @if (formControl.invalid) {\n <mat-error class=\"small-error\">\n {{ formHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n </mat-form-field>\n }\n @case (SettingType.Int) {\n <mat-form-field\n class=\"small-form-field\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\">\n @if (formControl.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n <input\n matInput\n type=\"number\"\n required\n name=\"index\"\n appDigitOnly\n focus\n [isFocused]=\"setFocus\"\n [formControl]=\"formControl\"\n [digitOnlyAllowNegatives]=\"true\" />\n </mat-form-field>\n }\n @case (SettingType.Double) {\n <mat-form-field\n class=\"small-form-field\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\">\n @if (formControl.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n <input\n matInput\n type=\"number\"\n required\n name=\"index\"\n inputDisplayNormalizer\n focus\n [isFocused]=\"setFocus\"\n [formControl]=\"formControl\" />\n </mat-form-field>\n }\n @case (SettingType.Boolean) {\n <div\n class=\"toggle\"\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\">\n <label class=\"switch\">\n <input type=\"checkbox\" name=\"index\" [formControl]=\"formControl\" />\n <span class=\"slider\"></span>\n </label>\n </div>\n }\n }\n</ng-template>\n", styles: [".switch{display:inline-flex;align-items:center;width:66px;height:30px}.switch input{display:none}.switch input:checked+.slider{background-color:var(--flag-bool-slider-on)}.switch input:checked+.slider:before{transform:translate(36px)}.switch input:checked+.slider:after{content:\"On\";padding-left:0;padding-right:12px}.switch .slider{display:flex;align-items:center;justify-content:center;cursor:pointer;width:66px;height:30px;background-color:var(--flag-bool-slider-off);transition:background-color .4s;border-radius:34px;position:relative}.switch .slider:before{content:\"\";position:absolute;left:4px;height:22px;width:22px;background-color:var(--flag-bool-slider-remaining);transition:transform .4s;border-radius:50%}.switch .slider:after{content:\"Off\";color:var(--flag-bool-slider-remaining);font-size:10px;font-family:Verdana,sans-serif;padding-right:0;padding-left:11px}\n", ".content .mat-column-color{padding-left:4px!important;padding-right:4px!important;padding-top:12px}.content .mat-column-reorder{padding-right:0!important;padding-top:16px}.content .mat-column-usages{min-width:120px}.content .row.align-top{vertical-align:top}.content .delete{padding-top:6px}.content .drag-handle{cursor:-webkit-grab;cursor:-moz-grab;line-height:8px}.content .toggle{padding-left:4px}.content .usages{display:flex;align-items:center;padding:6px 0}.content .usages .usage{padding:2px 8px 2px 0}.content .usages .usage-button{align-self:flex-start}.content .predefined-component{padding:12px 0}.content .predefined-component.variationid{padding-top:15px}.content .small-error{max-width:180px}.content .add-variation{padding-top:8px;padding-bottom:8px;display:flex}.content .dialog-description{padding-top:8px;padding-bottom:16px}.content .dialog-table{padding-top:0;padding-bottom:0}\n"], dependencies: [{ kind: "component", type: LoaderComponent, selector: "app-loader", inputs: ["skipTimeOut"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.AsyncValidationDirective, selector: "[ngModel],[formControlName],[formControl]", inputs: ["async"] }, { kind: "directive", type: i2.RxwebFormDirective, selector: "[formGroup],[rxwebForm]", inputs: ["formGroup", "rxwebForm"] }, { kind: "directive", type: i2.RxFormControlDirective, selector: "[ngModel],[formControlName],[formControl]", inputs: ["rxalpha", "rxalphaNumeric", "rxascii", "rxcompare", "rxcompose", "rxcontains", "rxcreditCard", "rxdataUri", "rxdifferent", "rxdigit", "rxemail", "rxendsWith", "rxeven", "rxextension", "rxfactor", "rxfileSize", "rxgreaterThanEqualTo", "rxgreaterThan", "rxhexColor", "rxjson", "rxlatitude", "rxlatLong", "rxleapYear", "rxlessThan", "rxlessThanEqualTo", "rxlongitude", "rxlowerCase", "rxmac", "rxmaxDate", "rxmaxLength", "rxmaxNumber", "rxminDate", "rxminLength", "rxminNumber", "rxnumeric", "rxodd", "rxpassword", "rxport", "rxprimeNumber", "rxrequired", "rxrange", "rxrule", "rxstartsWith", "rxtime", "rxupperCase", "rxurl", "rxunique", "rxnotEmpty", "rxcusip", "rxgrid", "rxdate"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "component", type: MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "directive", type: MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "component", type: MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: DigitOnlyDirective, selector: "[appDigitOnly]", inputs: ["digitOnlyDecimal", "digitOnlyDecimalSeparator", "digitOnlyAllowNegatives", "digitOnlyAllowPaste", "digitOnlyNegativeSign"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: CopyableValueComponent, selector: "app-copyable-value", inputs: ["tooltip", "tooltipClass", "hint", "warnHint", "name", "value", "small", "bold", "borderless", "smallest", "dark", "wholeControlCopyable"] }, { kind: "directive", type: AutofocusDirective, selector: "[focus]", inputs: ["isFocused"] }] }); }
3800
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: VariationsDialogComponent, isStandalone: true, selector: "app-variations-dialog", ngImport: i0, template: "@if (setting.isLoading()) {\n <div mat-dialog-content class=\"content\">\n <app-loader />\n </div>\n} @else {\n <form [formGroup]=\"formGroup\" (ngSubmit)=\"onSubmit()\">\n <h1 mat-dialog-title>{{ data.manage ? \"Manage predefined variations\" : \"View predefined variations\" }}</h1>\n <div class=\"content\">\n <div class=\"dialog-description\" mat-dialog-content>\n @if (data.manage) {\n <p>\n Add, delete, and update predefined variations of the\n <strong>{{ data.settingName }}</strong>\n setting.\n <br />\n The\n <strong>served value</strong>\n is sent to SDKs and received by your applications. The\n <strong>display name</strong>\n appears in the targeting UI.\n <br />\n You can update a value or delete a variation only if it is not in use. As a help, you can see where each\n variation is used.\n </p>\n } @else {\n <p>\n The\n <strong>served value</strong>\n is sent to SDKs and received by your applications. The\n <strong>display name</strong>\n appears in the targeting UI.\n </p>\n }\n </div>\n\n <div class=\"dialog-table\" mat-dialog-content>\n <table\n mat-table\n cdkDropList\n [dataSource]=\"dataSource\"\n [cdkDropListData]=\"dataSource\"\n [cdkDropListDisabled]=\"!data.manage || settingType === SettingType.Boolean\"\n (cdkDropListDropped)=\"dropTable($event)\">\n <ng-container matColumnDef=\"reorder\">\n <th *matHeaderCellDef mat-header-cell></th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"drag-handle\">\n <div cdkDragHandle matTooltip=\"Drag here to reorder\" matTooltipPosition=\"above\">\n <mat-icon>drag_indicator</mat-icon>\n </div>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"color\">\n <th *matHeaderCellDef mat-header-cell></th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n <span [class]=\"'variation-indicator variation-color-' + getColorIndex(row, i)\"></span>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"value\">\n <th *matHeaderCellDef mat-header-cell>Served value *</th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n @switch (settingType) {\n @case (SettingType.Boolean) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.boolValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingType.String) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.stringValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingType.Int) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.intValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingType.Double) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.doubleValue,\n setFocus: i === focusIndex,\n }\" />\n }\n }\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"name\">\n <th *matHeaderCellDef mat-header-cell>Display name (optional)</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"small-form-field\">\n <input\n matInput\n [formControl]=\"row.controls.name\"\n [placeholder]=\"row.controls.valueForComparison.value\" />\n @if (row.controls.name.invalid) {\n <mat-error class=\"small-error\">\n {{ formHelper.getErrorMessage(row.controls.name) }}\n </mat-error>\n }\n </mat-form-field>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"hint\">\n <th *matHeaderCellDef mat-header-cell>Hint (optional)</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"small-form-field suffixed\">\n <input matInput [formControl]=\"row.controls.hint\" />\n <button\n matSuffix\n class=\"input-suffix-button\"\n type=\"button\"\n mat-icon-button\n matTooltip=\"Advanced editor\"\n (click)=\"expandHint(row.controls.hint)\">\n <mat-icon class=\"icon-transform-rotate\">edit_note</mat-icon>\n </button>\n @if (row.controls.hint.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(row.controls.hint) }}\n </mat-error>\n }\n </mat-form-field>\n </div>\n </td>\n </ng-container>\n <ng-container matColumnDef=\"variationId\">\n <th *matHeaderCellDef mat-header-cell>Variation ID</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <app-copyable-value [value]=\"row.controls.variationId.value\" [small]=\"true\" />\n </td>\n </ng-container>\n <ng-container matColumnDef=\"usages\">\n <th *matHeaderCellDef mat-header-cell>Usages</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <div class=\"usages\">\n <button\n type=\"button\"\n class=\"usage-button\"\n mat-icon-button\n [disabled]=\"!row.controls.usages.controls.length && !row.controls.usagesInOtherEnvironments.value\"\n (click)=\"row.controls.usagesExpanded.setValue(!row.controls.usagesExpanded.value)\">\n @if (row.controls.usagesExpanded.value) {\n <mat-icon>expand_less</mat-icon>\n } @else {\n <mat-icon>expand_more</mat-icon>\n }\n </button>\n <div>\n @if (row.controls.usagesExpanded.value) {\n @for (usage of row.controls.usages.controls; track $index) {\n <div class=\"usage\">\n <a target=\"_blank\" rel=\"noopener noreferrer\" [href]=\"usage.controls.routerLink.value\">\n {{ usage.controls.displayValue.value }}\n </a>\n </div>\n }\n @if (row.controls.usagesInOtherEnvironments.value > 0) {\n {{ row.controls.usagesInOtherEnvironments.value }} usage{{\n row.controls.usagesInOtherEnvironments.value > 1 ? \"s\" : \"\"\n }}\n in environments you don't have access to.\n } @else if (row.controls.usages.controls.length === 0) {\n <div>no usages</div>\n }\n } @else {\n <div>\n @if (row.controls.usages.controls.length + row.controls.usagesInOtherEnvironments.value > 0) {\n {{ row.controls.usages.controls.length + row.controls.usagesInOtherEnvironments.value }}\n usage{{\n row.controls.usages.controls.length + row.controls.usagesInOtherEnvironments.value > 1\n ? \"s\"\n : \"\"\n }}\n } @else {\n <div>no usages</div>\n }\n </div>\n }\n </div>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"actions\">\n <th *matHeaderCellDef mat-header-cell>{{ dataSource.data.length }} / {{ maxPredefinedVariations }}</th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div\n class=\"delete\"\n [matTooltip]=\"\n formGroup.controls.predefinedVariations.controls.length > 2\n ? 'Cannot remove a variation that is already in use.'\n : 'At least 2 predefined variations should be set.'\n \"\n [matTooltipDisabled]=\"\n row.controls.usages.controls.length === 0 &&\n row.controls.usagesInOtherEnvironments.value === 0 &&\n formGroup.controls.predefinedVariations.controls.length > 2\n \">\n <button\n mat-icon-button\n type=\"button\"\n matTooltip=\"Remove variation\"\n [disabled]=\"\n formGroup.controls.predefinedVariations.controls.length <= 2 ||\n row.controls.usages.controls.length > 0 ||\n row.controls.usagesInOtherEnvironments.value > 0\n \"\n (click)=\"removeVariation(i)\">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n <tr *matHeaderRowDef=\"displayedColumns\" mat-header-row></tr>\n <tr *matRowDef=\"let row; columns: displayedColumns\" mat-row cdkDrag [cdkDragData]=\"row\"></tr>\n </table>\n @if (\n formGroup.controls.predefinedVariations.invalid &&\n formHelper.getErrorMessage(formGroup.controls.predefinedVariations)\n ) {\n <mat-error>\n {{ formHelper.getErrorMessage(formGroup.controls.predefinedVariations) }}\n </mat-error>\n }\n </div>\n @if (data.manage && settingType !== SettingType.Boolean) {\n <div class=\"add-variation\" mat-dialog-content>\n <div\n [matTooltip]=\"'Maximum ' + maxPredefinedVariations + ' variations can be added.'\"\n [matTooltipDisabled]=\"dataSource.data.length < maxPredefinedVariations\">\n <button\n type=\"button\"\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"dataSource.data.length >= maxPredefinedVariations\"\n (click)=\"addVariation()\">\n <mat-icon>add</mat-icon>\n Add variation\n </button>\n </div>\n </div>\n }\n </div>\n\n <div mat-dialog-actions>\n @if (data.manage) {\n <button\n type=\"submit\"\n mat-flat-button\n color=\"primary\"\n [disabled]=\"submitting() || !formGroup.dirty || !formGroup.valid\">\n Save\n </button>\n <button type=\"button\" mat-stroked-button [mat-dialog-close]>Cancel</button>\n } @else {\n <button type=\"button\" color=\"primary\" mat-flat-button [mat-dialog-close]>Close</button>\n }\n </div>\n </form>\n}\n\n<ng-template #settingValueTemplate let-formControl=\"formControl\" let-setFocus=\"setFocus\">\n @switch (settingType) {\n @case (SettingType.String) {\n <mat-form-field class=\"small-form-field text suffixed\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <input\n matInput\n type=\"text\"\n placeholder=\"Add text ...\"\n focus\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\"\n [isFocused]=\"setFocus\"\n [formControl]=\"formControl\" />\n <button\n matSuffix\n class=\"input-suffix-button\"\n type=\"button\"\n mat-icon-button\n matTooltip=\"Advanced editor\"\n (click)=\"expandText(formControl)\">\n <mat-icon class=\"icon-transform-rotate\">edit_note</mat-icon>\n </button>\n @if (formControl.invalid) {\n <mat-error class=\"small-error\">\n {{ formHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n </mat-form-field>\n }\n @case (SettingType.Int) {\n <mat-form-field\n class=\"small-form-field\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\">\n @if (formControl.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n <input\n matInput\n type=\"number\"\n required\n name=\"index\"\n appDigitOnly\n focus\n [isFocused]=\"setFocus\"\n [formControl]=\"formControl\"\n [digitOnlyAllowNegatives]=\"true\" />\n </mat-form-field>\n }\n @case (SettingType.Double) {\n <mat-form-field\n class=\"small-form-field\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\">\n @if (formControl.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n <input\n matInput\n type=\"number\"\n required\n name=\"index\"\n inputDisplayNormalizer\n focus\n [isFocused]=\"setFocus\"\n [formControl]=\"formControl\" />\n </mat-form-field>\n }\n @case (SettingType.Boolean) {\n <div\n class=\"toggle\"\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\">\n <label class=\"switch\">\n <input type=\"checkbox\" name=\"index\" [formControl]=\"formControl\" />\n <span class=\"slider\"></span>\n </label>\n </div>\n }\n }\n</ng-template>\n", styles: [".switch{display:inline-flex;align-items:center;width:66px;height:30px}.switch input{display:none}.switch input:checked+.slider{background-color:var(--flag-bool-slider-on)}.switch input:checked+.slider:before{transform:translate(36px)}.switch input:checked+.slider:after{content:\"On\";padding-left:0;padding-right:12px}.switch .slider{display:flex;align-items:center;justify-content:center;cursor:pointer;width:66px;height:30px;background-color:var(--flag-bool-slider-off);transition:background-color .4s;border-radius:34px;position:relative}.switch .slider:before{content:\"\";position:absolute;left:4px;height:22px;width:22px;background-color:var(--flag-bool-slider-remaining);transition:transform .4s;border-radius:50%}.switch .slider:after{content:\"Off\";color:var(--flag-bool-slider-remaining);font-size:10px;font-family:Verdana,sans-serif;padding-right:0;padding-left:11px}\n", ".content .mat-column-color{padding-left:4px!important;padding-right:4px!important;padding-top:12px}.content .mat-column-reorder{padding-right:0!important;padding-top:16px}.content .mat-column-usages{min-width:120px}.content .row.align-top{vertical-align:top}.content .delete{padding-top:6px}.content .drag-handle{cursor:-webkit-grab;cursor:-moz-grab;line-height:8px}.content .toggle{padding-left:4px}.content .usages{display:flex;align-items:center;padding:6px 0}.content .usages .usage{padding:2px 8px 2px 0}.content .usages .usage-button{align-self:flex-start}.content .predefined-component{padding:12px 0}.content .predefined-component.variationid{padding-top:15px}.content .small-error{max-width:180px}.content .add-variation{padding-top:8px;padding-bottom:8px;display:flex}.content .dialog-description{padding-top:8px;padding-bottom:16px}.content .dialog-table{padding-top:0;padding-bottom:0}\n"], dependencies: [{ kind: "component", type: LoaderComponent, selector: "app-loader", inputs: ["skipTimeOut"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.AsyncValidationDirective, selector: "[ngModel],[formControlName],[formControl]", inputs: ["async"] }, { kind: "directive", type: i2.RxwebFormDirective, selector: "[formGroup],[rxwebForm]", inputs: ["formGroup", "rxwebForm"] }, { kind: "directive", type: i2.RxFormControlDirective, selector: "[ngModel],[formControlName],[formControl]", inputs: ["rxalpha", "rxalphaNumeric", "rxascii", "rxcompare", "rxcompose", "rxcontains", "rxcreditCard", "rxdataUri", "rxdifferent", "rxdigit", "rxemail", "rxendsWith", "rxeven", "rxextension", "rxfactor", "rxfileSize", "rxgreaterThanEqualTo", "rxgreaterThan", "rxhexColor", "rxjson", "rxlatitude", "rxlatLong", "rxleapYear", "rxlessThan", "rxlessThanEqualTo", "rxlongitude", "rxlowerCase", "rxmac", "rxmaxDate", "rxmaxLength", "rxmaxNumber", "rxminDate", "rxminLength", "rxminNumber", "rxnumeric", "rxodd", "rxpassword", "rxport", "rxprimeNumber", "rxrequired", "rxrange", "rxrule", "rxstartsWith", "rxtime", "rxupperCase", "rxurl", "rxunique", "rxnotEmpty", "rxcusip", "rxgrid", "rxdate"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "component", type: MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "directive", type: MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "component", type: MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: DigitOnlyDirective, selector: "[appDigitOnly]", inputs: ["digitOnlyDecimal", "digitOnlyDecimalSeparator", "digitOnlyAllowNegatives", "digitOnlyAllowPaste", "digitOnlyNegativeSign"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: CopyableValueComponent, selector: "app-copyable-value", inputs: ["tooltip", "tooltipClass", "hint", "warnHint", "name", "value", "small", "bold", "borderless", "smallest", "dark", "wholeControlCopyable"] }, { kind: "directive", type: AutofocusDirective, selector: "[focus]", inputs: ["isFocused"] }] }); }
3801
3801
  }
3802
3802
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: VariationsDialogComponent, decorators: [{
3803
3803
  type: Component,
@@ -3836,7 +3836,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
3836
3836
  CdkDragHandle,
3837
3837
  CopyableValueComponent,
3838
3838
  AutofocusDirective
3839
- ], template: "@if (setting.isLoading()) {\n <div mat-dialog-content class=\"content\">\n <app-loader />\n </div>\n} @else {\n <form [formGroup]=\"formGroup\" (ngSubmit)=\"onSubmit()\">\n <h1 mat-dialog-title>{{ data.manage ? \"Manage predefined variations\" : \"View predefined variations\" }}</h1>\n <div class=\"content\">\n <div class=\"dialog-description\" mat-dialog-content>\n @if (data.manage) {\n <p>\n Add, delete, and update predefined variations of the\n <strong>{{ data.settingName }}</strong>\n setting.\n <br />\n The\n <strong>served value</strong>\n is sent to SDKs and received by your applications. The\n <strong>display name</strong>\n appears in the targeting UI.\n <br />\n You can update a value or delete a variation only if it is not in use. As a help, you can see where each\n variation is used.\n </p>\n } @else {\n <p>\n The\n <strong>served value</strong>\n is sent to SDKs and received by your applications. The\n <strong>display name</strong>\n appears in the targeting UI.\n </p>\n }\n </div>\n\n <div class=\"dialog-table\" mat-dialog-content>\n <table\n mat-table\n cdkDropList\n [dataSource]=\"dataSource\"\n [cdkDropListData]=\"dataSource\"\n [cdkDropListDisabled]=\"!data.manage || settingType === SettingType.Boolean\"\n (cdkDropListDropped)=\"dropTable($event)\">\n <ng-container matColumnDef=\"reorder\">\n <th *matHeaderCellDef mat-header-cell></th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"drag-handle\">\n <div cdkDragHandle matTooltip=\"Drag here to reorder\" matTooltipPosition=\"above\">\n <mat-icon>drag_indicator</mat-icon>\n </div>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"color\">\n <th *matHeaderCellDef mat-header-cell></th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n <span [class]=\"'variation-indicator variation-color-' + getColorIndex(row, i)\"></span>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"value\">\n <th *matHeaderCellDef mat-header-cell>Served value *</th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n @switch (settingType) {\n @case (SettingType.Boolean) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.boolValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingType.String) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.stringValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingType.Int) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.intValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingType.Double) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.doubleValue,\n setFocus: i === focusIndex,\n }\" />\n }\n }\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"name\">\n <th *matHeaderCellDef mat-header-cell>Display name (optional)</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"small-form-field\">\n <input\n matInput\n [formControl]=\"row.controls.name\"\n [placeholder]=\"row.controls.valueForComparison.value\" />\n @if (row.controls.name.invalid) {\n <mat-error class=\"small-error\">\n {{ formHelper.getErrorMessage(row.controls.name) }}\n </mat-error>\n }\n </mat-form-field>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"hint\">\n <th *matHeaderCellDef mat-header-cell>Hint (optional)</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"small-form-field suffixed\">\n <input matInput [formControl]=\"row.controls.hint\" />\n <button\n matSuffix\n class=\"input-suffix-button\"\n type=\"button\"\n mat-icon-button\n matTooltip=\"Advanced editor\"\n (click)=\"expandHint(row.controls.hint)\">\n <mat-icon class=\"icon-transform-rotate\">edit_note</mat-icon>\n </button>\n @if (row.controls.hint.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(row.controls.hint) }}\n </mat-error>\n }\n </mat-form-field>\n </div>\n </td>\n </ng-container>\n <ng-container matColumnDef=\"variationId\">\n <th *matHeaderCellDef mat-header-cell>Variation ID</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <app-copyable-value [value]=\"row.controls.variationId.value\" [small]=\"true\" />\n </td>\n </ng-container>\n <ng-container matColumnDef=\"usages\">\n <th *matHeaderCellDef mat-header-cell>Usages</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <div class=\"usages\">\n <button\n type=\"button\"\n class=\"usage-button\"\n mat-icon-button\n [disabled]=\"!row.controls.usages.controls.length && !row.controls.usagesInOtherEnvironments.value\"\n (click)=\"row.controls.usagesExpanded.setValue(!row.controls.usagesExpanded.value)\">\n @if (row.controls.usagesExpanded.value) {\n <mat-icon>expand_less</mat-icon>\n } @else {\n <mat-icon>expand_more</mat-icon>\n }\n </button>\n <div>\n @if (row.controls.usagesExpanded.value) {\n @for (usage of row.controls.usages.controls; track $index) {\n <div class=\"usage\">\n <a target=\"_blank\" rel=\"noopener noreferrer\" [href]=\"usage.controls.routerLink.value\">\n {{ usage.controls.displayValue.value }}\n </a>\n </div>\n }\n @if (row.controls.usagesInOtherEnvironments.value > 0) {\n {{ row.controls.usagesInOtherEnvironments.value }} usage{{\n row.controls.usagesInOtherEnvironments.value > 1 ? \"s\" : \"\"\n }}\n in environments you don't have access to.\n } @else if (row.controls.usages.controls.length === 0) {\n <div>no usages</div>\n }\n } @else {\n <div>\n @if (row.controls.usages.controls.length + row.controls.usagesInOtherEnvironments.value > 0) {\n {{ row.controls.usages.controls.length + row.controls.usagesInOtherEnvironments.value }}\n usage{{\n row.controls.usages.controls.length + row.controls.usagesInOtherEnvironments.value > 1\n ? \"s\"\n : \"\"\n }}\n } @else {\n <div>no usages</div>\n }\n </div>\n }\n </div>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"actions\">\n <th *matHeaderCellDef mat-header-cell>{{ dataSource.data.length }} / {{ maxPredefinedVariations }}</th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div\n class=\"delete\"\n [matTooltip]=\"\n formGroup.controls.predefinedVariations.controls.length > 2\n ? 'Cannot remove a variation that is already in use.'\n : 'At least 2 predefined variations should be set.'\n \"\n [matTooltipDisabled]=\"\n row.controls.usages.controls.length === 0 &&\n formGroup.controls.predefinedVariations.controls.length > 2\n \">\n <button\n mat-icon-button\n type=\"button\"\n matTooltip=\"Remove variation\"\n [disabled]=\"\n formGroup.controls.predefinedVariations.controls.length <= 2 ||\n row.controls.usages.controls.length > 0\n \"\n (click)=\"removeVariation(i)\">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n <tr *matHeaderRowDef=\"displayedColumns\" mat-header-row></tr>\n <tr *matRowDef=\"let row; columns: displayedColumns\" mat-row cdkDrag [cdkDragData]=\"row\"></tr>\n </table>\n @if (\n formGroup.controls.predefinedVariations.invalid &&\n formHelper.getErrorMessage(formGroup.controls.predefinedVariations)\n ) {\n <mat-error>\n {{ formHelper.getErrorMessage(formGroup.controls.predefinedVariations) }}\n </mat-error>\n }\n </div>\n @if (data.manage && settingType !== SettingType.Boolean) {\n <div class=\"add-variation\" mat-dialog-content>\n <div\n [matTooltip]=\"'Maximum ' + maxPredefinedVariations + ' variations can be added.'\"\n [matTooltipDisabled]=\"dataSource.data.length < maxPredefinedVariations\">\n <button\n type=\"button\"\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"dataSource.data.length >= maxPredefinedVariations\"\n (click)=\"addVariation()\">\n <mat-icon>add</mat-icon>\n Add variation\n </button>\n </div>\n </div>\n }\n </div>\n\n <div mat-dialog-actions>\n @if (data.manage) {\n <button\n type=\"submit\"\n mat-flat-button\n color=\"primary\"\n [disabled]=\"submitting() || !formGroup.dirty || !formGroup.valid\">\n Save\n </button>\n <button type=\"button\" mat-stroked-button [mat-dialog-close]>Cancel</button>\n } @else {\n <button type=\"button\" color=\"primary\" mat-flat-button [mat-dialog-close]>Close</button>\n }\n </div>\n </form>\n}\n\n<ng-template #settingValueTemplate let-formControl=\"formControl\" let-setFocus=\"setFocus\">\n @switch (settingType) {\n @case (SettingType.String) {\n <mat-form-field class=\"small-form-field text suffixed\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <input\n matInput\n type=\"text\"\n placeholder=\"Add text ...\"\n focus\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\"\n [isFocused]=\"setFocus\"\n [formControl]=\"formControl\" />\n <button\n matSuffix\n class=\"input-suffix-button\"\n type=\"button\"\n mat-icon-button\n matTooltip=\"Advanced editor\"\n (click)=\"expandText(formControl)\">\n <mat-icon class=\"icon-transform-rotate\">edit_note</mat-icon>\n </button>\n @if (formControl.invalid) {\n <mat-error class=\"small-error\">\n {{ formHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n </mat-form-field>\n }\n @case (SettingType.Int) {\n <mat-form-field\n class=\"small-form-field\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\">\n @if (formControl.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n <input\n matInput\n type=\"number\"\n required\n name=\"index\"\n appDigitOnly\n focus\n [isFocused]=\"setFocus\"\n [formControl]=\"formControl\"\n [digitOnlyAllowNegatives]=\"true\" />\n </mat-form-field>\n }\n @case (SettingType.Double) {\n <mat-form-field\n class=\"small-form-field\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\">\n @if (formControl.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n <input\n matInput\n type=\"number\"\n required\n name=\"index\"\n inputDisplayNormalizer\n focus\n [isFocused]=\"setFocus\"\n [formControl]=\"formControl\" />\n </mat-form-field>\n }\n @case (SettingType.Boolean) {\n <div\n class=\"toggle\"\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\">\n <label class=\"switch\">\n <input type=\"checkbox\" name=\"index\" [formControl]=\"formControl\" />\n <span class=\"slider\"></span>\n </label>\n </div>\n }\n }\n</ng-template>\n", styles: [".switch{display:inline-flex;align-items:center;width:66px;height:30px}.switch input{display:none}.switch input:checked+.slider{background-color:var(--flag-bool-slider-on)}.switch input:checked+.slider:before{transform:translate(36px)}.switch input:checked+.slider:after{content:\"On\";padding-left:0;padding-right:12px}.switch .slider{display:flex;align-items:center;justify-content:center;cursor:pointer;width:66px;height:30px;background-color:var(--flag-bool-slider-off);transition:background-color .4s;border-radius:34px;position:relative}.switch .slider:before{content:\"\";position:absolute;left:4px;height:22px;width:22px;background-color:var(--flag-bool-slider-remaining);transition:transform .4s;border-radius:50%}.switch .slider:after{content:\"Off\";color:var(--flag-bool-slider-remaining);font-size:10px;font-family:Verdana,sans-serif;padding-right:0;padding-left:11px}\n", ".content .mat-column-color{padding-left:4px!important;padding-right:4px!important;padding-top:12px}.content .mat-column-reorder{padding-right:0!important;padding-top:16px}.content .mat-column-usages{min-width:120px}.content .row.align-top{vertical-align:top}.content .delete{padding-top:6px}.content .drag-handle{cursor:-webkit-grab;cursor:-moz-grab;line-height:8px}.content .toggle{padding-left:4px}.content .usages{display:flex;align-items:center;padding:6px 0}.content .usages .usage{padding:2px 8px 2px 0}.content .usages .usage-button{align-self:flex-start}.content .predefined-component{padding:12px 0}.content .predefined-component.variationid{padding-top:15px}.content .small-error{max-width:180px}.content .add-variation{padding-top:8px;padding-bottom:8px;display:flex}.content .dialog-description{padding-top:8px;padding-bottom:16px}.content .dialog-table{padding-top:0;padding-bottom:0}\n"] }]
3839
+ ], template: "@if (setting.isLoading()) {\n <div mat-dialog-content class=\"content\">\n <app-loader />\n </div>\n} @else {\n <form [formGroup]=\"formGroup\" (ngSubmit)=\"onSubmit()\">\n <h1 mat-dialog-title>{{ data.manage ? \"Manage predefined variations\" : \"View predefined variations\" }}</h1>\n <div class=\"content\">\n <div class=\"dialog-description\" mat-dialog-content>\n @if (data.manage) {\n <p>\n Add, delete, and update predefined variations of the\n <strong>{{ data.settingName }}</strong>\n setting.\n <br />\n The\n <strong>served value</strong>\n is sent to SDKs and received by your applications. The\n <strong>display name</strong>\n appears in the targeting UI.\n <br />\n You can update a value or delete a variation only if it is not in use. As a help, you can see where each\n variation is used.\n </p>\n } @else {\n <p>\n The\n <strong>served value</strong>\n is sent to SDKs and received by your applications. The\n <strong>display name</strong>\n appears in the targeting UI.\n </p>\n }\n </div>\n\n <div class=\"dialog-table\" mat-dialog-content>\n <table\n mat-table\n cdkDropList\n [dataSource]=\"dataSource\"\n [cdkDropListData]=\"dataSource\"\n [cdkDropListDisabled]=\"!data.manage || settingType === SettingType.Boolean\"\n (cdkDropListDropped)=\"dropTable($event)\">\n <ng-container matColumnDef=\"reorder\">\n <th *matHeaderCellDef mat-header-cell></th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"drag-handle\">\n <div cdkDragHandle matTooltip=\"Drag here to reorder\" matTooltipPosition=\"above\">\n <mat-icon>drag_indicator</mat-icon>\n </div>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"color\">\n <th *matHeaderCellDef mat-header-cell></th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n <span [class]=\"'variation-indicator variation-color-' + getColorIndex(row, i)\"></span>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"value\">\n <th *matHeaderCellDef mat-header-cell>Served value *</th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n @switch (settingType) {\n @case (SettingType.Boolean) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.boolValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingType.String) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.stringValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingType.Int) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.intValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingType.Double) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.doubleValue,\n setFocus: i === focusIndex,\n }\" />\n }\n }\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"name\">\n <th *matHeaderCellDef mat-header-cell>Display name (optional)</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"small-form-field\">\n <input\n matInput\n [formControl]=\"row.controls.name\"\n [placeholder]=\"row.controls.valueForComparison.value\" />\n @if (row.controls.name.invalid) {\n <mat-error class=\"small-error\">\n {{ formHelper.getErrorMessage(row.controls.name) }}\n </mat-error>\n }\n </mat-form-field>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"hint\">\n <th *matHeaderCellDef mat-header-cell>Hint (optional)</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"small-form-field suffixed\">\n <input matInput [formControl]=\"row.controls.hint\" />\n <button\n matSuffix\n class=\"input-suffix-button\"\n type=\"button\"\n mat-icon-button\n matTooltip=\"Advanced editor\"\n (click)=\"expandHint(row.controls.hint)\">\n <mat-icon class=\"icon-transform-rotate\">edit_note</mat-icon>\n </button>\n @if (row.controls.hint.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(row.controls.hint) }}\n </mat-error>\n }\n </mat-form-field>\n </div>\n </td>\n </ng-container>\n <ng-container matColumnDef=\"variationId\">\n <th *matHeaderCellDef mat-header-cell>Variation ID</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <app-copyable-value [value]=\"row.controls.variationId.value\" [small]=\"true\" />\n </td>\n </ng-container>\n <ng-container matColumnDef=\"usages\">\n <th *matHeaderCellDef mat-header-cell>Usages</th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <div class=\"usages\">\n <button\n type=\"button\"\n class=\"usage-button\"\n mat-icon-button\n [disabled]=\"!row.controls.usages.controls.length && !row.controls.usagesInOtherEnvironments.value\"\n (click)=\"row.controls.usagesExpanded.setValue(!row.controls.usagesExpanded.value)\">\n @if (row.controls.usagesExpanded.value) {\n <mat-icon>expand_less</mat-icon>\n } @else {\n <mat-icon>expand_more</mat-icon>\n }\n </button>\n <div>\n @if (row.controls.usagesExpanded.value) {\n @for (usage of row.controls.usages.controls; track $index) {\n <div class=\"usage\">\n <a target=\"_blank\" rel=\"noopener noreferrer\" [href]=\"usage.controls.routerLink.value\">\n {{ usage.controls.displayValue.value }}\n </a>\n </div>\n }\n @if (row.controls.usagesInOtherEnvironments.value > 0) {\n {{ row.controls.usagesInOtherEnvironments.value }} usage{{\n row.controls.usagesInOtherEnvironments.value > 1 ? \"s\" : \"\"\n }}\n in environments you don't have access to.\n } @else if (row.controls.usages.controls.length === 0) {\n <div>no usages</div>\n }\n } @else {\n <div>\n @if (row.controls.usages.controls.length + row.controls.usagesInOtherEnvironments.value > 0) {\n {{ row.controls.usages.controls.length + row.controls.usagesInOtherEnvironments.value }}\n usage{{\n row.controls.usages.controls.length + row.controls.usagesInOtherEnvironments.value > 1\n ? \"s\"\n : \"\"\n }}\n } @else {\n <div>no usages</div>\n }\n </div>\n }\n </div>\n </div>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"actions\">\n <th *matHeaderCellDef mat-header-cell>{{ dataSource.data.length }} / {{ maxPredefinedVariations }}</th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div\n class=\"delete\"\n [matTooltip]=\"\n formGroup.controls.predefinedVariations.controls.length > 2\n ? 'Cannot remove a variation that is already in use.'\n : 'At least 2 predefined variations should be set.'\n \"\n [matTooltipDisabled]=\"\n row.controls.usages.controls.length === 0 &&\n row.controls.usagesInOtherEnvironments.value === 0 &&\n formGroup.controls.predefinedVariations.controls.length > 2\n \">\n <button\n mat-icon-button\n type=\"button\"\n matTooltip=\"Remove variation\"\n [disabled]=\"\n formGroup.controls.predefinedVariations.controls.length <= 2 ||\n row.controls.usages.controls.length > 0 ||\n row.controls.usagesInOtherEnvironments.value > 0\n \"\n (click)=\"removeVariation(i)\">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </td>\n </ng-container>\n <tr *matHeaderRowDef=\"displayedColumns\" mat-header-row></tr>\n <tr *matRowDef=\"let row; columns: displayedColumns\" mat-row cdkDrag [cdkDragData]=\"row\"></tr>\n </table>\n @if (\n formGroup.controls.predefinedVariations.invalid &&\n formHelper.getErrorMessage(formGroup.controls.predefinedVariations)\n ) {\n <mat-error>\n {{ formHelper.getErrorMessage(formGroup.controls.predefinedVariations) }}\n </mat-error>\n }\n </div>\n @if (data.manage && settingType !== SettingType.Boolean) {\n <div class=\"add-variation\" mat-dialog-content>\n <div\n [matTooltip]=\"'Maximum ' + maxPredefinedVariations + ' variations can be added.'\"\n [matTooltipDisabled]=\"dataSource.data.length < maxPredefinedVariations\">\n <button\n type=\"button\"\n mat-stroked-button\n color=\"primary\"\n [disabled]=\"dataSource.data.length >= maxPredefinedVariations\"\n (click)=\"addVariation()\">\n <mat-icon>add</mat-icon>\n Add variation\n </button>\n </div>\n </div>\n }\n </div>\n\n <div mat-dialog-actions>\n @if (data.manage) {\n <button\n type=\"submit\"\n mat-flat-button\n color=\"primary\"\n [disabled]=\"submitting() || !formGroup.dirty || !formGroup.valid\">\n Save\n </button>\n <button type=\"button\" mat-stroked-button [mat-dialog-close]>Cancel</button>\n } @else {\n <button type=\"button\" color=\"primary\" mat-flat-button [mat-dialog-close]>Close</button>\n }\n </div>\n </form>\n}\n\n<ng-template #settingValueTemplate let-formControl=\"formControl\" let-setFocus=\"setFocus\">\n @switch (settingType) {\n @case (SettingType.String) {\n <mat-form-field class=\"small-form-field text suffixed\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <input\n matInput\n type=\"text\"\n placeholder=\"Add text ...\"\n focus\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\"\n [isFocused]=\"setFocus\"\n [formControl]=\"formControl\" />\n <button\n matSuffix\n class=\"input-suffix-button\"\n type=\"button\"\n mat-icon-button\n matTooltip=\"Advanced editor\"\n (click)=\"expandText(formControl)\">\n <mat-icon class=\"icon-transform-rotate\">edit_note</mat-icon>\n </button>\n @if (formControl.invalid) {\n <mat-error class=\"small-error\">\n {{ formHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n </mat-form-field>\n }\n @case (SettingType.Int) {\n <mat-form-field\n class=\"small-form-field\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\">\n @if (formControl.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n <input\n matInput\n type=\"number\"\n required\n name=\"index\"\n appDigitOnly\n focus\n [isFocused]=\"setFocus\"\n [formControl]=\"formControl\"\n [digitOnlyAllowNegatives]=\"true\" />\n </mat-form-field>\n }\n @case (SettingType.Double) {\n <mat-form-field\n class=\"small-form-field\"\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\">\n @if (formControl.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n <input\n matInput\n type=\"number\"\n required\n name=\"index\"\n inputDisplayNormalizer\n focus\n [isFocused]=\"setFocus\"\n [formControl]=\"formControl\" />\n </mat-form-field>\n }\n @case (SettingType.Boolean) {\n <div\n class=\"toggle\"\n matTooltip=\"This variation is in use. The value cannot be changed.\"\n [matTooltipDisabled]=\"!formControl.disabled || !data.manage\">\n <label class=\"switch\">\n <input type=\"checkbox\" name=\"index\" [formControl]=\"formControl\" />\n <span class=\"slider\"></span>\n </label>\n </div>\n }\n }\n</ng-template>\n", styles: [".switch{display:inline-flex;align-items:center;width:66px;height:30px}.switch input{display:none}.switch input:checked+.slider{background-color:var(--flag-bool-slider-on)}.switch input:checked+.slider:before{transform:translate(36px)}.switch input:checked+.slider:after{content:\"On\";padding-left:0;padding-right:12px}.switch .slider{display:flex;align-items:center;justify-content:center;cursor:pointer;width:66px;height:30px;background-color:var(--flag-bool-slider-off);transition:background-color .4s;border-radius:34px;position:relative}.switch .slider:before{content:\"\";position:absolute;left:4px;height:22px;width:22px;background-color:var(--flag-bool-slider-remaining);transition:transform .4s;border-radius:50%}.switch .slider:after{content:\"Off\";color:var(--flag-bool-slider-remaining);font-size:10px;font-family:Verdana,sans-serif;padding-right:0;padding-left:11px}\n", ".content .mat-column-color{padding-left:4px!important;padding-right:4px!important;padding-top:12px}.content .mat-column-reorder{padding-right:0!important;padding-top:16px}.content .mat-column-usages{min-width:120px}.content .row.align-top{vertical-align:top}.content .delete{padding-top:6px}.content .drag-handle{cursor:-webkit-grab;cursor:-moz-grab;line-height:8px}.content .toggle{padding-left:4px}.content .usages{display:flex;align-items:center;padding:6px 0}.content .usages .usage{padding:2px 8px 2px 0}.content .usages .usage-button{align-self:flex-start}.content .predefined-component{padding:12px 0}.content .predefined-component.variationid{padding-top:15px}.content .small-error{max-width:180px}.content .add-variation{padding-top:8px;padding-bottom:8px;display:flex}.content .dialog-description{padding-top:8px;padding-bottom:16px}.content .dialog-table{padding-top:0;padding-bottom:0}\n"] }]
3840
3840
  }] });
3841
3841
 
3842
3842
  class DependeesDialogComponent {
@@ -6296,7 +6296,7 @@ class FeatureFlagItemComponent extends BaseComponent {
6296
6296
  this.saveSucceeded.emit();
6297
6297
  },
6298
6298
  error: (error) => {
6299
- console.log(error);
6299
+ this.submitting = false;
6300
6300
  if (error instanceof HttpErrorResponse
6301
6301
  && error.status === 400
6302
6302
  && FormHelper.getHttpErrorResponseMessage(error, "Reason") === "Reason required.") {
@@ -6307,9 +6307,6 @@ class FeatureFlagItemComponent extends BaseComponent {
6307
6307
  if (result?.button === "save" && result.reason) {
6308
6308
  this.updateSettingValues(updateModel, result.reason);
6309
6309
  }
6310
- else {
6311
- this.submitting = false;
6312
- }
6313
6310
  });
6314
6311
  return;
6315
6312
  }
@@ -6321,10 +6318,28 @@ class FeatureFlagItemComponent extends BaseComponent {
6321
6318
  });
6322
6319
  return;
6323
6320
  }
6321
+ if (error instanceof HttpErrorResponse
6322
+ && error.status === 400
6323
+ && FormHelper.getHttpErrorResponseMessage(error, "PrerequisiteFlagCondition") === "Prerequisite setting not found.") {
6324
+ const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
6325
+ width: "450px",
6326
+ data: {
6327
+ title: "Cannot save feature flags",
6328
+ body: "A feature flag referenced in a prerequisite condition has been deleted. Reload the config to see its latest state, apply your changes and try the save again.",
6329
+ yesButtonLabel: "Reload",
6330
+ hideCancelButton: true,
6331
+ },
6332
+ });
6333
+ dialogRef.afterClosed().subscribe(() => {
6334
+ this.reloadSettingValues();
6335
+ });
6336
+ return;
6337
+ }
6324
6338
  if (error instanceof HttpErrorResponse
6325
6339
  && error.status === 400
6326
6340
  && (FormHelper.getHttpErrorResponseMessage(error, "DefaultValue")?.includes("Variation could not be found.")
6327
6341
  || FormHelper.getHttpErrorResponseMessage(error, "Value")?.includes("Variation could not be found.")
6342
+ || FormHelper.getHttpErrorResponseMessage(error, "PrerequisiteComparisonValue")?.includes("Variation could not be found.")
6328
6343
  || FormHelper.getHttpErrorResponseMessage(error, "PredefinedVariationId")?.includes("Could not find Variation."))) {
6329
6344
  this.openDiscardDialog("Cannot save feature flags", "A predefined variation referenced by one of your feature flags has been deleted. Reload the config to see its latest state, apply your changes and try the save again.", "Reload", "", true, "450px").subscribe(() => {
6330
6345
  this.reloadSettingValues();