ng-configcat-publicapi-ui 5.6.2 → 5.6.3
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OVERLAY_DEFAULT_CONFIG, Overlay } from '@angular/cdk/overlay';
|
|
2
2
|
import { DatePipe, NgClass, NgTemplateOutlet, SlicePipe, KeyValuePipe } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { inject, Injectable, ChangeDetectionStrategy, Component, viewChild, DestroyRef, DOCUMENT, InjectionToken, HostListener, Directive, input, ElementRef, model, effect, output, forwardRef, signal, viewChildren, linkedSignal,
|
|
4
|
+
import { inject, Injectable, ChangeDetectionStrategy, Component, viewChild, DestroyRef, DOCUMENT, InjectionToken, HostListener, Directive, input, ElementRef, model, effect, output, forwardRef, signal, computed, viewChildren, linkedSignal, ViewEncapsulation, ChangeDetectorRef } from '@angular/core';
|
|
5
5
|
import { MAT_AUTOCOMPLETE_SCROLL_STRATEGY, MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
|
|
6
6
|
import { MAT_BUTTON_TOGGLE_DEFAULT_OPTIONS, MatButtonToggleGroup, MatButtonToggle } from '@angular/material/button-toggle';
|
|
7
7
|
import { MAT_DATEPICKER_SCROLL_STRATEGY, MatDatepicker, MatDatepickerToggle, MatDatepickerInput } from '@angular/material/datepicker';
|
|
@@ -2697,6 +2697,14 @@ class SettingListComponent {
|
|
|
2697
2697
|
this.deleteSettingRequested = output();
|
|
2698
2698
|
this.formValuesChanged = output();
|
|
2699
2699
|
this.saveFailed = output();
|
|
2700
|
+
// Track actual value changes, not just form interaction. If a value is modified then reverted to its original state,
|
|
2701
|
+
// it's not considered dirty. This ensures save/publish buttons activate only for genuine changes, avoiding unnecessary backend operations.
|
|
2702
|
+
this.initialValueJson = signal("", /* @ts-ignore */
|
|
2703
|
+
...(ngDevMode ? [{ debugName: "initialValueJson" }] : /* istanbul ignore next */ []));
|
|
2704
|
+
this.settingValueFormGroupChanged = signal("", /* @ts-ignore */
|
|
2705
|
+
...(ngDevMode ? [{ debugName: "settingValueFormGroupChanged" }] : /* istanbul ignore next */ []));
|
|
2706
|
+
this.formGroupDirty = computed(() => this.settingValueFormGroupChanged() !== this.initialValueJson(), /* @ts-ignore */
|
|
2707
|
+
...(ngDevMode ? [{ debugName: "formGroupDirty" }] : /* istanbul ignore next */ []));
|
|
2700
2708
|
this.loading = true;
|
|
2701
2709
|
this.submitting = false;
|
|
2702
2710
|
this.showFeedBackMessage = false;
|
|
@@ -2744,8 +2752,12 @@ class SettingListComponent {
|
|
|
2744
2752
|
}
|
|
2745
2753
|
createFormGroup() {
|
|
2746
2754
|
this.formGroup = this.formHelper.createSettingValuesFormGroup(this.settingValues);
|
|
2755
|
+
const initialValueRaw = JSON.stringify(this.formGroup.getRawValue());
|
|
2756
|
+
this.initialValueJson.set(initialValueRaw);
|
|
2757
|
+
this.settingValueFormGroupChanged.set(initialValueRaw);
|
|
2747
2758
|
this.formValuesChangedSubscription = this.formGroup.valueChanges.subscribe(() => {
|
|
2748
2759
|
this.formValuesChanged.emit();
|
|
2760
|
+
this.settingValueFormGroupChanged.set(JSON.stringify(this.formGroup.getRawValue()));
|
|
2749
2761
|
});
|
|
2750
2762
|
}
|
|
2751
2763
|
settingValuesFormArray() {
|
|
@@ -2877,11 +2889,11 @@ class SettingListComponent {
|
|
|
2877
2889
|
});
|
|
2878
2890
|
}
|
|
2879
2891
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SettingListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2880
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: SettingListComponent, isStandalone: true, selector: "app-setting-list", 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 }, dashboardBasePath: { classPropertyName: "dashboardBasePath", publicName: "dashboardBasePath", isSignal: true, isRequired: false, transformFunction: null }, canDeleteSetting: { classPropertyName: "canDeleteSetting", publicName: "canDeleteSetting", isSignal: true, isRequired: false, transformFunction: null }, onSave: { classPropertyName: "onSave", publicName: "onSave", isSignal: true, isRequired: true, transformFunction: null }, loadSettingValues: { classPropertyName: "loadSettingValues", publicName: "loadSettingValues", isSignal: true, isRequired: true, transformFunction: null }, loadSegments: { classPropertyName: "loadSegments", publicName: "loadSegments", isSignal: true, isRequired: true, 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: { loadSucceeded: "loadSucceeded", deleteSettingRequested: "deleteSettingRequested", formValuesChanged: "formValuesChanged", saveFailed: "saveFailed" }, usesOnChanges: true, ngImport: i0, template: "@if (!loading) {\n <form [formGroup]=\"formGroup\" (ngSubmit)=\"submit()\">\n @for (settingValueFromGroup of formGroup!.controls.settingValues.controls; track $index; let i = $index) {\n <div class=\"wrapper\">\n <div class=\"size-obs\" [style.display]=\"'block'\">\n <div>\n <app-setting\n [formGroup]=\"settingValueFromGroup\"\n [readOnly]=\"readOnly\"\n [canDeleteSetting]=\"canDeleteSetting()\"\n [deleteSettingText]=\"deleteSettingText()\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [model]=\"settingValues!.settingValues[i]\"\n [segments]=\"segments\"\n [productId]=\"productId()\"\n [configId]=\"configId()\"\n [environmentId]=\"environmentId()\"\n [dashboardBasePath]=\"dashboardBasePath()\"\n [featureFlagLimitations]=\"settingValues!.featureFlagLimitations\"\n (subscriptionLimitReached)=\"onSubscriptionLimitReached()\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\" />\n </div>\n </div>\n </div>\n }\n @if (!readOnly &&
|
|
2892
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: SettingListComponent, isStandalone: true, selector: "app-setting-list", 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 }, dashboardBasePath: { classPropertyName: "dashboardBasePath", publicName: "dashboardBasePath", isSignal: true, isRequired: false, transformFunction: null }, canDeleteSetting: { classPropertyName: "canDeleteSetting", publicName: "canDeleteSetting", isSignal: true, isRequired: false, transformFunction: null }, onSave: { classPropertyName: "onSave", publicName: "onSave", isSignal: true, isRequired: true, transformFunction: null }, loadSettingValues: { classPropertyName: "loadSettingValues", publicName: "loadSettingValues", isSignal: true, isRequired: true, transformFunction: null }, loadSegments: { classPropertyName: "loadSegments", publicName: "loadSegments", isSignal: true, isRequired: true, 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: { loadSucceeded: "loadSucceeded", deleteSettingRequested: "deleteSettingRequested", formValuesChanged: "formValuesChanged", saveFailed: "saveFailed" }, usesOnChanges: true, ngImport: i0, template: "@if (!loading) {\n <form [formGroup]=\"formGroup\" (ngSubmit)=\"submit()\">\n @for (settingValueFromGroup of formGroup!.controls.settingValues.controls; track $index; let i = $index) {\n <div class=\"wrapper\">\n <div class=\"size-obs\" [style.display]=\"'block'\">\n <div>\n <app-setting\n [formGroup]=\"settingValueFromGroup\"\n [readOnly]=\"readOnly\"\n [canDeleteSetting]=\"canDeleteSetting()\"\n [deleteSettingText]=\"deleteSettingText()\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [model]=\"settingValues!.settingValues[i]\"\n [segments]=\"segments\"\n [productId]=\"productId()\"\n [configId]=\"configId()\"\n [environmentId]=\"environmentId()\"\n [dashboardBasePath]=\"dashboardBasePath()\"\n [featureFlagLimitations]=\"settingValues!.featureFlagLimitations\"\n (subscriptionLimitReached)=\"onSubscriptionLimitReached()\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\" />\n </div>\n </div>\n </div>\n }\n @if (!readOnly && formGroupDirty()) {\n <div class=\"save\">\n <button class=\"save-button\" mat-flat-button color=\"warn\" type=\"submit\" [disabled]=\"submitting\">\n <mat-icon>backup</mat-icon>\n <span>Save & publish changes</span>\n </button>\n <button type=\"button\" class=\"revert-button\" mat-stroked-button [disabled]=\"submitting\" (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.</span>\n </div>\n }\n </div>\n }\n </div>\n }\n </form>\n}\n", styles: [".wrapper{margin:1rem 0;padding:0 .5rem}.size-obs .hidden{display:none}.size-obs .visible{display:block}.show-hide a{cursor:pointer;font-size:.8rem}.save{position:sticky;bottom:0;min-height:38px;padding:.5rem 0 .5rem 12px;background-color:var(--page-background-color);display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;z-index:999}.save .save-button{animation:shadow-pulse 1s 3}.save .save-button:disabled{animation:none}.save>*{margin:.3em}.save .revert{margin:0 16px;font-size:14px}.save .yes{margin:0 5px}.error{color:var(--flag-validation-error);padding:5px;font-size:.9em}.error a{color:var(--flag-validation-error);text-decoration:underline}@media(max-width:700px){.save{padding:.5rem 0}}\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: SettingComponent, selector: "app-setting", inputs: ["dashboardBasePath", "productId", "environmentId", "configId", "featureFlagLimitations", "formGroup", "readOnly", "canDeleteSetting", "deleteSettingText", "showEnvironmentName", "segments", "model"], outputs: ["deleteSettingRequested", "subscriptionLimitReached"] }, { 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: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
2881
2893
|
}
|
|
2882
2894
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SettingListComponent, decorators: [{
|
|
2883
2895
|
type: Component,
|
|
2884
|
-
args: [{ selector: "app-setting-list", changeDetection: ChangeDetectionStrategy.Eager, imports: [FormsModule, ReactiveFormsModule, RxReactiveFormsModule, SettingComponent, MatButton, MatIcon], template: "@if (!loading) {\n <form [formGroup]=\"formGroup\" (ngSubmit)=\"submit()\">\n @for (settingValueFromGroup of formGroup!.controls.settingValues.controls; track $index; let i = $index) {\n <div class=\"wrapper\">\n <div class=\"size-obs\" [style.display]=\"'block'\">\n <div>\n <app-setting\n [formGroup]=\"settingValueFromGroup\"\n [readOnly]=\"readOnly\"\n [canDeleteSetting]=\"canDeleteSetting()\"\n [deleteSettingText]=\"deleteSettingText()\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [model]=\"settingValues!.settingValues[i]\"\n [segments]=\"segments\"\n [productId]=\"productId()\"\n [configId]=\"configId()\"\n [environmentId]=\"environmentId()\"\n [dashboardBasePath]=\"dashboardBasePath()\"\n [featureFlagLimitations]=\"settingValues!.featureFlagLimitations\"\n (subscriptionLimitReached)=\"onSubscriptionLimitReached()\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\" />\n </div>\n </div>\n </div>\n }\n @if (!readOnly &&
|
|
2896
|
+
args: [{ selector: "app-setting-list", changeDetection: ChangeDetectionStrategy.Eager, imports: [FormsModule, ReactiveFormsModule, RxReactiveFormsModule, SettingComponent, MatButton, MatIcon], template: "@if (!loading) {\n <form [formGroup]=\"formGroup\" (ngSubmit)=\"submit()\">\n @for (settingValueFromGroup of formGroup!.controls.settingValues.controls; track $index; let i = $index) {\n <div class=\"wrapper\">\n <div class=\"size-obs\" [style.display]=\"'block'\">\n <div>\n <app-setting\n [formGroup]=\"settingValueFromGroup\"\n [readOnly]=\"readOnly\"\n [canDeleteSetting]=\"canDeleteSetting()\"\n [deleteSettingText]=\"deleteSettingText()\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [model]=\"settingValues!.settingValues[i]\"\n [segments]=\"segments\"\n [productId]=\"productId()\"\n [configId]=\"configId()\"\n [environmentId]=\"environmentId()\"\n [dashboardBasePath]=\"dashboardBasePath()\"\n [featureFlagLimitations]=\"settingValues!.featureFlagLimitations\"\n (subscriptionLimitReached)=\"onSubscriptionLimitReached()\"\n (deleteSettingRequested)=\"onDeleteSettingRequested($event)\" />\n </div>\n </div>\n </div>\n }\n @if (!readOnly && formGroupDirty()) {\n <div class=\"save\">\n <button class=\"save-button\" mat-flat-button color=\"warn\" type=\"submit\" [disabled]=\"submitting\">\n <mat-icon>backup</mat-icon>\n <span>Save & publish changes</span>\n </button>\n <button type=\"button\" class=\"revert-button\" mat-stroked-button [disabled]=\"submitting\" (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.</span>\n </div>\n }\n </div>\n }\n </div>\n }\n </form>\n}\n", styles: [".wrapper{margin:1rem 0;padding:0 .5rem}.size-obs .hidden{display:none}.size-obs .visible{display:block}.show-hide a{cursor:pointer;font-size:.8rem}.save{position:sticky;bottom:0;min-height:38px;padding:.5rem 0 .5rem 12px;background-color:var(--page-background-color);display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;z-index:999}.save .save-button{animation:shadow-pulse 1s 3}.save .save-button:disabled{animation:none}.save>*{margin:.3em}.save .revert{margin:0 16px;font-size:14px}.save .yes{margin:0 5px}.error{color:var(--flag-validation-error);padding:5px;font-size:.9em}.error a{color:var(--flag-validation-error);text-decoration:underline}@media(max-width:700px){.save{padding:.5rem 0}}\n"] }]
|
|
2885
2897
|
}], 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 }] }], dashboardBasePath: [{ type: i0.Input, args: [{ isSignal: true, alias: "dashboardBasePath", required: false }] }], canDeleteSetting: [{ type: i0.Input, args: [{ isSignal: true, alias: "canDeleteSetting", required: false }] }], onSave: [{ type: i0.Input, args: [{ isSignal: true, alias: "onSave", required: true }] }], loadSettingValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadSettingValues", required: true }] }], loadSegments: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadSegments", required: true }] }], deleteSettingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "deleteSettingText", required: false }] }], showEnvironmentName: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEnvironmentName", required: false }] }], loadSucceeded: [{ type: i0.Output, args: ["loadSucceeded"] }], deleteSettingRequested: [{ type: i0.Output, args: ["deleteSettingRequested"] }], formValuesChanged: [{ type: i0.Output, args: ["formValuesChanged"] }], saveFailed: [{ type: i0.Output, args: ["saveFailed"] }] } });
|
|
2886
2898
|
|
|
2887
2899
|
class SettingItemComponent extends BaseComponent {
|
|
@@ -3751,6 +3763,22 @@ class CreateChangeRequestDialogComponent {
|
|
|
3751
3763
|
error: (error) => {
|
|
3752
3764
|
this.saving.set(false);
|
|
3753
3765
|
FormHelper.handleErrors(this.formGroup, error);
|
|
3766
|
+
// Concurrent update and concurrent delete common handling
|
|
3767
|
+
if (error instanceof HttpErrorResponse && (error.status === 409 || error.status === 404)) {
|
|
3768
|
+
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
|
3769
|
+
width: "450px",
|
|
3770
|
+
data: {
|
|
3771
|
+
title: "There was a conflict while trying to create your change request",
|
|
3772
|
+
body: "Seems like some of the feature flags or settings were deleted or updated by someone else while you were editing them. Reload the config to see its latest state, apply your changes and try the save again.",
|
|
3773
|
+
yesButtonLabel: "Reload",
|
|
3774
|
+
hideCancelButton: true,
|
|
3775
|
+
},
|
|
3776
|
+
});
|
|
3777
|
+
dialogRef.afterClosed().subscribe(() => {
|
|
3778
|
+
this.dialogRef.close({ shouldReloadSettingValues: true });
|
|
3779
|
+
});
|
|
3780
|
+
return;
|
|
3781
|
+
}
|
|
3754
3782
|
if (error instanceof HttpErrorResponse
|
|
3755
3783
|
&& error.status === 400
|
|
3756
3784
|
&& FormHelper.getHttpErrorResponseMessage(error, "SegmentCondition") === "Segment not found.") {
|
|
@@ -3841,7 +3869,7 @@ class CreateChangeRequestDialogComponent {
|
|
|
3841
3869
|
};
|
|
3842
3870
|
}
|
|
3843
3871
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: CreateChangeRequestDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3844
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: CreateChangeRequestDialogComponent, isStandalone: true, selector: "app-create-change-request-dialog", viewQueries: [{ propertyName: "reasonInput", first: true, predicate: ["reason"], descendants: true, isSignal: true }], ngImport: i0, template: "<div mat-dialog-title cdkDrag cdkDragRootElement=\".cdk-overlay-pane\" cdkDragHandle class=\"draggable title\">\n @if (data.isSchedule) {\n <div>Schedule change request</div>\n } @else {\n <div>Create change request</div>\n }\n</div>\n\n<div mat-dialog-content>\n <form class=\"form\" [formGroup]=\"formGroup\">\n <mat-form-field appearance=\"outline\" class=\"field-name\">\n <mat-label>Title</mat-label>\n <mat-hint>A short name your team will see on the ConfigCat Dashboard.</mat-hint>\n <input matInput formControlName=\"title\" placeholder=\"e.g. Enable dark mode for beta users\" maxlength=\"255\" />\n @if (formGroup.controls.title.invalid) {\n <mat-error>\n A short name your team will see on the ConfigCat Dashboard.\n {{ FormHelper.getErrorMessage(formGroup.controls.title) }}\n </mat-error>\n }\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" class=\"field-reason\" subscriptSizing=\"dynamic\">\n <mat-label>\n Notes\n @if (!data.reasonRequired) {\n <span class=\"optional\">(optional)</span>\n }\n </mat-label>\n <mat-hint>\n This will appear in the Audit Log (in the Notes section when you expand the corresponding entry) upon applying\n the change request.\n </mat-hint>\n <textarea\n #reason\n matInput\n formControlName=\"reason\"\n rows=\"2\"\n maxlength=\"1000\"\n placeholder=\"Why is this change needed?\"></textarea>\n @if (formGroup.controls.reason.invalid) {\n <mat-error>\n Notes are mandatory for the target environment. {{ FormHelper.getErrorMessage(formGroup.controls.reason) }}\n </mat-error>\n }\n </mat-form-field>\n\n @if (data.isSchedule) {\n <div class=\"section\">\n <h3>When should the proposed changes be applied?</h3>\n <div class=\"scheduled\">\n <div class=\"date-selector\">\n <app-date-time-picker [formControl]=\"formGroup.controls.applyAt\" />\n @if (formGroup.controls.applyAt.invalid) {\n @let scheduleErrorMessage = FormHelper.getErrorMessage(formGroup.controls.applyAt);\n @if (scheduleErrorMessage) {\n <mat-error class=\"error\">\n {{ scheduleErrorMessage }}\n </mat-error>\n }\n }\n </div>\n @if (data.environmentApproveRequired && data.canBypassApproval) {\n <div>\n <mat-checkbox\n matInput\n color=\"primary\"\n class=\"bypass-approval-checkbox\"\n formControlName=\"bypassApproval\"\n matTooltip=\"Enabling this option will bypass the approval requirement of the target environment and \n lets the change request be applied on schedule even if it's not approved.\"\n matTooltipPosition=\"below\">\n Bypass approval requirement for scheduled changes\n </mat-checkbox>\n </div>\n }\n <app-box type=\"info\">\n The proposed changes will be applied at the scheduled time.\n <br />\n If conflicting changes occur before the scheduled time, they will prevent applying the scheduled changes.\n <br />\n You can always cancel the scheduled operation before it is executed and apply the changes manually.\n </app-box>\n </div>\n </div>\n }\n </form>\n</div>\n\n<div mat-dialog-actions>\n <button class=\"submit-button\" mat-flat-button type=\"submit\" color=\"success\" [disabled]=\"saving()\" (click)=\"submit()\">\n @if (data.isSchedule) {\n <mat-icon class=\"icon-transform-rotate\">schedule</mat-icon>\n } @else {\n <mat-icon>merge_type</mat-icon>\n }\n <span>{{ submitLabel }}</span>\n </button>\n <button type=\"button\" mat-stroked-button [mat-dialog-close]>Cancel</button>\n</div>\n", styles: [".title{display:flex;justify-content:space-between;align-items:center;gap:16px}.title .sub-title{font-size:13px;font-weight:400;color:var(--panel-description-color)}.form{display:flex;flex-direction:column;gap:10px;margin-top:10px;margin-bottom:10px}.form .field-name,.form .field-reason,.form .field-apply-at{width:100%}.form .optional{font-size:12px;font-weight:400;color:var(--panel-description-color)}h3{font-size:14px;font-weight:500;color:var(--text-color)}.changes-title{display:flex;justify-content:space-between;align-items:center}.error{font-size:10px}.section{margin-top:.8rem}.section .scheduled{display:flex;flex-direction:column;flex-wrap:wrap;gap:12px}.section .scheduled .bypass-approval-checkbox{--mat-checkbox-label-text-size: 12px;--mat-checkbox-label-text-color: var(--panel-description-color);margin-left:-2px}\n"], dependencies: [{ 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]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[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: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { 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: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { 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: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { 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"] }, { kind: "component", type: BoxComponent, selector: "app-box", inputs: ["type", "title"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { 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: DateTimePickerComponent, selector: "app-date-time-picker", inputs: ["dateTooltip", "timeTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3872
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: CreateChangeRequestDialogComponent, isStandalone: true, selector: "app-create-change-request-dialog", viewQueries: [{ propertyName: "reasonInput", first: true, predicate: ["reason"], descendants: true, isSignal: true }], ngImport: i0, template: "<div mat-dialog-title cdkDrag cdkDragRootElement=\".cdk-overlay-pane\" cdkDragHandle class=\"draggable title\">\n @if (data.isSchedule) {\n <div>Schedule change request</div>\n } @else {\n <div>Create change request</div>\n }\n</div>\n\n<div mat-dialog-content>\n <form class=\"form\" [formGroup]=\"formGroup\">\n <mat-form-field appearance=\"outline\" class=\"field-name\">\n <mat-label>Title</mat-label>\n <mat-hint>A short name your team will see on the ConfigCat Dashboard.</mat-hint>\n <input matInput formControlName=\"title\" placeholder=\"e.g. Enable dark mode for beta users\" maxlength=\"255\" />\n @if (formGroup.controls.title.invalid) {\n <mat-error>\n A short name your team will see on the ConfigCat Dashboard.\n {{ FormHelper.getErrorMessage(formGroup.controls.title) }}\n </mat-error>\n }\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" class=\"field-reason\" subscriptSizing=\"dynamic\">\n <mat-label>\n Notes\n @if (!data.reasonRequired) {\n <span class=\"optional\">(optional)</span>\n }\n </mat-label>\n <mat-hint>\n This will appear in the Audit Log (in the Notes section when you expand the corresponding entry) upon applying\n the change request.\n </mat-hint>\n <textarea\n #reason\n matInput\n formControlName=\"reason\"\n rows=\"2\"\n maxlength=\"1000\"\n placeholder=\"Why is this change needed?\"></textarea>\n @if (formGroup.controls.reason.invalid) {\n <mat-error>\n Notes are mandatory for the target environment. {{ FormHelper.getErrorMessage(formGroup.controls.reason) }}\n </mat-error>\n }\n </mat-form-field>\n\n @if (data.isSchedule) {\n <div class=\"section\">\n <h3>When should the proposed changes be applied?</h3>\n <div class=\"scheduled\">\n <div class=\"date-selector\">\n <app-date-time-picker [formControl]=\"formGroup.controls.applyAt\" />\n @if (formGroup.controls.applyAt.invalid) {\n @let scheduleErrorMessage = FormHelper.getErrorMessage(formGroup.controls.applyAt);\n @if (scheduleErrorMessage) {\n <mat-error class=\"error\">\n {{ scheduleErrorMessage }}\n </mat-error>\n }\n }\n </div>\n @if (data.environmentApproveRequired && data.canBypassApproval) {\n <div>\n <mat-checkbox\n matInput\n color=\"primary\"\n class=\"bypass-approval-checkbox\"\n formControlName=\"bypassApproval\"\n matTooltip=\"Enabling this option will bypass the approval requirement of the target environment and \n lets the change request be applied on schedule even if it's not approved.\"\n matTooltipPosition=\"below\">\n Bypass approval requirement for scheduled changes\n </mat-checkbox>\n </div>\n }\n <app-box type=\"info\">\n The proposed changes will be applied at the scheduled time.\n <br />\n If conflicting changes occur before the scheduled time, they will prevent applying the scheduled changes.\n <br />\n You can always cancel the scheduled operation before it is executed and apply the changes manually.\n </app-box>\n </div>\n </div>\n }\n @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <mat-error>\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\n </mat-error>\n }\n </form>\n</div>\n\n<div mat-dialog-actions>\n <button class=\"submit-button\" mat-flat-button type=\"submit\" color=\"success\" [disabled]=\"saving()\" (click)=\"submit()\">\n @if (data.isSchedule) {\n <mat-icon class=\"icon-transform-rotate\">schedule</mat-icon>\n } @else {\n <mat-icon>merge_type</mat-icon>\n }\n <span>{{ submitLabel }}</span>\n </button>\n <button type=\"button\" mat-stroked-button [mat-dialog-close]>Cancel</button>\n</div>\n", styles: [".title{display:flex;justify-content:space-between;align-items:center;gap:16px}.title .sub-title{font-size:13px;font-weight:400;color:var(--panel-description-color)}.form{display:flex;flex-direction:column;gap:10px;margin-top:10px;margin-bottom:10px}.form .field-name,.form .field-reason,.form .field-apply-at{width:100%}.form .optional{font-size:12px;font-weight:400;color:var(--panel-description-color)}h3{font-size:14px;font-weight:500;color:var(--text-color)}.changes-title{display:flex;justify-content:space-between;align-items:center}.error{font-size:10px;color:var(--flag-validation-error)}.section{margin-top:.8rem}.section .scheduled{display:flex;flex-direction:column;flex-wrap:wrap;gap:12px}.section .scheduled .bypass-approval-checkbox{--mat-checkbox-label-text-size: 12px;--mat-checkbox-label-text-color: var(--panel-description-color);margin-left:-2px}\n"], dependencies: [{ 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]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[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: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { 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: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { 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: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { 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"] }, { kind: "component", type: BoxComponent, selector: "app-box", inputs: ["type", "title"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { 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: DateTimePickerComponent, selector: "app-date-time-picker", inputs: ["dateTooltip", "timeTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3845
3873
|
}
|
|
3846
3874
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: CreateChangeRequestDialogComponent, decorators: [{
|
|
3847
3875
|
type: Component,
|
|
@@ -3865,7 +3893,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImpor
|
|
|
3865
3893
|
CdkDrag,
|
|
3866
3894
|
CdkDragHandle,
|
|
3867
3895
|
DateTimePickerComponent,
|
|
3868
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div mat-dialog-title cdkDrag cdkDragRootElement=\".cdk-overlay-pane\" cdkDragHandle class=\"draggable title\">\n @if (data.isSchedule) {\n <div>Schedule change request</div>\n } @else {\n <div>Create change request</div>\n }\n</div>\n\n<div mat-dialog-content>\n <form class=\"form\" [formGroup]=\"formGroup\">\n <mat-form-field appearance=\"outline\" class=\"field-name\">\n <mat-label>Title</mat-label>\n <mat-hint>A short name your team will see on the ConfigCat Dashboard.</mat-hint>\n <input matInput formControlName=\"title\" placeholder=\"e.g. Enable dark mode for beta users\" maxlength=\"255\" />\n @if (formGroup.controls.title.invalid) {\n <mat-error>\n A short name your team will see on the ConfigCat Dashboard.\n {{ FormHelper.getErrorMessage(formGroup.controls.title) }}\n </mat-error>\n }\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" class=\"field-reason\" subscriptSizing=\"dynamic\">\n <mat-label>\n Notes\n @if (!data.reasonRequired) {\n <span class=\"optional\">(optional)</span>\n }\n </mat-label>\n <mat-hint>\n This will appear in the Audit Log (in the Notes section when you expand the corresponding entry) upon applying\n the change request.\n </mat-hint>\n <textarea\n #reason\n matInput\n formControlName=\"reason\"\n rows=\"2\"\n maxlength=\"1000\"\n placeholder=\"Why is this change needed?\"></textarea>\n @if (formGroup.controls.reason.invalid) {\n <mat-error>\n Notes are mandatory for the target environment. {{ FormHelper.getErrorMessage(formGroup.controls.reason) }}\n </mat-error>\n }\n </mat-form-field>\n\n @if (data.isSchedule) {\n <div class=\"section\">\n <h3>When should the proposed changes be applied?</h3>\n <div class=\"scheduled\">\n <div class=\"date-selector\">\n <app-date-time-picker [formControl]=\"formGroup.controls.applyAt\" />\n @if (formGroup.controls.applyAt.invalid) {\n @let scheduleErrorMessage = FormHelper.getErrorMessage(formGroup.controls.applyAt);\n @if (scheduleErrorMessage) {\n <mat-error class=\"error\">\n {{ scheduleErrorMessage }}\n </mat-error>\n }\n }\n </div>\n @if (data.environmentApproveRequired && data.canBypassApproval) {\n <div>\n <mat-checkbox\n matInput\n color=\"primary\"\n class=\"bypass-approval-checkbox\"\n formControlName=\"bypassApproval\"\n matTooltip=\"Enabling this option will bypass the approval requirement of the target environment and \n lets the change request be applied on schedule even if it's not approved.\"\n matTooltipPosition=\"below\">\n Bypass approval requirement for scheduled changes\n </mat-checkbox>\n </div>\n }\n <app-box type=\"info\">\n The proposed changes will be applied at the scheduled time.\n <br />\n If conflicting changes occur before the scheduled time, they will prevent applying the scheduled changes.\n <br />\n You can always cancel the scheduled operation before it is executed and apply the changes manually.\n </app-box>\n </div>\n </div>\n }\n </form>\n</div>\n\n<div mat-dialog-actions>\n <button class=\"submit-button\" mat-flat-button type=\"submit\" color=\"success\" [disabled]=\"saving()\" (click)=\"submit()\">\n @if (data.isSchedule) {\n <mat-icon class=\"icon-transform-rotate\">schedule</mat-icon>\n } @else {\n <mat-icon>merge_type</mat-icon>\n }\n <span>{{ submitLabel }}</span>\n </button>\n <button type=\"button\" mat-stroked-button [mat-dialog-close]>Cancel</button>\n</div>\n", styles: [".title{display:flex;justify-content:space-between;align-items:center;gap:16px}.title .sub-title{font-size:13px;font-weight:400;color:var(--panel-description-color)}.form{display:flex;flex-direction:column;gap:10px;margin-top:10px;margin-bottom:10px}.form .field-name,.form .field-reason,.form .field-apply-at{width:100%}.form .optional{font-size:12px;font-weight:400;color:var(--panel-description-color)}h3{font-size:14px;font-weight:500;color:var(--text-color)}.changes-title{display:flex;justify-content:space-between;align-items:center}.error{font-size:10px}.section{margin-top:.8rem}.section .scheduled{display:flex;flex-direction:column;flex-wrap:wrap;gap:12px}.section .scheduled .bypass-approval-checkbox{--mat-checkbox-label-text-size: 12px;--mat-checkbox-label-text-color: var(--panel-description-color);margin-left:-2px}\n"] }]
|
|
3896
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div mat-dialog-title cdkDrag cdkDragRootElement=\".cdk-overlay-pane\" cdkDragHandle class=\"draggable title\">\n @if (data.isSchedule) {\n <div>Schedule change request</div>\n } @else {\n <div>Create change request</div>\n }\n</div>\n\n<div mat-dialog-content>\n <form class=\"form\" [formGroup]=\"formGroup\">\n <mat-form-field appearance=\"outline\" class=\"field-name\">\n <mat-label>Title</mat-label>\n <mat-hint>A short name your team will see on the ConfigCat Dashboard.</mat-hint>\n <input matInput formControlName=\"title\" placeholder=\"e.g. Enable dark mode for beta users\" maxlength=\"255\" />\n @if (formGroup.controls.title.invalid) {\n <mat-error>\n A short name your team will see on the ConfigCat Dashboard.\n {{ FormHelper.getErrorMessage(formGroup.controls.title) }}\n </mat-error>\n }\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" class=\"field-reason\" subscriptSizing=\"dynamic\">\n <mat-label>\n Notes\n @if (!data.reasonRequired) {\n <span class=\"optional\">(optional)</span>\n }\n </mat-label>\n <mat-hint>\n This will appear in the Audit Log (in the Notes section when you expand the corresponding entry) upon applying\n the change request.\n </mat-hint>\n <textarea\n #reason\n matInput\n formControlName=\"reason\"\n rows=\"2\"\n maxlength=\"1000\"\n placeholder=\"Why is this change needed?\"></textarea>\n @if (formGroup.controls.reason.invalid) {\n <mat-error>\n Notes are mandatory for the target environment. {{ FormHelper.getErrorMessage(formGroup.controls.reason) }}\n </mat-error>\n }\n </mat-form-field>\n\n @if (data.isSchedule) {\n <div class=\"section\">\n <h3>When should the proposed changes be applied?</h3>\n <div class=\"scheduled\">\n <div class=\"date-selector\">\n <app-date-time-picker [formControl]=\"formGroup.controls.applyAt\" />\n @if (formGroup.controls.applyAt.invalid) {\n @let scheduleErrorMessage = FormHelper.getErrorMessage(formGroup.controls.applyAt);\n @if (scheduleErrorMessage) {\n <mat-error class=\"error\">\n {{ scheduleErrorMessage }}\n </mat-error>\n }\n }\n </div>\n @if (data.environmentApproveRequired && data.canBypassApproval) {\n <div>\n <mat-checkbox\n matInput\n color=\"primary\"\n class=\"bypass-approval-checkbox\"\n formControlName=\"bypassApproval\"\n matTooltip=\"Enabling this option will bypass the approval requirement of the target environment and \n lets the change request be applied on schedule even if it's not approved.\"\n matTooltipPosition=\"below\">\n Bypass approval requirement for scheduled changes\n </mat-checkbox>\n </div>\n }\n <app-box type=\"info\">\n The proposed changes will be applied at the scheduled time.\n <br />\n If conflicting changes occur before the scheduled time, they will prevent applying the scheduled changes.\n <br />\n You can always cancel the scheduled operation before it is executed and apply the changes manually.\n </app-box>\n </div>\n </div>\n }\n @if (formGroup.errors && formGroup.errors[\"serverSide\"]) {\n <mat-error>\n <span>{{ formGroup.errors[\"serverSide\"] }}</span>\n </mat-error>\n }\n </form>\n</div>\n\n<div mat-dialog-actions>\n <button class=\"submit-button\" mat-flat-button type=\"submit\" color=\"success\" [disabled]=\"saving()\" (click)=\"submit()\">\n @if (data.isSchedule) {\n <mat-icon class=\"icon-transform-rotate\">schedule</mat-icon>\n } @else {\n <mat-icon>merge_type</mat-icon>\n }\n <span>{{ submitLabel }}</span>\n </button>\n <button type=\"button\" mat-stroked-button [mat-dialog-close]>Cancel</button>\n</div>\n", styles: [".title{display:flex;justify-content:space-between;align-items:center;gap:16px}.title .sub-title{font-size:13px;font-weight:400;color:var(--panel-description-color)}.form{display:flex;flex-direction:column;gap:10px;margin-top:10px;margin-bottom:10px}.form .field-name,.form .field-reason,.form .field-apply-at{width:100%}.form .optional{font-size:12px;font-weight:400;color:var(--panel-description-color)}h3{font-size:14px;font-weight:500;color:var(--text-color)}.changes-title{display:flex;justify-content:space-between;align-items:center}.error{font-size:10px;color:var(--flag-validation-error)}.section{margin-top:.8rem}.section .scheduled{display:flex;flex-direction:column;flex-wrap:wrap;gap:12px}.section .scheduled .bypass-approval-checkbox{--mat-checkbox-label-text-size: 12px;--mat-checkbox-label-text-color: var(--panel-description-color);margin-left:-2px}\n"] }]
|
|
3869
3897
|
}], propDecorators: { reasonInput: [{ type: i0.ViewChild, args: ["reason", { isSignal: true }] }] } });
|
|
3870
3898
|
|
|
3871
3899
|
class CopyableValueComponent {
|
|
@@ -6985,6 +7013,14 @@ class FeatureFlagItemComponent extends BaseComponent {
|
|
|
6985
7013
|
this.showFeedBackMessage = false;
|
|
6986
7014
|
this.hasSettingValues = false;
|
|
6987
7015
|
this.hasOtherEnvironment = false;
|
|
7016
|
+
// Track actual value changes, not just form interaction. If a value is modified then reverted to its original state,
|
|
7017
|
+
// it's not considered dirty. This ensures save/publish buttons activate only for genuine changes, avoiding unnecessary backend operations.
|
|
7018
|
+
this.initialValueJson = signal("", /* @ts-ignore */
|
|
7019
|
+
...(ngDevMode ? [{ debugName: "initialValueJson" }] : /* istanbul ignore next */ []));
|
|
7020
|
+
this.settingValueFormGroupChanged = signal("", /* @ts-ignore */
|
|
7021
|
+
...(ngDevMode ? [{ debugName: "settingValueFormGroupChanged" }] : /* istanbul ignore next */ []));
|
|
7022
|
+
this.formGroupDirty = computed(() => this.settingValueFormGroupChanged() !== this.initialValueJson(), /* @ts-ignore */
|
|
7023
|
+
...(ngDevMode ? [{ debugName: "formGroupDirty" }] : /* istanbul ignore next */ []));
|
|
6988
7024
|
this.comparisonAttributes = computed(() => {
|
|
6989
7025
|
const settingFormula = this.settingFormula();
|
|
6990
7026
|
if (this.loading || !settingFormula)
|
|
@@ -7054,8 +7090,12 @@ class FeatureFlagItemComponent extends BaseComponent {
|
|
|
7054
7090
|
};
|
|
7055
7091
|
this.unsubscribeFormValueChangesSubscription();
|
|
7056
7092
|
this.createFormGroupFromState(model);
|
|
7093
|
+
const initialValueRaw = JSON.stringify(this.formGroup.getRawValue());
|
|
7094
|
+
this.initialValueJson.set(initialValueRaw);
|
|
7095
|
+
this.settingValueFormGroupChanged.set(initialValueRaw);
|
|
7057
7096
|
this.formValueChangesSubscription = this.formGroup.valueChanges.subscribe(() => {
|
|
7058
7097
|
this.formValuesChanged.emit();
|
|
7098
|
+
this.settingValueFormGroupChanged.set(JSON.stringify(this.formGroup.getRawValue()));
|
|
7059
7099
|
});
|
|
7060
7100
|
this.recalcAddButtons();
|
|
7061
7101
|
this.recalcPrerequisites();
|
|
@@ -7214,6 +7254,9 @@ class FeatureFlagItemComponent extends BaseComponent {
|
|
|
7214
7254
|
this.messagingService.showSuccessSnack("Change request created successfully.", 5000);
|
|
7215
7255
|
this.reloadSettingValues();
|
|
7216
7256
|
}
|
|
7257
|
+
else if (result?.shouldReloadSettingValues) {
|
|
7258
|
+
this.reloadSettingValues();
|
|
7259
|
+
}
|
|
7217
7260
|
});
|
|
7218
7261
|
}
|
|
7219
7262
|
updateSettingValues(updateModel, bypassApproval, reason, latestVersionId) {
|
|
@@ -7524,7 +7567,7 @@ class FeatureFlagItemComponent extends BaseComponent {
|
|
|
7524
7567
|
});
|
|
7525
7568
|
}
|
|
7526
7569
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: FeatureFlagItemComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
7527
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", 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 }, customize: { classPropertyName: "customize", publicName: "customize", 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: "@let settingFormulaValue = settingFormula();\n<div class=\"container\">\n @if (!loading && settingFormulaValue) {\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 [comparisonAttributes]=\"comparisonAttributes()\"\n [featureFlagLimitations]=\"settingFormulaValue.featureFlagLimitations\"\n [hasOtherEnvironment]=\"false\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [environmentName]=\"settingFormulaValue.environment.name\"\n [canDeleteSetting]=\"canDeleteSetting()\"\n [predefinedVariationsEnabled]=\"true\"\n [dashboardBasePath]=\"dashboardBasePath\"\n [customize]=\"customize()\"\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 (!settingFormulaValue.readOnly && formGroup!.dirty) {\n <div class=\"save\">\n <div class=\"save-button-group\">\n @if (!settingFormulaValue.approveRequired) {\n <button\n class=\"save-button right-side-flat\"\n mat-flat-button\n color=\"warn\"\n type=\"submit\"\n [disabled]=\"submitting\">\n <mat-icon>backup</mat-icon>\n <span>Save & publish changes</span>\n </button>\n <button\n class=\"save-button-dropdown\"\n mat-flat-button\n color=\"warn\"\n type=\"button\"\n [disabled]=\"submitting\"\n [matMenuTriggerFor]=\"proposeMenu\">\n <mat-icon>arrow_drop_down</mat-icon>\n </button>\n <mat-menu #proposeMenu=\"matMenu\" xPosition=\"before\">\n <button type=\"button\" mat-menu-item (click)=\"createChangeRequest(false)\">\n <mat-icon>call_merge</mat-icon>\n <span>Propose changes</span>\n </button>\n <button type=\"button\" mat-menu-item (click)=\"createChangeRequest(true)\">\n <mat-icon class=\"icon-transform-rotate\">schedule</mat-icon>\n <span>Schedule changes</span>\n </button>\n </mat-menu>\n } @else {\n <button\n class=\"save-button right-side-flat\"\n mat-flat-button\n type=\"button\"\n color=\"success\"\n [disabled]=\"submitting\"\n (click)=\"createChangeRequest(false)\">\n <mat-icon>call_merge</mat-icon>\n <span>Propose changes</span>\n </button>\n <button\n class=\"save-button-dropdown\"\n mat-flat-button\n color=\"success\"\n type=\"button\"\n [disabled]=\"submitting\"\n [matMenuTriggerFor]=\"proposeMenu\">\n <mat-icon>arrow_drop_down</mat-icon>\n </button>\n <mat-menu #proposeMenu=\"matMenu\" xPosition=\"before\" class=\"full-width-menu\">\n <button type=\"button\" mat-menu-item (click)=\"createChangeRequest(true)\">\n <mat-icon class=\"icon-transform-rotate\">schedule</mat-icon>\n <span>Schedule changes</span>\n </button>\n @if (settingFormulaValue.canBypassApproval) {\n <button type=\"button\" mat-menu-item (click)=\"submit(true)\">\n <mat-icon>backup</mat-icon>\n <span>Save & publish without approval</span>\n </button>\n }\n </mat-menu>\n }\n </div>\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. </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}.container .save .save-button:disabled{animation:none}.container .save .save-button-group{display:flex;align-items:stretch}.container .save .save-button-group .save-button.right-side-flat{border-top-right-radius:0;border-bottom-right-radius:0}.container .save .save-button-group .save-button-dropdown{border-top-left-radius:0;border-bottom-left-radius:0;min-width:unset;height:38px;padding:0 12px;border-left:1px var(--save-separator-color) solid}.container .save .save-button-group .save-button-dropdown .mat-icon{margin-right:0;margin-left:0}.container .save .save-button-group .save-button-dropdown:disabled{border-left-color:var(--save-separator-disabled-color)}.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", "canDeleteSetting", "predefinedVariationsEnabled", "dashboardBasePath", "comparisonAttributes", "customize"], 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"] }, { kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
7570
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", 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 }, customize: { classPropertyName: "customize", publicName: "customize", 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: "@let settingFormulaValue = settingFormula();\n<div class=\"container\">\n @if (!loading && settingFormulaValue) {\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 [comparisonAttributes]=\"comparisonAttributes()\"\n [featureFlagLimitations]=\"settingFormulaValue.featureFlagLimitations\"\n [hasOtherEnvironment]=\"false\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [environmentName]=\"settingFormulaValue.environment.name\"\n [canDeleteSetting]=\"canDeleteSetting()\"\n [predefinedVariationsEnabled]=\"true\"\n [dashboardBasePath]=\"dashboardBasePath\"\n [customize]=\"customize()\"\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 (!settingFormulaValue.readOnly && formGroupDirty()) {\n <div class=\"save\">\n <div class=\"save-button-group\">\n @if (!settingFormulaValue.approveRequired) {\n <button\n class=\"save-button right-side-flat\"\n mat-flat-button\n color=\"warn\"\n type=\"submit\"\n [disabled]=\"submitting\">\n <mat-icon>backup</mat-icon>\n <span>Save & publish changes</span>\n </button>\n <button\n class=\"save-button-dropdown\"\n mat-flat-button\n color=\"warn\"\n type=\"button\"\n [disabled]=\"submitting\"\n [matMenuTriggerFor]=\"proposeMenu\">\n <mat-icon>arrow_drop_down</mat-icon>\n </button>\n <mat-menu #proposeMenu=\"matMenu\" xPosition=\"before\">\n <button type=\"button\" mat-menu-item (click)=\"createChangeRequest(false)\">\n <mat-icon>call_merge</mat-icon>\n <span>Propose changes</span>\n </button>\n <button type=\"button\" mat-menu-item (click)=\"createChangeRequest(true)\">\n <mat-icon class=\"icon-transform-rotate\">schedule</mat-icon>\n <span>Schedule changes</span>\n </button>\n </mat-menu>\n } @else {\n <button\n class=\"save-button right-side-flat\"\n mat-flat-button\n type=\"button\"\n color=\"success\"\n [disabled]=\"submitting\"\n (click)=\"createChangeRequest(false)\">\n <mat-icon>call_merge</mat-icon>\n <span>Propose changes</span>\n </button>\n <button\n class=\"save-button-dropdown\"\n mat-flat-button\n color=\"success\"\n type=\"button\"\n [disabled]=\"submitting\"\n [matMenuTriggerFor]=\"proposeMenu\">\n <mat-icon>arrow_drop_down</mat-icon>\n </button>\n <mat-menu #proposeMenu=\"matMenu\" xPosition=\"before\" class=\"full-width-menu\">\n <button type=\"button\" mat-menu-item (click)=\"createChangeRequest(true)\">\n <mat-icon class=\"icon-transform-rotate\">schedule</mat-icon>\n <span>Schedule changes</span>\n </button>\n @if (settingFormulaValue.canBypassApproval) {\n <button type=\"button\" mat-menu-item (click)=\"submit(true)\">\n <mat-icon>backup</mat-icon>\n <span>Save & publish without approval</span>\n </button>\n }\n </mat-menu>\n }\n </div>\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. </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}.container .save .save-button:disabled{animation:none}.container .save .save-button-group{display:flex;align-items:stretch}.container .save .save-button-group .save-button.right-side-flat{border-top-right-radius:0;border-bottom-right-radius:0}.container .save .save-button-group .save-button-dropdown{border-top-left-radius:0;border-bottom-left-radius:0;min-width:unset;height:38px;padding:0 12px;border-left:1px var(--save-separator-color) solid}.container .save .save-button-group .save-button-dropdown .mat-icon{margin-right:0;margin-left:0}.container .save .save-button-group .save-button-dropdown:disabled{border-left-color:var(--save-separator-disabled-color)}.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", "canDeleteSetting", "predefinedVariationsEnabled", "dashboardBasePath", "comparisonAttributes", "customize"], 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"] }, { kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
7528
7571
|
}
|
|
7529
7572
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: FeatureFlagItemComponent, decorators: [{
|
|
7530
7573
|
type: Component,
|
|
@@ -7540,7 +7583,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImpor
|
|
|
7540
7583
|
MatMenu,
|
|
7541
7584
|
MatMenuItem,
|
|
7542
7585
|
MatMenuTrigger,
|
|
7543
|
-
], template: "@let settingFormulaValue = settingFormula();\n<div class=\"container\">\n @if (!loading && settingFormulaValue) {\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 [comparisonAttributes]=\"comparisonAttributes()\"\n [featureFlagLimitations]=\"settingFormulaValue.featureFlagLimitations\"\n [hasOtherEnvironment]=\"false\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [environmentName]=\"settingFormulaValue.environment.name\"\n [canDeleteSetting]=\"canDeleteSetting()\"\n [predefinedVariationsEnabled]=\"true\"\n [dashboardBasePath]=\"dashboardBasePath\"\n [customize]=\"customize()\"\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 (!settingFormulaValue.readOnly && formGroup!.dirty) {\n <div class=\"save\">\n <div class=\"save-button-group\">\n @if (!settingFormulaValue.approveRequired) {\n <button\n class=\"save-button right-side-flat\"\n mat-flat-button\n color=\"warn\"\n type=\"submit\"\n [disabled]=\"submitting\">\n <mat-icon>backup</mat-icon>\n <span>Save & publish changes</span>\n </button>\n <button\n class=\"save-button-dropdown\"\n mat-flat-button\n color=\"warn\"\n type=\"button\"\n [disabled]=\"submitting\"\n [matMenuTriggerFor]=\"proposeMenu\">\n <mat-icon>arrow_drop_down</mat-icon>\n </button>\n <mat-menu #proposeMenu=\"matMenu\" xPosition=\"before\">\n <button type=\"button\" mat-menu-item (click)=\"createChangeRequest(false)\">\n <mat-icon>call_merge</mat-icon>\n <span>Propose changes</span>\n </button>\n <button type=\"button\" mat-menu-item (click)=\"createChangeRequest(true)\">\n <mat-icon class=\"icon-transform-rotate\">schedule</mat-icon>\n <span>Schedule changes</span>\n </button>\n </mat-menu>\n } @else {\n <button\n class=\"save-button right-side-flat\"\n mat-flat-button\n type=\"button\"\n color=\"success\"\n [disabled]=\"submitting\"\n (click)=\"createChangeRequest(false)\">\n <mat-icon>call_merge</mat-icon>\n <span>Propose changes</span>\n </button>\n <button\n class=\"save-button-dropdown\"\n mat-flat-button\n color=\"success\"\n type=\"button\"\n [disabled]=\"submitting\"\n [matMenuTriggerFor]=\"proposeMenu\">\n <mat-icon>arrow_drop_down</mat-icon>\n </button>\n <mat-menu #proposeMenu=\"matMenu\" xPosition=\"before\" class=\"full-width-menu\">\n <button type=\"button\" mat-menu-item (click)=\"createChangeRequest(true)\">\n <mat-icon class=\"icon-transform-rotate\">schedule</mat-icon>\n <span>Schedule changes</span>\n </button>\n @if (settingFormulaValue.canBypassApproval) {\n <button type=\"button\" mat-menu-item (click)=\"submit(true)\">\n <mat-icon>backup</mat-icon>\n <span>Save & publish without approval</span>\n </button>\n }\n </mat-menu>\n }\n </div>\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. </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}.container .save .save-button:disabled{animation:none}.container .save .save-button-group{display:flex;align-items:stretch}.container .save .save-button-group .save-button.right-side-flat{border-top-right-radius:0;border-bottom-right-radius:0}.container .save .save-button-group .save-button-dropdown{border-top-left-radius:0;border-bottom-left-radius:0;min-width:unset;height:38px;padding:0 12px;border-left:1px var(--save-separator-color) solid}.container .save .save-button-group .save-button-dropdown .mat-icon{margin-right:0;margin-left:0}.container .save .save-button-group .save-button-dropdown:disabled{border-left-color:var(--save-separator-disabled-color)}.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"] }]
|
|
7586
|
+
], template: "@let settingFormulaValue = settingFormula();\n<div class=\"container\">\n @if (!loading && settingFormulaValue) {\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 [comparisonAttributes]=\"comparisonAttributes()\"\n [featureFlagLimitations]=\"settingFormulaValue.featureFlagLimitations\"\n [hasOtherEnvironment]=\"false\"\n [showEnvironmentName]=\"showEnvironmentName()\"\n [environmentName]=\"settingFormulaValue.environment.name\"\n [canDeleteSetting]=\"canDeleteSetting()\"\n [predefinedVariationsEnabled]=\"true\"\n [dashboardBasePath]=\"dashboardBasePath\"\n [customize]=\"customize()\"\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 (!settingFormulaValue.readOnly && formGroupDirty()) {\n <div class=\"save\">\n <div class=\"save-button-group\">\n @if (!settingFormulaValue.approveRequired) {\n <button\n class=\"save-button right-side-flat\"\n mat-flat-button\n color=\"warn\"\n type=\"submit\"\n [disabled]=\"submitting\">\n <mat-icon>backup</mat-icon>\n <span>Save & publish changes</span>\n </button>\n <button\n class=\"save-button-dropdown\"\n mat-flat-button\n color=\"warn\"\n type=\"button\"\n [disabled]=\"submitting\"\n [matMenuTriggerFor]=\"proposeMenu\">\n <mat-icon>arrow_drop_down</mat-icon>\n </button>\n <mat-menu #proposeMenu=\"matMenu\" xPosition=\"before\">\n <button type=\"button\" mat-menu-item (click)=\"createChangeRequest(false)\">\n <mat-icon>call_merge</mat-icon>\n <span>Propose changes</span>\n </button>\n <button type=\"button\" mat-menu-item (click)=\"createChangeRequest(true)\">\n <mat-icon class=\"icon-transform-rotate\">schedule</mat-icon>\n <span>Schedule changes</span>\n </button>\n </mat-menu>\n } @else {\n <button\n class=\"save-button right-side-flat\"\n mat-flat-button\n type=\"button\"\n color=\"success\"\n [disabled]=\"submitting\"\n (click)=\"createChangeRequest(false)\">\n <mat-icon>call_merge</mat-icon>\n <span>Propose changes</span>\n </button>\n <button\n class=\"save-button-dropdown\"\n mat-flat-button\n color=\"success\"\n type=\"button\"\n [disabled]=\"submitting\"\n [matMenuTriggerFor]=\"proposeMenu\">\n <mat-icon>arrow_drop_down</mat-icon>\n </button>\n <mat-menu #proposeMenu=\"matMenu\" xPosition=\"before\" class=\"full-width-menu\">\n <button type=\"button\" mat-menu-item (click)=\"createChangeRequest(true)\">\n <mat-icon class=\"icon-transform-rotate\">schedule</mat-icon>\n <span>Schedule changes</span>\n </button>\n @if (settingFormulaValue.canBypassApproval) {\n <button type=\"button\" mat-menu-item (click)=\"submit(true)\">\n <mat-icon>backup</mat-icon>\n <span>Save & publish without approval</span>\n </button>\n }\n </mat-menu>\n }\n </div>\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. </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}.container .save .save-button:disabled{animation:none}.container .save .save-button-group{display:flex;align-items:stretch}.container .save .save-button-group .save-button.right-side-flat{border-top-right-radius:0;border-bottom-right-radius:0}.container .save .save-button-group .save-button-dropdown{border-top-left-radius:0;border-bottom-left-radius:0;min-width:unset;height:38px;padding:0 12px;border-left:1px var(--save-separator-color) solid}.container .save .save-button-group .save-button-dropdown .mat-icon{margin-right:0;margin-left:0}.container .save .save-button-group .save-button-dropdown:disabled{border-left-color:var(--save-separator-disabled-color)}.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"] }]
|
|
7544
7587
|
}], 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 }] }], customize: [{ type: i0.Input, args: [{ isSignal: true, alias: "customize", 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"] }] } });
|
|
7545
7588
|
|
|
7546
7589
|
const DEFAULT_CUSTOMIZE_LINK_FEATURE_FLAG = {
|