ng-configcat-publicapi-ui 5.3.15 → 5.4.0

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.
@@ -43,6 +43,7 @@ import { CdkCopyToClipboard, Clipboard } from '@angular/cdk/clipboard';
43
43
  import { ENTER, COMMA } from '@angular/cdk/keycodes';
44
44
  import { MatRadioGroup, MatRadioButton } from '@angular/material/radio';
45
45
  import { MatPaginator } from '@angular/material/paginator';
46
+ import { MatCheckbox } from '@angular/material/checkbox';
46
47
 
47
48
  const defaultPublicApiBasePath = "https://api.configcat.com";
48
49
  const defaultDashboardBasePath = "https://app.configcat.com";
@@ -289,6 +290,9 @@ class FormHelper {
289
290
  if (control.hasError("max")) {
290
291
  return "The value must be less than " + (control.errors["max"].max + 1) + ".";
291
292
  }
293
+ if (control.hasError("json")) {
294
+ return "The value must be valid JSON.";
295
+ }
292
296
  return "";
293
297
  }
294
298
  /**
@@ -690,6 +694,17 @@ function nonEmptyStringValidator(c) {
690
694
  }
691
695
  return errors;
692
696
  }
697
+ function jsonValidator(c) {
698
+ if (typeof c.value !== "string")
699
+ return { json: { valid: false } };
700
+ try {
701
+ JSON.parse(c.value);
702
+ }
703
+ catch {
704
+ return { json: { valid: false } };
705
+ }
706
+ return null;
707
+ }
693
708
  // eslint-disable-next-line sonarjs/no-invariant-returns
694
709
  function validateUniqueVariations(c) {
695
710
  const control = c;
@@ -748,36 +763,36 @@ function getValueControl(control) {
748
763
 
749
764
  function generateSettingValuesFormGroup(model, readOnly, settings, featureFlagLimitations) {
750
765
  return new FormGroup({
751
- defaultValue: generateValueFormGroup(model.defaultValue, model.setting.settingType, model.setting.predefinedVariations, readOnly, featureFlagLimitations),
766
+ defaultValue: generateValueFormGroup(model.defaultValue, model.setting.settingType, model.setting.predefinedVariations, readOnly, featureFlagLimitations, model.setting.isJson),
752
767
  percentageEvaluationAttribute: generatePercentageEvaluationAttributeFormControl(model.percentageEvaluationAttribute, readOnly),
753
- targetingRules: new FormArray(model.targetingRules.map(ft => generateTargetingRuleFormGroup(ft, model.setting.settingType, model.setting.predefinedVariations, readOnly, settings, featureFlagLimitations))),
768
+ targetingRules: new FormArray(model.targetingRules.map(ft => generateTargetingRuleFormGroup(ft, model.setting.settingType, model.setting.predefinedVariations, readOnly, settings, featureFlagLimitations, model.setting.isJson))),
754
769
  });
755
770
  }
756
771
  function generatePercentageEvaluationAttributeFormControl(percentageEvaluationAttribute, readOnly) {
757
772
  return new FormControl({ value: percentageEvaluationAttribute, disabled: readOnly }, { validators: [validateEmptyString, Validators.maxLength(1000)], nonNullable: true });
758
773
  }
759
- function generateTargetingRuleFormGroup(model, settingType, predefinedVariations, readOnly, settings, featureFlagLimitations) {
774
+ function generateTargetingRuleFormGroup(model, settingType, predefinedVariations, readOnly, settings, featureFlagLimitations, isJson) {
760
775
  const conditions = new FormArray(model.conditions.map(tr => generateConditionFormGroup(tr, readOnly, settings, featureFlagLimitations)));
761
776
  if (model.percentageOptions.length > 0) {
762
777
  return new FormGroup({
763
778
  conditions,
764
- percentageOptions: new FormArray(model.percentageOptions.map(pr => generatePercentageOptionFormGroup(pr, settingType, predefinedVariations, readOnly, featureFlagLimitations)), [validatePercentageSum]),
779
+ percentageOptions: new FormArray(model.percentageOptions.map(pr => generatePercentageOptionFormGroup(pr, settingType, predefinedVariations, readOnly, featureFlagLimitations, isJson)), [validatePercentageSum]),
765
780
  });
766
781
  }
767
782
  else if (model.value) {
768
783
  return new FormGroup({
769
784
  conditions,
770
- value: generateValueFormGroup(model.value, settingType, predefinedVariations, readOnly, featureFlagLimitations),
785
+ value: generateValueFormGroup(model.value, settingType, predefinedVariations, readOnly, featureFlagLimitations, isJson),
771
786
  });
772
787
  }
773
788
  throw Error("Invalid model");
774
789
  }
775
- function generateTargetingRuleWithEmptyPercentageOptions(settingType, predefinedVariations, readOnly, settings, featureFlagLimitations) {
790
+ function generateTargetingRuleWithEmptyPercentageOptions(settingType, predefinedVariations, readOnly, settings, featureFlagLimitations, isJson) {
776
791
  return generateTargetingRuleFormGroup({
777
792
  conditions: [],
778
793
  percentageOptions: getEmptyPercentageOptions(settingType, predefinedVariations, featureFlagLimitations),
779
794
  value: null,
780
- }, settingType, predefinedVariations, readOnly, settings, featureFlagLimitations);
795
+ }, settingType, predefinedVariations, readOnly, settings, featureFlagLimitations, isJson);
781
796
  }
782
797
  function getEmptyPercentageOptions(settingType, predefinedVariations, featureFlagLimitations) {
783
798
  if (predefinedVariations.length) {
@@ -807,7 +822,7 @@ function getEmptyPercentageOptions(settingType, predefinedVariations, featureFla
807
822
  throw new Error("Invalid SettingType");
808
823
  }
809
824
  }
810
- function generatePercentageOptionFormGroup(model, settingType, predefinedVariations, readOnly, featureFlagLimitations) {
825
+ function generatePercentageOptionFormGroup(model, settingType, predefinedVariations, readOnly, featureFlagLimitations, isJson) {
811
826
  return new FormGroup({
812
827
  percentage: new FormControl({ value: model.percentage, disabled: readOnly }, {
813
828
  nonNullable: true,
@@ -819,7 +834,7 @@ function generatePercentageOptionFormGroup(model, settingType, predefinedVariati
819
834
  Validators.pattern(percentageRegex),
820
835
  ],
821
836
  }),
822
- value: generateValueFormGroup(model.value, settingType, predefinedVariations, readOnly || settingType === SettingType.Boolean, featureFlagLimitations),
837
+ value: generateValueFormGroup(model.value, settingType, predefinedVariations, readOnly || settingType === SettingType.Boolean, featureFlagLimitations, isJson),
823
838
  });
824
839
  }
825
840
  function generateConditionFormGroup(model, readOnly, settings, featureFlagLimitations) {
@@ -876,14 +891,14 @@ function generatePrerequisiteFlagConditionFormGroup(value, readOnly, settings, f
876
891
  return new FormGroup({
877
892
  prerequisiteSettingId: new FormControl({ value: value.prerequisiteSettingId, disabled: readOnly }, { nonNullable: true, validators: [Validators.required] }),
878
893
  comparator: new FormControl({ value: comparator, disabled: readOnly }, { nonNullable: true, validators: [Validators.required] }),
879
- prerequisiteComparisonValue: generateValueFormGroup({ boolValue: true, intValue: null, doubleValue: null, stringValue: null, predefinedVariationId: null }, setting.settingType, setting.predefinedVariations, readOnly, featureFlagLimitations),
894
+ prerequisiteComparisonValue: generateValueFormGroup({ boolValue: true, intValue: null, doubleValue: null, stringValue: null, predefinedVariationId: null }, setting.settingType, setting.predefinedVariations, readOnly, featureFlagLimitations, setting.isJson),
880
895
  });
881
896
  }
882
897
  else {
883
898
  return new FormGroup({
884
899
  prerequisiteSettingId: new FormControl({ value: value.prerequisiteSettingId, disabled: readOnly }, { nonNullable: true, validators: [Validators.required] }),
885
900
  comparator: new FormControl({ value: value.comparator, disabled: readOnly }, { nonNullable: true, validators: [Validators.required] }),
886
- prerequisiteComparisonValue: generateValueFormGroup(value.prerequisiteComparisonValue, setting.settingType, setting.predefinedVariations, readOnly, featureFlagLimitations),
901
+ prerequisiteComparisonValue: generateValueFormGroup(value.prerequisiteComparisonValue, setting.settingType, setting.predefinedVariations, readOnly, featureFlagLimitations, setting.isJson),
887
902
  });
888
903
  }
889
904
  }
@@ -903,7 +918,7 @@ function generateEmptyPrerequisiteFlagConditionFormGroup(featureFlagLimitations)
903
918
  nonNullable: true,
904
919
  validators: [Validators.required],
905
920
  }),
906
- prerequisiteComparisonValue: generateValueFormGroup({ boolValue: true, intValue: null, doubleValue: null, stringValue: null, predefinedVariationId: null }, SettingType.Boolean, [], false, featureFlagLimitations),
921
+ prerequisiteComparisonValue: generateValueFormGroup({ boolValue: true, intValue: null, doubleValue: null, stringValue: null, predefinedVariationId: null }, SettingType.Boolean, [], false, featureFlagLimitations, false),
907
922
  });
908
923
  }
909
924
  function getNextIndex(formArray) {
@@ -1016,10 +1031,10 @@ function generatePrerequisiteDefaultValue(settingType, predefinedVariations) {
1016
1031
  throw new Error("Invalid SettingType");
1017
1032
  }
1018
1033
  }
1019
- function generateDefaultValueFormGroup(settingType, predefinedVariations, readOnly, featureFlagLimitations) {
1020
- return generateValueFormGroup(generateDefaultValue(settingType, predefinedVariations), settingType, predefinedVariations, readOnly, featureFlagLimitations);
1034
+ function generateDefaultValueFormGroup(settingType, predefinedVariations, readOnly, featureFlagLimitations, isJson) {
1035
+ return generateValueFormGroup(generateDefaultValue(settingType, predefinedVariations), settingType, predefinedVariations, readOnly, featureFlagLimitations, isJson);
1021
1036
  }
1022
- function generateValueFormGroup(value, settingType, predefinedVariations, readOnly, featureFlagLimitations) {
1037
+ function generateValueFormGroup(value, settingType, predefinedVariations, readOnly, featureFlagLimitations, isJson) {
1023
1038
  if (predefinedVariations.length) {
1024
1039
  return new FormGroup({
1025
1040
  predefinedVariationId: new FormControl({ value: value.predefinedVariationId ?? predefinedVariations[0].predefinedVariationId, disabled: readOnly }, { nonNullable: true, validators: [Validators.required] }),
@@ -1032,7 +1047,7 @@ function generateValueFormGroup(value, settingType, predefinedVariations, readOn
1032
1047
  });
1033
1048
  case SettingType.String:
1034
1049
  return new FormGroup({
1035
- stringValue: new FormControl({ value: value.stringValue ?? "", disabled: readOnly }, { nonNullable: true, validators: getValidatorsForSettingType(settingType, featureFlagLimitations) }),
1050
+ stringValue: new FormControl({ value: value.stringValue ?? "", disabled: readOnly }, { nonNullable: true, validators: getValidatorsForSettingType(settingType, featureFlagLimitations, isJson) }),
1036
1051
  });
1037
1052
  case SettingType.Int:
1038
1053
  return new FormGroup({
@@ -1094,7 +1109,7 @@ function getComparisonValueType(comparator) {
1094
1109
  throw new Error("Invalid comparator");
1095
1110
  }
1096
1111
  }
1097
- function getValidatorsForSettingType(settingType, featureFlagLimitations) {
1112
+ function getValidatorsForSettingType(settingType, featureFlagLimitations, isJson = false) {
1098
1113
  switch (settingType) {
1099
1114
  case SettingType.Int:
1100
1115
  return [
@@ -1112,7 +1127,9 @@ function getValidatorsForSettingType(settingType, featureFlagLimitations) {
1112
1127
  Validators.max(Number.MAX_VALUE),
1113
1128
  ];
1114
1129
  case SettingType.String:
1115
- return [Validators.required, Validators.maxLength(featureFlagLimitations.maxStringFlagValueLength)];
1130
+ return isJson
1131
+ ? [Validators.required, Validators.maxLength(featureFlagLimitations.maxStringFlagValueLength), jsonValidator]
1132
+ : [Validators.required, Validators.maxLength(featureFlagLimitations.maxStringFlagValueLength)];
1116
1133
  case SettingType.Boolean:
1117
1134
  return [Validators.required];
1118
1135
  default:
@@ -1962,7 +1979,6 @@ class AceEditorComponent {
1962
1979
  }
1963
1980
  }, ...(ngDevMode ? [{ debugName: "valueSetEffect" }] : /* istanbul ignore next */ []));
1964
1981
  this.readOnly = input(false, ...(ngDevMode ? [{ debugName: "readOnly" }] : /* istanbul ignore next */ []));
1965
- this.valueChange = output();
1966
1982
  // eslint-disable-next-line @angular-eslint/no-output-on-prefix
1967
1983
  this.onChange = output();
1968
1984
  }
@@ -1995,7 +2011,7 @@ class AceEditorComponent {
1995
2011
  this.onChangeModel(this._value);
1996
2012
  }
1997
2013
  this.onChange.emit(this._value);
1998
- this.valueChange.emit(this._value);
2014
+ this.value.set(this._value);
1999
2015
  }
2000
2016
  });
2001
2017
  }
@@ -2051,7 +2067,7 @@ class AceEditorComponent {
2051
2067
  /* unused */
2052
2068
  }
2053
2069
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: AceEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2054
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.17", type: AceEditorComponent, isStandalone: true, selector: "app-ace-editor", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, readOnly: { classPropertyName: "readOnly", publicName: "readOnly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", valueChange: "valueChange", onChange: "onChange" }, providers: [
2070
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.17", type: AceEditorComponent, isStandalone: true, selector: "app-ace-editor", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, readOnly: { classPropertyName: "readOnly", publicName: "readOnly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", onChange: "onChange" }, providers: [
2055
2071
  {
2056
2072
  provide: NG_VALUE_ACCESSOR,
2057
2073
  useExisting: forwardRef(() => AceEditorComponent),
@@ -2068,7 +2084,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
2068
2084
  multi: true,
2069
2085
  },
2070
2086
  ], preserveWhitespaces: false, template: "<div #aceEditor class=\"ace-editor-container\"></div>\n", styles: [".ace-editor-container{width:100%;height:100%;border:thin solid var(--input-border-color);box-sizing:border-box}\n"] }]
2071
- }], propDecorators: { editor: [{ type: i0.ViewChild, args: ["aceEditor", { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], readOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readOnly", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], onChange: [{ type: i0.Output, args: ["onChange"] }] } });
2087
+ }], propDecorators: { editor: [{ type: i0.ViewChild, args: ["aceEditor", { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], readOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readOnly", required: false }] }], onChange: [{ type: i0.Output, args: ["onChange"] }] } });
2072
2088
 
2073
2089
  class PopOutEditorComponent {
2074
2090
  constructor() {
@@ -2807,9 +2823,8 @@ class SettingItemComponent extends BaseComponent {
2807
2823
  this.showEnvironmentName = input(true, ...(ngDevMode ? [{ debugName: "showEnvironmentName" }] : /* istanbul ignore next */ []));
2808
2824
  this.deleteSettingRequested = output();
2809
2825
  this.loadSucceeded = output();
2810
- this.loadFailed = output();
2811
2826
  this.saveSucceeded = output();
2812
- this.saveFailed = output();
2827
+ this.componentError = output();
2813
2828
  this.formValuesChanged = output();
2814
2829
  this.loadSettingValues = () => {
2815
2830
  return this.createSettingValuesService()
@@ -2825,7 +2840,7 @@ class SettingItemComponent extends BaseComponent {
2825
2840
  };
2826
2841
  return settingValues;
2827
2842
  }), catchError((error) => {
2828
- this.loadFailed.emit(error);
2843
+ this.componentError.emit(error);
2829
2844
  throw error;
2830
2845
  }));
2831
2846
  };
@@ -2835,6 +2850,7 @@ class SettingItemComponent extends BaseComponent {
2835
2850
  .pipe(map(segments => {
2836
2851
  return segments;
2837
2852
  }), catchError((error) => {
2853
+ this.componentError.emit(error);
2838
2854
  throw error;
2839
2855
  }));
2840
2856
  };
@@ -2856,6 +2872,9 @@ class SettingItemComponent extends BaseComponent {
2856
2872
  };
2857
2873
  this.saveSucceeded.emit(settingValues);
2858
2874
  return settingValues;
2875
+ }), catchError((error) => {
2876
+ this.componentError.emit(error);
2877
+ throw error;
2859
2878
  }));
2860
2879
  };
2861
2880
  this.dashboardBasePath = this.getDashboardBasePath();
@@ -2863,8 +2882,8 @@ class SettingItemComponent extends BaseComponent {
2863
2882
  itemLoadSucceeded() {
2864
2883
  this.loadSucceeded.emit(true);
2865
2884
  }
2866
- itenSaveFailed(error) {
2867
- this.saveFailed.emit(error);
2885
+ itemSaveFailed(error) {
2886
+ this.componentError.emit(error);
2868
2887
  }
2869
2888
  onDeleteSettingRequested(setting) {
2870
2889
  this.deleteSettingRequested.emit({
@@ -2877,12 +2896,12 @@ class SettingItemComponent extends BaseComponent {
2877
2896
  this.formValuesChanged.emit();
2878
2897
  }
2879
2898
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SettingItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2880
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: SettingItemComponent, isStandalone: true, selector: "app-setting-item", inputs: { productId: { classPropertyName: "productId", publicName: "productId", isSignal: true, isRequired: true, transformFunction: null }, environmentId: { classPropertyName: "environmentId", publicName: "environmentId", isSignal: true, isRequired: true, transformFunction: null }, configId: { classPropertyName: "configId", publicName: "configId", isSignal: true, isRequired: true, transformFunction: null }, settingId: { classPropertyName: "settingId", publicName: "settingId", isSignal: true, isRequired: true, transformFunction: null }, canDeleteSetting: { classPropertyName: "canDeleteSetting", publicName: "canDeleteSetting", isSignal: true, isRequired: false, transformFunction: null }, deleteSettingText: { classPropertyName: "deleteSettingText", publicName: "deleteSettingText", isSignal: true, isRequired: false, transformFunction: null }, showEnvironmentName: { classPropertyName: "showEnvironmentName", publicName: "showEnvironmentName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { deleteSettingRequested: "deleteSettingRequested", loadSucceeded: "loadSucceeded", loadFailed: "loadFailed", saveSucceeded: "saveSucceeded", saveFailed: "saveFailed", formValuesChanged: "formValuesChanged" }, usesInheritance: true, ngImport: i0, template: "<app-setting-list\n [canDeleteSetting]=\"canDeleteSetting()\"\n [onSave]=\"handleSave\"\n [loadSettingValues]=\"loadSettingValues\"\n [loadSegments]=\"loadSegments\"\n [deleteSettingText]=\"deleteSettingText()\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [productId]=\"productId()\"\n [configId]=\"configId()\"\n [environmentId]=\"environmentId()\"\n [dashboardBasePath]=\"dashboardBasePath\"\n (loadSucceeded)=\"itemLoadSucceeded()\"\n (saveFailed)=\"itenSaveFailed($event)\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\"\n (formValuesChanged)=\"onFormValuesChanged()\" />\n", styles: [".end{margin-left:auto}.flex{display:flex;flex-wrap:wrap;align-items:center}.show-hide-toggle{margin-left:1em;cursor:pointer}@media(max-width:1200px){.setting-full .setting-details{width:300px}}@media(max-width:700px){.setting-full{flex-wrap:wrap}.setting-full .setting-details{padding:.2em 0 .2em .2em}.setting-full .all-other{margin:.5em .3em}}\n"], dependencies: [{ kind: "component", type: SettingListComponent, selector: "app-setting-list", inputs: ["productId", "environmentId", "configId", "dashboardBasePath", "canDeleteSetting", "onSave", "loadSettingValues", "loadSegments", "deleteSettingText", "showEnvironmentName"], outputs: ["loadSucceeded", "deleteSettingRequested", "formValuesChanged", "saveFailed"] }] }); }
2899
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: SettingItemComponent, isStandalone: true, selector: "app-setting-item", inputs: { productId: { classPropertyName: "productId", publicName: "productId", isSignal: true, isRequired: true, transformFunction: null }, environmentId: { classPropertyName: "environmentId", publicName: "environmentId", isSignal: true, isRequired: true, transformFunction: null }, configId: { classPropertyName: "configId", publicName: "configId", isSignal: true, isRequired: true, transformFunction: null }, settingId: { classPropertyName: "settingId", publicName: "settingId", isSignal: true, isRequired: true, transformFunction: null }, canDeleteSetting: { classPropertyName: "canDeleteSetting", publicName: "canDeleteSetting", isSignal: true, isRequired: false, transformFunction: null }, deleteSettingText: { classPropertyName: "deleteSettingText", publicName: "deleteSettingText", isSignal: true, isRequired: false, transformFunction: null }, showEnvironmentName: { classPropertyName: "showEnvironmentName", publicName: "showEnvironmentName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { deleteSettingRequested: "deleteSettingRequested", loadSucceeded: "loadSucceeded", saveSucceeded: "saveSucceeded", componentError: "componentError", formValuesChanged: "formValuesChanged" }, usesInheritance: true, ngImport: i0, template: "<app-setting-list\n [canDeleteSetting]=\"canDeleteSetting()\"\n [onSave]=\"handleSave\"\n [loadSettingValues]=\"loadSettingValues\"\n [loadSegments]=\"loadSegments\"\n [deleteSettingText]=\"deleteSettingText()\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [productId]=\"productId()\"\n [configId]=\"configId()\"\n [environmentId]=\"environmentId()\"\n [dashboardBasePath]=\"dashboardBasePath\"\n (loadSucceeded)=\"itemLoadSucceeded()\"\n (saveFailed)=\"itemSaveFailed($event)\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\"\n (formValuesChanged)=\"onFormValuesChanged()\" />\n", styles: [".end{margin-left:auto}.flex{display:flex;flex-wrap:wrap;align-items:center}.show-hide-toggle{margin-left:1em;cursor:pointer}@media(max-width:1200px){.setting-full .setting-details{width:300px}}@media(max-width:700px){.setting-full{flex-wrap:wrap}.setting-full .setting-details{padding:.2em 0 .2em .2em}.setting-full .all-other{margin:.5em .3em}}\n"], dependencies: [{ kind: "component", type: SettingListComponent, selector: "app-setting-list", inputs: ["productId", "environmentId", "configId", "dashboardBasePath", "canDeleteSetting", "onSave", "loadSettingValues", "loadSegments", "deleteSettingText", "showEnvironmentName"], outputs: ["loadSucceeded", "deleteSettingRequested", "formValuesChanged", "saveFailed"] }] }); }
2881
2900
  }
2882
2901
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SettingItemComponent, decorators: [{
2883
2902
  type: Component,
2884
- args: [{ selector: "app-setting-item", imports: [SettingListComponent], template: "<app-setting-list\n [canDeleteSetting]=\"canDeleteSetting()\"\n [onSave]=\"handleSave\"\n [loadSettingValues]=\"loadSettingValues\"\n [loadSegments]=\"loadSegments\"\n [deleteSettingText]=\"deleteSettingText()\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [productId]=\"productId()\"\n [configId]=\"configId()\"\n [environmentId]=\"environmentId()\"\n [dashboardBasePath]=\"dashboardBasePath\"\n (loadSucceeded)=\"itemLoadSucceeded()\"\n (saveFailed)=\"itenSaveFailed($event)\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\"\n (formValuesChanged)=\"onFormValuesChanged()\" />\n", styles: [".end{margin-left:auto}.flex{display:flex;flex-wrap:wrap;align-items:center}.show-hide-toggle{margin-left:1em;cursor:pointer}@media(max-width:1200px){.setting-full .setting-details{width:300px}}@media(max-width:700px){.setting-full{flex-wrap:wrap}.setting-full .setting-details{padding:.2em 0 .2em .2em}.setting-full .all-other{margin:.5em .3em}}\n"] }]
2885
- }], ctorParameters: () => [], propDecorators: { productId: [{ type: i0.Input, args: [{ isSignal: true, alias: "productId", required: true }] }], environmentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "environmentId", required: true }] }], configId: [{ type: i0.Input, args: [{ isSignal: true, alias: "configId", required: true }] }], settingId: [{ type: i0.Input, args: [{ isSignal: true, alias: "settingId", required: true }] }], canDeleteSetting: [{ type: i0.Input, args: [{ isSignal: true, alias: "canDeleteSetting", required: false }] }], deleteSettingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "deleteSettingText", required: false }] }], showEnvironmentName: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEnvironmentName", required: false }] }], deleteSettingRequested: [{ type: i0.Output, args: ["deleteSettingRequested"] }], loadSucceeded: [{ type: i0.Output, args: ["loadSucceeded"] }], loadFailed: [{ type: i0.Output, args: ["loadFailed"] }], saveSucceeded: [{ type: i0.Output, args: ["saveSucceeded"] }], saveFailed: [{ type: i0.Output, args: ["saveFailed"] }], formValuesChanged: [{ type: i0.Output, args: ["formValuesChanged"] }] } });
2903
+ args: [{ selector: "app-setting-item", imports: [SettingListComponent], template: "<app-setting-list\n [canDeleteSetting]=\"canDeleteSetting()\"\n [onSave]=\"handleSave\"\n [loadSettingValues]=\"loadSettingValues\"\n [loadSegments]=\"loadSegments\"\n [deleteSettingText]=\"deleteSettingText()\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [productId]=\"productId()\"\n [configId]=\"configId()\"\n [environmentId]=\"environmentId()\"\n [dashboardBasePath]=\"dashboardBasePath\"\n (loadSucceeded)=\"itemLoadSucceeded()\"\n (saveFailed)=\"itemSaveFailed($event)\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\"\n (formValuesChanged)=\"onFormValuesChanged()\" />\n", styles: [".end{margin-left:auto}.flex{display:flex;flex-wrap:wrap;align-items:center}.show-hide-toggle{margin-left:1em;cursor:pointer}@media(max-width:1200px){.setting-full .setting-details{width:300px}}@media(max-width:700px){.setting-full{flex-wrap:wrap}.setting-full .setting-details{padding:.2em 0 .2em .2em}.setting-full .all-other{margin:.5em .3em}}\n"] }]
2904
+ }], ctorParameters: () => [], propDecorators: { productId: [{ type: i0.Input, args: [{ isSignal: true, alias: "productId", required: true }] }], environmentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "environmentId", required: true }] }], configId: [{ type: i0.Input, args: [{ isSignal: true, alias: "configId", required: true }] }], settingId: [{ type: i0.Input, args: [{ isSignal: true, alias: "settingId", required: true }] }], canDeleteSetting: [{ type: i0.Input, args: [{ isSignal: true, alias: "canDeleteSetting", required: false }] }], deleteSettingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "deleteSettingText", required: false }] }], showEnvironmentName: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEnvironmentName", required: false }] }], deleteSettingRequested: [{ type: i0.Output, args: ["deleteSettingRequested"] }], loadSucceeded: [{ type: i0.Output, args: ["loadSucceeded"] }], saveSucceeded: [{ type: i0.Output, args: ["saveSucceeded"] }], componentError: [{ type: i0.Output, args: ["componentError"] }], formValuesChanged: [{ type: i0.Output, args: ["formValuesChanged"] }] } });
2886
2905
 
2887
2906
  class AuthorizationComponent {
2888
2907
  constructor() {
@@ -2955,6 +2974,7 @@ class ProductSelectComponent extends BaseSelectComponent {
2955
2974
  super(...arguments);
2956
2975
  this.valueFormControl = input.required(...(ngDevMode ? [{ debugName: "valueFormControl" }] : /* istanbul ignore next */ []));
2957
2976
  this.preSelectedProductId = input(...(ngDevMode ? [undefined, { debugName: "preSelectedProductId" }] : /* istanbul ignore next */ []));
2977
+ this.componentError = output();
2958
2978
  this.filterText = signal("", ...(ngDevMode ? [{ debugName: "filterText" }] : /* istanbul ignore next */ []));
2959
2979
  this.tooltips = viewChildren(MatTooltip, ...(ngDevMode ? [{ debugName: "tooltips" }] : /* istanbul ignore next */ []));
2960
2980
  this.filteredProducts = linkedSignal(() => {
@@ -2991,6 +3011,9 @@ class ProductSelectComponent extends BaseSelectComponent {
2991
3011
  else {
2992
3012
  this.valueFormControl().setValue("");
2993
3013
  }
3014
+ }), catchError$1((error) => {
3015
+ this.componentError.emit(error);
3016
+ return of([]);
2994
3017
  }));
2995
3018
  },
2996
3019
  });
@@ -3006,7 +3029,7 @@ class ProductSelectComponent extends BaseSelectComponent {
3006
3029
  }
3007
3030
  }
3008
3031
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ProductSelectComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3009
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: ProductSelectComponent, isStandalone: true, selector: "app-product-select", inputs: { valueFormControl: { classPropertyName: "valueFormControl", publicName: "valueFormControl", isSignal: true, isRequired: true, transformFunction: null }, preSelectedProductId: { classPropertyName: "preSelectedProductId", publicName: "preSelectedProductId", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "tooltips", predicate: MatTooltip, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Product</mat-label>\n <mat-select\n #productSelect=\"matSelect\"\n placeholder=\"Product\"\n name=\"productValue\"\n [formControl]=\"valueFormControl()\"\n [panelClass]=\"customDropdown() ? 'custom-dropdown-below' : ''\"\n (openedChange)=\"onSelectOpenedChange($event)\">\n <div class=\"menu-filter small-density-form-field\">\n <mat-form-field\n subscriptSizing=\"dynamic\"\n appearance=\"outline\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <input matInput placeholder=\"Filter products\" [(ngModel)]=\"filterText\" />\n <span matSuffix [hidden]=\"!filterText()\">\n <button\n type=\"button\"\n mat-icon-button\n class=\"clear-filter\"\n aria-label=\"Clear\"\n matTooltip=\"Clear search filters\"\n (click)=\"clearFilter()\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </mat-form-field>\n </div>\n <mat-divider />\n @for (product of filteredProducts(); track product.productId) {\n <mat-option\n [value]=\"product.productId\"\n [ngClass]=\"{ hidden: product.hidden }\"\n [matTooltip]=\"\n product.description ? `Name: ${product.name}\\nDescription: ${product.description}` : `Name: ${product.name}`\n \"\n [matTooltipDisabled]=\"!productSelect.panelOpen\"\n [matTooltipClass]=\"['wide-tooltip', 'multiline-tooltip', 'left-aligned']\">\n {{ product.name }}\n </mat-option>\n } @empty {\n <mat-option disabled>No product available.</mat-option>\n }\n @if (!hasFilteredProduct()) {\n <mat-option disabled>No product found.</mat-option>\n }\n </mat-select>\n</mat-form-field>\n", styles: [".form-field{width:100%}.filter{display:flex;margin:0 8px 8px;justify-content:space-around}.filter mat-form-field{width:100%}.hidden{display:none}\n"], dependencies: [{ kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.AsyncValidationDirective, selector: "[ngModel],[formControlName],[formControl]", inputs: ["async"] }, { 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: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] }); }
3032
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: ProductSelectComponent, isStandalone: true, selector: "app-product-select", inputs: { valueFormControl: { classPropertyName: "valueFormControl", publicName: "valueFormControl", isSignal: true, isRequired: true, transformFunction: null }, preSelectedProductId: { classPropertyName: "preSelectedProductId", publicName: "preSelectedProductId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { componentError: "componentError" }, viewQueries: [{ propertyName: "tooltips", predicate: MatTooltip, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Product</mat-label>\n <mat-select\n #productSelect=\"matSelect\"\n placeholder=\"Product\"\n name=\"productValue\"\n [formControl]=\"valueFormControl()\"\n [panelClass]=\"customDropdown() ? 'custom-dropdown-below' : ''\"\n (openedChange)=\"onSelectOpenedChange($event)\">\n <div class=\"menu-filter small-density-form-field\">\n <mat-form-field\n subscriptSizing=\"dynamic\"\n appearance=\"outline\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <input matInput placeholder=\"Filter products\" [(ngModel)]=\"filterText\" />\n <span matSuffix [hidden]=\"!filterText()\">\n <button\n type=\"button\"\n mat-icon-button\n class=\"clear-filter\"\n aria-label=\"Clear\"\n matTooltip=\"Clear search filters\"\n (click)=\"clearFilter()\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </mat-form-field>\n </div>\n <mat-divider />\n @for (product of filteredProducts(); track product.productId) {\n <mat-option\n [value]=\"product.productId\"\n [ngClass]=\"{ hidden: product.hidden }\"\n [matTooltip]=\"\n product.description ? `Name: ${product.name}\\nDescription: ${product.description}` : `Name: ${product.name}`\n \"\n [matTooltipDisabled]=\"!productSelect.panelOpen\"\n [matTooltipClass]=\"['wide-tooltip', 'multiline-tooltip', 'left-aligned']\">\n {{ product.name }}\n </mat-option>\n } @empty {\n <mat-option disabled>No product available.</mat-option>\n }\n @if (!hasFilteredProduct()) {\n <mat-option disabled>No product found.</mat-option>\n }\n </mat-select>\n</mat-form-field>\n", styles: [".form-field{width:100%}.filter{display:flex;margin:0 8px 8px;justify-content:space-around}.filter mat-form-field{width:100%}.hidden{display:none}\n"], dependencies: [{ kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.AsyncValidationDirective, selector: "[ngModel],[formControlName],[formControl]", inputs: ["async"] }, { 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: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] }); }
3010
3033
  }
3011
3034
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ProductSelectComponent, decorators: [{
3012
3035
  type: Component,
@@ -3026,7 +3049,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3026
3049
  MatSuffix,
3027
3050
  MatIconButton,
3028
3051
  ], template: "<mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Product</mat-label>\n <mat-select\n #productSelect=\"matSelect\"\n placeholder=\"Product\"\n name=\"productValue\"\n [formControl]=\"valueFormControl()\"\n [panelClass]=\"customDropdown() ? 'custom-dropdown-below' : ''\"\n (openedChange)=\"onSelectOpenedChange($event)\">\n <div class=\"menu-filter small-density-form-field\">\n <mat-form-field\n subscriptSizing=\"dynamic\"\n appearance=\"outline\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <input matInput placeholder=\"Filter products\" [(ngModel)]=\"filterText\" />\n <span matSuffix [hidden]=\"!filterText()\">\n <button\n type=\"button\"\n mat-icon-button\n class=\"clear-filter\"\n aria-label=\"Clear\"\n matTooltip=\"Clear search filters\"\n (click)=\"clearFilter()\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </mat-form-field>\n </div>\n <mat-divider />\n @for (product of filteredProducts(); track product.productId) {\n <mat-option\n [value]=\"product.productId\"\n [ngClass]=\"{ hidden: product.hidden }\"\n [matTooltip]=\"\n product.description ? `Name: ${product.name}\\nDescription: ${product.description}` : `Name: ${product.name}`\n \"\n [matTooltipDisabled]=\"!productSelect.panelOpen\"\n [matTooltipClass]=\"['wide-tooltip', 'multiline-tooltip', 'left-aligned']\">\n {{ product.name }}\n </mat-option>\n } @empty {\n <mat-option disabled>No product available.</mat-option>\n }\n @if (!hasFilteredProduct()) {\n <mat-option disabled>No product found.</mat-option>\n }\n </mat-select>\n</mat-form-field>\n", styles: [".form-field{width:100%}.filter{display:flex;margin:0 8px 8px;justify-content:space-around}.filter mat-form-field{width:100%}.hidden{display:none}\n"] }]
3029
- }], propDecorators: { valueFormControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormControl", required: true }] }], preSelectedProductId: [{ type: i0.Input, args: [{ isSignal: true, alias: "preSelectedProductId", required: false }] }], tooltips: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => MatTooltip), { isSignal: true }] }] } });
3052
+ }], propDecorators: { valueFormControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormControl", required: true }] }], preSelectedProductId: [{ type: i0.Input, args: [{ isSignal: true, alias: "preSelectedProductId", required: false }] }], componentError: [{ type: i0.Output, args: ["componentError"] }], tooltips: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => MatTooltip), { isSignal: true }] }] } });
3030
3053
 
3031
3054
  class ConfigSelectComponent extends BaseSelectComponent {
3032
3055
  constructor() {
@@ -3034,6 +3057,7 @@ class ConfigSelectComponent extends BaseSelectComponent {
3034
3057
  this.valueFormControl = input.required(...(ngDevMode ? [{ debugName: "valueFormControl" }] : /* istanbul ignore next */ []));
3035
3058
  this.productId = input.required(...(ngDevMode ? [{ debugName: "productId" }] : /* istanbul ignore next */ []));
3036
3059
  this.preSelectedConfigId = input(...(ngDevMode ? [undefined, { debugName: "preSelectedConfigId" }] : /* istanbul ignore next */ []));
3060
+ this.componentError = output();
3037
3061
  this.filterText = signal("", ...(ngDevMode ? [{ debugName: "filterText" }] : /* istanbul ignore next */ []));
3038
3062
  this.tooltips = viewChildren(MatTooltip, ...(ngDevMode ? [{ debugName: "tooltips" }] : /* istanbul ignore next */ []));
3039
3063
  this.filteredConfigs = linkedSignal(() => {
@@ -3064,6 +3088,9 @@ class ConfigSelectComponent extends BaseSelectComponent {
3064
3088
  else {
3065
3089
  this.valueFormControl().setValue("");
3066
3090
  }
3091
+ }), catchError$1((error) => {
3092
+ this.componentError.emit(error);
3093
+ return of([]);
3067
3094
  }));
3068
3095
  },
3069
3096
  });
@@ -3079,7 +3106,7 @@ class ConfigSelectComponent extends BaseSelectComponent {
3079
3106
  }
3080
3107
  }
3081
3108
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ConfigSelectComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3082
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: ConfigSelectComponent, isStandalone: true, selector: "app-config-select", inputs: { valueFormControl: { classPropertyName: "valueFormControl", publicName: "valueFormControl", isSignal: true, isRequired: true, transformFunction: null }, productId: { classPropertyName: "productId", publicName: "productId", isSignal: true, isRequired: true, transformFunction: null }, preSelectedConfigId: { classPropertyName: "preSelectedConfigId", publicName: "preSelectedConfigId", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
3109
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: ConfigSelectComponent, isStandalone: true, selector: "app-config-select", inputs: { valueFormControl: { classPropertyName: "valueFormControl", publicName: "valueFormControl", isSignal: true, isRequired: true, transformFunction: null }, productId: { classPropertyName: "productId", publicName: "productId", isSignal: true, isRequired: true, transformFunction: null }, preSelectedConfigId: { classPropertyName: "preSelectedConfigId", publicName: "preSelectedConfigId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { componentError: "componentError" }, providers: [
3083
3110
  {
3084
3111
  provide: NG_VALUE_ACCESSOR,
3085
3112
  useExisting: forwardRef(() => ConfigSelectComponent),
@@ -3111,13 +3138,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3111
3138
  MatSuffix,
3112
3139
  MatIconButton,
3113
3140
  ], template: "@if (configs.hasValue()) {\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Config</mat-label>\n <mat-select\n #configSelect=\"matSelect\"\n placeholder=\"Config\"\n name=\"value\"\n disableOptionCentering\n [formControl]=\"valueFormControl()\"\n [panelClass]=\"customDropdown() ? 'custom-dropdown-below' : ''\"\n (openedChange)=\"onSelectOpenedChange($event)\">\n <div class=\"menu-filter small-density-form-field\">\n <mat-form-field\n subscriptSizing=\"dynamic\"\n appearance=\"outline\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <input matInput placeholder=\"Filter configs\" [(ngModel)]=\"filterText\" />\n <span matSuffix [hidden]=\"!filterText()\">\n <button\n type=\"button\"\n mat-icon-button\n class=\"clear-filter\"\n aria-label=\"Clear\"\n matTooltip=\"Clear search filters\"\n (click)=\"clearFilter()\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </mat-form-field>\n </div>\n <mat-divider />\n\n @for (config of filteredConfigs(); track config.configId) {\n <mat-option\n [value]=\"config.configId\"\n [ngClass]=\"{ hidden: config.hidden }\"\n [matTooltip]=\"\n config.description ? `Name: ${config.name}\\nDescription: ${config.description}` : `Name: ${config.name}`\n \"\n [matTooltipDisabled]=\"!configSelect.panelOpen\"\n [matTooltipClass]=\"['wide-tooltip', 'multiline-tooltip', 'left-aligned']\">\n {{ config.name }}\n </mat-option>\n } @empty {\n <mat-option disabled>No config available.</mat-option>\n }\n @if (!hasFilteredConfig()) {\n <mat-option disabled>No config found.</mat-option>\n }\n </mat-select>\n </mat-form-field>\n}\n", styles: [".form-field{width:100%}.filter{display:flex;margin:0 8px 8px;justify-content:space-around}.filter mat-form-field{width:100%}.hidden{display:none}\n"] }]
3114
- }], propDecorators: { valueFormControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormControl", required: true }] }], productId: [{ type: i0.Input, args: [{ isSignal: true, alias: "productId", required: true }] }], preSelectedConfigId: [{ type: i0.Input, args: [{ isSignal: true, alias: "preSelectedConfigId", required: false }] }], tooltips: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => MatTooltip), { isSignal: true }] }] } });
3141
+ }], propDecorators: { valueFormControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormControl", required: true }] }], productId: [{ type: i0.Input, args: [{ isSignal: true, alias: "productId", required: true }] }], preSelectedConfigId: [{ type: i0.Input, args: [{ isSignal: true, alias: "preSelectedConfigId", required: false }] }], componentError: [{ type: i0.Output, args: ["componentError"] }], tooltips: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => MatTooltip), { isSignal: true }] }] } });
3115
3142
 
3116
3143
  class EnvironmentSelectComponent extends BaseSelectComponent {
3117
3144
  constructor() {
3118
3145
  super(...arguments);
3119
3146
  this.valueFormControl = input.required(...(ngDevMode ? [{ debugName: "valueFormControl" }] : /* istanbul ignore next */ []));
3120
3147
  this.productId = input.required(...(ngDevMode ? [{ debugName: "productId" }] : /* istanbul ignore next */ []));
3148
+ this.componentError = output();
3121
3149
  this.filterText = signal("", ...(ngDevMode ? [{ debugName: "filterText" }] : /* istanbul ignore next */ []));
3122
3150
  this.tooltips = viewChildren(MatTooltip, ...(ngDevMode ? [{ debugName: "tooltips" }] : /* istanbul ignore next */ []));
3123
3151
  this.filteredEnvironments = linkedSignal(() => {
@@ -3143,6 +3171,9 @@ class EnvironmentSelectComponent extends BaseSelectComponent {
3143
3171
  else {
3144
3172
  this.valueFormControl().setValue("");
3145
3173
  }
3174
+ }), catchError$1((error) => {
3175
+ this.componentError.emit(error);
3176
+ return of([]);
3146
3177
  }));
3147
3178
  },
3148
3179
  });
@@ -3158,7 +3189,7 @@ class EnvironmentSelectComponent extends BaseSelectComponent {
3158
3189
  }
3159
3190
  }
3160
3191
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: EnvironmentSelectComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3161
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: EnvironmentSelectComponent, isStandalone: true, selector: "app-environment-select", inputs: { valueFormControl: { classPropertyName: "valueFormControl", publicName: "valueFormControl", isSignal: true, isRequired: true, transformFunction: null }, productId: { classPropertyName: "productId", publicName: "productId", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "tooltips", predicate: MatTooltip, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (environments.hasValue()) {\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Environment</mat-label>\n <mat-select\n #environmentSelect=\"matSelect\"\n placeholder=\"Environment\"\n name=\"value\"\n [formControl]=\"valueFormControl()\"\n [panelClass]=\"customDropdown() ? 'custom-dropdown-below' : ''\"\n (openedChange)=\"onSelectOpenedChange($event)\">\n <div class=\"menu-filter small-density-form-field\">\n <mat-form-field\n subscriptSizing=\"dynamic\"\n appearance=\"outline\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <input matInput placeholder=\"Filter environments\" [(ngModel)]=\"filterText\" />\n <span matSuffix [hidden]=\"!filterText()\">\n <button\n type=\"button\"\n mat-icon-button\n class=\"clear-filter\"\n aria-label=\"Clear\"\n matTooltip=\"Clear search filters\"\n (click)=\"clearFilter()\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </mat-form-field>\n </div>\n <mat-divider />\n\n @for (environment of filteredEnvironments(); track environment.environmentId) {\n <mat-option\n [value]=\"environment.environmentId\"\n [ngClass]=\"{ hidden: environment.hidden }\"\n [matTooltip]=\"\n environment.description\n ? `Name: ${environment.name}\\nDescription: ${environment.description}`\n : `Name: ${environment.name}`\n \"\n [matTooltipDisabled]=\"!environmentSelect.panelOpen\"\n [matTooltipClass]=\"['wide-tooltip', 'multiline-tooltip', 'left-aligned']\">\n {{ environment.name }}\n </mat-option>\n } @empty {\n <mat-option disabled>No environment available.</mat-option>\n }\n @if (!hasFilteredEnvironment()) {\n <mat-option disabled>No environment found.</mat-option>\n }\n </mat-select>\n </mat-form-field>\n}\n", styles: [".form-field{width:100%}.filter{display:flex;margin:0 8px 8px;justify-content:space-around}.filter mat-form-field{width:100%}.hidden{display:none}\n"], dependencies: [{ kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.AsyncValidationDirective, selector: "[ngModel],[formControlName],[formControl]", inputs: ["async"] }, { 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: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] }); }
3192
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: EnvironmentSelectComponent, isStandalone: true, selector: "app-environment-select", inputs: { valueFormControl: { classPropertyName: "valueFormControl", publicName: "valueFormControl", isSignal: true, isRequired: true, transformFunction: null }, productId: { classPropertyName: "productId", publicName: "productId", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { componentError: "componentError" }, viewQueries: [{ propertyName: "tooltips", predicate: MatTooltip, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (environments.hasValue()) {\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Environment</mat-label>\n <mat-select\n #environmentSelect=\"matSelect\"\n placeholder=\"Environment\"\n name=\"value\"\n [formControl]=\"valueFormControl()\"\n [panelClass]=\"customDropdown() ? 'custom-dropdown-below' : ''\"\n (openedChange)=\"onSelectOpenedChange($event)\">\n <div class=\"menu-filter small-density-form-field\">\n <mat-form-field\n subscriptSizing=\"dynamic\"\n appearance=\"outline\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <input matInput placeholder=\"Filter environments\" [(ngModel)]=\"filterText\" />\n <span matSuffix [hidden]=\"!filterText()\">\n <button\n type=\"button\"\n mat-icon-button\n class=\"clear-filter\"\n aria-label=\"Clear\"\n matTooltip=\"Clear search filters\"\n (click)=\"clearFilter()\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </mat-form-field>\n </div>\n <mat-divider />\n\n @for (environment of filteredEnvironments(); track environment.environmentId) {\n <mat-option\n [value]=\"environment.environmentId\"\n [ngClass]=\"{ hidden: environment.hidden }\"\n [matTooltip]=\"\n environment.description\n ? `Name: ${environment.name}\\nDescription: ${environment.description}`\n : `Name: ${environment.name}`\n \"\n [matTooltipDisabled]=\"!environmentSelect.panelOpen\"\n [matTooltipClass]=\"['wide-tooltip', 'multiline-tooltip', 'left-aligned']\">\n {{ environment.name }}\n </mat-option>\n } @empty {\n <mat-option disabled>No environment available.</mat-option>\n }\n @if (!hasFilteredEnvironment()) {\n <mat-option disabled>No environment found.</mat-option>\n }\n </mat-select>\n </mat-form-field>\n}\n", styles: [".form-field{width:100%}.filter{display:flex;margin:0 8px 8px;justify-content:space-around}.filter mat-form-field{width:100%}.hidden{display:none}\n"], dependencies: [{ kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.AsyncValidationDirective, selector: "[ngModel],[formControlName],[formControl]", inputs: ["async"] }, { 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: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] }); }
3162
3193
  }
3163
3194
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: EnvironmentSelectComponent, decorators: [{
3164
3195
  type: Component,
@@ -3178,13 +3209,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3178
3209
  MatSuffix,
3179
3210
  MatIconButton,
3180
3211
  ], template: "@if (environments.hasValue()) {\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Environment</mat-label>\n <mat-select\n #environmentSelect=\"matSelect\"\n placeholder=\"Environment\"\n name=\"value\"\n [formControl]=\"valueFormControl()\"\n [panelClass]=\"customDropdown() ? 'custom-dropdown-below' : ''\"\n (openedChange)=\"onSelectOpenedChange($event)\">\n <div class=\"menu-filter small-density-form-field\">\n <mat-form-field\n subscriptSizing=\"dynamic\"\n appearance=\"outline\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <input matInput placeholder=\"Filter environments\" [(ngModel)]=\"filterText\" />\n <span matSuffix [hidden]=\"!filterText()\">\n <button\n type=\"button\"\n mat-icon-button\n class=\"clear-filter\"\n aria-label=\"Clear\"\n matTooltip=\"Clear search filters\"\n (click)=\"clearFilter()\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </mat-form-field>\n </div>\n <mat-divider />\n\n @for (environment of filteredEnvironments(); track environment.environmentId) {\n <mat-option\n [value]=\"environment.environmentId\"\n [ngClass]=\"{ hidden: environment.hidden }\"\n [matTooltip]=\"\n environment.description\n ? `Name: ${environment.name}\\nDescription: ${environment.description}`\n : `Name: ${environment.name}`\n \"\n [matTooltipDisabled]=\"!environmentSelect.panelOpen\"\n [matTooltipClass]=\"['wide-tooltip', 'multiline-tooltip', 'left-aligned']\">\n {{ environment.name }}\n </mat-option>\n } @empty {\n <mat-option disabled>No environment available.</mat-option>\n }\n @if (!hasFilteredEnvironment()) {\n <mat-option disabled>No environment found.</mat-option>\n }\n </mat-select>\n </mat-form-field>\n}\n", styles: [".form-field{width:100%}.filter{display:flex;margin:0 8px 8px;justify-content:space-around}.filter mat-form-field{width:100%}.hidden{display:none}\n"] }]
3181
- }], propDecorators: { valueFormControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormControl", required: true }] }], productId: [{ type: i0.Input, args: [{ isSignal: true, alias: "productId", required: true }] }], tooltips: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => MatTooltip), { isSignal: true }] }] } });
3212
+ }], propDecorators: { valueFormControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormControl", required: true }] }], productId: [{ type: i0.Input, args: [{ isSignal: true, alias: "productId", required: true }] }], componentError: [{ type: i0.Output, args: ["componentError"] }], tooltips: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => MatTooltip), { isSignal: true }] }] } });
3182
3213
 
3183
3214
  class SettingSelectComponent extends BaseSelectComponent {
3184
3215
  constructor() {
3185
3216
  super(...arguments);
3186
3217
  this.valueFormControl = input.required(...(ngDevMode ? [{ debugName: "valueFormControl" }] : /* istanbul ignore next */ []));
3187
3218
  this.configId = input.required(...(ngDevMode ? [{ debugName: "configId" }] : /* istanbul ignore next */ []));
3219
+ this.componentError = output();
3188
3220
  this.SettingTypeEnum = SettingType;
3189
3221
  this.filterText = signal("", ...(ngDevMode ? [{ debugName: "filterText" }] : /* istanbul ignore next */ []));
3190
3222
  this.tooltips = viewChildren(MatTooltip, ...(ngDevMode ? [{ debugName: "tooltips" }] : /* istanbul ignore next */ []));
@@ -3212,6 +3244,9 @@ class SettingSelectComponent extends BaseSelectComponent {
3212
3244
  else {
3213
3245
  this.valueFormControl().setValue("");
3214
3246
  }
3247
+ }), catchError$1((error) => {
3248
+ this.componentError.emit(error);
3249
+ return of([]);
3215
3250
  }));
3216
3251
  },
3217
3252
  });
@@ -3234,7 +3269,7 @@ class SettingSelectComponent extends BaseSelectComponent {
3234
3269
  }
3235
3270
  }
3236
3271
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SettingSelectComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3237
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SettingSelectComponent, isStandalone: true, selector: "app-setting-select", inputs: { valueFormControl: { classPropertyName: "valueFormControl", publicName: "valueFormControl", isSignal: true, isRequired: true, transformFunction: null }, configId: { classPropertyName: "configId", publicName: "configId", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "tooltips", predicate: MatTooltip, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (settings.hasValue()) {\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Feature flag or setting</mat-label>\n <mat-select\n #settingSelect=\"matSelect\"\n placeholder=\"Feature flag or setting\"\n name=\"value\"\n [formControl]=\"valueFormControl()\"\n [panelClass]=\"customDropdown() ? 'custom-dropdown-below' : ''\"\n (openedChange)=\"onSelectOpenedChange($event)\">\n <mat-select-trigger>\n @if (valueFormControl().value) {\n {{ this.selectedSettingTriggerText() }}\n }\n </mat-select-trigger>\n <div class=\"menu-filter small-density-form-field\">\n <mat-form-field\n subscriptSizing=\"dynamic\"\n appearance=\"outline\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <input matInput placeholder=\"Filter settings\" [(ngModel)]=\"filterText\" />\n <span matSuffix [hidden]=\"!filterText()\">\n <button\n type=\"button\"\n mat-icon-button\n class=\"clear-filter\"\n aria-label=\"Clear\"\n matTooltip=\"Clear search filters\"\n (click)=\"clearFilter()\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </mat-form-field>\n </div>\n <mat-divider />\n @for (setting of filteredSettings(); track setting.settingId) {\n <mat-option [value]=\"setting.settingId\" [ngClass]=\"{ hidden: setting.hidden }\">\n <div class=\"feature-flag-selector-item\">\n @switch (setting.settingType) {\n @case (SettingTypeEnum.Boolean) {\n <img\n class=\"feature-flag-selector-img\"\n src=\"./assets/images/setting-types/feature_flag.svg\"\n alt=\"feature flag\" />\n }\n @case (SettingTypeEnum.String) {\n <img\n class=\"feature-flag-selector-img\"\n src=\"./assets/images/setting-types/text.svg\"\n alt=\"text setting\" />\n }\n @case (SettingTypeEnum.Int) {\n <img\n class=\"feature-flag-selector-img\"\n src=\"./assets/images/setting-types/whole.svg\"\n alt=\"whole number setting\" />\n }\n @case (SettingTypeEnum.Double) {\n <img\n class=\"feature-flag-selector-img\"\n src=\"./assets/images/setting-types/decimal.svg\"\n alt=\"decimal number setting\" />\n }\n }\n <div class=\"item-text-wrapper\">\n <span [matTooltip]=\"setting.name\" [matTooltipDisabled]=\"!settingSelect.panelOpen || !setting.name\">\n {{ setting.name }}\n </span>\n <code\n class=\"highlight copyable-like small\"\n [matTooltip]=\"setting.key\"\n [matTooltipDisabled]=\"!settingSelect.panelOpen || !setting.key\">\n {{ setting.key }}\n </code>\n </div>\n </div>\n </mat-option>\n } @empty {\n <mat-option disabled>No setting available.</mat-option>\n }\n @if (!hasFilteredSetting()) {\n <mat-option disabled>No setting found.</mat-option>\n }\n </mat-select>\n </mat-form-field>\n}\n", styles: [".form-field{width:100%}.filter{display:flex;margin:0 8px 8px;justify-content:space-around}.filter mat-form-field{width:100%}.hidden{display:none}.feature-flag-selector-item{display:flex;flex-wrap:nowrap}.feature-flag-selector-item>.item-text-wrapper{display:flex;min-width:0;align-items:center;flex-wrap:wrap;column-gap:.25em}.feature-flag-selector-item>.item-text-wrapper>*{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.feature-flag-selector-item .feature-flag-selector-img{width:24px;height:24px;margin-right:8px;align-self:center}\n"], dependencies: [{ kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.AsyncValidationDirective, selector: "[ngModel],[formControlName],[formControl]", inputs: ["async"] }, { 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: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatSelectTrigger, selector: "mat-select-trigger" }] }); }
3272
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SettingSelectComponent, isStandalone: true, selector: "app-setting-select", inputs: { valueFormControl: { classPropertyName: "valueFormControl", publicName: "valueFormControl", isSignal: true, isRequired: true, transformFunction: null }, configId: { classPropertyName: "configId", publicName: "configId", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { componentError: "componentError" }, viewQueries: [{ propertyName: "tooltips", predicate: MatTooltip, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (settings.hasValue()) {\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Feature flag or setting</mat-label>\n <mat-select\n #settingSelect=\"matSelect\"\n placeholder=\"Feature flag or setting\"\n name=\"value\"\n [formControl]=\"valueFormControl()\"\n [panelClass]=\"customDropdown() ? 'custom-dropdown-below' : ''\"\n (openedChange)=\"onSelectOpenedChange($event)\">\n <mat-select-trigger>\n @if (valueFormControl().value) {\n {{ this.selectedSettingTriggerText() }}\n }\n </mat-select-trigger>\n <div class=\"menu-filter small-density-form-field\">\n <mat-form-field\n subscriptSizing=\"dynamic\"\n appearance=\"outline\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <input matInput placeholder=\"Filter settings\" [(ngModel)]=\"filterText\" />\n <span matSuffix [hidden]=\"!filterText()\">\n <button\n type=\"button\"\n mat-icon-button\n class=\"clear-filter\"\n aria-label=\"Clear\"\n matTooltip=\"Clear search filters\"\n (click)=\"clearFilter()\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </mat-form-field>\n </div>\n <mat-divider />\n @for (setting of filteredSettings(); track setting.settingId) {\n <mat-option [value]=\"setting.settingId\" [ngClass]=\"{ hidden: setting.hidden }\">\n <div class=\"feature-flag-selector-item\">\n @switch (setting.settingType) {\n @case (SettingTypeEnum.Boolean) {\n <img\n class=\"feature-flag-selector-img\"\n src=\"./assets/images/setting-types/feature_flag.svg\"\n alt=\"feature flag\" />\n }\n @case (SettingTypeEnum.String) {\n <img\n class=\"feature-flag-selector-img\"\n src=\"./assets/images/setting-types/text.svg\"\n alt=\"text setting\" />\n }\n @case (SettingTypeEnum.Int) {\n <img\n class=\"feature-flag-selector-img\"\n src=\"./assets/images/setting-types/whole.svg\"\n alt=\"whole number setting\" />\n }\n @case (SettingTypeEnum.Double) {\n <img\n class=\"feature-flag-selector-img\"\n src=\"./assets/images/setting-types/decimal.svg\"\n alt=\"decimal number setting\" />\n }\n }\n <div class=\"item-text-wrapper\">\n <span [matTooltip]=\"setting.name\" [matTooltipDisabled]=\"!settingSelect.panelOpen || !setting.name\">\n {{ setting.name }}\n </span>\n <code\n class=\"highlight copyable-like small\"\n [matTooltip]=\"setting.key\"\n [matTooltipDisabled]=\"!settingSelect.panelOpen || !setting.key\">\n {{ setting.key }}\n </code>\n </div>\n </div>\n </mat-option>\n } @empty {\n <mat-option disabled>No setting available.</mat-option>\n }\n @if (!hasFilteredSetting()) {\n <mat-option disabled>No setting found.</mat-option>\n }\n </mat-select>\n </mat-form-field>\n}\n", styles: [".form-field{width:100%}.filter{display:flex;margin:0 8px 8px;justify-content:space-around}.filter mat-form-field{width:100%}.hidden{display:none}.feature-flag-selector-item{display:flex;flex-wrap:nowrap}.feature-flag-selector-item>.item-text-wrapper{display:flex;min-width:0;align-items:center;flex-wrap:wrap;column-gap:.25em}.feature-flag-selector-item>.item-text-wrapper>*{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.feature-flag-selector-item .feature-flag-selector-img{width:24px;height:24px;margin-right:8px;align-self:center}\n"], dependencies: [{ kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.AsyncValidationDirective, selector: "[ngModel],[formControlName],[formControl]", inputs: ["async"] }, { 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: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatSelectTrigger, selector: "mat-select-trigger" }] }); }
3238
3273
  }
3239
3274
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SettingSelectComponent, decorators: [{
3240
3275
  type: Component,
@@ -3255,7 +3290,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3255
3290
  MatIconButton,
3256
3291
  MatSelectTrigger,
3257
3292
  ], template: "@if (settings.hasValue()) {\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Feature flag or setting</mat-label>\n <mat-select\n #settingSelect=\"matSelect\"\n placeholder=\"Feature flag or setting\"\n name=\"value\"\n [formControl]=\"valueFormControl()\"\n [panelClass]=\"customDropdown() ? 'custom-dropdown-below' : ''\"\n (openedChange)=\"onSelectOpenedChange($event)\">\n <mat-select-trigger>\n @if (valueFormControl().value) {\n {{ this.selectedSettingTriggerText() }}\n }\n </mat-select-trigger>\n <div class=\"menu-filter small-density-form-field\">\n <mat-form-field\n subscriptSizing=\"dynamic\"\n appearance=\"outline\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n <input matInput placeholder=\"Filter settings\" [(ngModel)]=\"filterText\" />\n <span matSuffix [hidden]=\"!filterText()\">\n <button\n type=\"button\"\n mat-icon-button\n class=\"clear-filter\"\n aria-label=\"Clear\"\n matTooltip=\"Clear search filters\"\n (click)=\"clearFilter()\">\n <mat-icon>close</mat-icon>\n </button>\n </span>\n </mat-form-field>\n </div>\n <mat-divider />\n @for (setting of filteredSettings(); track setting.settingId) {\n <mat-option [value]=\"setting.settingId\" [ngClass]=\"{ hidden: setting.hidden }\">\n <div class=\"feature-flag-selector-item\">\n @switch (setting.settingType) {\n @case (SettingTypeEnum.Boolean) {\n <img\n class=\"feature-flag-selector-img\"\n src=\"./assets/images/setting-types/feature_flag.svg\"\n alt=\"feature flag\" />\n }\n @case (SettingTypeEnum.String) {\n <img\n class=\"feature-flag-selector-img\"\n src=\"./assets/images/setting-types/text.svg\"\n alt=\"text setting\" />\n }\n @case (SettingTypeEnum.Int) {\n <img\n class=\"feature-flag-selector-img\"\n src=\"./assets/images/setting-types/whole.svg\"\n alt=\"whole number setting\" />\n }\n @case (SettingTypeEnum.Double) {\n <img\n class=\"feature-flag-selector-img\"\n src=\"./assets/images/setting-types/decimal.svg\"\n alt=\"decimal number setting\" />\n }\n }\n <div class=\"item-text-wrapper\">\n <span [matTooltip]=\"setting.name\" [matTooltipDisabled]=\"!settingSelect.panelOpen || !setting.name\">\n {{ setting.name }}\n </span>\n <code\n class=\"highlight copyable-like small\"\n [matTooltip]=\"setting.key\"\n [matTooltipDisabled]=\"!settingSelect.panelOpen || !setting.key\">\n {{ setting.key }}\n </code>\n </div>\n </div>\n </mat-option>\n } @empty {\n <mat-option disabled>No setting available.</mat-option>\n }\n @if (!hasFilteredSetting()) {\n <mat-option disabled>No setting found.</mat-option>\n }\n </mat-select>\n </mat-form-field>\n}\n", styles: [".form-field{width:100%}.filter{display:flex;margin:0 8px 8px;justify-content:space-around}.filter mat-form-field{width:100%}.hidden{display:none}.feature-flag-selector-item{display:flex;flex-wrap:nowrap}.feature-flag-selector-item>.item-text-wrapper{display:flex;min-width:0;align-items:center;flex-wrap:wrap;column-gap:.25em}.feature-flag-selector-item>.item-text-wrapper>*{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.feature-flag-selector-item .feature-flag-selector-img{width:24px;height:24px;margin-right:8px;align-self:center}\n"] }]
3258
- }], propDecorators: { valueFormControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormControl", required: true }] }], configId: [{ type: i0.Input, args: [{ isSignal: true, alias: "configId", required: true }] }], tooltips: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => MatTooltip), { isSignal: true }] }] } });
3293
+ }], propDecorators: { valueFormControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormControl", required: true }] }], configId: [{ type: i0.Input, args: [{ isSignal: true, alias: "configId", required: true }] }], componentError: [{ type: i0.Output, args: ["componentError"] }], tooltips: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => MatTooltip), { isSignal: true }] }] } });
3259
3294
 
3260
3295
  class DeleteSettingDialogComponent {
3261
3296
  constructor() {
@@ -3325,6 +3360,9 @@ class ErrorHandler {
3325
3360
  formGroup.setErrors({ serverSide: "Something went wrong." });
3326
3361
  }
3327
3362
  break;
3363
+ case 401:
3364
+ formGroup.setErrors({ serverSide: "Unauthorized access. Try to refresh the page or log in again." });
3365
+ break;
3328
3366
  case 402:
3329
3367
  formGroup.setErrors({ serverSide: "You have reached the limits of your plan." });
3330
3368
  break;
@@ -3333,6 +3371,7 @@ class ErrorHandler {
3333
3371
  break;
3334
3372
  default:
3335
3373
  formGroup.setErrors({ serverSide: "Something went wrong on our side. This is not your fault. Please try again." });
3374
+ console.log(error);
3336
3375
  break;
3337
3376
  }
3338
3377
  }
@@ -3340,6 +3379,7 @@ class ErrorHandler {
3340
3379
  formGroup.setErrors({
3341
3380
  serverSide: "Something went wrong on our side. This is not your fault. Please try again.",
3342
3381
  });
3382
+ console.log(error);
3343
3383
  }
3344
3384
  }
3345
3385
  }
@@ -3529,16 +3569,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3529
3569
 
3530
3570
  class PopoutTextEditorDialogComponent {
3531
3571
  constructor() {
3572
+ this.formHelper = FormHelper;
3532
3573
  this.dialogRef = inject(MatDialogRef);
3533
- this.data = inject(MAT_DIALOG_DATA);
3534
3574
  this.destroyRef = inject(DestroyRef);
3535
- this.jsonData = null;
3536
- this.format = "text";
3537
- this.formHelper = FormHelper;
3575
+ this.data = inject(MAT_DIALOG_DATA);
3576
+ this.jsonData = signal(this.data.value, ...(ngDevMode ? [{ debugName: "jsonData" }] : /* istanbul ignore next */ []));
3577
+ this.format = signal(this.data.disableTextEditor ? "json" : "text", ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
3578
+ this.control = new FormControl({ value: this.data.value, disabled: this.data.readOnly }, { nonNullable: true, validators: [...this.data.validators] });
3538
3579
  }
3539
3580
  ngOnInit() {
3540
- this.jsonData = this.data.value;
3541
- this.control = new FormControl({ value: this.data.value, disabled: this.data.readOnly }, { nonNullable: true, validators: [...this.data.validators] });
3542
3581
  if (!this.control.valid) {
3543
3582
  this.control.markAsTouched();
3544
3583
  }
@@ -3546,8 +3585,8 @@ class PopoutTextEditorDialogComponent {
3546
3585
  this.control.setValue(value, { onlySelf: true, emitEvent: false, emitModelToViewChange: true });
3547
3586
  this.control.markAsDirty();
3548
3587
  this.control.markAsTouched();
3549
- if (this.jsonData !== value) {
3550
- this.jsonData = value;
3588
+ if (this.jsonData() !== value) {
3589
+ this.jsonData.set(value);
3551
3590
  }
3552
3591
  });
3553
3592
  }
@@ -3570,7 +3609,7 @@ class PopoutTextEditorDialogComponent {
3570
3609
  this.dialogRef.close({ value: this.control.value });
3571
3610
  }
3572
3611
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: PopoutTextEditorDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3573
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: PopoutTextEditorDialogComponent, isStandalone: true, selector: "app-popout-text-editor-dialog", ngImport: i0, template: "<h2 mat-dialog-title>Advanced editor</h2>\n<div mat-dialog-content class=\"container\">\n <p class=\"description\">\n {{ data.description }}\n </p>\n @if (!data.disableJsonEditor) {\n <mat-button-toggle-group [(ngModel)]=\"format\">\n <mat-button-toggle value=\"text\">Text</mat-button-toggle>\n <mat-button-toggle value=\"json\">JSON</mat-button-toggle>\n </mat-button-toggle-group>\n }\n\n @if (format === \"text\") {\n <mat-form-field appearance=\"outline\" class=\"editor-container editor-clear\" subscriptSizing=\"dynamic\">\n <textarea\n matInput\n autofocus\n focus\n rows=\"17\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"17\"\n cdkAutosizeMaxRows=\"26\"\n appPastedDataTrimmer\n [formControl]=\"control\"></textarea>\n @if (control.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(control) }}\n </mat-error>\n }\n @if (data.maxValueLength && data.maxValueLength - (control.value?.length ?? 0) > -1) {\n <mat-hint>\n Remaining characters:\n {{ data.maxValueLength - (control.value?.length ?? 0) }}\n </mat-hint>\n }\n </mat-form-field>\n } @else if (format === \"json\") {\n <div class=\"editor-container\">\n <app-ace-editor [readOnly]=\"data.readOnly\" [(value)]=\"jsonData\" (onChange)=\"onJsonChanged($event)\" />\n @if (control.invalid) {\n <span class=\"error mat-mdc-form-field-error\">\n {{ formHelper.getErrorMessage(control) }}\n </span>\n }\n </div>\n }\n</div>\n<div mat-dialog-actions>\n @if (!data.readOnly) {\n <button\n type=\"button\"\n mat-flat-button\n color=\"primary\"\n [disabled]=\"!control.touched || !control.valid\"\n (click)=\"set()\">\n Set\n </button>\n <button type=\"button\" mat-stroked-button [mat-dialog-close]>Cancel</button>\n } @else {\n <button type=\"button\" mat-stroked-button color=\"primary\" [mat-dialog-close]>Close</button>\n }\n</div>\n", styles: [".container{width:100%}.container .editor-container{margin:10px 0;width:100%;height:432px}.container .editor-clear{width:100%}.container .error{font-size:10px;padding:0 8px}.container .description{padding:5px 0}\n"], dependencies: [{ kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { 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: CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "directive", type: AutofocusDirective, selector: "[focus]", inputs: ["isFocused"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.AsyncValidationDirective, selector: "[ngModel],[formControlName],[formControl]", inputs: ["async"] }, { 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: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: AceEditorComponent, selector: "app-ace-editor", inputs: ["value", "readOnly"], outputs: ["valueChange", "onChange"] }, { 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: PastedDataTrimmerDirective, selector: "[appPastedDataTrimmer]" }] }); }
3612
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: PopoutTextEditorDialogComponent, isStandalone: true, selector: "app-popout-text-editor-dialog", ngImport: i0, template: "<h2 mat-dialog-title>Advanced editor</h2>\n<div mat-dialog-content class=\"container\">\n <p class=\"description\">\n {{ data.description }}\n </p>\n @if (!data.disableJsonEditor && !data.disableTextEditor) {\n <mat-button-toggle-group [(ngModel)]=\"format\">\n <mat-button-toggle value=\"text\">Text</mat-button-toggle>\n <mat-button-toggle value=\"json\">JSON</mat-button-toggle>\n </mat-button-toggle-group>\n }\n\n @if (format() === \"text\") {\n <mat-form-field appearance=\"outline\" class=\"editor-container editor-clear\" subscriptSizing=\"dynamic\">\n <textarea\n matInput\n autofocus\n focus\n rows=\"17\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"17\"\n cdkAutosizeMaxRows=\"26\"\n appPastedDataTrimmer\n [formControl]=\"control\"></textarea>\n @if (control.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(control) }}\n </mat-error>\n }\n @if (data.maxValueLength && data.maxValueLength - (control.value?.length ?? 0) > -1) {\n <mat-hint>\n Remaining characters:\n {{ data.maxValueLength - (control.value?.length ?? 0) }}\n </mat-hint>\n }\n </mat-form-field>\n } @else if (format() === \"json\") {\n <div class=\"editor-container\">\n <app-ace-editor [readOnly]=\"data.readOnly\" [(value)]=\"jsonData\" (onChange)=\"onJsonChanged($event)\" />\n @if (control.invalid) {\n <span class=\"error mat-mdc-form-field-error\">\n {{ formHelper.getErrorMessage(control) }}\n </span>\n }\n </div>\n }\n</div>\n<div mat-dialog-actions>\n @if (!data.readOnly) {\n <button\n type=\"button\"\n mat-flat-button\n color=\"primary\"\n [disabled]=\"!control.touched || !control.valid\"\n (click)=\"set()\">\n Set\n </button>\n <button type=\"button\" mat-stroked-button [mat-dialog-close]>Cancel</button>\n } @else {\n <button type=\"button\" mat-stroked-button color=\"primary\" [mat-dialog-close]>Close</button>\n }\n</div>\n", styles: [".container{width:100%}.container .editor-container{margin:10px 0;width:100%;height:432px}.container .editor-clear{width:100%}.container .error{font-size:10px;padding:0 8px}.container .description{padding:5px 0}\n"], dependencies: [{ kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { 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: CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "directive", type: AutofocusDirective, selector: "[focus]", inputs: ["isFocused"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.AsyncValidationDirective, selector: "[ngModel],[formControlName],[formControl]", inputs: ["async"] }, { 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: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: AceEditorComponent, selector: "app-ace-editor", inputs: ["value", "readOnly"], outputs: ["valueChange", "onChange"] }, { 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: PastedDataTrimmerDirective, selector: "[appPastedDataTrimmer]" }] }); }
3574
3613
  }
3575
3614
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: PopoutTextEditorDialogComponent, decorators: [{
3576
3615
  type: Component,
@@ -3594,7 +3633,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3594
3633
  MatButton,
3595
3634
  MatDialogClose,
3596
3635
  PastedDataTrimmerDirective,
3597
- ], template: "<h2 mat-dialog-title>Advanced editor</h2>\n<div mat-dialog-content class=\"container\">\n <p class=\"description\">\n {{ data.description }}\n </p>\n @if (!data.disableJsonEditor) {\n <mat-button-toggle-group [(ngModel)]=\"format\">\n <mat-button-toggle value=\"text\">Text</mat-button-toggle>\n <mat-button-toggle value=\"json\">JSON</mat-button-toggle>\n </mat-button-toggle-group>\n }\n\n @if (format === \"text\") {\n <mat-form-field appearance=\"outline\" class=\"editor-container editor-clear\" subscriptSizing=\"dynamic\">\n <textarea\n matInput\n autofocus\n focus\n rows=\"17\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"17\"\n cdkAutosizeMaxRows=\"26\"\n appPastedDataTrimmer\n [formControl]=\"control\"></textarea>\n @if (control.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(control) }}\n </mat-error>\n }\n @if (data.maxValueLength && data.maxValueLength - (control.value?.length ?? 0) > -1) {\n <mat-hint>\n Remaining characters:\n {{ data.maxValueLength - (control.value?.length ?? 0) }}\n </mat-hint>\n }\n </mat-form-field>\n } @else if (format === \"json\") {\n <div class=\"editor-container\">\n <app-ace-editor [readOnly]=\"data.readOnly\" [(value)]=\"jsonData\" (onChange)=\"onJsonChanged($event)\" />\n @if (control.invalid) {\n <span class=\"error mat-mdc-form-field-error\">\n {{ formHelper.getErrorMessage(control) }}\n </span>\n }\n </div>\n }\n</div>\n<div mat-dialog-actions>\n @if (!data.readOnly) {\n <button\n type=\"button\"\n mat-flat-button\n color=\"primary\"\n [disabled]=\"!control.touched || !control.valid\"\n (click)=\"set()\">\n Set\n </button>\n <button type=\"button\" mat-stroked-button [mat-dialog-close]>Cancel</button>\n } @else {\n <button type=\"button\" mat-stroked-button color=\"primary\" [mat-dialog-close]>Close</button>\n }\n</div>\n", styles: [".container{width:100%}.container .editor-container{margin:10px 0;width:100%;height:432px}.container .editor-clear{width:100%}.container .error{font-size:10px;padding:0 8px}.container .description{padding:5px 0}\n"] }]
3636
+ ], template: "<h2 mat-dialog-title>Advanced editor</h2>\n<div mat-dialog-content class=\"container\">\n <p class=\"description\">\n {{ data.description }}\n </p>\n @if (!data.disableJsonEditor && !data.disableTextEditor) {\n <mat-button-toggle-group [(ngModel)]=\"format\">\n <mat-button-toggle value=\"text\">Text</mat-button-toggle>\n <mat-button-toggle value=\"json\">JSON</mat-button-toggle>\n </mat-button-toggle-group>\n }\n\n @if (format() === \"text\") {\n <mat-form-field appearance=\"outline\" class=\"editor-container editor-clear\" subscriptSizing=\"dynamic\">\n <textarea\n matInput\n autofocus\n focus\n rows=\"17\"\n cdkTextareaAutosize\n cdkAutosizeMinRows=\"17\"\n cdkAutosizeMaxRows=\"26\"\n appPastedDataTrimmer\n [formControl]=\"control\"></textarea>\n @if (control.invalid) {\n <mat-error>\n {{ formHelper.getErrorMessage(control) }}\n </mat-error>\n }\n @if (data.maxValueLength && data.maxValueLength - (control.value?.length ?? 0) > -1) {\n <mat-hint>\n Remaining characters:\n {{ data.maxValueLength - (control.value?.length ?? 0) }}\n </mat-hint>\n }\n </mat-form-field>\n } @else if (format() === \"json\") {\n <div class=\"editor-container\">\n <app-ace-editor [readOnly]=\"data.readOnly\" [(value)]=\"jsonData\" (onChange)=\"onJsonChanged($event)\" />\n @if (control.invalid) {\n <span class=\"error mat-mdc-form-field-error\">\n {{ formHelper.getErrorMessage(control) }}\n </span>\n }\n </div>\n }\n</div>\n<div mat-dialog-actions>\n @if (!data.readOnly) {\n <button\n type=\"button\"\n mat-flat-button\n color=\"primary\"\n [disabled]=\"!control.touched || !control.valid\"\n (click)=\"set()\">\n Set\n </button>\n <button type=\"button\" mat-stroked-button [mat-dialog-close]>Cancel</button>\n } @else {\n <button type=\"button\" mat-stroked-button color=\"primary\" [mat-dialog-close]>Close</button>\n }\n</div>\n", styles: [".container{width:100%}.container .editor-container{margin:10px 0;width:100%;height:432px}.container .editor-clear{width:100%}.container .error{font-size:10px;padding:0 8px}.container .description{padding:5px 0}\n"] }]
3598
3637
  }] });
3599
3638
 
3600
3639
  class VariationsDialogComponent {
@@ -3612,6 +3651,7 @@ class VariationsDialogComponent {
3612
3651
  this.formHelper = FormHelper;
3613
3652
  this.stringValidators = [Validators.required,
3614
3653
  Validators.maxLength(this.data.maxStringFlagValueLength)];
3654
+ this.jsonValidators = [...this.stringValidators, jsonValidator];
3615
3655
  this.intValidators = [
3616
3656
  Validators.required,
3617
3657
  validateNumberNan,
@@ -3701,7 +3741,7 @@ class VariationsDialogComponent {
3701
3741
  });
3702
3742
  case SettingType.String:
3703
3743
  return this.formBuilder.group({
3704
- stringValue: new FormControl({ value: predefinedVariationValue.stringValue, disabled }, { nonNullable: true, validators: this.stringValidators }),
3744
+ stringValue: new FormControl({ value: predefinedVariationValue.stringValue, disabled }, { nonNullable: true, validators: this.data.isJson ? this.jsonValidators : this.stringValidators }),
3705
3745
  });
3706
3746
  case SettingType.Int:
3707
3747
  return this.formBuilder.group({
@@ -3753,7 +3793,7 @@ class VariationsDialogComponent {
3753
3793
  validators: [Validators.required, Validators.maxLength(this.data.maxStringFlagValueLength)],
3754
3794
  maxValueLength: this.data.maxStringFlagValueLength,
3755
3795
  description: "Modify the text within the editor to change the value.",
3756
- disableJsonEditor: true,
3796
+ disableTextEditor: this.data.isJson,
3757
3797
  },
3758
3798
  });
3759
3799
  dialogRef.afterClosed().subscribe(data => {
@@ -3774,6 +3814,7 @@ class VariationsDialogComponent {
3774
3814
  validators: [Validators.maxLength(1000)],
3775
3815
  maxValueLength: 1000,
3776
3816
  description: "Modify the text within the editor to change the hint.",
3817
+ disableJsonEditor: true,
3777
3818
  },
3778
3819
  });
3779
3820
  dialogRef.afterClosed().subscribe(data => {
@@ -3858,7 +3899,7 @@ class VariationsDialogComponent {
3858
3899
  return getPredefinedVariationColorIndex(this.settingType, getRawPredefinedVariationValue(row.controls.value), index);
3859
3900
  }
3860
3901
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: VariationsDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3861
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", 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 @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <div class=\"error\" mat-dialog-content>\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\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}.content .error{color:var(--flag-validation-error);padding-top:8px;padding-bottom:8px}\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"] }] }); }
3902
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", 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>\n <div class=\"centered\">\n <span>Served value *</span>\n <mat-icon\n matTooltip=\"Your application will get this value when evaluating the setting.\"\n class=\"info-icon header-tooltip-icon\">\n info\n </mat-icon>\n </div>\n </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>\n <div class=\"centered\">\n <span>Display name (optional)</span>\n <mat-icon\n matTooltip=\"Optional friendly name. This will be displayed on the ConfigCat Dashboard.\"\n class=\"info-icon header-tooltip-icon\">\n info\n </mat-icon>\n </div>\n </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>\n <div class=\"centered\">\n <span>Hint (optional)</span>\n <mat-icon\n matTooltip=\"Optional hint. This will be displayed in a tooltip.\"\n class=\"info-icon header-tooltip-icon\">\n info\n </mat-icon>\n </div>\n </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 @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <div class=\"error\" mat-dialog-content>\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\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 .centered{display:flex;align-items:center}.content mat-icon.info-icon{color:var(--info-icon-color);margin-left:8px}.content .dialog-table{padding-top:0;padding-bottom:0}.content .dialog-table .header-tooltip-icon{font-size:14px;width:14px;height:14px}.content .error{color:var(--flag-validation-error);padding-top:8px;padding-bottom:8px}\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"] }] }); }
3862
3903
  }
3863
3904
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: VariationsDialogComponent, decorators: [{
3864
3905
  type: Component,
@@ -3897,7 +3938,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
3897
3938
  CdkDragHandle,
3898
3939
  CopyableValueComponent,
3899
3940
  AutofocusDirective
3900
- ], 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 @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <div class=\"error\" mat-dialog-content>\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\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}.content .error{color:var(--flag-validation-error);padding-top:8px;padding-bottom:8px}\n"] }]
3941
+ ], 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>\n <div class=\"centered\">\n <span>Served value *</span>\n <mat-icon\n matTooltip=\"Your application will get this value when evaluating the setting.\"\n class=\"info-icon header-tooltip-icon\">\n info\n </mat-icon>\n </div>\n </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>\n <div class=\"centered\">\n <span>Display name (optional)</span>\n <mat-icon\n matTooltip=\"Optional friendly name. This will be displayed on the ConfigCat Dashboard.\"\n class=\"info-icon header-tooltip-icon\">\n info\n </mat-icon>\n </div>\n </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>\n <div class=\"centered\">\n <span>Hint (optional)</span>\n <mat-icon\n matTooltip=\"Optional hint. This will be displayed in a tooltip.\"\n class=\"info-icon header-tooltip-icon\">\n info\n </mat-icon>\n </div>\n </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 @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <div class=\"error\" mat-dialog-content>\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\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 .centered{display:flex;align-items:center}.content mat-icon.info-icon{color:var(--info-icon-color);margin-left:8px}.content .dialog-table{padding-top:0;padding-bottom:0}.content .dialog-table .header-tooltip-icon{font-size:14px;width:14px;height:14px}.content .error{color:var(--flag-validation-error);padding-top:8px;padding-bottom:8px}\n"] }]
3901
3942
  }] });
3902
3943
 
3903
3944
  class DependeesDialogComponent {
@@ -3956,11 +3997,12 @@ class FeatureFlagValueComponent {
3956
3997
  data: {
3957
3998
  value: stringValueControl.value,
3958
3999
  readOnly: stringValueControl.disabled,
3959
- validators: getValidatorsForSettingType(SettingType.String, this.featureFlagLimitations()),
4000
+ validators: getValidatorsForSettingType(SettingType.String, this.featureFlagLimitations(), this.setting().isJson),
3960
4001
  maxValueLength: this.featureFlagLimitations().maxStringFlagValueLength ?? 100000,
3961
4002
  description: this.isPrerequisite()
3962
4003
  ? "Modify the text within the editor to change the prerequisite flag comparison value. The editor supports JSON syntax highlighting."
3963
4004
  : "Modify the text within the editor to change the feature flag value. The editor supports JSON syntax highlighting.",
4005
+ disableTextEditor: this.setting().isJson,
3964
4006
  },
3965
4007
  });
3966
4008
  dialogRef.afterClosed().subscribe(data => {
@@ -4104,7 +4146,7 @@ class PrerequisiteFlagConditionComponent {
4104
4146
  const prerequisiteSettingType = newSetting?.settingType ?? SettingType.Boolean;
4105
4147
  const variations = newSetting?.predefinedVariations ?? [];
4106
4148
  if (changeNeeded) {
4107
- this.formGroup().setControl("prerequisiteComparisonValue", generateValueFormGroup(generatePrerequisiteDefaultValue(prerequisiteSettingType, variations), prerequisiteSettingType, variations, false, this.featureFlagLimitations()));
4149
+ this.formGroup().setControl("prerequisiteComparisonValue", generateValueFormGroup(generatePrerequisiteDefaultValue(prerequisiteSettingType, variations), prerequisiteSettingType, variations, false, this.featureFlagLimitations(), newSetting?.isJson ?? false));
4108
4150
  }
4109
4151
  this.prerequisiteConditionChanged.emit();
4110
4152
  }
@@ -5574,7 +5616,7 @@ class PercentageOptionsComponent {
5574
5616
  this.formArray().push(generatePercentageOptionFormGroup({
5575
5617
  percentage: 0,
5576
5618
  value: generateDefaultValue(this.flagState().settingValue.setting.settingType, remainingPredefinedVariations),
5577
- }, this.flagState().settingValue.setting.settingType, this.flagState().settingValue.setting.predefinedVariations, false, this.featureFlagLimitations()));
5619
+ }, this.flagState().settingValue.setting.settingType, this.flagState().settingValue.setting.predefinedVariations, false, this.featureFlagLimitations(), this.flagState().settingValue.setting.isJson));
5578
5620
  this.formArray().markAsDirty();
5579
5621
  this.percentageOptionsCount.set(this.formArray().controls.length);
5580
5622
  }
@@ -5673,11 +5715,11 @@ class TargetingRuleComponent {
5673
5715
  generatePercentageOptionFormGroup({
5674
5716
  percentage: 100,
5675
5717
  value: { boolValue: null, intValue: null, doubleValue: null, stringValue: null, predefinedVariationId: currentValue.predefinedVariationId },
5676
- }, flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, false, this.featureFlagLimitations()),
5718
+ }, flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, false, this.featureFlagLimitations(), flagState.settingValue.setting.isJson),
5677
5719
  generatePercentageOptionFormGroup({
5678
5720
  percentage: 0,
5679
5721
  value: { boolValue: null, intValue: null, doubleValue: null, stringValue: null, predefinedVariationId: nextPredefinedVariationId },
5680
- }, flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, false, this.featureFlagLimitations()),
5722
+ }, flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, false, this.featureFlagLimitations(), flagState.settingValue.setting.isJson),
5681
5723
  ], [validatePercentageSum]));
5682
5724
  formGroup.removeControl("value");
5683
5725
  formGroup.markAsDirty();
@@ -5689,11 +5731,11 @@ class TargetingRuleComponent {
5689
5731
  generatePercentageOptionFormGroup({
5690
5732
  percentage: currentValue.boolValue ? 100 : 0,
5691
5733
  value: { boolValue: true, intValue: null, doubleValue: null, stringValue: null, predefinedVariationId: null },
5692
- }, flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, false, this.featureFlagLimitations()),
5734
+ }, flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, false, this.featureFlagLimitations(), flagState.settingValue.setting.isJson),
5693
5735
  generatePercentageOptionFormGroup({
5694
5736
  percentage: currentValue.boolValue ? 0 : 100,
5695
5737
  value: { boolValue: false, intValue: null, doubleValue: null, stringValue: null, predefinedVariationId: null },
5696
- }, flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, false, this.featureFlagLimitations()),
5738
+ }, flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, false, this.featureFlagLimitations(), flagState.settingValue.setting.isJson),
5697
5739
  ], [validatePercentageSum]));
5698
5740
  formGroup.removeControl("value");
5699
5741
  formGroup.markAsDirty();
@@ -5703,8 +5745,8 @@ class TargetingRuleComponent {
5703
5745
  case SettingType.Int:
5704
5746
  case SettingType.Double: {
5705
5747
  formGroup.setControl("percentageOptions", new FormArray([
5706
- generatePercentageOptionFormGroup({ percentage: 100, value: currentValue }, flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, false, this.featureFlagLimitations()),
5707
- generatePercentageOptionFormGroup({ percentage: 0, value: { boolValue: null, intValue: null, doubleValue: null, stringValue: null, predefinedVariationId: null } }, flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, false, this.featureFlagLimitations()),
5748
+ generatePercentageOptionFormGroup({ percentage: 100, value: currentValue }, flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, false, this.featureFlagLimitations(), flagState.settingValue.setting.isJson),
5749
+ generatePercentageOptionFormGroup({ percentage: 0, value: { boolValue: null, intValue: null, doubleValue: null, stringValue: null, predefinedVariationId: null } }, flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, false, this.featureFlagLimitations(), flagState.settingValue.setting.isJson),
5708
5750
  ], [validatePercentageSum]));
5709
5751
  formGroup.removeControl("value");
5710
5752
  formGroup.markAsDirty();
@@ -5735,7 +5777,7 @@ class TargetingRuleComponent {
5735
5777
  return;
5736
5778
  }
5737
5779
  const lastValue = getRawSettiongValue(formGroup.controls.percentageOptions.controls[0].controls.value);
5738
- formGroup.setControl("value", generateValueFormGroup(lastValue, this.flagState().settingValue.setting.settingType, this.flagState().settingValue.setting.predefinedVariations, false, this.featureFlagLimitations()));
5780
+ formGroup.setControl("value", generateValueFormGroup(lastValue, this.flagState().settingValue.setting.settingType, this.flagState().settingValue.setting.predefinedVariations, false, this.featureFlagLimitations(), this.flagState().settingValue.setting.isJson));
5739
5781
  formGroup.removeControl("percentageOptions");
5740
5782
  formGroup.markAsDirty();
5741
5783
  }
@@ -5799,7 +5841,7 @@ class EvaluationFormulaComponent {
5799
5841
  segmentCondition: null,
5800
5842
  }, this.flagState().readOnly, this.flagState().prerequisiteSettings, this.featureFlagLimitations()),
5801
5843
  ]),
5802
- value: generateDefaultValueFormGroup(this.flagState().settingValue.setting.settingType, this.flagState().settingValue.setting.predefinedVariations, this.flagState().readOnly, this.featureFlagLimitations()),
5844
+ value: generateDefaultValueFormGroup(this.flagState().settingValue.setting.settingType, this.flagState().settingValue.setting.predefinedVariations, this.flagState().readOnly, this.featureFlagLimitations(), this.flagState().settingValue.setting.isJson),
5803
5845
  });
5804
5846
  this.addTargetingRuleFormGroup(formGroup);
5805
5847
  formGroup.markAsDirty();
@@ -5820,7 +5862,7 @@ class EvaluationFormulaComponent {
5820
5862
  segmentCondition: generateEmptySegmentConditionFormGroup(),
5821
5863
  }),
5822
5864
  ]),
5823
- value: generateDefaultValueFormGroup(this.flagState().settingValue.setting.settingType, this.flagState().settingValue.setting.predefinedVariations, this.flagState().readOnly, this.featureFlagLimitations()),
5865
+ value: generateDefaultValueFormGroup(this.flagState().settingValue.setting.settingType, this.flagState().settingValue.setting.predefinedVariations, this.flagState().readOnly, this.featureFlagLimitations(), this.flagState().settingValue.setting.isJson),
5824
5866
  });
5825
5867
  this.addTargetingRuleFormGroup(formGroup);
5826
5868
  formGroup.markAsDirty();
@@ -5837,7 +5879,7 @@ class EvaluationFormulaComponent {
5837
5879
  prerequisiteFlagCondition: generateEmptyPrerequisiteFlagConditionFormGroup(this.featureFlagLimitations()),
5838
5880
  }),
5839
5881
  ]),
5840
- value: generateDefaultValueFormGroup(this.flagState().settingValue.setting.settingType, this.flagState().settingValue.setting.predefinedVariations, this.flagState().readOnly, this.featureFlagLimitations()),
5882
+ value: generateDefaultValueFormGroup(this.flagState().settingValue.setting.settingType, this.flagState().settingValue.setting.predefinedVariations, this.flagState().readOnly, this.featureFlagLimitations(), this.flagState().settingValue.setting.isJson),
5841
5883
  });
5842
5884
  this.addTargetingRuleFormGroup(formGroup);
5843
5885
  formGroup.markAsDirty();
@@ -5852,7 +5894,7 @@ class EvaluationFormulaComponent {
5852
5894
  if (!this.checkFeatureFlagLimitations()) {
5853
5895
  return false;
5854
5896
  }
5855
- const formGroup = generateTargetingRuleWithEmptyPercentageOptions(flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, flagState.readOnly, flagState.prerequisiteSettings, this.featureFlagLimitations());
5897
+ const formGroup = generateTargetingRuleWithEmptyPercentageOptions(flagState.settingValue.setting.settingType, flagState.settingValue.setting.predefinedVariations, flagState.readOnly, flagState.prerequisiteSettings, this.featureFlagLimitations(), flagState.settingValue.setting.isJson);
5856
5898
  this.addTargetingRuleFormGroup(formGroup);
5857
5899
  formGroup.markAsDirty();
5858
5900
  this.recalcAddButtons.emit();
@@ -6239,7 +6281,7 @@ class FeatureFlagItemComponent extends BaseComponent {
6239
6281
  this.loadSucceeded = output();
6240
6282
  this.loadFailed = output();
6241
6283
  this.saveSucceeded = output();
6242
- this.saveFailed = output();
6284
+ this.componentError = output();
6243
6285
  this.expandedStateChanged = output();
6244
6286
  this.formValuesChanged = output();
6245
6287
  this.loading = true;
@@ -6257,7 +6299,6 @@ class FeatureFlagItemComponent extends BaseComponent {
6257
6299
  }
6258
6300
  reloadSettingValues() {
6259
6301
  this.loading = true;
6260
- this.createSettingValuesV2Service();
6261
6302
  forkJoin({
6262
6303
  segments: this.createSegmentsService().getSegments(this.productId()),
6263
6304
  settings: this.createSettingsService().getSettings(this.configId()),
@@ -6272,6 +6313,7 @@ class FeatureFlagItemComponent extends BaseComponent {
6272
6313
  name: sv.name,
6273
6314
  settingType: sv.settingType,
6274
6315
  predefinedVariations: sv.predefinedVariations,
6316
+ isJson: sv.isJson,
6275
6317
  };
6276
6318
  });
6277
6319
  this.segments = result.segments;
@@ -6328,9 +6370,9 @@ class FeatureFlagItemComponent extends BaseComponent {
6328
6370
  });
6329
6371
  }
6330
6372
  revertDirtyValuesFromState() {
6331
- this.formGroup.setControl("defaultValue", generateValueFormGroup(this.settingFormula.defaultValue, this.settingFormula.setting.settingType, this.settingFormula.setting.predefinedVariations, this.settingFormula.readOnly, this.settingFormula.featureFlagLimitations));
6373
+ this.formGroup.setControl("defaultValue", generateValueFormGroup(this.settingFormula.defaultValue, this.settingFormula.setting.settingType, this.settingFormula.setting.predefinedVariations, this.settingFormula.readOnly, this.settingFormula.featureFlagLimitations, this.settingFormula.setting.isJson));
6332
6374
  this.formGroup.setControl("percentageEvaluationAttribute", new FormControl({ value: this.settingFormula.percentageEvaluationAttribute, disabled: this.settingFormula.readOnly }, { validators: [Validators.max(1000)], nonNullable: true }));
6333
- this.formGroup.setControl("targetingRules", new FormArray(this.settingFormula.targetingRules.map(ft => generateTargetingRuleFormGroup(ft, this.settingFormula.setting.settingType, this.settingFormula.setting.predefinedVariations, this.settingFormula.readOnly, this.prerequisiteSettings, this.settingFormula.featureFlagLimitations))));
6375
+ this.formGroup.setControl("targetingRules", new FormArray(this.settingFormula.targetingRules.map(ft => generateTargetingRuleFormGroup(ft, this.settingFormula.setting.settingType, this.settingFormula.setting.predefinedVariations, this.settingFormula.readOnly, this.prerequisiteSettings, this.settingFormula.featureFlagLimitations, this.settingFormula.setting.isJson))));
6334
6376
  this.recalcAddButtons();
6335
6377
  this.formGroup.markAsPristine();
6336
6378
  this.formGroup.markAsUntouched();
@@ -6431,7 +6473,7 @@ class FeatureFlagItemComponent extends BaseComponent {
6431
6473
  this.formGroup.setErrors({ internalServerError: "Internal server error" });
6432
6474
  this.formGroup.markAsTouched();
6433
6475
  this.showFeedBackMessage = true;
6434
- this.saveFailed.emit();
6476
+ this.componentError.emit(error);
6435
6477
  },
6436
6478
  });
6437
6479
  }
@@ -6564,7 +6606,7 @@ class FeatureFlagItemComponent extends BaseComponent {
6564
6606
  },
6565
6607
  });
6566
6608
  dialogRef.afterClosed().subscribe(() => {
6567
- this.saveFailed.emit();
6609
+ this.componentError.emit(new Error("Concurent Delete Error."));
6568
6610
  });
6569
6611
  },
6570
6612
  error: (error) => {
@@ -6574,12 +6616,18 @@ class FeatureFlagItemComponent extends BaseComponent {
6574
6616
  });
6575
6617
  }
6576
6618
  openVariationsDialog(event) {
6577
- this.createProductsService().getProduct(this.productId()).subscribe({
6578
- next: product => {
6619
+ forkJoin({
6620
+ product: this.createProductsService().getProduct(this.productId()),
6621
+ setting: this.createSettingsService().getSetting(event.settingId),
6622
+ }).subscribe({
6623
+ next: result => {
6624
+ const setting = result.setting;
6625
+ const product = result.product;
6579
6626
  const dialogRef = this.dialog.open(VariationsDialogComponent, {
6580
6627
  data: {
6581
- settingId: event.settingId,
6582
- settingName: event.settingName,
6628
+ settingId: setting.settingId,
6629
+ settingName: setting.name,
6630
+ isJson: setting.isJson,
6583
6631
  manage: true,
6584
6632
  organizationId: product.organization.organizationId,
6585
6633
  productId: this.productId(),
@@ -6598,17 +6646,20 @@ class FeatureFlagItemComponent extends BaseComponent {
6598
6646
  },
6599
6647
  error: (error) => {
6600
6648
  console.log(error);
6649
+ if (error instanceof HttpErrorResponse && error.status === 401) {
6650
+ this.componentError.emit(error);
6651
+ }
6601
6652
  this.messagingService.showErrorSnack("Could not load predefined variations dialog.");
6602
6653
  },
6603
6654
  });
6604
6655
  }
6605
6656
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: FeatureFlagItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6606
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: FeatureFlagItemComponent, isStandalone: true, selector: "app-feature-flag-item", inputs: { productId: { classPropertyName: "productId", publicName: "productId", isSignal: true, isRequired: true, transformFunction: null }, environmentId: { classPropertyName: "environmentId", publicName: "environmentId", isSignal: true, isRequired: true, transformFunction: null }, configId: { classPropertyName: "configId", publicName: "configId", isSignal: true, isRequired: true, transformFunction: null }, settingId: { classPropertyName: "settingId", publicName: "settingId", isSignal: true, isRequired: true, transformFunction: null }, canDeleteSetting: { classPropertyName: "canDeleteSetting", publicName: "canDeleteSetting", isSignal: true, isRequired: false, transformFunction: null }, deleteSettingText: { classPropertyName: "deleteSettingText", publicName: "deleteSettingText", isSignal: true, isRequired: false, transformFunction: null }, showEnvironmentName: { classPropertyName: "showEnvironmentName", publicName: "showEnvironmentName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { deleteSettingRequested: "deleteSettingRequested", loadSucceeded: "loadSucceeded", loadFailed: "loadFailed", saveSucceeded: "saveSucceeded", saveFailed: "saveFailed", expandedStateChanged: "expandedStateChanged", formValuesChanged: "formValuesChanged" }, usesInheritance: true, ngImport: i0, template: "<div class=\"container\">\n @if (!loading) {\n <form id=\"feature-flag-form\" [formGroup]=\"formGroup\" (ngSubmit)=\"submit()\">\n <div [ngClass]=\"{ 'invalid-flag': formGroup.invalid }\">\n <app-feature-flag\n [formGroup]=\"formGroup\"\n [flagState]=\"flagState\"\n [segments]=\"segments\"\n [featureFlagLimitations]=\"settingFormula.featureFlagLimitations\"\n [hasOtherEnvironment]=\"false\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [environmentName]=\"settingFormula.environment.name\"\n [deleteSettingText]=\"deleteSettingText()\"\n [canDeleteSetting]=\"canDeleteSetting()\"\n [predefinedVariationsEnabled]=\"true\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\"\n (subscriptionLimitReached)=\"subscriptionLimitReachedCalled()\"\n (addSegmentConditionRequestedWithoutSegments)=\"addSegmentConditionRequestedWithoutSegments()\"\n (prerequisiteConditionChanged)=\"recalcPrerequisites()\"\n (recalcAddButtons)=\"recalcAddButtons()\"\n (expandedChanged)=\"expandedChanged($event)\"\n (viewVariationsRequested)=\"viewVariations($event)\" />\n </div>\n @if (!settingFormula.readOnly && formGroup!.dirty) {\n <div class=\"save\">\n <button\n class=\"save-button\"\n mat-flat-button\n color=\"warn\"\n type=\"submit\"\n [class.animate]=\"formGroup.dirty\"\n [disabled]=\"submitting\"\n [track]=\"['save & publish click', 'feature flags and settings']\">\n <mat-icon>backup</mat-icon>\n <span>Save & publish changes</span>\n </button>\n <button\n type=\"button\"\n class=\"revert-button\"\n mat-stroked-button\n [disabled]=\"submitting\"\n [track]=\"['revert click', 'feature flags and settings']\"\n (click)=\"revert()\">\n <span>Revert</span>\n </button>\n @if (formGroup.touched && formGroup.invalid && showFeedBackMessage) {\n <div class=\"feedback\">\n @if (formGroup.errors && formGroup.errors[\"internalServerError\"]) {\n <div class=\"error\">\n <span>\n Something went wrong and we could not save your settings. You can try again or\n <a href=\"https://configcat.com/support\" target=\"_blank\" rel=\"noopener noreferrer\">contact us.</a>\n </span>\n </div>\n }\n @if (!formGroup.errors || !formGroup.errors[\"internalServerError\"]) {\n <div class=\"error\">\n <span>Oh no! A feature flag has invalid or missing data.&nbsp;</span>\n </div>\n }\n </div>\n }\n </div>\n }\n </form>\n }\n</div>\n", styles: [".container{padding:0 .5rem 1rem}.container .container-content{padding-top:1rem}.container .size-obs{min-width:40px;min-height:120px}.container .size-obs .hidden{display:none}.container .size-obs .visible{display:block}.container .controls{display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:.5rem;padding-top:.2rem;gap:1rem}.container .controls .controls-left{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}.container .controls .controls-left .add-feature-flag-wrapper{display:flex;flex-wrap:nowrap}.container .controls .controls-left .add-feature-flag-wrapper .add-feature-flag{border-bottom-right-radius:0%;border-top-right-radius:0%}.container .controls .controls-left .add-feature-flag-wrapper .add-other-setting{min-width:0;border-bottom-left-radius:0%;border-top-left-radius:0%;border-left:0px;padding:0 12px}.container .controls .controls-left .add-feature-flag-wrapper .add-other-setting .mat-icon{margin-right:0;margin-left:0}.container .controls .controls-left .tag-filter{min-width:0}.container .controls .controls-left .tag-filter mat-form-field{max-width:600px;min-width:246px}.container .controls .controls-left .tag-filter mat-form-field input{max-width:100px}.container .controls .controls-left .tag-filter .tag{font-size:.9em;max-width:120px;min-width:0}.container .controls .more-container{display:flex;gap:.5rem}.container .controls .more-container .more-button{padding:0 8px;min-width:unset}.container .controls .more-container .more-button mat-icon{margin-left:unset;margin-right:unset}.container .controls .option-icon{opacity:.7}.container .controls .option-name{font-size:14px}.container .controls .option-name mat-icon{font-size:22px;width:22px;height:22px}.container .not-found{text-align:center;padding-top:2rem}.container .not-found img{width:300px}.container .history-link{display:flex;align-items:center;margin-left:.2em}.container .history-link mat-icon{margin-right:5px;font-size:20px;width:20px;height:20px}.container .jump{cursor:pointer}.container .feature-flags-container{margin-bottom:.3rem}.container .save{position:sticky;bottom:0;background-color:var(--page-background-color);display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;z-index:999;padding-top:1rem;padding-bottom:1rem;gap:.5rem}.container .save .save-button{height:38px;font-size:13px!important;animation:shadow-pulse 1s 3}.container .save .save-button:disabled{animation:none}.container .error{color:var(--flag-validation-error);padding:5px;font-size:.9em}.container .error a{color:var(--flag-validation-error);text-decoration:underline}.container .steps{display:flex;align-items:center;margin:1rem 0;justify-content:space-between;flex-wrap:wrap}.container .steps .steps-left{display:flex;flex-wrap:nowrap;align-items:center;justify-content:flex-start}.container .steps .steps-left>h2{cursor:pointer}.container .steps .connected{display:flex;align-items:center}.container .divider{margin-top:1.3rem}.add-menu-item{display:flex;align-items:center;text-wrap:nowrap}.add-menu-item .add-menu-img{width:24px;height:24px;margin-right:8px}.top-menu-selector .strong{font-weight:600}.top-menu-selector .feature-flag-selector-item{display:flex;flex-wrap:nowrap}.top-menu-selector .feature-flag-selector-item .feature-flag-selector-img{width:24px;height:24px;margin-right:8px;align-self:center}.top-menu-selector .feature-flag-selector-item span{overflow:hidden;text-overflow:ellipsis}.top-menu-selector .filter{display:flex;margin:0 8px 8px;justify-content:space-around}.top-menu-selector .filter mat-form-field{width:100%}.top-menu-selector .filter-not-found{margin-left:12px}.connect-title{font-size:17px;font-weight:700;margin:16px 0;cursor:pointer}.search-key-icon{display:inline-flex;justify-content:center;align-items:center;font-size:11px;width:1.8em;height:1.8em;margin-right:1px;background-color:var(--flag-search-bar-icon-background);border-radius:3px;border:1px solid var(--flag-search-bar-icon-border)}@media(max-width:750px){.container{padding:0 .5rem 1rem}.expand-collapse{flex-wrap:wrap!important}.expand-collapse .btn{margin-bottom:2px}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.RxwebFormDirective, selector: "[formGroup],[rxwebForm]", inputs: ["formGroup", "rxwebForm"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: FeatureFlagComponent, selector: "app-feature-flag", inputs: ["formGroup", "flagState", "segments", "featureFlagLimitations", "hasOtherEnvironment", "environmentName", "showEnvironmentName", "deleteSettingText", "canDeleteSetting", "predefinedVariationsEnabled"], outputs: ["addSegmentConditionRequestedWithoutSegments", "expandedChanged", "deleteSettingRequested", "subscriptionLimitReached", "prerequisiteConditionChanged", "recalcAddButtons", "viewVariationsRequested"] }, { 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: TrackingDirective, selector: "[track]", inputs: ["track"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
6657
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: FeatureFlagItemComponent, isStandalone: true, selector: "app-feature-flag-item", inputs: { productId: { classPropertyName: "productId", publicName: "productId", isSignal: true, isRequired: true, transformFunction: null }, environmentId: { classPropertyName: "environmentId", publicName: "environmentId", isSignal: true, isRequired: true, transformFunction: null }, configId: { classPropertyName: "configId", publicName: "configId", isSignal: true, isRequired: true, transformFunction: null }, settingId: { classPropertyName: "settingId", publicName: "settingId", isSignal: true, isRequired: true, transformFunction: null }, canDeleteSetting: { classPropertyName: "canDeleteSetting", publicName: "canDeleteSetting", isSignal: true, isRequired: false, transformFunction: null }, deleteSettingText: { classPropertyName: "deleteSettingText", publicName: "deleteSettingText", isSignal: true, isRequired: false, transformFunction: null }, showEnvironmentName: { classPropertyName: "showEnvironmentName", publicName: "showEnvironmentName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { deleteSettingRequested: "deleteSettingRequested", loadSucceeded: "loadSucceeded", loadFailed: "loadFailed", saveSucceeded: "saveSucceeded", componentError: "componentError", expandedStateChanged: "expandedStateChanged", formValuesChanged: "formValuesChanged" }, usesInheritance: true, ngImport: i0, template: "<div class=\"container\">\n @if (!loading) {\n <form id=\"feature-flag-form\" [formGroup]=\"formGroup\" (ngSubmit)=\"submit()\">\n <div [ngClass]=\"{ 'invalid-flag': formGroup.invalid }\">\n <app-feature-flag\n [formGroup]=\"formGroup\"\n [flagState]=\"flagState\"\n [segments]=\"segments\"\n [featureFlagLimitations]=\"settingFormula.featureFlagLimitations\"\n [hasOtherEnvironment]=\"false\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [environmentName]=\"settingFormula.environment.name\"\n [deleteSettingText]=\"deleteSettingText()\"\n [canDeleteSetting]=\"canDeleteSetting()\"\n [predefinedVariationsEnabled]=\"true\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\"\n (subscriptionLimitReached)=\"subscriptionLimitReachedCalled()\"\n (addSegmentConditionRequestedWithoutSegments)=\"addSegmentConditionRequestedWithoutSegments()\"\n (prerequisiteConditionChanged)=\"recalcPrerequisites()\"\n (recalcAddButtons)=\"recalcAddButtons()\"\n (expandedChanged)=\"expandedChanged($event)\"\n (viewVariationsRequested)=\"viewVariations($event)\" />\n </div>\n @if (!settingFormula.readOnly && formGroup!.dirty) {\n <div class=\"save\">\n <button\n class=\"save-button\"\n mat-flat-button\n color=\"warn\"\n type=\"submit\"\n [class.animate]=\"formGroup.dirty\"\n [disabled]=\"submitting\"\n [track]=\"['save & publish click', 'feature flags and settings']\">\n <mat-icon>backup</mat-icon>\n <span>Save & publish changes</span>\n </button>\n <button\n type=\"button\"\n class=\"revert-button\"\n mat-stroked-button\n [disabled]=\"submitting\"\n [track]=\"['revert click', 'feature flags and settings']\"\n (click)=\"revert()\">\n <span>Revert</span>\n </button>\n @if (formGroup.touched && formGroup.invalid && showFeedBackMessage) {\n <div class=\"feedback\">\n @if (formGroup.errors && formGroup.errors[\"internalServerError\"]) {\n <div class=\"error\">\n <span>\n Something went wrong and we could not save your settings. You can try again or\n <a href=\"https://configcat.com/support\" target=\"_blank\" rel=\"noopener noreferrer\">contact us.</a>\n </span>\n </div>\n }\n @if (!formGroup.errors || !formGroup.errors[\"internalServerError\"]) {\n <div class=\"error\">\n <span>Oh no! A feature flag has invalid or missing data.&nbsp;</span>\n </div>\n }\n </div>\n }\n </div>\n }\n </form>\n }\n</div>\n", styles: [".container{padding:0 .5rem 1rem}.container .container-content{padding-top:1rem}.container .size-obs{min-width:40px;min-height:120px}.container .size-obs .hidden{display:none}.container .size-obs .visible{display:block}.container .controls{display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:.5rem;padding-top:.2rem;gap:1rem}.container .controls .controls-left{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}.container .controls .controls-left .add-feature-flag-wrapper{display:flex;flex-wrap:nowrap}.container .controls .controls-left .add-feature-flag-wrapper .add-feature-flag{border-bottom-right-radius:0%;border-top-right-radius:0%}.container .controls .controls-left .add-feature-flag-wrapper .add-other-setting{min-width:0;border-bottom-left-radius:0%;border-top-left-radius:0%;border-left:0px;padding:0 12px}.container .controls .controls-left .add-feature-flag-wrapper .add-other-setting .mat-icon{margin-right:0;margin-left:0}.container .controls .controls-left .tag-filter{min-width:0}.container .controls .controls-left .tag-filter mat-form-field{max-width:600px;min-width:246px}.container .controls .controls-left .tag-filter mat-form-field input{max-width:100px}.container .controls .controls-left .tag-filter .tag{font-size:.9em;max-width:120px;min-width:0}.container .controls .more-container{display:flex;gap:.5rem}.container .controls .more-container .more-button{padding:0 8px;min-width:unset}.container .controls .more-container .more-button mat-icon{margin-left:unset;margin-right:unset}.container .controls .option-icon{opacity:.7}.container .controls .option-name{font-size:14px}.container .controls .option-name mat-icon{font-size:22px;width:22px;height:22px}.container .not-found{text-align:center;padding-top:2rem}.container .not-found img{width:300px}.container .history-link{display:flex;align-items:center;margin-left:.2em}.container .history-link mat-icon{margin-right:5px;font-size:20px;width:20px;height:20px}.container .jump{cursor:pointer}.container .feature-flags-container{margin-bottom:.3rem}.container .save{position:sticky;bottom:0;background-color:var(--page-background-color);display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;z-index:999;padding-top:1rem;padding-bottom:1rem;gap:.5rem}.container .save .save-button{height:38px;font-size:13px!important;animation:shadow-pulse 1s 3}.container .save .save-button:disabled{animation:none}.container .error{color:var(--flag-validation-error);padding:5px;font-size:.9em}.container .error a{color:var(--flag-validation-error);text-decoration:underline}.container .steps{display:flex;align-items:center;margin:1rem 0;justify-content:space-between;flex-wrap:wrap}.container .steps .steps-left{display:flex;flex-wrap:nowrap;align-items:center;justify-content:flex-start}.container .steps .steps-left>h2{cursor:pointer}.container .steps .connected{display:flex;align-items:center}.container .divider{margin-top:1.3rem}.add-menu-item{display:flex;align-items:center;text-wrap:nowrap}.add-menu-item .add-menu-img{width:24px;height:24px;margin-right:8px}.top-menu-selector .strong{font-weight:600}.top-menu-selector .feature-flag-selector-item{display:flex;flex-wrap:nowrap}.top-menu-selector .feature-flag-selector-item .feature-flag-selector-img{width:24px;height:24px;margin-right:8px;align-self:center}.top-menu-selector .feature-flag-selector-item span{overflow:hidden;text-overflow:ellipsis}.top-menu-selector .filter{display:flex;margin:0 8px 8px;justify-content:space-around}.top-menu-selector .filter mat-form-field{width:100%}.top-menu-selector .filter-not-found{margin-left:12px}.connect-title{font-size:17px;font-weight:700;margin:16px 0;cursor:pointer}.search-key-icon{display:inline-flex;justify-content:center;align-items:center;font-size:11px;width:1.8em;height:1.8em;margin-right:1px;background-color:var(--flag-search-bar-icon-background);border-radius:3px;border:1px solid var(--flag-search-bar-icon-border)}@media(max-width:750px){.container{padding:0 .5rem 1rem}.expand-collapse{flex-wrap:wrap!important}.expand-collapse .btn{margin-bottom:2px}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.RxwebFormDirective, selector: "[formGroup],[rxwebForm]", inputs: ["formGroup", "rxwebForm"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: FeatureFlagComponent, selector: "app-feature-flag", inputs: ["formGroup", "flagState", "segments", "featureFlagLimitations", "hasOtherEnvironment", "environmentName", "showEnvironmentName", "deleteSettingText", "canDeleteSetting", "predefinedVariationsEnabled"], outputs: ["addSegmentConditionRequestedWithoutSegments", "expandedChanged", "deleteSettingRequested", "subscriptionLimitReached", "prerequisiteConditionChanged", "recalcAddButtons", "viewVariationsRequested"] }, { 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: TrackingDirective, selector: "[track]", inputs: ["track"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
6607
6658
  }
6608
6659
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: FeatureFlagItemComponent, decorators: [{
6609
6660
  type: Component,
6610
6661
  args: [{ selector: "app-feature-flag-item", imports: [FormsModule, ReactiveFormsModule, RxReactiveFormsModule, NgClass, FeatureFlagComponent, MatButton, TrackingDirective, MatIcon], template: "<div class=\"container\">\n @if (!loading) {\n <form id=\"feature-flag-form\" [formGroup]=\"formGroup\" (ngSubmit)=\"submit()\">\n <div [ngClass]=\"{ 'invalid-flag': formGroup.invalid }\">\n <app-feature-flag\n [formGroup]=\"formGroup\"\n [flagState]=\"flagState\"\n [segments]=\"segments\"\n [featureFlagLimitations]=\"settingFormula.featureFlagLimitations\"\n [hasOtherEnvironment]=\"false\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [environmentName]=\"settingFormula.environment.name\"\n [deleteSettingText]=\"deleteSettingText()\"\n [canDeleteSetting]=\"canDeleteSetting()\"\n [predefinedVariationsEnabled]=\"true\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\"\n (subscriptionLimitReached)=\"subscriptionLimitReachedCalled()\"\n (addSegmentConditionRequestedWithoutSegments)=\"addSegmentConditionRequestedWithoutSegments()\"\n (prerequisiteConditionChanged)=\"recalcPrerequisites()\"\n (recalcAddButtons)=\"recalcAddButtons()\"\n (expandedChanged)=\"expandedChanged($event)\"\n (viewVariationsRequested)=\"viewVariations($event)\" />\n </div>\n @if (!settingFormula.readOnly && formGroup!.dirty) {\n <div class=\"save\">\n <button\n class=\"save-button\"\n mat-flat-button\n color=\"warn\"\n type=\"submit\"\n [class.animate]=\"formGroup.dirty\"\n [disabled]=\"submitting\"\n [track]=\"['save & publish click', 'feature flags and settings']\">\n <mat-icon>backup</mat-icon>\n <span>Save & publish changes</span>\n </button>\n <button\n type=\"button\"\n class=\"revert-button\"\n mat-stroked-button\n [disabled]=\"submitting\"\n [track]=\"['revert click', 'feature flags and settings']\"\n (click)=\"revert()\">\n <span>Revert</span>\n </button>\n @if (formGroup.touched && formGroup.invalid && showFeedBackMessage) {\n <div class=\"feedback\">\n @if (formGroup.errors && formGroup.errors[\"internalServerError\"]) {\n <div class=\"error\">\n <span>\n Something went wrong and we could not save your settings. You can try again or\n <a href=\"https://configcat.com/support\" target=\"_blank\" rel=\"noopener noreferrer\">contact us.</a>\n </span>\n </div>\n }\n @if (!formGroup.errors || !formGroup.errors[\"internalServerError\"]) {\n <div class=\"error\">\n <span>Oh no! A feature flag has invalid or missing data.&nbsp;</span>\n </div>\n }\n </div>\n }\n </div>\n }\n </form>\n }\n</div>\n", styles: [".container{padding:0 .5rem 1rem}.container .container-content{padding-top:1rem}.container .size-obs{min-width:40px;min-height:120px}.container .size-obs .hidden{display:none}.container .size-obs .visible{display:block}.container .controls{display:flex;flex-wrap:wrap;justify-content:space-between;padding-bottom:.5rem;padding-top:.2rem;gap:1rem}.container .controls .controls-left{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem}.container .controls .controls-left .add-feature-flag-wrapper{display:flex;flex-wrap:nowrap}.container .controls .controls-left .add-feature-flag-wrapper .add-feature-flag{border-bottom-right-radius:0%;border-top-right-radius:0%}.container .controls .controls-left .add-feature-flag-wrapper .add-other-setting{min-width:0;border-bottom-left-radius:0%;border-top-left-radius:0%;border-left:0px;padding:0 12px}.container .controls .controls-left .add-feature-flag-wrapper .add-other-setting .mat-icon{margin-right:0;margin-left:0}.container .controls .controls-left .tag-filter{min-width:0}.container .controls .controls-left .tag-filter mat-form-field{max-width:600px;min-width:246px}.container .controls .controls-left .tag-filter mat-form-field input{max-width:100px}.container .controls .controls-left .tag-filter .tag{font-size:.9em;max-width:120px;min-width:0}.container .controls .more-container{display:flex;gap:.5rem}.container .controls .more-container .more-button{padding:0 8px;min-width:unset}.container .controls .more-container .more-button mat-icon{margin-left:unset;margin-right:unset}.container .controls .option-icon{opacity:.7}.container .controls .option-name{font-size:14px}.container .controls .option-name mat-icon{font-size:22px;width:22px;height:22px}.container .not-found{text-align:center;padding-top:2rem}.container .not-found img{width:300px}.container .history-link{display:flex;align-items:center;margin-left:.2em}.container .history-link mat-icon{margin-right:5px;font-size:20px;width:20px;height:20px}.container .jump{cursor:pointer}.container .feature-flags-container{margin-bottom:.3rem}.container .save{position:sticky;bottom:0;background-color:var(--page-background-color);display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;z-index:999;padding-top:1rem;padding-bottom:1rem;gap:.5rem}.container .save .save-button{height:38px;font-size:13px!important;animation:shadow-pulse 1s 3}.container .save .save-button:disabled{animation:none}.container .error{color:var(--flag-validation-error);padding:5px;font-size:.9em}.container .error a{color:var(--flag-validation-error);text-decoration:underline}.container .steps{display:flex;align-items:center;margin:1rem 0;justify-content:space-between;flex-wrap:wrap}.container .steps .steps-left{display:flex;flex-wrap:nowrap;align-items:center;justify-content:flex-start}.container .steps .steps-left>h2{cursor:pointer}.container .steps .connected{display:flex;align-items:center}.container .divider{margin-top:1.3rem}.add-menu-item{display:flex;align-items:center;text-wrap:nowrap}.add-menu-item .add-menu-img{width:24px;height:24px;margin-right:8px}.top-menu-selector .strong{font-weight:600}.top-menu-selector .feature-flag-selector-item{display:flex;flex-wrap:nowrap}.top-menu-selector .feature-flag-selector-item .feature-flag-selector-img{width:24px;height:24px;margin-right:8px;align-self:center}.top-menu-selector .feature-flag-selector-item span{overflow:hidden;text-overflow:ellipsis}.top-menu-selector .filter{display:flex;margin:0 8px 8px;justify-content:space-around}.top-menu-selector .filter mat-form-field{width:100%}.top-menu-selector .filter-not-found{margin-left:12px}.connect-title{font-size:17px;font-weight:700;margin:16px 0;cursor:pointer}.search-key-icon{display:inline-flex;justify-content:center;align-items:center;font-size:11px;width:1.8em;height:1.8em;margin-right:1px;background-color:var(--flag-search-bar-icon-background);border-radius:3px;border:1px solid var(--flag-search-bar-icon-border)}@media(max-width:750px){.container{padding:0 .5rem 1rem}.expand-collapse{flex-wrap:wrap!important}.expand-collapse .btn{margin-bottom:2px}}\n"] }]
6611
- }], ctorParameters: () => [], propDecorators: { productId: [{ type: i0.Input, args: [{ isSignal: true, alias: "productId", required: true }] }], environmentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "environmentId", required: true }] }], configId: [{ type: i0.Input, args: [{ isSignal: true, alias: "configId", required: true }] }], settingId: [{ type: i0.Input, args: [{ isSignal: true, alias: "settingId", required: true }] }], canDeleteSetting: [{ type: i0.Input, args: [{ isSignal: true, alias: "canDeleteSetting", required: false }] }], deleteSettingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "deleteSettingText", required: false }] }], showEnvironmentName: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEnvironmentName", required: false }] }], deleteSettingRequested: [{ type: i0.Output, args: ["deleteSettingRequested"] }], loadSucceeded: [{ type: i0.Output, args: ["loadSucceeded"] }], loadFailed: [{ type: i0.Output, args: ["loadFailed"] }], saveSucceeded: [{ type: i0.Output, args: ["saveSucceeded"] }], saveFailed: [{ type: i0.Output, args: ["saveFailed"] }], expandedStateChanged: [{ type: i0.Output, args: ["expandedStateChanged"] }], formValuesChanged: [{ type: i0.Output, args: ["formValuesChanged"] }] } });
6662
+ }], ctorParameters: () => [], propDecorators: { productId: [{ type: i0.Input, args: [{ isSignal: true, alias: "productId", required: true }] }], environmentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "environmentId", required: true }] }], configId: [{ type: i0.Input, args: [{ isSignal: true, alias: "configId", required: true }] }], settingId: [{ type: i0.Input, args: [{ isSignal: true, alias: "settingId", required: true }] }], canDeleteSetting: [{ type: i0.Input, args: [{ isSignal: true, alias: "canDeleteSetting", required: false }] }], deleteSettingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "deleteSettingText", required: false }] }], showEnvironmentName: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEnvironmentName", required: false }] }], deleteSettingRequested: [{ type: i0.Output, args: ["deleteSettingRequested"] }], loadSucceeded: [{ type: i0.Output, args: ["loadSucceeded"] }], loadFailed: [{ type: i0.Output, args: ["loadFailed"] }], saveSucceeded: [{ type: i0.Output, args: ["saveSucceeded"] }], componentError: [{ type: i0.Output, args: ["componentError"] }], expandedStateChanged: [{ type: i0.Output, args: ["expandedStateChanged"] }], formValuesChanged: [{ type: i0.Output, args: ["formValuesChanged"] }] } });
6612
6663
 
6613
6664
  class LinkFeatureFlagComponent {
6614
6665
  constructor() {
@@ -6620,6 +6671,7 @@ class LinkFeatureFlagComponent {
6620
6671
  this.resizeRequested = output();
6621
6672
  this.cancelInitiated = output();
6622
6673
  this.selectDropdownPanelChangedReqested = output();
6674
+ this.componentError = output();
6623
6675
  this.formBuilder = inject(NonNullableFormBuilder);
6624
6676
  this.formGroup = this.formBuilder.group({
6625
6677
  productId: new FormControl("", {
@@ -6673,8 +6725,11 @@ class LinkFeatureFlagComponent {
6673
6725
  selectDropdownPanelChanged(useSelector) {
6674
6726
  this.selectDropdownPanelChangedReqested.emit(useSelector);
6675
6727
  }
6728
+ dropdownComponentFailed(error) {
6729
+ this.componentError.emit(error);
6730
+ }
6676
6731
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: LinkFeatureFlagComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6677
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: LinkFeatureFlagComponent, isStandalone: true, selector: "app-link-feature-flag", inputs: { authorizationParameters: { classPropertyName: "authorizationParameters", publicName: "authorizationParameters", isSignal: true, isRequired: false, transformFunction: null }, hideCancelButton: { classPropertyName: "hideCancelButton", publicName: "hideCancelButton", isSignal: true, isRequired: false, transformFunction: null }, addButtonLabel: { classPropertyName: "addButtonLabel", publicName: "addButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelButtonLabel: { classPropertyName: "cancelButtonLabel", publicName: "cancelButtonLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { linkInitiated: "linkInitiated", resizeRequested: "resizeRequested", cancelInitiated: "cancelInitiated", selectDropdownPanelChangedReqested: "selectDropdownPanelChangedReqested" }, ngImport: i0, template: "<div class=\"container\">\n <form class=\"form\" [formGroup]=\"formGroup\" (ngSubmit)=\"add()\">\n <div>\n <app-product-select\n name=\"productId\"\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [valueFormControl]=\"formGroup.controls.productId\"\n [customDropdown]=\"true\" />\n @if (formGroup.controls.productId.value) {\n <app-config-select\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [customDropdown]=\"true\"\n [productId]=\"formGroup.controls.productId.value\"\n [valueFormControl]=\"formGroup.controls.configId\"\n (dropdownOpened)=\"selectDropdownPanelChanged($event)\" />\n }\n @if (formGroup.controls.productId.value) {\n <app-environment-select\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [productId]=\"formGroup.controls.productId.value\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [valueFormControl]=\"formGroup.controls.environmentId\"\n [customDropdown]=\"true\"\n (dropdownOpened)=\"selectDropdownPanelChanged($event)\" />\n }\n @if (formGroup.controls.configId.value) {\n <app-setting-select\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [configId]=\"formGroup.controls.configId.value\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [valueFormControl]=\"formGroup.controls.settingId\"\n [customDropdown]=\"true\"\n (dropdownOpened)=\"selectDropdownPanelChanged($event)\" />\n }\n </div>\n <div class=\"buttons\">\n <button mat-raised-button color=\"primary\" type=\"submit\" [disabled]=\"submitting() || !formGroup.valid\">\n {{ addButtonLabel() ? addButtonLabel() : \"Add\" }}\n </button>\n @if (!hideCancelButton()) {\n <button mat-stroked-button type=\"button\" (click)=\"cancel()\">\n {{ cancelButtonLabel() ? cancelButtonLabel() : \"Cancel\" }}\n </button>\n }\n </div>\n </form>\n</div>\n", styles: [".container{margin:8px 8px 16px}.container .form>*{width:100%}.container .form .error{color:var(--flag-validation-error);margin:0 5px 5px}.buttons{margin-bottom:16px}.buttons>*{margin-right:16px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.RxwebFormDirective, selector: "[formGroup],[rxwebForm]", inputs: ["formGroup", "rxwebForm"] }, { 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: "component", type: ProductSelectComponent, selector: "app-product-select", inputs: ["valueFormControl", "preSelectedProductId"] }, { kind: "component", type: ConfigSelectComponent, selector: "app-config-select", inputs: ["valueFormControl", "productId", "preSelectedConfigId"] }, { kind: "component", type: EnvironmentSelectComponent, selector: "app-environment-select", inputs: ["valueFormControl", "productId"] }, { kind: "component", type: SettingSelectComponent, selector: "app-setting-select", inputs: ["valueFormControl", "configId"] }] }); }
6732
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: LinkFeatureFlagComponent, isStandalone: true, selector: "app-link-feature-flag", inputs: { authorizationParameters: { classPropertyName: "authorizationParameters", publicName: "authorizationParameters", isSignal: true, isRequired: false, transformFunction: null }, hideCancelButton: { classPropertyName: "hideCancelButton", publicName: "hideCancelButton", isSignal: true, isRequired: false, transformFunction: null }, addButtonLabel: { classPropertyName: "addButtonLabel", publicName: "addButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelButtonLabel: { classPropertyName: "cancelButtonLabel", publicName: "cancelButtonLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { linkInitiated: "linkInitiated", resizeRequested: "resizeRequested", cancelInitiated: "cancelInitiated", selectDropdownPanelChangedReqested: "selectDropdownPanelChangedReqested", componentError: "componentError" }, ngImport: i0, template: "<div class=\"container\">\n <form class=\"form\" [formGroup]=\"formGroup\" (ngSubmit)=\"add()\">\n <div>\n <app-product-select\n name=\"productId\"\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [valueFormControl]=\"formGroup.controls.productId\"\n [customDropdown]=\"true\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n @if (formGroup.controls.productId.value) {\n <app-config-select\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [customDropdown]=\"true\"\n [productId]=\"formGroup.controls.productId.value\"\n [valueFormControl]=\"formGroup.controls.configId\"\n (dropdownOpened)=\"selectDropdownPanelChanged($event)\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n }\n @if (formGroup.controls.productId.value) {\n <app-environment-select\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [productId]=\"formGroup.controls.productId.value\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [valueFormControl]=\"formGroup.controls.environmentId\"\n [customDropdown]=\"true\"\n (dropdownOpened)=\"selectDropdownPanelChanged($event)\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n }\n @if (formGroup.controls.configId.value) {\n <app-setting-select\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [configId]=\"formGroup.controls.configId.value\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [valueFormControl]=\"formGroup.controls.settingId\"\n [customDropdown]=\"true\"\n (dropdownOpened)=\"selectDropdownPanelChanged($event)\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n }\n </div>\n <div class=\"buttons\">\n <button mat-raised-button color=\"primary\" type=\"submit\" [disabled]=\"submitting() || !formGroup.valid\">\n {{ addButtonLabel() ? addButtonLabel() : \"Add\" }}\n </button>\n @if (!hideCancelButton()) {\n <button mat-stroked-button type=\"button\" (click)=\"cancel()\">\n {{ cancelButtonLabel() ? cancelButtonLabel() : \"Cancel\" }}\n </button>\n }\n </div>\n </form>\n</div>\n", styles: [".container{margin:8px 8px 16px}.container .form>*{width:100%}.container .form .error{color:var(--flag-validation-error);margin:0 5px 5px}.buttons{margin-bottom:16px}.buttons>*{margin-right:16px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: RxReactiveFormsModule }, { kind: "directive", type: i2.RxwebFormDirective, selector: "[formGroup],[rxwebForm]", inputs: ["formGroup", "rxwebForm"] }, { 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: "component", type: ProductSelectComponent, selector: "app-product-select", inputs: ["valueFormControl", "preSelectedProductId"], outputs: ["componentError"] }, { kind: "component", type: ConfigSelectComponent, selector: "app-config-select", inputs: ["valueFormControl", "productId", "preSelectedConfigId"], outputs: ["componentError"] }, { kind: "component", type: EnvironmentSelectComponent, selector: "app-environment-select", inputs: ["valueFormControl", "productId"], outputs: ["componentError"] }, { kind: "component", type: SettingSelectComponent, selector: "app-setting-select", inputs: ["valueFormControl", "configId"], outputs: ["componentError"] }] }); }
6678
6733
  }
6679
6734
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: LinkFeatureFlagComponent, decorators: [{
6680
6735
  type: Component,
@@ -6687,8 +6742,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
6687
6742
  ConfigSelectComponent,
6688
6743
  EnvironmentSelectComponent,
6689
6744
  SettingSelectComponent,
6690
- ], template: "<div class=\"container\">\n <form class=\"form\" [formGroup]=\"formGroup\" (ngSubmit)=\"add()\">\n <div>\n <app-product-select\n name=\"productId\"\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [valueFormControl]=\"formGroup.controls.productId\"\n [customDropdown]=\"true\" />\n @if (formGroup.controls.productId.value) {\n <app-config-select\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [customDropdown]=\"true\"\n [productId]=\"formGroup.controls.productId.value\"\n [valueFormControl]=\"formGroup.controls.configId\"\n (dropdownOpened)=\"selectDropdownPanelChanged($event)\" />\n }\n @if (formGroup.controls.productId.value) {\n <app-environment-select\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [productId]=\"formGroup.controls.productId.value\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [valueFormControl]=\"formGroup.controls.environmentId\"\n [customDropdown]=\"true\"\n (dropdownOpened)=\"selectDropdownPanelChanged($event)\" />\n }\n @if (formGroup.controls.configId.value) {\n <app-setting-select\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [configId]=\"formGroup.controls.configId.value\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [valueFormControl]=\"formGroup.controls.settingId\"\n [customDropdown]=\"true\"\n (dropdownOpened)=\"selectDropdownPanelChanged($event)\" />\n }\n </div>\n <div class=\"buttons\">\n <button mat-raised-button color=\"primary\" type=\"submit\" [disabled]=\"submitting() || !formGroup.valid\">\n {{ addButtonLabel() ? addButtonLabel() : \"Add\" }}\n </button>\n @if (!hideCancelButton()) {\n <button mat-stroked-button type=\"button\" (click)=\"cancel()\">\n {{ cancelButtonLabel() ? cancelButtonLabel() : \"Cancel\" }}\n </button>\n }\n </div>\n </form>\n</div>\n", styles: [".container{margin:8px 8px 16px}.container .form>*{width:100%}.container .form .error{color:var(--flag-validation-error);margin:0 5px 5px}.buttons{margin-bottom:16px}.buttons>*{margin-right:16px}\n"] }]
6691
- }], propDecorators: { authorizationParameters: [{ type: i0.Input, args: [{ isSignal: true, alias: "authorizationParameters", required: false }] }], hideCancelButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideCancelButton", required: false }] }], addButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "addButtonLabel", required: false }] }], cancelButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelButtonLabel", required: false }] }], linkInitiated: [{ type: i0.Output, args: ["linkInitiated"] }], resizeRequested: [{ type: i0.Output, args: ["resizeRequested"] }], cancelInitiated: [{ type: i0.Output, args: ["cancelInitiated"] }], selectDropdownPanelChangedReqested: [{ type: i0.Output, args: ["selectDropdownPanelChangedReqested"] }] } });
6745
+ ], template: "<div class=\"container\">\n <form class=\"form\" [formGroup]=\"formGroup\" (ngSubmit)=\"add()\">\n <div>\n <app-product-select\n name=\"productId\"\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [valueFormControl]=\"formGroup.controls.productId\"\n [customDropdown]=\"true\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n @if (formGroup.controls.productId.value) {\n <app-config-select\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [customDropdown]=\"true\"\n [productId]=\"formGroup.controls.productId.value\"\n [valueFormControl]=\"formGroup.controls.configId\"\n (dropdownOpened)=\"selectDropdownPanelChanged($event)\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n }\n @if (formGroup.controls.productId.value) {\n <app-environment-select\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [productId]=\"formGroup.controls.productId.value\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [valueFormControl]=\"formGroup.controls.environmentId\"\n [customDropdown]=\"true\"\n (dropdownOpened)=\"selectDropdownPanelChanged($event)\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n }\n @if (formGroup.controls.configId.value) {\n <app-setting-select\n [basicAuthUsername]=\"authorizationParameters()!.basicAuthUsername\"\n [configId]=\"formGroup.controls.configId.value\"\n [basicAuthPassword]=\"authorizationParameters()!.basicAuthPassword\"\n [valueFormControl]=\"formGroup.controls.settingId\"\n [customDropdown]=\"true\"\n (dropdownOpened)=\"selectDropdownPanelChanged($event)\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n }\n </div>\n <div class=\"buttons\">\n <button mat-raised-button color=\"primary\" type=\"submit\" [disabled]=\"submitting() || !formGroup.valid\">\n {{ addButtonLabel() ? addButtonLabel() : \"Add\" }}\n </button>\n @if (!hideCancelButton()) {\n <button mat-stroked-button type=\"button\" (click)=\"cancel()\">\n {{ cancelButtonLabel() ? cancelButtonLabel() : \"Cancel\" }}\n </button>\n }\n </div>\n </form>\n</div>\n", styles: [".container{margin:8px 8px 16px}.container .form>*{width:100%}.container .form .error{color:var(--flag-validation-error);margin:0 5px 5px}.buttons{margin-bottom:16px}.buttons>*{margin-right:16px}\n"] }]
6746
+ }], propDecorators: { authorizationParameters: [{ type: i0.Input, args: [{ isSignal: true, alias: "authorizationParameters", required: false }] }], hideCancelButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideCancelButton", required: false }] }], addButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "addButtonLabel", required: false }] }], cancelButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelButtonLabel", required: false }] }], linkInitiated: [{ type: i0.Output, args: ["linkInitiated"] }], resizeRequested: [{ type: i0.Output, args: ["resizeRequested"] }], cancelInitiated: [{ type: i0.Output, args: ["cancelInitiated"] }], selectDropdownPanelChangedReqested: [{ type: i0.Output, args: ["selectDropdownPanelChangedReqested"] }], componentError: [{ type: i0.Output, args: ["componentError"] }] } });
6692
6747
 
6693
6748
  class BoxComponent {
6694
6749
  constructor() {
@@ -6724,6 +6779,7 @@ class CreateFeatureFlagComponent extends BaseComponent {
6724
6779
  this.resizeRequested = output();
6725
6780
  this.cancelInitiated = output();
6726
6781
  this.selectDropdownPanelChangedReqested = output();
6782
+ this.componentError = output();
6727
6783
  this.SettingTypeEnum = SettingType;
6728
6784
  this.FormHelper = FormHelper;
6729
6785
  this.EvaluationVersion = EvaluationVersion;
@@ -6746,6 +6802,7 @@ class CreateFeatureFlagComponent extends BaseComponent {
6746
6802
  this.displayedColumns = [];
6747
6803
  this.stringValidators = [Validators.required,
6748
6804
  Validators.maxLength(this.maxStringFlagValueLength)];
6805
+ this.jsonValidators = [...this.stringValidators, jsonValidator];
6749
6806
  this.intValidators = [
6750
6807
  Validators.required,
6751
6808
  validateNumberNan,
@@ -6787,6 +6844,7 @@ class CreateFeatureFlagComponent extends BaseComponent {
6787
6844
  validators: [Validators.required],
6788
6845
  }),
6789
6846
  useVariations: new FormControl(false, { nonNullable: true }),
6847
+ isJson: new FormControl(false, { nonNullable: true }),
6790
6848
  predefinedVariations: new FormArray([], { validators: [validateUniqueVariations] }),
6791
6849
  initialValuesPerEnvironment: new FormControl(false, { nonNullable: true }),
6792
6850
  initialValueForAll: this.initialValueForAllFormControlFunction(SettingType.Boolean),
@@ -6808,70 +6866,102 @@ class CreateFeatureFlagComponent extends BaseComponent {
6808
6866
  //Product valueChanges
6809
6867
  this.formGroup.controls.productId.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => {
6810
6868
  this.loadingProduct.set(true);
6811
- this.createProductsService().getProduct(value).subscribe(product => {
6812
- this.reasonRequired.set(product.reasonRequired);
6813
- const hintValidators = product.reasonRequired ? [Validators.required, Validators.maxLength(255)] : [Validators.maxLength(255)];
6814
- this.formGroup.controls.hint.clearValidators();
6815
- this.formGroup.controls.hint.addValidators(hintValidators);
6816
- this.loadingEnviroments.set(true);
6817
- this.createEnvironmentsService().getEnvironments(product.productId).subscribe(enviroments => {
6818
- this.selectedProductEnviroment = enviroments;
6819
- this.formGroup.controls.initialValues = new FormArray(enviroments.map(env => this.formBuilder.group({
6820
- environmentName: new FormControl(env.name, { nonNullable: true }),
6821
- environmentId: new FormControl(env.environmentId, { nonNullable: true }),
6822
- settingValue: this.initialValueForAllFormControlFunction(this.formGroup.controls.settingType.value),
6823
- predefinedVariationIndex: new FormControl(0, { nonNullable: true }),
6824
- })));
6825
- this.loadingEnviroments.set(false);
6826
- });
6827
- if (this.selectedProductOrganiaztionId !== product.organization.organizationId) {
6828
- this.loadinOrganizationLimitations.set(true);
6829
- this.selectedProductOrganiaztionId = product.organization.organizationId;
6830
- this.createOrganizationService().getOrganizationLimitations(this.selectedProductOrganiaztionId).subscribe(organizationLimitations => {
6831
- this.maxStringFlagValueLength = organizationLimitations.maxStringFlagValueLength;
6832
- this.maxPredefinedVariations = organizationLimitations.maxPredefinedVariations;
6833
- this.stringValidators = [Validators.required, Validators.maxLength(this.maxStringFlagValueLength)];
6834
- this.loadinOrganizationLimitations.set(false);
6869
+ this.createProductsService().getProduct(value).subscribe({
6870
+ next: (product) => {
6871
+ this.reasonRequired.set(product.reasonRequired);
6872
+ const hintValidators = product.reasonRequired ? [Validators.required, Validators.maxLength(255)] : [Validators.maxLength(255)];
6873
+ this.formGroup.controls.hint.clearValidators();
6874
+ this.formGroup.controls.hint.addValidators(hintValidators);
6875
+ this.loadingEnviroments.set(true);
6876
+ this.createEnvironmentsService().getEnvironments(product.productId).subscribe({
6877
+ next: (enviroments) => {
6878
+ this.selectedProductEnviroment = enviroments;
6879
+ this.formGroup.setControl("initialValues", new FormArray(enviroments.map(env => this.formBuilder.group({
6880
+ environmentName: new FormControl(env.name, { nonNullable: true }),
6881
+ environmentId: new FormControl(env.environmentId, { nonNullable: true }),
6882
+ settingValue: this.initialValueForAllFormControlFunction(this.formGroup.controls.settingType.value),
6883
+ predefinedVariationIndex: new FormControl(0, { nonNullable: true }),
6884
+ }))));
6885
+ // Keep newly created controls in sync with the current toggle state.
6886
+ this.enableDisableControls();
6887
+ this.loadingEnviroments.set(false);
6888
+ },
6889
+ error: (error) => {
6890
+ this.loadingEnviroments.set(false);
6891
+ this.componentError.emit(error);
6892
+ },
6835
6893
  });
6836
- }
6837
- this.loadingProduct.set(false);
6894
+ if (this.selectedProductOrganiaztionId !== product.organization.organizationId) {
6895
+ this.loadinOrganizationLimitations.set(true);
6896
+ this.selectedProductOrganiaztionId = product.organization.organizationId;
6897
+ this.createOrganizationService().getOrganizationLimitations(this.selectedProductOrganiaztionId).subscribe({
6898
+ next: (organizationLimitations) => {
6899
+ this.maxStringFlagValueLength = organizationLimitations.maxStringFlagValueLength;
6900
+ this.maxPredefinedVariations = organizationLimitations.maxPredefinedVariations;
6901
+ this.stringValidators = [Validators.required, Validators.maxLength(this.maxStringFlagValueLength)];
6902
+ this.loadinOrganizationLimitations.set(false);
6903
+ },
6904
+ error: (error) => {
6905
+ this.loadinOrganizationLimitations.set(false);
6906
+ this.componentError.emit(error);
6907
+ },
6908
+ });
6909
+ }
6910
+ this.loadingProduct.set(false);
6911
+ },
6912
+ error: (error) => {
6913
+ this.loadingProduct.set(false);
6914
+ this.componentError.emit(error);
6915
+ },
6838
6916
  });
6839
6917
  });
6840
6918
  //Config valueChanges
6841
6919
  this.formGroup.controls.configId.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => {
6842
6920
  this.loadingConfigurations.set(true);
6843
- this.createConfigsService().getConfig(value).subscribe(config => {
6844
- this.configEvaluationVersion = config.evaluationVersion;
6845
- this.loadingConfigurations.set(false);
6921
+ this.createConfigsService().getConfig(value).subscribe({
6922
+ next: (config) => {
6923
+ this.configEvaluationVersion = config.evaluationVersion;
6924
+ this.loadingConfigurations.set(false);
6925
+ },
6926
+ error: (error) => {
6927
+ this.loadingConfigurations.set(false);
6928
+ this.componentError.emit(error);
6929
+ },
6846
6930
  });
6847
6931
  });
6848
- //InitialValuesPerEnvironment valueChanges
6849
- this.formGroup.controls.initialValuesPerEnvironment.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => {
6850
- if (value) {
6851
- this.formGroup.controls.initialValues.enable();
6852
- this.formGroup.controls.initialValueForAll.disable();
6853
- this.formGroup.controls.initialValueForAllVariationIndex.disable();
6854
- }
6855
- else {
6856
- this.formGroup.controls.initialValues.disable();
6857
- this.formGroup.controls.initialValueForAll.enable();
6858
- this.formGroup.controls.initialValueForAllVariationIndex.enable();
6859
- }
6932
+ //IsJson valueChanges
6933
+ this.formGroup.controls.isJson.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => {
6934
+ const validators = value ? this.jsonValidators : this.stringValidators;
6935
+ this.formGroup.controls.initialValueForAll.setValidators(validators);
6936
+ this.formGroup.controls.initialValueForAll.updateValueAndValidity();
6937
+ this.formGroup.controls.initialValueForAll.markAsTouched();
6938
+ this.formGroup.controls.initialValues.controls.forEach(c => {
6939
+ c.controls.settingValue.setValidators(validators);
6940
+ c.controls.settingValue.updateValueAndValidity();
6941
+ c.controls.settingValue.markAsTouched();
6942
+ });
6943
+ this.formGroup.controls.predefinedVariations.controls.forEach(c => {
6944
+ c.controls.value.controls.stringValue.setValidators(validators);
6945
+ c.controls.value.controls.stringValue.updateValueAndValidity();
6946
+ c.controls.value.controls.stringValue.markAsTouched();
6947
+ });
6948
+ this.formGroup.controls.predefinedVariations.updateValueAndValidity();
6860
6949
  this.formGroup.updateValueAndValidity();
6861
6950
  });
6951
+ //InitialValuesPerEnvironment valueChanges
6952
+ this.formGroup.controls.initialValuesPerEnvironment.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
6953
+ this.enableDisableControls();
6954
+ });
6862
6955
  //UseVariations valueChanges
6863
- this.formGroup.controls.useVariations.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => {
6864
- if (value) {
6865
- this.formGroup.controls.predefinedVariations.enable();
6866
- }
6867
- else {
6868
- this.formGroup.controls.predefinedVariations.disable();
6869
- }
6870
- this.formGroup.updateValueAndValidity();
6956
+ this.formGroup.controls.useVariations.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
6957
+ this.enableDisableControls();
6871
6958
  });
6872
6959
  //InitialValueForAll valueChanges
6873
6960
  this.formGroup.controls.initialValueForAll.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(value => {
6874
- this.formGroup.controls.initialValues.controls.forEach(c => c.controls.settingValue.patchValue(value, { emitEvent: false }));
6961
+ this.formGroup.controls.initialValues.controls.forEach(c => {
6962
+ c.controls.settingValue.patchValue(value, { emitEvent: false });
6963
+ c.controls.settingValue.updateValueAndValidity();
6964
+ });
6875
6965
  });
6876
6966
  //PredefinedVariations valueChanges
6877
6967
  this.formGroup.controls.predefinedVariations.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
@@ -6892,12 +6982,46 @@ class CreateFeatureFlagComponent extends BaseComponent {
6892
6982
  });
6893
6983
  this.loading.set(false);
6894
6984
  }
6985
+ enableDisableControls() {
6986
+ if (this.formGroup.controls.initialValuesPerEnvironment.value) {
6987
+ this.formGroup.controls.initialValues.enable();
6988
+ this.formGroup.controls.initialValueForAll.disable();
6989
+ this.formGroup.controls.initialValueForAllVariationIndex.disable();
6990
+ }
6991
+ else {
6992
+ this.formGroup.controls.initialValues.disable();
6993
+ if (this.formGroup.controls.useVariations.value) {
6994
+ this.formGroup.controls.initialValueForAllVariationIndex.enable();
6995
+ this.formGroup.controls.initialValueForAll.disable();
6996
+ }
6997
+ else {
6998
+ this.formGroup.controls.initialValueForAllVariationIndex.disable();
6999
+ this.formGroup.controls.initialValueForAll.enable();
7000
+ }
7001
+ }
7002
+ if (this.formGroup.controls.useVariations.value) {
7003
+ this.formGroup.controls.predefinedVariations.enable();
7004
+ this.formGroup.controls.initialValues.controls.forEach(c => {
7005
+ c.controls.settingValue.disable();
7006
+ c.controls.predefinedVariationIndex.enable();
7007
+ });
7008
+ }
7009
+ else {
7010
+ this.formGroup.controls.predefinedVariations.disable();
7011
+ this.formGroup.controls.initialValues.controls.forEach(c => {
7012
+ c.controls.settingValue.enable();
7013
+ c.controls.predefinedVariationIndex.disable();
7014
+ });
7015
+ }
7016
+ this.formGroup.controls.initialValues.updateValueAndValidity();
7017
+ this.formGroup.updateValueAndValidity();
7018
+ }
6895
7019
  initialValueForAllFormControlFunction(settingType) {
6896
7020
  switch (settingType) {
6897
7021
  case SettingType.Boolean:
6898
7022
  return new FormControl(false, { nonNullable: true });
6899
7023
  case SettingType.String:
6900
- return new FormControl("initial placeholder text", { validators: this.stringValidators, nonNullable: true });
7024
+ return new FormControl("My initial value", { validators: this.formGroup.controls.isJson.value ? this.jsonValidators : this.stringValidators, nonNullable: true });
6901
7025
  case SettingType.Int:
6902
7026
  return new FormControl(42, { validators: this.intValidators, nonNullable: true });
6903
7027
  case SettingType.Double:
@@ -6912,20 +7036,20 @@ class CreateFeatureFlagComponent extends BaseComponent {
6912
7036
  this.formGroup.controls.predefinedVariations.clear();
6913
7037
  switch (newSettingType) {
6914
7038
  case SettingType.Boolean:
6915
- this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, false));
6916
- this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, true));
7039
+ this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, false, false));
7040
+ this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, false, true));
6917
7041
  break;
6918
7042
  case SettingType.String:
6919
- this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, void 0, "Variation A"));
6920
- this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, void 0, "Variation B"));
7043
+ this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, this.formGroup.controls.isJson.value, void 0, "Variation A"));
7044
+ this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, this.formGroup.controls.isJson.value, void 0, "Variation B"));
6921
7045
  break;
6922
7046
  case SettingType.Int:
6923
- this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, void 0, void 0, 1));
6924
- this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, void 0, void 0, 2));
7047
+ this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, false, void 0, void 0, 1));
7048
+ this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, false, void 0, void 0, 2));
6925
7049
  break;
6926
7050
  case SettingType.Double:
6927
- this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, false, void 0, void 0, 3.14));
6928
- this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, false, void 0, void 0, 1.618));
7051
+ this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, false, false, void 0, void 0, 3.14));
7052
+ this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(newSettingType, false, false, void 0, void 0, 1.618));
6929
7053
  break;
6930
7054
  }
6931
7055
  this.formGroup.controls.initialValueForAll.clearValidators();
@@ -6939,6 +7063,7 @@ class CreateFeatureFlagComponent extends BaseComponent {
6939
7063
  this.formGroup.controls.initialValues.controls.forEach(initValueForEnv => {
6940
7064
  initValueForEnv.setControl("settingValue", this.initialValueForAllFormControlFunction(newSettingType));
6941
7065
  });
7066
+ this.enableDisableControls();
6942
7067
  this.formGroup.updateValueAndValidity();
6943
7068
  this.setDataSource();
6944
7069
  }
@@ -6986,6 +7111,7 @@ class CreateFeatureFlagComponent extends BaseComponent {
6986
7111
  hint: this.formGroup.controls.hint.value,
6987
7112
  initialValues: initialValues,
6988
7113
  predefinedVariations: predefinedVariations,
7114
+ isJson: this.formGroup.controls.isJson.value,
6989
7115
  })
6990
7116
  .subscribe({
6991
7117
  next: setting => {
@@ -6999,7 +7125,9 @@ class CreateFeatureFlagComponent extends BaseComponent {
6999
7125
  error: (error) => {
7000
7126
  this.submitting.set(false);
7001
7127
  ErrorHandler.handleErrors(this.formGroup, error);
7002
- console.log(error);
7128
+ if (error instanceof HttpErrorResponse && error.status === 401) {
7129
+ this.componentError.emit(error);
7130
+ }
7003
7131
  },
7004
7132
  });
7005
7133
  }
@@ -7012,18 +7140,18 @@ class CreateFeatureFlagComponent extends BaseComponent {
7012
7140
  selectDropdownPanelChanged(useSelector) {
7013
7141
  this.selectDropdownPanelChangedReqested.emit(useSelector);
7014
7142
  }
7015
- createEmptyVariationFormGroup(settingType, boolValue = false, stringValue = "", intValue = 0, doubleValue = 0) {
7143
+ createEmptyVariationFormGroup(settingType, isJson, boolValue = false, stringValue = "", intValue = 0, doubleValue = 0) {
7016
7144
  return this.formBuilder.group({
7017
7145
  name: new FormControl(null),
7018
7146
  hint: new FormControl(null),
7019
- value: this.createEmptyVariationValueFormGroup(settingType, boolValue, stringValue, intValue, doubleValue),
7147
+ value: this.createEmptyVariationValueFormGroup(settingType, isJson, boolValue, stringValue, intValue, doubleValue),
7020
7148
  valueForComparison: new FormControl({
7021
7149
  value: getPredefinedVariationValueDisplayValue(settingType, { boolValue, stringValue, intValue, doubleValue }),
7022
7150
  disabled: true,
7023
7151
  }),
7024
7152
  });
7025
7153
  }
7026
- createEmptyVariationValueFormGroup(settingType, boolValue = false, stringValue = "", intValue = 0, doubleValue = 0) {
7154
+ createEmptyVariationValueFormGroup(settingType, isJson, boolValue = false, stringValue = "", intValue = 0, doubleValue = 0) {
7027
7155
  switch (settingType) {
7028
7156
  case SettingType.Boolean:
7029
7157
  return this.formBuilder.group({
@@ -7031,7 +7159,7 @@ class CreateFeatureFlagComponent extends BaseComponent {
7031
7159
  });
7032
7160
  case SettingType.String:
7033
7161
  return this.formBuilder.group({
7034
- stringValue: new FormControl(stringValue, { nonNullable: true, validators: this.stringValidators }),
7162
+ stringValue: new FormControl(stringValue, { nonNullable: true, validators: isJson ? this.jsonValidators : this.stringValidators }),
7035
7163
  });
7036
7164
  case SettingType.Int:
7037
7165
  return this.formBuilder.group({
@@ -7046,10 +7174,10 @@ class CreateFeatureFlagComponent extends BaseComponent {
7046
7174
  }
7047
7175
  }
7048
7176
  addVariation() {
7049
- this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(this.formGroup.controls.settingType.value));
7177
+ this.formGroup.controls.predefinedVariations.push(this.createEmptyVariationFormGroup(this.formGroup.controls.settingType.value, this.formGroup.controls.isJson.value));
7050
7178
  this.formGroup.controls.predefinedVariations.markAsDirty();
7051
- this.setDataSource();
7052
7179
  this.focusIndex = this.formGroup.controls.predefinedVariations.length - 1;
7180
+ this.setDataSource();
7053
7181
  }
7054
7182
  removeVariation(index) {
7055
7183
  this.formGroup.controls.predefinedVariations.removeAt(index);
@@ -7113,8 +7241,11 @@ class CreateFeatureFlagComponent extends BaseComponent {
7113
7241
  getColorIndex(row, index) {
7114
7242
  return getPredefinedVariationColorIndex(this.formGroup.controls.settingType.value, getRawPredefinedVariationValue(row.controls.value), index);
7115
7243
  }
7244
+ dropdownComponentFailed(error) {
7245
+ this.componentError.emit(error);
7246
+ }
7116
7247
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: CreateFeatureFlagComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
7117
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: CreateFeatureFlagComponent, isStandalone: true, selector: "app-create-feature-flag", inputs: { hideCancelButton: { classPropertyName: "hideCancelButton", publicName: "hideCancelButton", isSignal: true, isRequired: false, transformFunction: null }, createButtonLabel: { classPropertyName: "createButtonLabel", publicName: "createButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelButtonLabel: { classPropertyName: "cancelButtonLabel", publicName: "cancelButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, targetSectionHeader: { classPropertyName: "targetSectionHeader", publicName: "targetSectionHeader", isSignal: true, isRequired: false, transformFunction: null }, targetSectionDescription: { classPropertyName: "targetSectionDescription", publicName: "targetSectionDescription", isSignal: true, isRequired: false, transformFunction: null }, flagSectionHeader: { classPropertyName: "flagSectionHeader", publicName: "flagSectionHeader", isSignal: true, isRequired: false, transformFunction: null }, flagSectionDescription: { classPropertyName: "flagSectionDescription", publicName: "flagSectionDescription", isSignal: true, isRequired: false, transformFunction: null }, linkSectionHeader: { classPropertyName: "linkSectionHeader", publicName: "linkSectionHeader", isSignal: true, isRequired: false, transformFunction: null }, linkSectionDescription: { classPropertyName: "linkSectionDescription", publicName: "linkSectionDescription", isSignal: true, isRequired: false, transformFunction: null }, hideLinkSection: { classPropertyName: "hideLinkSection", publicName: "hideLinkSection", isSignal: true, isRequired: false, transformFunction: null }, presetProductAndConfig: { classPropertyName: "presetProductAndConfig", publicName: "presetProductAndConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { createInitiated: "createInitiated", resizeRequested: "resizeRequested", cancelInitiated: "cancelInitiated", selectDropdownPanelChangedReqested: "selectDropdownPanelChangedReqested" }, usesInheritance: true, ngImport: i0, template: "<div class=\"container\">\n <form class=\"form\" [formGroup]=\"formGroup\" (ngSubmit)=\"create()\">\n <div>\n <div class=\"header\">1. {{ targetSectionHeader() ? targetSectionHeader() : \"Select Product and Config\" }}</div>\n @if (targetSectionDescription()) {\n <p>{{ targetSectionDescription() }}</p>\n }\n @if (this.presetProductAndConfig()) {\n <p>\n Pre selected product\n <b>{{ this.presetProductAndConfig()!.productName }}</b>\n </p>\n <p>\n Pre selected config\n <b>{{ this.presetProductAndConfig()!.configName }}</b>\n </p>\n }\n <app-product-select\n name=\"productId\"\n [hidden]=\"this.presetProductAndConfig()\"\n [basicAuthUsername]=\"basicAuthUsername()\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [preSelectedProductId]=\"this.presetProductAndConfig()?.productId\"\n [valueFormControl]=\"formGroup.controls.productId\"\n [customDropdown]=\"true\" />\n @if (formGroup.controls.productId.value) {\n <app-config-select\n [hidden]=\"this.presetProductAndConfig()\"\n [basicAuthUsername]=\"basicAuthUsername()\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [preSelectedConfigId]=\"this.presetProductAndConfig()?.configId\"\n [productId]=\"formGroup.controls.productId.value\"\n [valueFormControl]=\"formGroup.controls.configId\"\n [customDropdown]=\"true\" />\n }\n\n <div class=\"header\">2. {{ flagSectionHeader() ? flagSectionHeader() : \"Setup Feature Flag\" }}</div>\n @if (flagSectionDescription()) {\n <p>{{ flagSectionDescription() }}</p>\n }\n @if (loadingComputed()) {\n <app-loader />\n } @else {\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Type</mat-label>\n <mat-select placeholder=\"Type\" formControlName=\"settingType\" panelClass=\"'custom-dropdown-below'\">\n <mat-option [value]=\"SettingTypeEnum.Boolean\">Feature Flag (bool)</mat-option>\n <mat-option [value]=\"SettingTypeEnum.String\">Text (string)</mat-option>\n <mat-option [value]=\"SettingTypeEnum.Int\">Whole Number (integer)</mat-option>\n <mat-option [value]=\"SettingTypeEnum.Double\">Decimal Number (double)</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"form-field name\" appearance=\"outline\">\n <mat-label>Name for humans</mat-label>\n <input matInput placeholder=\"My awesome feature\" formControlName=\"name\" />\n <mat-hint>A friendly name that best describes your setting.</mat-hint>\n @if (formGroup.controls.name.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.name) }}\n </mat-error>\n }\n </mat-form-field>\n <mat-form-field class=\"form-field key\" appearance=\"outline\">\n <mat-label>Key for programs</mat-label>\n <input matInput placeholder=\"isMyAwesomeFeatureEnabled\" formControlName=\"key\" />\n <mat-hint>Your applications will access your setting via this key.</mat-hint>\n @if (formGroup.controls.key.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.key) }}\n </mat-error>\n }\n </mat-form-field>\n <mat-form-field class=\"form-field hint\" appearance=\"outline\">\n @if (!reasonRequired()) {\n <mat-label>Hint (Optional)</mat-label>\n } @else {\n <mat-label>Hint</mat-label>\n }\n <textarea matInput placeholder=\"Hint or description (Optional)\" formControlName=\"hint\"></textarea>\n <mat-hint>A description to help you remember the purpose of your setting.</mat-hint>\n @if (formGroup.controls.hint.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.hint) }}\n </mat-error>\n }\n </mat-form-field>\n\n <div class=\"init-value-section\">\n @if (configEvaluationVersion === EvaluationVersion.V2) {\n <h3>How do you want to set values?</h3>\n <div class=\"value-mode-question\">\n <mat-form-field appearance=\"outline\" class=\"small-form-field value-mode-select\" subscriptSizing=\"dynamic\">\n <mat-select formControlName=\"useVariations\" class=\"choose\">\n <mat-option [value]=\"false\">\n {{\n formGroup.controls.settingType.value === SettingTypeEnum.Boolean\n ? \"use an ON/OFF toggle\"\n : \"enter free-form values\"\n }}\n </mat-option>\n <mat-option [value]=\"true\">choose from predefined variations</mat-option>\n </mat-select>\n </mat-form-field>\n <a href=\"https://configcat.com/docs/advanced/predefined-variations\" class=\"readmore\" target=\"_blank\">\n <mat-icon color=\"primary\" matTooltip=\"Click to read more about value-modes.\">info</mat-icon>\n </a>\n </div>\n @if (formGroup.controls.useVariations.value) {\n <div class=\"header small\">Variations</div>\n <div class=\"variations\">\n <div class=\"predef-var-table-scroll\">\n <table mat-table [dataSource]=\"dataSource\">\n <ng-container matColumnDef=\"color\">\n <th *matHeaderCellDef mat-header-cell></th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row\">\n <span [class]=\"'variation-indicator variation-color-' + getColorIndex(row, i)\"></span>\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 (formGroup.controls.settingType.value) {\n @case (SettingTypeEnum.Boolean) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.boolValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingTypeEnum.String) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.stringValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingTypeEnum.Int) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.intValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingTypeEnum.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 <mat-form-field\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n class=\"small-form-field suffixed\">\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 <input matInput [formControl]=\"row.controls.hint\" />\n @if (row.controls.hint.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(row.controls.hint) }}\n </mat-error>\n }\n </mat-form-field>\n </td>\n </ng-container>\n <ng-container matColumnDef=\"actions\">\n <th *matHeaderCellDef mat-header-cell>\n {{ dataSource.data.length }} / {{ maxPredefinedVariations }}\n </th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div\n [matTooltip]=\"\n formGroup.controls.predefinedVariations.controls.length > 2\n ? 'Remove item'\n : 'At least 2 predefined variations should be set.'\n \">\n <button\n mat-icon-button\n type=\"button\"\n [disabled]=\"formGroup.controls.predefinedVariations.controls.length <= 2\"\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></tr>\n </table>\n </div>\n\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 class=\"add-variation\">\n @if (this.formGroup.controls.settingType.value !== SettingTypeEnum.Boolean) {\n <div\n [matTooltip]=\"'Maximum ' + maxPredefinedVariations + ' predefined 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 } @else {\n <app-box type=\"info\" class=\"bool-variation-info\">\n For more variations, create a flag of another type.\n <a\n href=\"https://configcat.com/docs/main-concepts/#about-setting-types\"\n target=\"_blank\"\n rel=\"noopener noreferrer\">\n Read more\n </a>\n about setting types.\n </app-box>\n }\n </div>\n </div>\n }\n }\n\n <div class=\"header small\">Initial values</div>\n <div class=\"initial-value-first-line\">\n The initial value\n <mat-form-field\n appearance=\"outline\"\n class=\"small-form-field initial-value-environment-type\"\n subscriptSizing=\"dynamic\">\n <mat-select formControlName=\"initialValuesPerEnvironment\">\n <mat-option [value]=\"false\">in all environments</mat-option>\n <mat-option [value]=\"true\">per environment</mat-option>\n </mat-select>\n </mat-form-field>\n will be set to\n </div>\n @if (!formGroup.controls.initialValuesPerEnvironment.value) {\n @if (formGroup.controls.useVariations.value) {\n <div class=\"value-field all\">\n <ng-container\n [ngTemplateOutlet]=\"predefinedVariationTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: formGroup.controls.initialValueForAllVariationIndex }\" />\n </div>\n } @else {\n <div class=\"value-field all\">\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: formGroup.controls.initialValueForAll }\" />\n </div>\n }\n }\n\n @if (formGroup.controls.initialValuesPerEnvironment.value) {\n @for (initialValue of formGroup.controls.initialValues.controls; track $index; let index = $index) {\n <div formArrayName=\"initialValues\">\n <div class=\"value-field\" [formGroupName]=\"index\">\n @if (formGroup.controls.useVariations.value) {\n <ng-container\n [ngTemplateOutlet]=\"predefinedVariationTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: initialValue.controls.predefinedVariationIndex }\" />\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: initialValue.controls.settingValue }\" />\n }\n <div class=\"environment\">\n in\n <strong [matTooltip]=\"initialValue.controls.environmentName.value\">\n {{ initialValue.controls.environmentName.value }}\n </strong>\n </div>\n </div>\n </div>\n }\n }\n </div>\n }\n\n @if (!hideLinkSection()) {\n <div class=\"header\">\n 3. {{ linkSectionHeader() ? linkSectionHeader() : \"Select which environment should we link to this card\" }}\n </div>\n @if (linkSectionDescription()) {\n <p>{{ linkSectionDescription() }}</p>\n }\n @if (formGroup.controls.productId.value) {\n <app-environment-select\n [basicAuthUsername]=\"basicAuthUsername()\"\n [productId]=\"formGroup.controls.productId.value\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [valueFormControl]=\"formGroup.controls.environmentId\"\n [customDropdown]=\"true\" />\n }\n }\n </div>\n @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <div class=\"error\">\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\n </div>\n }\n <div class=\"buttons\">\n <button\n mat-raised-button\n color=\"primary\"\n type=\"submit\"\n [disabled]=\"submitting() || loadingComputed() || !formGroup.valid\">\n {{ createButtonLabel() ? createButtonLabel() : \"Create\" }}\n </button>\n @if (!hideCancelButton()) {\n <button mat-stroked-button type=\"button\" (click)=\"cancel()\">\n {{ cancelButtonLabel() ? cancelButtonLabel() : \"Cancel\" }}\n </button>\n }\n </div>\n </form>\n</div>\n\n<ng-template #settingValueTemplate let-formControl=\"formControl\" let-setFocus=\"setFocus\">\n @switch (formGroup.controls.settingType.value) {\n @case (SettingTypeEnum.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 [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 (SettingTypeEnum.Int) {\n <mat-form-field class=\"small-form-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n @if (formControl.invalid) {\n <mat-error class=\"small-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 (SettingTypeEnum.Double) {\n <mat-form-field class=\"small-form-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n @if (formControl.invalid) {\n <mat-error class=\"small-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 (SettingTypeEnum.Boolean) {\n <div class=\"toggle\">\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\n<ng-template #predefinedVariationTemplate let-formControl=\"formControl\">\n <mat-form-field class=\"small-form-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-select [formControl]=\"formControl\">\n @for (predefinedVariation of formGroup.controls.predefinedVariations.controls; let idx = $index; track $index) {\n <mat-option [value]=\"idx\">\n @if (predefinedVariation.controls.name.value) {\n {{ predefinedVariation.controls.name.value }}\n } @else {\n {{ predefinedVariation.controls.valueForComparison.value }}\n }\n </mat-option>\n }\n </mat-select>\n @if (formControl.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n </mat-form-field>\n</ng-template>\n", styles: [".container{margin:8px 8px 16px}.container .form>*{width:100%}.container .form>* .form-field{width:100%;padding-bottom:8px}.container .form>* .form-field.key{margin-bottom:16px}.container .form>* .form-field.name{margin-bottom:16px}.container .form>* .initial-value-first-line{align-items:center;min-height:34px;margin-bottom:8px}.container .form>* .initial-value-first-line .initial-value-environment-type{margin:0 6px;min-width:160px}.container .form>* .value-field{display:flex;align-items:center;width:100%}.container .form>* .value-field.all{display:inline-flex;margin-left:6px}.container .form>* .value-field.all mat-form-field{min-width:200px}.container .form>* .value-field.all mat-form-field.text{flex-grow:1;width:100%;min-width:100%}.container .form>* .value-field:not(.all){margin-bottom:8px}.container .form>* .value-field:not(.all) mat-form-field{min-width:200px}.container .form>* .value-field:not(.all) mat-form-field.text{min-width:330px}.container .form>* .value-field .environment{margin-left:1em;white-space:nowrap;text-overflow:ellipsis;overflow-x:hidden}.container .form>* .init-value-section{margin-bottom:16px}.container .form>* .init-value-section .predefined-component{padding:8px 0}.container .form>* .init-value-section .small-error{max-width:180px}.container .form>* .init-value-section .readmore{margin-left:8px}.container .form>* .init-value-section .value-mode-question{display:flex;align-items:center}.container .form>* .init-value-section .value-mode-question a{display:flex;align-items:center}.container .form>* .init-value-section .value-mode-question a mat-icon{color:var(--info-icon-color)}.container .form>* .init-value-section .value-mode-question .value-mode-select{min-width:240px}.container .form>* .init-value-section .variations{display:flex;flex-direction:column}.container .form>* .init-value-section .variations .mat-column-color{padding-right:0!important}.container .form>* .init-value-section .variations .variation-header{margin-bottom:8px}.container .form>* .init-value-section .variations .add-variation{margin-top:12px;display:flex}.container .form>* .init-value-section .variations .toggle{margin-left:4px}.container .form>* .init-value-section .variations .predef-var-table-scroll{display:block;overflow-x:auto}.container .form>* .init-value-section .variations .predef-var-table-scroll .mat-mdc-table{min-width:100%}.container .error{color:var(--flag-validation-error);margin:0 5px 5px}.container .header{font-size:18px;margin-top:16px;margin-bottom:16px}.container .header.small{font-size:16px;margin-top:16px;margin-bottom:16px}.buttons{margin-bottom:16px}.buttons>*{margin-right:16px}\n", ".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"], dependencies: [{ kind: "directive", type: AutofocusDirective, selector: "[focus]", inputs: ["isFocused"] }, { kind: "directive", type: DigitOnlyDirective, selector: "[appDigitOnly]", inputs: ["digitOnlyDecimal", "digitOnlyDecimalSeparator", "digitOnlyAllowNegatives", "digitOnlyAllowPaste", "digitOnlyNegativeSign"] }, { kind: "component", type: ProductSelectComponent, selector: "app-product-select", inputs: ["valueFormControl", "preSelectedProductId"] }, { kind: "component", type: ConfigSelectComponent, selector: "app-config-select", inputs: ["valueFormControl", "productId", "preSelectedConfigId"] }, { kind: "component", type: EnvironmentSelectComponent, selector: "app-environment-select", inputs: ["valueFormControl", "productId"] }, { 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: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { 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: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption$1, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: "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: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { 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: "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: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: LoaderComponent, selector: "app-loader", inputs: ["skipTimeOut"] }, { kind: "component", type: BoxComponent, selector: "app-box", inputs: ["type", "title"] }] }); }
7248
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: CreateFeatureFlagComponent, isStandalone: true, selector: "app-create-feature-flag", inputs: { hideCancelButton: { classPropertyName: "hideCancelButton", publicName: "hideCancelButton", isSignal: true, isRequired: false, transformFunction: null }, createButtonLabel: { classPropertyName: "createButtonLabel", publicName: "createButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelButtonLabel: { classPropertyName: "cancelButtonLabel", publicName: "cancelButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, targetSectionHeader: { classPropertyName: "targetSectionHeader", publicName: "targetSectionHeader", isSignal: true, isRequired: false, transformFunction: null }, targetSectionDescription: { classPropertyName: "targetSectionDescription", publicName: "targetSectionDescription", isSignal: true, isRequired: false, transformFunction: null }, flagSectionHeader: { classPropertyName: "flagSectionHeader", publicName: "flagSectionHeader", isSignal: true, isRequired: false, transformFunction: null }, flagSectionDescription: { classPropertyName: "flagSectionDescription", publicName: "flagSectionDescription", isSignal: true, isRequired: false, transformFunction: null }, linkSectionHeader: { classPropertyName: "linkSectionHeader", publicName: "linkSectionHeader", isSignal: true, isRequired: false, transformFunction: null }, linkSectionDescription: { classPropertyName: "linkSectionDescription", publicName: "linkSectionDescription", isSignal: true, isRequired: false, transformFunction: null }, hideLinkSection: { classPropertyName: "hideLinkSection", publicName: "hideLinkSection", isSignal: true, isRequired: false, transformFunction: null }, presetProductAndConfig: { classPropertyName: "presetProductAndConfig", publicName: "presetProductAndConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { createInitiated: "createInitiated", resizeRequested: "resizeRequested", cancelInitiated: "cancelInitiated", selectDropdownPanelChangedReqested: "selectDropdownPanelChangedReqested", componentError: "componentError" }, usesInheritance: true, ngImport: i0, template: "<div class=\"container\">\n <form class=\"form\" [formGroup]=\"formGroup\" (ngSubmit)=\"create()\">\n <div>\n <div class=\"header\">1. {{ targetSectionHeader() ? targetSectionHeader() : \"Select Product and Config\" }}</div>\n @if (targetSectionDescription()) {\n <p>{{ targetSectionDescription() }}</p>\n }\n @if (this.presetProductAndConfig()) {\n <p>\n Pre selected product\n <b>{{ this.presetProductAndConfig()!.productName }}</b>\n </p>\n <p>\n Pre selected config\n <b>{{ this.presetProductAndConfig()!.configName }}</b>\n </p>\n }\n <app-product-select\n name=\"productId\"\n [hidden]=\"this.presetProductAndConfig()\"\n [basicAuthUsername]=\"basicAuthUsername()\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [preSelectedProductId]=\"this.presetProductAndConfig()?.productId\"\n [valueFormControl]=\"formGroup.controls.productId\"\n [customDropdown]=\"true\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n @if (formGroup.controls.productId.value) {\n <app-config-select\n [hidden]=\"this.presetProductAndConfig()\"\n [basicAuthUsername]=\"basicAuthUsername()\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [preSelectedConfigId]=\"this.presetProductAndConfig()?.configId\"\n [productId]=\"formGroup.controls.productId.value\"\n [valueFormControl]=\"formGroup.controls.configId\"\n [customDropdown]=\"true\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n }\n\n <div class=\"header\">2. {{ flagSectionHeader() ? flagSectionHeader() : \"Setup Feature Flag\" }}</div>\n @if (flagSectionDescription()) {\n <p>{{ flagSectionDescription() }}</p>\n }\n @if (loadingComputed()) {\n <app-loader />\n } @else {\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Type</mat-label>\n <mat-select placeholder=\"Type\" formControlName=\"settingType\" panelClass=\"'custom-dropdown-below'\">\n <mat-option [value]=\"SettingTypeEnum.Boolean\">Feature Flag (bool)</mat-option>\n <mat-option [value]=\"SettingTypeEnum.String\">Text (string)</mat-option>\n <mat-option [value]=\"SettingTypeEnum.Int\">Whole Number (integer)</mat-option>\n <mat-option [value]=\"SettingTypeEnum.Double\">Decimal Number (double)</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"form-field name\" appearance=\"outline\">\n <mat-label>Name for humans</mat-label>\n <input matInput placeholder=\"My awesome feature\" formControlName=\"name\" />\n <mat-hint>A short name your team will see on the ConfigCat Dashboard.</mat-hint>\n @if (formGroup.controls.name.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.name) }}\n </mat-error>\n }\n </mat-form-field>\n <mat-form-field class=\"form-field key\" appearance=\"outline\">\n <mat-label>Key for programs</mat-label>\n <input matInput placeholder=\"isMyAwesomeFeatureEnabled\" formControlName=\"key\" />\n <mat-hint>Your application will use this key to access the setting.</mat-hint>\n @if (formGroup.controls.key.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.key) }}\n </mat-error>\n }\n </mat-form-field>\n <mat-form-field class=\"form-field hint last\" appearance=\"outline\">\n @if (!reasonRequired()) {\n <mat-label>Hint (Optional)</mat-label>\n } @else {\n <mat-label>Hint</mat-label>\n }\n <textarea matInput placeholder=\"Hint or description (Optional)\" formControlName=\"hint\"></textarea>\n <mat-hint>Explain what this setting controls. This helps your team use it correctly later.</mat-hint>\n @if (formGroup.controls.hint.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.hint) }}\n </mat-error>\n }\n </mat-form-field>\n\n <div class=\"init-value-section\">\n @if (configEvaluationVersion === EvaluationVersion.V2) {\n @if (true && formGroup.controls.settingType.value === SettingTypeEnum.String) {\n <h4>Require valid JSON?</h4>\n <div class=\"centered\">\n <mat-checkbox color=\"primary\" formControlName=\"isJson\">\n <span>Only valid JSON values can be saved</span>\n </mat-checkbox>\n <mat-icon\n color=\"primary\"\n class=\"info-icon\"\n matTooltip=\"Your application will get a string value. You will need to parse it into JSON if necessary.\">\n info\n </mat-icon>\n </div>\n }\n\n <h4>How to set values?</h4>\n <div class=\"value-mode-question\">\n <mat-form-field appearance=\"outline\" class=\"small-form-field value-mode-select\" subscriptSizing=\"dynamic\">\n <mat-select formControlName=\"useVariations\" class=\"choose\">\n <mat-option [value]=\"false\">\n {{\n formGroup.controls.settingType.value === SettingTypeEnum.Boolean\n ? \"use an ON/OFF toggle\"\n : \"enter free-form values\"\n }}\n </mat-option>\n <mat-option [value]=\"true\">choose from predefined variations</mat-option>\n </mat-select>\n </mat-form-field>\n <a href=\"https://configcat.com/docs/advanced/predefined-variations\" target=\"_blank\">\n <mat-icon class=\"info-icon\" color=\"primary\" matTooltip=\"Click to read more about value-modes.\">\n info\n </mat-icon>\n </a>\n </div>\n @if (formGroup.controls.useVariations.value) {\n <p>Define the values team members can choose from. At least two variations are required.</p>\n <div class=\"variations\">\n <div class=\"predef-var-table-scroll\">\n <table mat-table [dataSource]=\"dataSource\">\n <ng-container matColumnDef=\"color\">\n <th *matHeaderCellDef mat-header-cell></th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row\">\n <span [class]=\"'variation-indicator variation-color-' + getColorIndex(row, i)\"></span>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"value\">\n <th *matHeaderCellDef mat-header-cell>\n <div class=\"centered\">\n <span>Served value *</span>\n <mat-icon\n matTooltip=\"Your application will get this value when evaluating the setting.\"\n class=\"info-icon header-tooltip-icon\">\n info\n </mat-icon>\n </div>\n </th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n @switch (formGroup.controls.settingType.value) {\n @case (SettingTypeEnum.Boolean) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.boolValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingTypeEnum.String) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.stringValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingTypeEnum.Int) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.intValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingTypeEnum.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>\n <div class=\"centered\">\n <span>Display name (optional)</span>\n <mat-icon\n matTooltip=\"Optional friendly name. This will be displayed on the ConfigCat Dashboard.\"\n class=\"info-icon header-tooltip-icon\">\n info\n </mat-icon>\n </div>\n </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>\n <div class=\"centered\">\n <span>Hint (optional)</span>\n <mat-icon\n matTooltip=\"Optional hint. This will be displayed in a tooltip.\"\n class=\"info-icon header-tooltip-icon\">\n info\n </mat-icon>\n </div>\n </th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <mat-form-field\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n class=\"small-form-field suffixed\">\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 <input matInput [formControl]=\"row.controls.hint\" />\n @if (row.controls.hint.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(row.controls.hint) }}\n </mat-error>\n }\n </mat-form-field>\n </td>\n </ng-container>\n <ng-container matColumnDef=\"actions\">\n <th *matHeaderCellDef mat-header-cell>\n <span>{{ dataSource.data.length }} / {{ maxPredefinedVariations }}</span>\n </th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div\n [matTooltip]=\"\n formGroup.controls.predefinedVariations.controls.length > 2\n ? 'Remove item'\n : 'At least 2 predefined variations should be set.'\n \">\n <button\n mat-icon-button\n type=\"button\"\n [disabled]=\"formGroup.controls.predefinedVariations.controls.length <= 2\"\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></tr>\n </table>\n </div>\n\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 class=\"add-variation\">\n @if (this.formGroup.controls.settingType.value !== SettingTypeEnum.Boolean) {\n <div\n [matTooltip]=\"'Maximum ' + maxPredefinedVariations + ' predefined 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 } @else {\n <app-box type=\"info\" class=\"bool-variation-info\">\n For more variations, create a flag of another type.\n <a\n href=\"https://configcat.com/docs/main-concepts/#about-setting-types\"\n target=\"_blank\"\n rel=\"noopener noreferrer\">\n Read more\n </a>\n about setting types.\n </app-box>\n }\n </div>\n </div>\n }\n }\n\n <h4>Initial values</h4>\n <div class=\"initial-value-first-line\">\n The initial value\n <mat-form-field\n appearance=\"outline\"\n class=\"small-form-field initial-value-environment-type\"\n subscriptSizing=\"dynamic\">\n <mat-select formControlName=\"initialValuesPerEnvironment\">\n <mat-option [value]=\"false\">in all environments</mat-option>\n <mat-option [value]=\"true\">per environment</mat-option>\n </mat-select>\n </mat-form-field>\n will be set to\n </div>\n @if (!formGroup.controls.initialValuesPerEnvironment.value) {\n @if (formGroup.controls.useVariations.value) {\n <div class=\"value-field all\">\n <ng-container\n [ngTemplateOutlet]=\"predefinedVariationTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: formGroup.controls.initialValueForAllVariationIndex }\" />\n </div>\n } @else {\n <div class=\"value-field all\">\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: formGroup.controls.initialValueForAll }\" />\n </div>\n }\n }\n\n @if (formGroup.controls.initialValuesPerEnvironment.value) {\n @for (initialValue of formGroup.controls.initialValues.controls; track $index; let index = $index) {\n <div formArrayName=\"initialValues\">\n <div class=\"value-field\" [formGroupName]=\"index\">\n @if (formGroup.controls.useVariations.value) {\n <ng-container\n [ngTemplateOutlet]=\"predefinedVariationTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: initialValue.controls.predefinedVariationIndex }\" />\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: initialValue.controls.settingValue }\" />\n }\n <div class=\"environment\">\n in\n <strong [matTooltip]=\"initialValue.controls.environmentName.value\">\n {{ initialValue.controls.environmentName.value }}\n </strong>\n </div>\n </div>\n </div>\n }\n }\n </div>\n }\n\n @if (!hideLinkSection()) {\n <div class=\"header\">\n 3. {{ linkSectionHeader() ? linkSectionHeader() : \"Select which environment should we link to this card\" }}\n </div>\n @if (linkSectionDescription()) {\n <p>{{ linkSectionDescription() }}</p>\n }\n @if (formGroup.controls.productId.value) {\n <app-environment-select\n [basicAuthUsername]=\"basicAuthUsername()\"\n [productId]=\"formGroup.controls.productId.value\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [valueFormControl]=\"formGroup.controls.environmentId\"\n [customDropdown]=\"true\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n }\n }\n </div>\n @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <div class=\"error\">\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\n </div>\n }\n <div class=\"buttons\">\n <button\n mat-raised-button\n color=\"primary\"\n type=\"submit\"\n [disabled]=\"submitting() || loadingComputed() || !formGroup.valid\">\n {{ createButtonLabel() ? createButtonLabel() : \"Create\" }}\n </button>\n @if (!hideCancelButton()) {\n <button mat-stroked-button type=\"button\" (click)=\"cancel()\">\n {{ cancelButtonLabel() ? cancelButtonLabel() : \"Cancel\" }}\n </button>\n }\n </div>\n </form>\n</div>\n\n<ng-template #settingValueTemplate let-formControl=\"formControl\" let-setFocus=\"setFocus\">\n @switch (formGroup.controls.settingType.value) {\n @case (SettingTypeEnum.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 [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 (SettingTypeEnum.Int) {\n <mat-form-field class=\"small-form-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n @if (formControl.invalid) {\n <mat-error class=\"small-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 (SettingTypeEnum.Double) {\n <mat-form-field class=\"small-form-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n @if (formControl.invalid) {\n <mat-error class=\"small-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 (SettingTypeEnum.Boolean) {\n <div class=\"toggle\">\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\n<ng-template #predefinedVariationTemplate let-formControl=\"formControl\">\n <mat-form-field class=\"small-form-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-select [formControl]=\"formControl\">\n @for (predefinedVariation of formGroup.controls.predefinedVariations.controls; let idx = $index; track $index) {\n <mat-option [value]=\"idx\">\n @if (predefinedVariation.controls.name.value) {\n {{ predefinedVariation.controls.name.value }}\n } @else {\n {{ predefinedVariation.controls.valueForComparison.value }}\n }\n </mat-option>\n }\n </mat-select>\n @if (formControl.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n </mat-form-field>\n</ng-template>\n", styles: [".container{margin:8px 8px 16px}.container .form>*{width:100%}.container .form>* .form-field{width:100%;padding-bottom:8px}.container .form>* .form-field.key{margin-bottom:16px}.container .form>* .form-field.name{margin-bottom:16px}.container .form>* .initial-value-first-line{align-items:center;min-height:34px;margin-bottom:8px}.container .form>* .initial-value-first-line .initial-value-environment-type{margin:0 6px;min-width:160px}.container .form>* .value-field{display:flex;align-items:center;width:100%}.container .form>* .value-field.all{display:inline-flex;margin-left:6px}.container .form>* .value-field.all mat-form-field{min-width:200px}.container .form>* .value-field.all mat-form-field.text{flex-grow:1;width:100%;min-width:100%}.container .form>* .value-field:not(.all){margin-bottom:8px}.container .form>* .value-field:not(.all) mat-form-field{min-width:200px}.container .form>* .value-field:not(.all) mat-form-field.text{min-width:330px}.container .form>* .value-field .environment{margin-left:1em;white-space:nowrap;text-overflow:ellipsis;overflow-x:hidden}.container .form>* .init-value-section{margin-bottom:16px}.container .form>* .init-value-section .predefined-component{padding:8px 0}.container .form>* .init-value-section .small-error{max-width:180px}.container .form>* .init-value-section .readmore{margin-left:8px}.container .form>* .init-value-section .value-mode-question{display:flex;align-items:center}.container .form>* .init-value-section .value-mode-question a{display:flex;align-items:center}.container .form>* .init-value-section .value-mode-question .value-mode-select{min-width:240px}.container .form>* .init-value-section .centered{display:flex;align-items:center}.container .form>* .init-value-section mat-icon.info-icon{color:var(--info-icon-color);margin-left:8px}.container .form>* .init-value-section .variations{display:flex;flex-direction:column}.container .form>* .init-value-section .variations .mat-column-color{padding-right:0!important}.container .form>* .init-value-section .variations .variation-header{margin-bottom:8px}.container .form>* .init-value-section .variations .add-variation{margin-top:12px;display:flex}.container .form>* .init-value-section .variations .toggle{margin-left:4px}.container .form>* .init-value-section .variations .header-tooltip-icon{font-size:14px;width:14px;height:14px}.container .form>* .init-value-section .variations .predef-var-table-scroll{display:block;overflow-x:auto}.container .form>* .init-value-section .variations .predef-var-table-scroll .mat-mdc-table{min-width:100%}.container .error{color:var(--flag-validation-error);margin:0 5px 5px}.container .header{font-size:18px;margin-top:16px;margin-bottom:16px}.container .header.small{font-size:16px;margin-top:16px;margin-bottom:16px}h4{margin-bottom:8px}.buttons{margin-bottom:16px}.buttons>*{margin-right:16px}\n", ".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"], dependencies: [{ kind: "directive", type: AutofocusDirective, selector: "[focus]", inputs: ["isFocused"] }, { kind: "directive", type: DigitOnlyDirective, selector: "[appDigitOnly]", inputs: ["digitOnlyDecimal", "digitOnlyDecimalSeparator", "digitOnlyAllowNegatives", "digitOnlyAllowPaste", "digitOnlyNegativeSign"] }, { kind: "component", type: ProductSelectComponent, selector: "app-product-select", inputs: ["valueFormControl", "preSelectedProductId"], outputs: ["componentError"] }, { kind: "component", type: ConfigSelectComponent, selector: "app-config-select", inputs: ["valueFormControl", "productId", "preSelectedConfigId"], outputs: ["componentError"] }, { kind: "component", type: EnvironmentSelectComponent, selector: "app-environment-select", inputs: ["valueFormControl", "productId"], outputs: ["componentError"] }, { 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: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { 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: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption$1, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: "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: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { 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: "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: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: LoaderComponent, selector: "app-loader", inputs: ["skipTimeOut"] }, { kind: "component", type: BoxComponent, selector: "app-box", inputs: ["type", "title"] }, { kind: "component", type: MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }] }); }
7118
7249
  }
7119
7250
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: CreateFeatureFlagComponent, decorators: [{
7120
7251
  type: Component,
@@ -7152,8 +7283,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
7152
7283
  MatIconButton,
7153
7284
  LoaderComponent,
7154
7285
  BoxComponent,
7155
- ], template: "<div class=\"container\">\n <form class=\"form\" [formGroup]=\"formGroup\" (ngSubmit)=\"create()\">\n <div>\n <div class=\"header\">1. {{ targetSectionHeader() ? targetSectionHeader() : \"Select Product and Config\" }}</div>\n @if (targetSectionDescription()) {\n <p>{{ targetSectionDescription() }}</p>\n }\n @if (this.presetProductAndConfig()) {\n <p>\n Pre selected product\n <b>{{ this.presetProductAndConfig()!.productName }}</b>\n </p>\n <p>\n Pre selected config\n <b>{{ this.presetProductAndConfig()!.configName }}</b>\n </p>\n }\n <app-product-select\n name=\"productId\"\n [hidden]=\"this.presetProductAndConfig()\"\n [basicAuthUsername]=\"basicAuthUsername()\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [preSelectedProductId]=\"this.presetProductAndConfig()?.productId\"\n [valueFormControl]=\"formGroup.controls.productId\"\n [customDropdown]=\"true\" />\n @if (formGroup.controls.productId.value) {\n <app-config-select\n [hidden]=\"this.presetProductAndConfig()\"\n [basicAuthUsername]=\"basicAuthUsername()\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [preSelectedConfigId]=\"this.presetProductAndConfig()?.configId\"\n [productId]=\"formGroup.controls.productId.value\"\n [valueFormControl]=\"formGroup.controls.configId\"\n [customDropdown]=\"true\" />\n }\n\n <div class=\"header\">2. {{ flagSectionHeader() ? flagSectionHeader() : \"Setup Feature Flag\" }}</div>\n @if (flagSectionDescription()) {\n <p>{{ flagSectionDescription() }}</p>\n }\n @if (loadingComputed()) {\n <app-loader />\n } @else {\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Type</mat-label>\n <mat-select placeholder=\"Type\" formControlName=\"settingType\" panelClass=\"'custom-dropdown-below'\">\n <mat-option [value]=\"SettingTypeEnum.Boolean\">Feature Flag (bool)</mat-option>\n <mat-option [value]=\"SettingTypeEnum.String\">Text (string)</mat-option>\n <mat-option [value]=\"SettingTypeEnum.Int\">Whole Number (integer)</mat-option>\n <mat-option [value]=\"SettingTypeEnum.Double\">Decimal Number (double)</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"form-field name\" appearance=\"outline\">\n <mat-label>Name for humans</mat-label>\n <input matInput placeholder=\"My awesome feature\" formControlName=\"name\" />\n <mat-hint>A friendly name that best describes your setting.</mat-hint>\n @if (formGroup.controls.name.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.name) }}\n </mat-error>\n }\n </mat-form-field>\n <mat-form-field class=\"form-field key\" appearance=\"outline\">\n <mat-label>Key for programs</mat-label>\n <input matInput placeholder=\"isMyAwesomeFeatureEnabled\" formControlName=\"key\" />\n <mat-hint>Your applications will access your setting via this key.</mat-hint>\n @if (formGroup.controls.key.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.key) }}\n </mat-error>\n }\n </mat-form-field>\n <mat-form-field class=\"form-field hint\" appearance=\"outline\">\n @if (!reasonRequired()) {\n <mat-label>Hint (Optional)</mat-label>\n } @else {\n <mat-label>Hint</mat-label>\n }\n <textarea matInput placeholder=\"Hint or description (Optional)\" formControlName=\"hint\"></textarea>\n <mat-hint>A description to help you remember the purpose of your setting.</mat-hint>\n @if (formGroup.controls.hint.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.hint) }}\n </mat-error>\n }\n </mat-form-field>\n\n <div class=\"init-value-section\">\n @if (configEvaluationVersion === EvaluationVersion.V2) {\n <h3>How do you want to set values?</h3>\n <div class=\"value-mode-question\">\n <mat-form-field appearance=\"outline\" class=\"small-form-field value-mode-select\" subscriptSizing=\"dynamic\">\n <mat-select formControlName=\"useVariations\" class=\"choose\">\n <mat-option [value]=\"false\">\n {{\n formGroup.controls.settingType.value === SettingTypeEnum.Boolean\n ? \"use an ON/OFF toggle\"\n : \"enter free-form values\"\n }}\n </mat-option>\n <mat-option [value]=\"true\">choose from predefined variations</mat-option>\n </mat-select>\n </mat-form-field>\n <a href=\"https://configcat.com/docs/advanced/predefined-variations\" class=\"readmore\" target=\"_blank\">\n <mat-icon color=\"primary\" matTooltip=\"Click to read more about value-modes.\">info</mat-icon>\n </a>\n </div>\n @if (formGroup.controls.useVariations.value) {\n <div class=\"header small\">Variations</div>\n <div class=\"variations\">\n <div class=\"predef-var-table-scroll\">\n <table mat-table [dataSource]=\"dataSource\">\n <ng-container matColumnDef=\"color\">\n <th *matHeaderCellDef mat-header-cell></th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row\">\n <span [class]=\"'variation-indicator variation-color-' + getColorIndex(row, i)\"></span>\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 (formGroup.controls.settingType.value) {\n @case (SettingTypeEnum.Boolean) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.boolValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingTypeEnum.String) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.stringValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingTypeEnum.Int) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.intValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingTypeEnum.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 <mat-form-field\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n class=\"small-form-field suffixed\">\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 <input matInput [formControl]=\"row.controls.hint\" />\n @if (row.controls.hint.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(row.controls.hint) }}\n </mat-error>\n }\n </mat-form-field>\n </td>\n </ng-container>\n <ng-container matColumnDef=\"actions\">\n <th *matHeaderCellDef mat-header-cell>\n {{ dataSource.data.length }} / {{ maxPredefinedVariations }}\n </th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div\n [matTooltip]=\"\n formGroup.controls.predefinedVariations.controls.length > 2\n ? 'Remove item'\n : 'At least 2 predefined variations should be set.'\n \">\n <button\n mat-icon-button\n type=\"button\"\n [disabled]=\"formGroup.controls.predefinedVariations.controls.length <= 2\"\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></tr>\n </table>\n </div>\n\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 class=\"add-variation\">\n @if (this.formGroup.controls.settingType.value !== SettingTypeEnum.Boolean) {\n <div\n [matTooltip]=\"'Maximum ' + maxPredefinedVariations + ' predefined 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 } @else {\n <app-box type=\"info\" class=\"bool-variation-info\">\n For more variations, create a flag of another type.\n <a\n href=\"https://configcat.com/docs/main-concepts/#about-setting-types\"\n target=\"_blank\"\n rel=\"noopener noreferrer\">\n Read more\n </a>\n about setting types.\n </app-box>\n }\n </div>\n </div>\n }\n }\n\n <div class=\"header small\">Initial values</div>\n <div class=\"initial-value-first-line\">\n The initial value\n <mat-form-field\n appearance=\"outline\"\n class=\"small-form-field initial-value-environment-type\"\n subscriptSizing=\"dynamic\">\n <mat-select formControlName=\"initialValuesPerEnvironment\">\n <mat-option [value]=\"false\">in all environments</mat-option>\n <mat-option [value]=\"true\">per environment</mat-option>\n </mat-select>\n </mat-form-field>\n will be set to\n </div>\n @if (!formGroup.controls.initialValuesPerEnvironment.value) {\n @if (formGroup.controls.useVariations.value) {\n <div class=\"value-field all\">\n <ng-container\n [ngTemplateOutlet]=\"predefinedVariationTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: formGroup.controls.initialValueForAllVariationIndex }\" />\n </div>\n } @else {\n <div class=\"value-field all\">\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: formGroup.controls.initialValueForAll }\" />\n </div>\n }\n }\n\n @if (formGroup.controls.initialValuesPerEnvironment.value) {\n @for (initialValue of formGroup.controls.initialValues.controls; track $index; let index = $index) {\n <div formArrayName=\"initialValues\">\n <div class=\"value-field\" [formGroupName]=\"index\">\n @if (formGroup.controls.useVariations.value) {\n <ng-container\n [ngTemplateOutlet]=\"predefinedVariationTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: initialValue.controls.predefinedVariationIndex }\" />\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: initialValue.controls.settingValue }\" />\n }\n <div class=\"environment\">\n in\n <strong [matTooltip]=\"initialValue.controls.environmentName.value\">\n {{ initialValue.controls.environmentName.value }}\n </strong>\n </div>\n </div>\n </div>\n }\n }\n </div>\n }\n\n @if (!hideLinkSection()) {\n <div class=\"header\">\n 3. {{ linkSectionHeader() ? linkSectionHeader() : \"Select which environment should we link to this card\" }}\n </div>\n @if (linkSectionDescription()) {\n <p>{{ linkSectionDescription() }}</p>\n }\n @if (formGroup.controls.productId.value) {\n <app-environment-select\n [basicAuthUsername]=\"basicAuthUsername()\"\n [productId]=\"formGroup.controls.productId.value\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [valueFormControl]=\"formGroup.controls.environmentId\"\n [customDropdown]=\"true\" />\n }\n }\n </div>\n @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <div class=\"error\">\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\n </div>\n }\n <div class=\"buttons\">\n <button\n mat-raised-button\n color=\"primary\"\n type=\"submit\"\n [disabled]=\"submitting() || loadingComputed() || !formGroup.valid\">\n {{ createButtonLabel() ? createButtonLabel() : \"Create\" }}\n </button>\n @if (!hideCancelButton()) {\n <button mat-stroked-button type=\"button\" (click)=\"cancel()\">\n {{ cancelButtonLabel() ? cancelButtonLabel() : \"Cancel\" }}\n </button>\n }\n </div>\n </form>\n</div>\n\n<ng-template #settingValueTemplate let-formControl=\"formControl\" let-setFocus=\"setFocus\">\n @switch (formGroup.controls.settingType.value) {\n @case (SettingTypeEnum.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 [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 (SettingTypeEnum.Int) {\n <mat-form-field class=\"small-form-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n @if (formControl.invalid) {\n <mat-error class=\"small-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 (SettingTypeEnum.Double) {\n <mat-form-field class=\"small-form-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n @if (formControl.invalid) {\n <mat-error class=\"small-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 (SettingTypeEnum.Boolean) {\n <div class=\"toggle\">\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\n<ng-template #predefinedVariationTemplate let-formControl=\"formControl\">\n <mat-form-field class=\"small-form-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-select [formControl]=\"formControl\">\n @for (predefinedVariation of formGroup.controls.predefinedVariations.controls; let idx = $index; track $index) {\n <mat-option [value]=\"idx\">\n @if (predefinedVariation.controls.name.value) {\n {{ predefinedVariation.controls.name.value }}\n } @else {\n {{ predefinedVariation.controls.valueForComparison.value }}\n }\n </mat-option>\n }\n </mat-select>\n @if (formControl.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n </mat-form-field>\n</ng-template>\n", styles: [".container{margin:8px 8px 16px}.container .form>*{width:100%}.container .form>* .form-field{width:100%;padding-bottom:8px}.container .form>* .form-field.key{margin-bottom:16px}.container .form>* .form-field.name{margin-bottom:16px}.container .form>* .initial-value-first-line{align-items:center;min-height:34px;margin-bottom:8px}.container .form>* .initial-value-first-line .initial-value-environment-type{margin:0 6px;min-width:160px}.container .form>* .value-field{display:flex;align-items:center;width:100%}.container .form>* .value-field.all{display:inline-flex;margin-left:6px}.container .form>* .value-field.all mat-form-field{min-width:200px}.container .form>* .value-field.all mat-form-field.text{flex-grow:1;width:100%;min-width:100%}.container .form>* .value-field:not(.all){margin-bottom:8px}.container .form>* .value-field:not(.all) mat-form-field{min-width:200px}.container .form>* .value-field:not(.all) mat-form-field.text{min-width:330px}.container .form>* .value-field .environment{margin-left:1em;white-space:nowrap;text-overflow:ellipsis;overflow-x:hidden}.container .form>* .init-value-section{margin-bottom:16px}.container .form>* .init-value-section .predefined-component{padding:8px 0}.container .form>* .init-value-section .small-error{max-width:180px}.container .form>* .init-value-section .readmore{margin-left:8px}.container .form>* .init-value-section .value-mode-question{display:flex;align-items:center}.container .form>* .init-value-section .value-mode-question a{display:flex;align-items:center}.container .form>* .init-value-section .value-mode-question a mat-icon{color:var(--info-icon-color)}.container .form>* .init-value-section .value-mode-question .value-mode-select{min-width:240px}.container .form>* .init-value-section .variations{display:flex;flex-direction:column}.container .form>* .init-value-section .variations .mat-column-color{padding-right:0!important}.container .form>* .init-value-section .variations .variation-header{margin-bottom:8px}.container .form>* .init-value-section .variations .add-variation{margin-top:12px;display:flex}.container .form>* .init-value-section .variations .toggle{margin-left:4px}.container .form>* .init-value-section .variations .predef-var-table-scroll{display:block;overflow-x:auto}.container .form>* .init-value-section .variations .predef-var-table-scroll .mat-mdc-table{min-width:100%}.container .error{color:var(--flag-validation-error);margin:0 5px 5px}.container .header{font-size:18px;margin-top:16px;margin-bottom:16px}.container .header.small{font-size:16px;margin-top:16px;margin-bottom:16px}.buttons{margin-bottom:16px}.buttons>*{margin-right:16px}\n", ".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"] }]
7156
- }], propDecorators: { hideCancelButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideCancelButton", required: false }] }], createButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "createButtonLabel", required: false }] }], cancelButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelButtonLabel", required: false }] }], targetSectionHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "targetSectionHeader", required: false }] }], targetSectionDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "targetSectionDescription", required: false }] }], flagSectionHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "flagSectionHeader", required: false }] }], flagSectionDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "flagSectionDescription", required: false }] }], linkSectionHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "linkSectionHeader", required: false }] }], linkSectionDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "linkSectionDescription", required: false }] }], hideLinkSection: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideLinkSection", required: false }] }], presetProductAndConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "presetProductAndConfig", required: false }] }], createInitiated: [{ type: i0.Output, args: ["createInitiated"] }], resizeRequested: [{ type: i0.Output, args: ["resizeRequested"] }], cancelInitiated: [{ type: i0.Output, args: ["cancelInitiated"] }], selectDropdownPanelChangedReqested: [{ type: i0.Output, args: ["selectDropdownPanelChangedReqested"] }] } });
7286
+ MatCheckbox,
7287
+ ], template: "<div class=\"container\">\n <form class=\"form\" [formGroup]=\"formGroup\" (ngSubmit)=\"create()\">\n <div>\n <div class=\"header\">1. {{ targetSectionHeader() ? targetSectionHeader() : \"Select Product and Config\" }}</div>\n @if (targetSectionDescription()) {\n <p>{{ targetSectionDescription() }}</p>\n }\n @if (this.presetProductAndConfig()) {\n <p>\n Pre selected product\n <b>{{ this.presetProductAndConfig()!.productName }}</b>\n </p>\n <p>\n Pre selected config\n <b>{{ this.presetProductAndConfig()!.configName }}</b>\n </p>\n }\n <app-product-select\n name=\"productId\"\n [hidden]=\"this.presetProductAndConfig()\"\n [basicAuthUsername]=\"basicAuthUsername()\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [preSelectedProductId]=\"this.presetProductAndConfig()?.productId\"\n [valueFormControl]=\"formGroup.controls.productId\"\n [customDropdown]=\"true\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n @if (formGroup.controls.productId.value) {\n <app-config-select\n [hidden]=\"this.presetProductAndConfig()\"\n [basicAuthUsername]=\"basicAuthUsername()\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [preSelectedConfigId]=\"this.presetProductAndConfig()?.configId\"\n [productId]=\"formGroup.controls.productId.value\"\n [valueFormControl]=\"formGroup.controls.configId\"\n [customDropdown]=\"true\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n }\n\n <div class=\"header\">2. {{ flagSectionHeader() ? flagSectionHeader() : \"Setup Feature Flag\" }}</div>\n @if (flagSectionDescription()) {\n <p>{{ flagSectionDescription() }}</p>\n }\n @if (loadingComputed()) {\n <app-loader />\n } @else {\n <mat-form-field class=\"form-field\" appearance=\"outline\">\n <mat-label>Type</mat-label>\n <mat-select placeholder=\"Type\" formControlName=\"settingType\" panelClass=\"'custom-dropdown-below'\">\n <mat-option [value]=\"SettingTypeEnum.Boolean\">Feature Flag (bool)</mat-option>\n <mat-option [value]=\"SettingTypeEnum.String\">Text (string)</mat-option>\n <mat-option [value]=\"SettingTypeEnum.Int\">Whole Number (integer)</mat-option>\n <mat-option [value]=\"SettingTypeEnum.Double\">Decimal Number (double)</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class=\"form-field name\" appearance=\"outline\">\n <mat-label>Name for humans</mat-label>\n <input matInput placeholder=\"My awesome feature\" formControlName=\"name\" />\n <mat-hint>A short name your team will see on the ConfigCat Dashboard.</mat-hint>\n @if (formGroup.controls.name.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.name) }}\n </mat-error>\n }\n </mat-form-field>\n <mat-form-field class=\"form-field key\" appearance=\"outline\">\n <mat-label>Key for programs</mat-label>\n <input matInput placeholder=\"isMyAwesomeFeatureEnabled\" formControlName=\"key\" />\n <mat-hint>Your application will use this key to access the setting.</mat-hint>\n @if (formGroup.controls.key.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.key) }}\n </mat-error>\n }\n </mat-form-field>\n <mat-form-field class=\"form-field hint last\" appearance=\"outline\">\n @if (!reasonRequired()) {\n <mat-label>Hint (Optional)</mat-label>\n } @else {\n <mat-label>Hint</mat-label>\n }\n <textarea matInput placeholder=\"Hint or description (Optional)\" formControlName=\"hint\"></textarea>\n <mat-hint>Explain what this setting controls. This helps your team use it correctly later.</mat-hint>\n @if (formGroup.controls.hint.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.hint) }}\n </mat-error>\n }\n </mat-form-field>\n\n <div class=\"init-value-section\">\n @if (configEvaluationVersion === EvaluationVersion.V2) {\n @if (true && formGroup.controls.settingType.value === SettingTypeEnum.String) {\n <h4>Require valid JSON?</h4>\n <div class=\"centered\">\n <mat-checkbox color=\"primary\" formControlName=\"isJson\">\n <span>Only valid JSON values can be saved</span>\n </mat-checkbox>\n <mat-icon\n color=\"primary\"\n class=\"info-icon\"\n matTooltip=\"Your application will get a string value. You will need to parse it into JSON if necessary.\">\n info\n </mat-icon>\n </div>\n }\n\n <h4>How to set values?</h4>\n <div class=\"value-mode-question\">\n <mat-form-field appearance=\"outline\" class=\"small-form-field value-mode-select\" subscriptSizing=\"dynamic\">\n <mat-select formControlName=\"useVariations\" class=\"choose\">\n <mat-option [value]=\"false\">\n {{\n formGroup.controls.settingType.value === SettingTypeEnum.Boolean\n ? \"use an ON/OFF toggle\"\n : \"enter free-form values\"\n }}\n </mat-option>\n <mat-option [value]=\"true\">choose from predefined variations</mat-option>\n </mat-select>\n </mat-form-field>\n <a href=\"https://configcat.com/docs/advanced/predefined-variations\" target=\"_blank\">\n <mat-icon class=\"info-icon\" color=\"primary\" matTooltip=\"Click to read more about value-modes.\">\n info\n </mat-icon>\n </a>\n </div>\n @if (formGroup.controls.useVariations.value) {\n <p>Define the values team members can choose from. At least two variations are required.</p>\n <div class=\"variations\">\n <div class=\"predef-var-table-scroll\">\n <table mat-table [dataSource]=\"dataSource\">\n <ng-container matColumnDef=\"color\">\n <th *matHeaderCellDef mat-header-cell></th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row\">\n <span [class]=\"'variation-indicator variation-color-' + getColorIndex(row, i)\"></span>\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"value\">\n <th *matHeaderCellDef mat-header-cell>\n <div class=\"centered\">\n <span>Served value *</span>\n <mat-icon\n matTooltip=\"Your application will get this value when evaluating the setting.\"\n class=\"info-icon header-tooltip-icon\">\n info\n </mat-icon>\n </div>\n </th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div class=\"predefined-component\">\n @switch (formGroup.controls.settingType.value) {\n @case (SettingTypeEnum.Boolean) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.boolValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingTypeEnum.String) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.stringValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingTypeEnum.Int) {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{\n formControl: row.controls.value.controls.intValue,\n setFocus: i === focusIndex,\n }\" />\n }\n @case (SettingTypeEnum.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>\n <div class=\"centered\">\n <span>Display name (optional)</span>\n <mat-icon\n matTooltip=\"Optional friendly name. This will be displayed on the ConfigCat Dashboard.\"\n class=\"info-icon header-tooltip-icon\">\n info\n </mat-icon>\n </div>\n </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>\n <div class=\"centered\">\n <span>Hint (optional)</span>\n <mat-icon\n matTooltip=\"Optional hint. This will be displayed in a tooltip.\"\n class=\"info-icon header-tooltip-icon\">\n info\n </mat-icon>\n </div>\n </th>\n <td *matCellDef=\"let row\" mat-cell class=\"row align-top\">\n <mat-form-field\n appearance=\"outline\"\n subscriptSizing=\"dynamic\"\n class=\"small-form-field suffixed\">\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 <input matInput [formControl]=\"row.controls.hint\" />\n @if (row.controls.hint.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(row.controls.hint) }}\n </mat-error>\n }\n </mat-form-field>\n </td>\n </ng-container>\n <ng-container matColumnDef=\"actions\">\n <th *matHeaderCellDef mat-header-cell>\n <span>{{ dataSource.data.length }} / {{ maxPredefinedVariations }}</span>\n </th>\n <td *matCellDef=\"let row; let i = index\" mat-cell class=\"row align-top\">\n <div\n [matTooltip]=\"\n formGroup.controls.predefinedVariations.controls.length > 2\n ? 'Remove item'\n : 'At least 2 predefined variations should be set.'\n \">\n <button\n mat-icon-button\n type=\"button\"\n [disabled]=\"formGroup.controls.predefinedVariations.controls.length <= 2\"\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></tr>\n </table>\n </div>\n\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 class=\"add-variation\">\n @if (this.formGroup.controls.settingType.value !== SettingTypeEnum.Boolean) {\n <div\n [matTooltip]=\"'Maximum ' + maxPredefinedVariations + ' predefined 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 } @else {\n <app-box type=\"info\" class=\"bool-variation-info\">\n For more variations, create a flag of another type.\n <a\n href=\"https://configcat.com/docs/main-concepts/#about-setting-types\"\n target=\"_blank\"\n rel=\"noopener noreferrer\">\n Read more\n </a>\n about setting types.\n </app-box>\n }\n </div>\n </div>\n }\n }\n\n <h4>Initial values</h4>\n <div class=\"initial-value-first-line\">\n The initial value\n <mat-form-field\n appearance=\"outline\"\n class=\"small-form-field initial-value-environment-type\"\n subscriptSizing=\"dynamic\">\n <mat-select formControlName=\"initialValuesPerEnvironment\">\n <mat-option [value]=\"false\">in all environments</mat-option>\n <mat-option [value]=\"true\">per environment</mat-option>\n </mat-select>\n </mat-form-field>\n will be set to\n </div>\n @if (!formGroup.controls.initialValuesPerEnvironment.value) {\n @if (formGroup.controls.useVariations.value) {\n <div class=\"value-field all\">\n <ng-container\n [ngTemplateOutlet]=\"predefinedVariationTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: formGroup.controls.initialValueForAllVariationIndex }\" />\n </div>\n } @else {\n <div class=\"value-field all\">\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: formGroup.controls.initialValueForAll }\" />\n </div>\n }\n }\n\n @if (formGroup.controls.initialValuesPerEnvironment.value) {\n @for (initialValue of formGroup.controls.initialValues.controls; track $index; let index = $index) {\n <div formArrayName=\"initialValues\">\n <div class=\"value-field\" [formGroupName]=\"index\">\n @if (formGroup.controls.useVariations.value) {\n <ng-container\n [ngTemplateOutlet]=\"predefinedVariationTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: initialValue.controls.predefinedVariationIndex }\" />\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"settingValueTemplate\"\n [ngTemplateOutletContext]=\"{ formControl: initialValue.controls.settingValue }\" />\n }\n <div class=\"environment\">\n in\n <strong [matTooltip]=\"initialValue.controls.environmentName.value\">\n {{ initialValue.controls.environmentName.value }}\n </strong>\n </div>\n </div>\n </div>\n }\n }\n </div>\n }\n\n @if (!hideLinkSection()) {\n <div class=\"header\">\n 3. {{ linkSectionHeader() ? linkSectionHeader() : \"Select which environment should we link to this card\" }}\n </div>\n @if (linkSectionDescription()) {\n <p>{{ linkSectionDescription() }}</p>\n }\n @if (formGroup.controls.productId.value) {\n <app-environment-select\n [basicAuthUsername]=\"basicAuthUsername()\"\n [productId]=\"formGroup.controls.productId.value\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [valueFormControl]=\"formGroup.controls.environmentId\"\n [customDropdown]=\"true\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n }\n }\n </div>\n @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <div class=\"error\">\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\n </div>\n }\n <div class=\"buttons\">\n <button\n mat-raised-button\n color=\"primary\"\n type=\"submit\"\n [disabled]=\"submitting() || loadingComputed() || !formGroup.valid\">\n {{ createButtonLabel() ? createButtonLabel() : \"Create\" }}\n </button>\n @if (!hideCancelButton()) {\n <button mat-stroked-button type=\"button\" (click)=\"cancel()\">\n {{ cancelButtonLabel() ? cancelButtonLabel() : \"Cancel\" }}\n </button>\n }\n </div>\n </form>\n</div>\n\n<ng-template #settingValueTemplate let-formControl=\"formControl\" let-setFocus=\"setFocus\">\n @switch (formGroup.controls.settingType.value) {\n @case (SettingTypeEnum.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 [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 (SettingTypeEnum.Int) {\n <mat-form-field class=\"small-form-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n @if (formControl.invalid) {\n <mat-error class=\"small-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 (SettingTypeEnum.Double) {\n <mat-form-field class=\"small-form-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n @if (formControl.invalid) {\n <mat-error class=\"small-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 (SettingTypeEnum.Boolean) {\n <div class=\"toggle\">\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\n<ng-template #predefinedVariationTemplate let-formControl=\"formControl\">\n <mat-form-field class=\"small-form-field\" appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-select [formControl]=\"formControl\">\n @for (predefinedVariation of formGroup.controls.predefinedVariations.controls; let idx = $index; track $index) {\n <mat-option [value]=\"idx\">\n @if (predefinedVariation.controls.name.value) {\n {{ predefinedVariation.controls.name.value }}\n } @else {\n {{ predefinedVariation.controls.valueForComparison.value }}\n }\n </mat-option>\n }\n </mat-select>\n @if (formControl.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formControl) }}\n </mat-error>\n }\n </mat-form-field>\n</ng-template>\n", styles: [".container{margin:8px 8px 16px}.container .form>*{width:100%}.container .form>* .form-field{width:100%;padding-bottom:8px}.container .form>* .form-field.key{margin-bottom:16px}.container .form>* .form-field.name{margin-bottom:16px}.container .form>* .initial-value-first-line{align-items:center;min-height:34px;margin-bottom:8px}.container .form>* .initial-value-first-line .initial-value-environment-type{margin:0 6px;min-width:160px}.container .form>* .value-field{display:flex;align-items:center;width:100%}.container .form>* .value-field.all{display:inline-flex;margin-left:6px}.container .form>* .value-field.all mat-form-field{min-width:200px}.container .form>* .value-field.all mat-form-field.text{flex-grow:1;width:100%;min-width:100%}.container .form>* .value-field:not(.all){margin-bottom:8px}.container .form>* .value-field:not(.all) mat-form-field{min-width:200px}.container .form>* .value-field:not(.all) mat-form-field.text{min-width:330px}.container .form>* .value-field .environment{margin-left:1em;white-space:nowrap;text-overflow:ellipsis;overflow-x:hidden}.container .form>* .init-value-section{margin-bottom:16px}.container .form>* .init-value-section .predefined-component{padding:8px 0}.container .form>* .init-value-section .small-error{max-width:180px}.container .form>* .init-value-section .readmore{margin-left:8px}.container .form>* .init-value-section .value-mode-question{display:flex;align-items:center}.container .form>* .init-value-section .value-mode-question a{display:flex;align-items:center}.container .form>* .init-value-section .value-mode-question .value-mode-select{min-width:240px}.container .form>* .init-value-section .centered{display:flex;align-items:center}.container .form>* .init-value-section mat-icon.info-icon{color:var(--info-icon-color);margin-left:8px}.container .form>* .init-value-section .variations{display:flex;flex-direction:column}.container .form>* .init-value-section .variations .mat-column-color{padding-right:0!important}.container .form>* .init-value-section .variations .variation-header{margin-bottom:8px}.container .form>* .init-value-section .variations .add-variation{margin-top:12px;display:flex}.container .form>* .init-value-section .variations .toggle{margin-left:4px}.container .form>* .init-value-section .variations .header-tooltip-icon{font-size:14px;width:14px;height:14px}.container .form>* .init-value-section .variations .predef-var-table-scroll{display:block;overflow-x:auto}.container .form>* .init-value-section .variations .predef-var-table-scroll .mat-mdc-table{min-width:100%}.container .error{color:var(--flag-validation-error);margin:0 5px 5px}.container .header{font-size:18px;margin-top:16px;margin-bottom:16px}.container .header.small{font-size:16px;margin-top:16px;margin-bottom:16px}h4{margin-bottom:8px}.buttons{margin-bottom:16px}.buttons>*{margin-right:16px}\n", ".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"] }]
7288
+ }], propDecorators: { hideCancelButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideCancelButton", required: false }] }], createButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "createButtonLabel", required: false }] }], cancelButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelButtonLabel", required: false }] }], targetSectionHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "targetSectionHeader", required: false }] }], targetSectionDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "targetSectionDescription", required: false }] }], flagSectionHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "flagSectionHeader", required: false }] }], flagSectionDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "flagSectionDescription", required: false }] }], linkSectionHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "linkSectionHeader", required: false }] }], linkSectionDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "linkSectionDescription", required: false }] }], hideLinkSection: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideLinkSection", required: false }] }], presetProductAndConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "presetProductAndConfig", required: false }] }], createInitiated: [{ type: i0.Output, args: ["createInitiated"] }], resizeRequested: [{ type: i0.Output, args: ["resizeRequested"] }], cancelInitiated: [{ type: i0.Output, args: ["cancelInitiated"] }], selectDropdownPanelChangedReqested: [{ type: i0.Output, args: ["selectDropdownPanelChangedReqested"] }], componentError: [{ type: i0.Output, args: ["componentError"] }] } });
7157
7289
 
7158
7290
  class CreateConfigComponent extends BaseComponent {
7159
7291
  constructor() {
@@ -7171,6 +7303,7 @@ class CreateConfigComponent extends BaseComponent {
7171
7303
  this.resizeRequested = output();
7172
7304
  this.cancelInitiated = output();
7173
7305
  this.selectDropdownPanelChangedReqested = output();
7306
+ this.componentError = output();
7174
7307
  this.loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
7175
7308
  this.submitting = signal(false, ...(ngDevMode ? [{ debugName: "submitting" }] : /* istanbul ignore next */ []));
7176
7309
  this.SettingTypeEnum = SettingType;
@@ -7224,7 +7357,9 @@ class CreateConfigComponent extends BaseComponent {
7224
7357
  error: (error) => {
7225
7358
  this.submitting.set(false);
7226
7359
  ErrorHandler.handleErrors(this.formGroup, error);
7227
- console.log(error);
7360
+ if (error instanceof HttpErrorResponse && error.status === 401) {
7361
+ this.componentError.emit(error);
7362
+ }
7228
7363
  },
7229
7364
  });
7230
7365
  }
@@ -7234,8 +7369,11 @@ class CreateConfigComponent extends BaseComponent {
7234
7369
  selectDropdownPanelChanged(useSelector) {
7235
7370
  this.selectDropdownPanelChangedReqested.emit(useSelector);
7236
7371
  }
7372
+ dropdownComponentFailed(error) {
7373
+ this.componentError.emit(error);
7374
+ }
7237
7375
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: CreateConfigComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
7238
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: CreateConfigComponent, isStandalone: true, selector: "app-create-config", inputs: { hideCancelButton: { classPropertyName: "hideCancelButton", publicName: "hideCancelButton", isSignal: true, isRequired: false, transformFunction: null }, createButtonLabel: { classPropertyName: "createButtonLabel", publicName: "createButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelButtonLabel: { classPropertyName: "cancelButtonLabel", publicName: "cancelButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, targetSectionHeader: { classPropertyName: "targetSectionHeader", publicName: "targetSectionHeader", isSignal: true, isRequired: false, transformFunction: null }, targetSectionDescription: { classPropertyName: "targetSectionDescription", publicName: "targetSectionDescription", isSignal: true, isRequired: false, transformFunction: null }, configSectionHeader: { classPropertyName: "configSectionHeader", publicName: "configSectionHeader", isSignal: true, isRequired: false, transformFunction: null }, configSectionDescription: { classPropertyName: "configSectionDescription", publicName: "configSectionDescription", isSignal: true, isRequired: false, transformFunction: null }, presetProduct: { classPropertyName: "presetProduct", publicName: "presetProduct", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { createInitiated: "createInitiated", resizeRequested: "resizeRequested", cancelInitiated: "cancelInitiated", selectDropdownPanelChangedReqested: "selectDropdownPanelChangedReqested" }, usesInheritance: true, ngImport: i0, template: "<div class=\"container\">\n <form class=\"form\" [formGroup]=\"formGroup\" (ngSubmit)=\"create()\">\n <div>\n <div class=\"header\">1. {{ targetSectionHeader() ? targetSectionHeader() : \"Select Product and Config\" }}</div>\n @if (targetSectionDescription()) {\n <p>{{ targetSectionDescription() }}</p>\n }\n @if (this.presetProduct()) {\n <p>\n Pre selected product\n <b>{{ this.presetProduct()!.productName }}</b>\n </p>\n }\n <app-product-select\n name=\"productId\"\n [hidden]=\"this.presetProduct()\"\n [basicAuthUsername]=\"basicAuthUsername()\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [preSelectedProductId]=\"this.presetProduct()?.productId\"\n [valueFormControl]=\"formGroup.controls.productId\"\n [customDropdown]=\"true\" />\n\n <div class=\"header\">2. {{ configSectionHeader() ? configSectionHeader() : \"Setup Feature Flag\" }}</div>\n @if (configSectionDescription()) {\n <p>{{ configSectionDescription() }}</p>\n }\n @if (loading()) {\n <app-loader />\n } @else {\n <mat-form-field class=\"form-field name\" appearance=\"outline\">\n <mat-label>Name</mat-label>\n <input matInput placeholder=\"Config's name\" formControlName=\"name\" />\n <mat-hint>A friendly name that best describes your config.</mat-hint>\n @if (formGroup.controls.name.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.name) }}\n </mat-error>\n }\n </mat-form-field>\n <mat-form-field class=\"form-field hint\" appearance=\"outline\">\n <mat-label>Config description (Optional)</mat-label>\n <textarea matInput placeholder=\"This config is responsible for...\" formControlName=\"description\"></textarea>\n <mat-hint>A description to help you remember the purpose of your config.</mat-hint>\n @if (formGroup.controls.description.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.description) }}\n </mat-error>\n }\n </mat-form-field>\n }\n </div>\n @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <div class=\"error\">\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\n </div>\n }\n <div class=\"buttons\">\n <button\n mat-raised-button\n color=\"primary\"\n type=\"submit\"\n [disabled]=\"submitting() || loading() || !formGroup.valid\">\n {{ createButtonLabel() ? createButtonLabel() : \"Create\" }}\n </button>\n @if (!hideCancelButton()) {\n <button mat-stroked-button type=\"button\" (click)=\"cancel()\">\n {{ cancelButtonLabel() ? cancelButtonLabel() : \"Cancel\" }}\n </button>\n }\n </div>\n </form>\n</div>\n", styles: [".container{margin:8px 8px 16px}.container .form>*{width:100%}.container .form>* .form-field{width:100%;padding-bottom:8px}.container .form>* .form-field.key{margin-bottom:16px}.container .form>* .form-field.name{margin-bottom:16px}.container .form>* .value-field{display:flex;align-items:center;width:100%}.container .form>* .value-field.all{display:inline-flex;margin-left:6px}.container .form>* .value-field.all mat-form-field{min-width:200px}.container .form>* .value-field.all mat-form-field.text{flex-grow:1;width:100%;min-width:100%}.container .form>* .value-field:not(.all){margin-bottom:8px}.container .form>* .value-field:not(.all) mat-form-field{min-width:200px}.container .form>* .value-field:not(.all) mat-form-field.text{min-width:330px}.container .error{color:var(--flag-validation-error);margin:0 5px 5px}.container .header{font-size:18px;margin-top:16px;margin-bottom:16px}.container .header.small{font-size:16px;margin-top:16px;margin-bottom:16px}.buttons{margin-bottom:16px}.buttons>*{margin-right:16px}\n"], dependencies: [{ kind: "component", type: ProductSelectComponent, selector: "app-product-select", inputs: ["valueFormControl", "preSelectedProductId"] }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { 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: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { 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: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { 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: "component", type: LoaderComponent, selector: "app-loader", inputs: ["skipTimeOut"] }] }); }
7376
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: CreateConfigComponent, isStandalone: true, selector: "app-create-config", inputs: { hideCancelButton: { classPropertyName: "hideCancelButton", publicName: "hideCancelButton", isSignal: true, isRequired: false, transformFunction: null }, createButtonLabel: { classPropertyName: "createButtonLabel", publicName: "createButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelButtonLabel: { classPropertyName: "cancelButtonLabel", publicName: "cancelButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, targetSectionHeader: { classPropertyName: "targetSectionHeader", publicName: "targetSectionHeader", isSignal: true, isRequired: false, transformFunction: null }, targetSectionDescription: { classPropertyName: "targetSectionDescription", publicName: "targetSectionDescription", isSignal: true, isRequired: false, transformFunction: null }, configSectionHeader: { classPropertyName: "configSectionHeader", publicName: "configSectionHeader", isSignal: true, isRequired: false, transformFunction: null }, configSectionDescription: { classPropertyName: "configSectionDescription", publicName: "configSectionDescription", isSignal: true, isRequired: false, transformFunction: null }, presetProduct: { classPropertyName: "presetProduct", publicName: "presetProduct", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { createInitiated: "createInitiated", resizeRequested: "resizeRequested", cancelInitiated: "cancelInitiated", selectDropdownPanelChangedReqested: "selectDropdownPanelChangedReqested", componentError: "componentError" }, usesInheritance: true, ngImport: i0, template: "<div class=\"container\">\n <form class=\"form\" [formGroup]=\"formGroup\" (ngSubmit)=\"create()\">\n <div>\n <div class=\"header\">1. {{ targetSectionHeader() ? targetSectionHeader() : \"Select Product and Config\" }}</div>\n @if (targetSectionDescription()) {\n <p>{{ targetSectionDescription() }}</p>\n }\n @if (this.presetProduct()) {\n <p>\n Pre selected product\n <b>{{ this.presetProduct()!.productName }}</b>\n </p>\n }\n <app-product-select\n name=\"productId\"\n [hidden]=\"this.presetProduct()\"\n [basicAuthUsername]=\"basicAuthUsername()\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [preSelectedProductId]=\"this.presetProduct()?.productId\"\n [valueFormControl]=\"formGroup.controls.productId\"\n [customDropdown]=\"true\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n\n <div class=\"header\">2. {{ configSectionHeader() ? configSectionHeader() : \"Setup Feature Flag\" }}</div>\n @if (configSectionDescription()) {\n <p>{{ configSectionDescription() }}</p>\n }\n @if (loading()) {\n <app-loader />\n } @else {\n <mat-form-field class=\"form-field name\" appearance=\"outline\">\n <mat-label>Name</mat-label>\n <input matInput placeholder=\"Config's name\" formControlName=\"name\" />\n <mat-hint>A friendly name that best describes your config.</mat-hint>\n @if (formGroup.controls.name.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.name) }}\n </mat-error>\n }\n </mat-form-field>\n <mat-form-field class=\"form-field hint\" appearance=\"outline\">\n <mat-label>Config description (Optional)</mat-label>\n <textarea matInput placeholder=\"This config is responsible for...\" formControlName=\"description\"></textarea>\n <mat-hint>A description to help you remember the purpose of your config.</mat-hint>\n @if (formGroup.controls.description.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.description) }}\n </mat-error>\n }\n </mat-form-field>\n }\n </div>\n @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <div class=\"error\">\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\n </div>\n }\n <div class=\"buttons\">\n <button\n mat-raised-button\n color=\"primary\"\n type=\"submit\"\n [disabled]=\"submitting() || loading() || !formGroup.valid\">\n {{ createButtonLabel() ? createButtonLabel() : \"Create\" }}\n </button>\n @if (!hideCancelButton()) {\n <button mat-stroked-button type=\"button\" (click)=\"cancel()\">\n {{ cancelButtonLabel() ? cancelButtonLabel() : \"Cancel\" }}\n </button>\n }\n </div>\n </form>\n</div>\n", styles: [".container{margin:8px 8px 16px}.container .form>*{width:100%}.container .form>* .form-field{width:100%;padding-bottom:8px}.container .form>* .form-field.key{margin-bottom:16px}.container .form>* .form-field.name{margin-bottom:16px}.container .form>* .value-field{display:flex;align-items:center;width:100%}.container .form>* .value-field.all{display:inline-flex;margin-left:6px}.container .form>* .value-field.all mat-form-field{min-width:200px}.container .form>* .value-field.all mat-form-field.text{flex-grow:1;width:100%;min-width:100%}.container .form>* .value-field:not(.all){margin-bottom:8px}.container .form>* .value-field:not(.all) mat-form-field{min-width:200px}.container .form>* .value-field:not(.all) mat-form-field.text{min-width:330px}.container .error{color:var(--flag-validation-error);margin:0 5px 5px}.container .header{font-size:18px;margin-top:16px;margin-bottom:16px}.container .header.small{font-size:16px;margin-top:16px;margin-bottom:16px}.buttons{margin-bottom:16px}.buttons>*{margin-right:16px}\n"], dependencies: [{ kind: "component", type: ProductSelectComponent, selector: "app-product-select", inputs: ["valueFormControl", "preSelectedProductId"], outputs: ["componentError"] }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { 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: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { 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: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { 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: "component", type: LoaderComponent, selector: "app-loader", inputs: ["skipTimeOut"] }] }); }
7239
7377
  }
7240
7378
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: CreateConfigComponent, decorators: [{
7241
7379
  type: Component,
@@ -7251,8 +7389,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
7251
7389
  MatError,
7252
7390
  MatButton,
7253
7391
  LoaderComponent,
7254
- ], template: "<div class=\"container\">\n <form class=\"form\" [formGroup]=\"formGroup\" (ngSubmit)=\"create()\">\n <div>\n <div class=\"header\">1. {{ targetSectionHeader() ? targetSectionHeader() : \"Select Product and Config\" }}</div>\n @if (targetSectionDescription()) {\n <p>{{ targetSectionDescription() }}</p>\n }\n @if (this.presetProduct()) {\n <p>\n Pre selected product\n <b>{{ this.presetProduct()!.productName }}</b>\n </p>\n }\n <app-product-select\n name=\"productId\"\n [hidden]=\"this.presetProduct()\"\n [basicAuthUsername]=\"basicAuthUsername()\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [preSelectedProductId]=\"this.presetProduct()?.productId\"\n [valueFormControl]=\"formGroup.controls.productId\"\n [customDropdown]=\"true\" />\n\n <div class=\"header\">2. {{ configSectionHeader() ? configSectionHeader() : \"Setup Feature Flag\" }}</div>\n @if (configSectionDescription()) {\n <p>{{ configSectionDescription() }}</p>\n }\n @if (loading()) {\n <app-loader />\n } @else {\n <mat-form-field class=\"form-field name\" appearance=\"outline\">\n <mat-label>Name</mat-label>\n <input matInput placeholder=\"Config's name\" formControlName=\"name\" />\n <mat-hint>A friendly name that best describes your config.</mat-hint>\n @if (formGroup.controls.name.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.name) }}\n </mat-error>\n }\n </mat-form-field>\n <mat-form-field class=\"form-field hint\" appearance=\"outline\">\n <mat-label>Config description (Optional)</mat-label>\n <textarea matInput placeholder=\"This config is responsible for...\" formControlName=\"description\"></textarea>\n <mat-hint>A description to help you remember the purpose of your config.</mat-hint>\n @if (formGroup.controls.description.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.description) }}\n </mat-error>\n }\n </mat-form-field>\n }\n </div>\n @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <div class=\"error\">\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\n </div>\n }\n <div class=\"buttons\">\n <button\n mat-raised-button\n color=\"primary\"\n type=\"submit\"\n [disabled]=\"submitting() || loading() || !formGroup.valid\">\n {{ createButtonLabel() ? createButtonLabel() : \"Create\" }}\n </button>\n @if (!hideCancelButton()) {\n <button mat-stroked-button type=\"button\" (click)=\"cancel()\">\n {{ cancelButtonLabel() ? cancelButtonLabel() : \"Cancel\" }}\n </button>\n }\n </div>\n </form>\n</div>\n", styles: [".container{margin:8px 8px 16px}.container .form>*{width:100%}.container .form>* .form-field{width:100%;padding-bottom:8px}.container .form>* .form-field.key{margin-bottom:16px}.container .form>* .form-field.name{margin-bottom:16px}.container .form>* .value-field{display:flex;align-items:center;width:100%}.container .form>* .value-field.all{display:inline-flex;margin-left:6px}.container .form>* .value-field.all mat-form-field{min-width:200px}.container .form>* .value-field.all mat-form-field.text{flex-grow:1;width:100%;min-width:100%}.container .form>* .value-field:not(.all){margin-bottom:8px}.container .form>* .value-field:not(.all) mat-form-field{min-width:200px}.container .form>* .value-field:not(.all) mat-form-field.text{min-width:330px}.container .error{color:var(--flag-validation-error);margin:0 5px 5px}.container .header{font-size:18px;margin-top:16px;margin-bottom:16px}.container .header.small{font-size:16px;margin-top:16px;margin-bottom:16px}.buttons{margin-bottom:16px}.buttons>*{margin-right:16px}\n"] }]
7255
- }], propDecorators: { hideCancelButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideCancelButton", required: false }] }], createButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "createButtonLabel", required: false }] }], cancelButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelButtonLabel", required: false }] }], targetSectionHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "targetSectionHeader", required: false }] }], targetSectionDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "targetSectionDescription", required: false }] }], configSectionHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "configSectionHeader", required: false }] }], configSectionDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "configSectionDescription", required: false }] }], presetProduct: [{ type: i0.Input, args: [{ isSignal: true, alias: "presetProduct", required: false }] }], createInitiated: [{ type: i0.Output, args: ["createInitiated"] }], resizeRequested: [{ type: i0.Output, args: ["resizeRequested"] }], cancelInitiated: [{ type: i0.Output, args: ["cancelInitiated"] }], selectDropdownPanelChangedReqested: [{ type: i0.Output, args: ["selectDropdownPanelChangedReqested"] }] } });
7392
+ ], template: "<div class=\"container\">\n <form class=\"form\" [formGroup]=\"formGroup\" (ngSubmit)=\"create()\">\n <div>\n <div class=\"header\">1. {{ targetSectionHeader() ? targetSectionHeader() : \"Select Product and Config\" }}</div>\n @if (targetSectionDescription()) {\n <p>{{ targetSectionDescription() }}</p>\n }\n @if (this.presetProduct()) {\n <p>\n Pre selected product\n <b>{{ this.presetProduct()!.productName }}</b>\n </p>\n }\n <app-product-select\n name=\"productId\"\n [hidden]=\"this.presetProduct()\"\n [basicAuthUsername]=\"basicAuthUsername()\"\n [basicAuthPassword]=\"basicAuthPassword()\"\n [preSelectedProductId]=\"this.presetProduct()?.productId\"\n [valueFormControl]=\"formGroup.controls.productId\"\n [customDropdown]=\"true\"\n (componentError)=\"dropdownComponentFailed($event)\" />\n\n <div class=\"header\">2. {{ configSectionHeader() ? configSectionHeader() : \"Setup Feature Flag\" }}</div>\n @if (configSectionDescription()) {\n <p>{{ configSectionDescription() }}</p>\n }\n @if (loading()) {\n <app-loader />\n } @else {\n <mat-form-field class=\"form-field name\" appearance=\"outline\">\n <mat-label>Name</mat-label>\n <input matInput placeholder=\"Config's name\" formControlName=\"name\" />\n <mat-hint>A friendly name that best describes your config.</mat-hint>\n @if (formGroup.controls.name.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.name) }}\n </mat-error>\n }\n </mat-form-field>\n <mat-form-field class=\"form-field hint\" appearance=\"outline\">\n <mat-label>Config description (Optional)</mat-label>\n <textarea matInput placeholder=\"This config is responsible for...\" formControlName=\"description\"></textarea>\n <mat-hint>A description to help you remember the purpose of your config.</mat-hint>\n @if (formGroup.controls.description.invalid) {\n <mat-error>\n {{ FormHelper.getErrorMessage(formGroup.controls.description) }}\n </mat-error>\n }\n </mat-form-field>\n }\n </div>\n @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <div class=\"error\">\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\n </div>\n }\n <div class=\"buttons\">\n <button\n mat-raised-button\n color=\"primary\"\n type=\"submit\"\n [disabled]=\"submitting() || loading() || !formGroup.valid\">\n {{ createButtonLabel() ? createButtonLabel() : \"Create\" }}\n </button>\n @if (!hideCancelButton()) {\n <button mat-stroked-button type=\"button\" (click)=\"cancel()\">\n {{ cancelButtonLabel() ? cancelButtonLabel() : \"Cancel\" }}\n </button>\n }\n </div>\n </form>\n</div>\n", styles: [".container{margin:8px 8px 16px}.container .form>*{width:100%}.container .form>* .form-field{width:100%;padding-bottom:8px}.container .form>* .form-field.key{margin-bottom:16px}.container .form>* .form-field.name{margin-bottom:16px}.container .form>* .value-field{display:flex;align-items:center;width:100%}.container .form>* .value-field.all{display:inline-flex;margin-left:6px}.container .form>* .value-field.all mat-form-field{min-width:200px}.container .form>* .value-field.all mat-form-field.text{flex-grow:1;width:100%;min-width:100%}.container .form>* .value-field:not(.all){margin-bottom:8px}.container .form>* .value-field:not(.all) mat-form-field{min-width:200px}.container .form>* .value-field:not(.all) mat-form-field.text{min-width:330px}.container .error{color:var(--flag-validation-error);margin:0 5px 5px}.container .header{font-size:18px;margin-top:16px;margin-bottom:16px}.container .header.small{font-size:16px;margin-top:16px;margin-bottom:16px}.buttons{margin-bottom:16px}.buttons>*{margin-right:16px}\n"] }]
7393
+ }], propDecorators: { hideCancelButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideCancelButton", required: false }] }], createButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "createButtonLabel", required: false }] }], cancelButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelButtonLabel", required: false }] }], targetSectionHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "targetSectionHeader", required: false }] }], targetSectionDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "targetSectionDescription", required: false }] }], configSectionHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "configSectionHeader", required: false }] }], configSectionDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "configSectionDescription", required: false }] }], presetProduct: [{ type: i0.Input, args: [{ isSignal: true, alias: "presetProduct", required: false }] }], createInitiated: [{ type: i0.Output, args: ["createInitiated"] }], resizeRequested: [{ type: i0.Output, args: ["resizeRequested"] }], cancelInitiated: [{ type: i0.Output, args: ["cancelInitiated"] }], selectDropdownPanelChangedReqested: [{ type: i0.Output, args: ["selectDropdownPanelChangedReqested"] }], componentError: [{ type: i0.Output, args: ["componentError"] }] } });
7256
7394
 
7257
7395
  /*
7258
7396
  * Public API Surface of ng-configcat-publicapi-ui