diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 41f28c14d6..b028007283 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -20,9 +20,11 @@ "@angular/platform-browser-dynamic": "^17.1.2", "@angular/router": "^17.1.2", "@danielmoncada/angular-datetime-picker": "^17.0.0", + "@ngrx/component-store": "^17.2.0", "@ngrx/effects": "^17.1.0", "@ngrx/entity": "^17.1.0", "@ngrx/router-store": "^17.1.0", + "@ngrx/signals": "^17.2.0", "@ngrx/store": "^17.1.0", "@ngrx/store-devtools": "^17.1.0", "@ngx-translate/core": "^15.0.0", @@ -41,6 +43,7 @@ "lodash.isequal": "^4.5.0", "ngx-skeleton-loader": "^9.0.0", "rxjs": "7.8.1", + "signals": "^1.0.0", "tslib": "^2.6.2", "uuid": "^9.0.1", "zone.js": "^0.14.3" @@ -4159,6 +4162,20 @@ "tslib": "^2.1.0" } }, + "node_modules/@ngrx/component-store": { + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/@ngrx/component-store/-/component-store-17.2.0.tgz", + "integrity": "sha512-ywhyoZpkbVIY1t5zf7xfWLGkY0A/fQdMjPehHloDI6bRLrmbllBhQRazwZ+FAGIi2myx1+mGcmAc6FbtIikedA==", + "license": "MIT", + "dependencies": { + "@ngrx/operators": "17.0.0-beta.0", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/core": "^17.0.0", + "rxjs": "^6.5.3 || ^7.5.0" + } + }, "node_modules/@ngrx/effects": { "version": "17.2.0", "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-17.2.0.tgz", @@ -4212,6 +4229,24 @@ "rxjs": "^6.5.3 || ^7.5.0" } }, + "node_modules/@ngrx/signals": { + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/@ngrx/signals/-/signals-17.2.0.tgz", + "integrity": "sha512-tkkxifeOVPOhpTqbHyK1WOx4qz49HLR/h0vhaa/MRGRIZoOR/6gR4KB3hbC8FD3FdnuNqOgOZ2lGsTfWPB/6BQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/core": "^17.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + }, + "peerDependenciesMeta": { + "rxjs": { + "optional": true + } + } + }, "node_modules/@ngrx/store": { "version": "17.2.0", "resolved": "https://registry.npmjs.org/@ngrx/store/-/store-17.2.0.tgz", @@ -15796,6 +15831,11 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/signals": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/signals/-/signals-1.0.0.tgz", + "integrity": "sha512-dE3lBiqgrgIvpGHYBy6/kiYKfh0HXRmbg0ocakBKiOefbal6ZeTtNlQlxsu9ADkNzv5OmRwRKu+IaTPSqJdZDg==" + }, "node_modules/sigstore": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.3.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index a867a36f26..f6f549dcbb 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -48,9 +48,11 @@ "@angular/platform-browser-dynamic": "^17.1.2", "@angular/router": "^17.1.2", "@danielmoncada/angular-datetime-picker": "^17.0.0", + "@ngrx/component-store": "^17.2.0", "@ngrx/effects": "^17.1.0", "@ngrx/entity": "^17.1.0", "@ngrx/router-store": "^17.1.0", + "@ngrx/signals": "^17.2.0", "@ngrx/store": "^17.1.0", "@ngrx/store-devtools": "^17.1.0", "@ngx-translate/core": "^15.0.0", @@ -69,6 +71,7 @@ "lodash.isequal": "^4.5.0", "ngx-skeleton-loader": "^9.0.0", "rxjs": "7.8.1", + "signals": "^1.0.0", "tslib": "^2.6.2", "uuid": "^9.0.1", "zone.js": "^0.14.3" @@ -101,12 +104,12 @@ "jest-environment-jsdom": "^29.5.0", "jest-preset-angular": "^13.1.4", "npm-run-all": "^4.1.5", + "replace-in-file": "^6.1.0", "rimraf": "^3.0.2", "standard-version": "^9.5.0", "ts-jest": "^29.0.8", "ts-node": "~10.8.0", "typescript": "~5.3.3", - "webpack-bundle-analyzer": "^4.6.1", - "replace-in-file": "^6.1.0" + "webpack-bundle-analyzer": "^4.6.1" } } \ No newline at end of file diff --git a/frontend/projects/upgrade/src/app/core/feature-flags/feature-flags.service.ts b/frontend/projects/upgrade/src/app/core/feature-flags/feature-flags.service.ts index 2d85183a4b..1182948775 100644 --- a/frontend/projects/upgrade/src/app/core/feature-flags/feature-flags.service.ts +++ b/frontend/projects/upgrade/src/app/core/feature-flags/feature-flags.service.ts @@ -22,7 +22,6 @@ import { selectSortKey, selectSortAs, selectAppContexts, - selectIsLoadingImportFeatureFlag, selectFeatureFlagIds, selectShouldShowWarningForSelectedFlag, selectWarningStatusForAllFlags, @@ -56,7 +55,6 @@ export class FeatureFlagsService { isLoadingUpsertFeatureFlag$ = this.store$.pipe(select(selectIsLoadingUpsertFeatureFlag)); isDuplicateKeyFound$ = this.store$.pipe(select(selectDuplicateKeyFound)); isLoadingFeatureFlagDelete$ = this.store$.pipe(select(selectIsLoadingFeatureFlagDelete)); - isLoadingImportFeatureFlag$ = this.store$.pipe(select(selectIsLoadingImportFeatureFlag)); isLoadingUpdateFeatureFlagStatus$ = this.store$.pipe(select(selectIsLoadingUpdateFeatureFlagStatus)); isLoadingUpsertPrivateSegmentList$ = this.store$.pipe(select(selectIsLoadingUpsertFeatureFlag)); allFeatureFlags$ = this.store$.pipe(select(selectAllFeatureFlagsSortedByDate)); @@ -152,10 +150,6 @@ export class FeatureFlagsService { this.store$.dispatch(FeatureFlagsActions.actionDeleteFeatureFlag({ flagId })); } - setIsLoadingImportFeatureFlag(isLoadingImportFeatureFlag: boolean) { - this.store$.dispatch(FeatureFlagsActions.actionSetIsLoadingImportFeatureFlag({ isLoadingImportFeatureFlag })); - } - emailFeatureFlagData(featureFlagId: string) { this.store$.dispatch(FeatureFlagsActions.actionEmailFeatureFlagData({ featureFlagId })); } diff --git a/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.actions.ts b/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.actions.ts index 8eb5cc2bf2..25bb63fe10 100644 --- a/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.actions.ts +++ b/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.actions.ts @@ -71,11 +71,6 @@ export const actionUpdateFeatureFlagSuccess = createAction( export const actionUpdateFeatureFlagFailure = createAction('[Feature Flags] Update Feature Flag Failure'); -export const actionSetIsLoadingImportFeatureFlag = createAction( - '[Feature Flags] Set Is Loading for Flag Import', - props<{ isLoadingImportFeatureFlag: boolean }>() -); - export const actionEmailFeatureFlagData = createAction( '[Feature Flags] Email Feature Flag Data', props<{ featureFlagId: string }>() diff --git a/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.model.ts b/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.model.ts index c04f82e479..a367cc31ae 100644 --- a/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.model.ts +++ b/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.model.ts @@ -181,7 +181,6 @@ export const FLAG_ROOT_DISPLAYED_COLUMNS = Object.values(FLAG_ROOT_COLUMN_NAMES) export interface FeatureFlagState extends EntityState { isLoadingUpsertFeatureFlag: boolean; - isLoadingImportFeatureFlag: boolean; isLoadingSelectedFeatureFlag: boolean; isLoadingFeatureFlags: boolean; isLoadingUpdateFeatureFlagStatus: boolean; diff --git a/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.reducer.ts b/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.reducer.ts index 4244219965..5c5f1983fa 100644 --- a/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.reducer.ts +++ b/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.reducer.ts @@ -12,7 +12,6 @@ export const { selectIds, selectEntities, selectAll, selectTotal } = adapter.get export const initialState: FeatureFlagState = adapter.getInitialState({ isLoadingUpsertFeatureFlag: false, - isLoadingImportFeatureFlag: false, isLoadingFeatureFlags: false, isLoadingUpdateFeatureFlagStatus: false, isLoadingFeatureFlagDetail: false, @@ -121,10 +120,6 @@ const reducer = createReducer( ...state, isLoadingFeatureFlags, })), - on(FeatureFlagsActions.actionSetIsLoadingImportFeatureFlag, (state, { isLoadingImportFeatureFlag }) => ({ - ...state, - isLoadingImportFeatureFlag, - })), on(FeatureFlagsActions.actionSetSkipFlags, (state, { skipFlags }) => ({ ...state, skipFlags })), on(FeatureFlagsActions.actionSetSearchKey, (state, { searchKey }) => ({ ...state, searchKey })), on(FeatureFlagsActions.actionSetSearchString, (state, { searchString }) => ({ ...state, searchValue: searchString })), diff --git a/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.selectors.ts b/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.selectors.ts index 770cb9e0ed..bf4e431335 100644 --- a/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.selectors.ts +++ b/frontend/projects/upgrade/src/app/core/feature-flags/store/feature-flags.selectors.ts @@ -118,11 +118,6 @@ export const selectFeatureFlagsListLength = createSelector( (featureFlags) => featureFlags.length ); -export const selectIsLoadingImportFeatureFlag = createSelector( - selectFeatureFlagsState, - (state) => state.isLoadingImportFeatureFlag -); - export const selectIsLoadingUpdateFeatureFlagStatus = createSelector( selectFeatureFlagsState, (state) => state.isLoadingUpdateFeatureFlagStatus diff --git a/frontend/projects/upgrade/src/app/core/local-storage/local-storage.service.ts b/frontend/projects/upgrade/src/app/core/local-storage/local-storage.service.ts index f5a26eea7b..dd7074c533 100755 --- a/frontend/projects/upgrade/src/app/core/local-storage/local-storage.service.ts +++ b/frontend/projects/upgrade/src/app/core/local-storage/local-storage.service.ts @@ -61,7 +61,6 @@ export class LocalStorageService { ids: [], entities: {}, isLoadingUpsertFeatureFlag: false, - isLoadingImportFeatureFlag: false, isLoadingSelectedFeatureFlag: false, isLoadingFeatureFlags: false, isLoadingUpdateFeatureFlagStatus: false, diff --git a/frontend/projects/upgrade/src/app/core/segments/store/segments.model.ts b/frontend/projects/upgrade/src/app/core/segments/store/segments.model.ts index 8738e72137..b4738eb92d 100644 --- a/frontend/projects/upgrade/src/app/core/segments/store/segments.model.ts +++ b/frontend/projects/upgrade/src/app/core/segments/store/segments.model.ts @@ -175,6 +175,7 @@ export interface UpsertPrivateSegmentListParams { export interface ImportListParams { listType: FEATURE_FLAG_LIST_FILTER_MODE; flagId: string; + modelType?: MODEL_TYPE; } export enum LIST_OPTION_TYPE { @@ -182,6 +183,11 @@ export enum LIST_OPTION_TYPE { SEGMENT = 'Segment', } +export enum MODEL_TYPE { + LIST = 'List', + FEATURE_FLAG = 'Feature Flag', +} + export const PRIVATE_SEGMENT_LIST_FORM_FIELDS = { LIST_TYPE: 'listType', SEGMENT: 'segment', diff --git a/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/feature-flag.signal.store.ts b/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/feature-flag.signal.store.ts new file mode 100644 index 0000000000..b0683813c6 --- /dev/null +++ b/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/feature-flag.signal.store.ts @@ -0,0 +1,161 @@ +import { FeatureFlag, ValidateFeatureFlagError } from '../../../../../core/feature-flags/store/feature-flags.model'; +import { FeatureFlagsDataService } from '../../../../../core/feature-flags/feature-flags.data.service'; +import { Injectable } from '@angular/core'; +import { ComponentStore } from '@ngrx/component-store'; +import { Observable, tap } from 'rxjs'; +import { FEATURE_FLAG_LIST_FILTER_MODE, IFeatureFlagFile } from 'upgrade_types'; +import { switchMap } from 'rxjs'; +import { FeatureFlagsService } from '../../../../../core/feature-flags/feature-flags.service'; + +type FeatureFlagState = { + isLoading: boolean; + isLoadingImportFeatureFlag: boolean; + importResults: { fileName: string; error: string | null }[]; + validationErrors: ValidateFeatureFlagError[]; +}; + +@Injectable() +export class FeatureFlagsStore extends ComponentStore { + constructor( + private featureFlagsDataService: FeatureFlagsDataService, + private featureFlagsService: FeatureFlagsService + ) { + super({ isLoading: false, isLoadingImportFeatureFlag: false, importResults: [], validationErrors: [] }); + } + + // selectors + readonly isLoading = this.selectSignal((state) => state.isLoading); + readonly isLoadingImportFeatureFlag = this.selectSignal((state) => state.isLoadingImportFeatureFlag); + readonly importResults = this.selectSignal((state) => state.importResults); + readonly validationErrors = this.selectSignal((state) => state.validationErrors); + + // computed + readonly featureFlagCount = this.selectSignal((state) => state.importResults.length); + + // Updaters + readonly setFeatureFlags = this.updater((state, featureFlags: FeatureFlag[]) => ({ + ...state, + featureFlags, + })); + + readonly setLoading = this.updater((state, isLoading: boolean) => ({ + ...state, + isLoading, + })); + + readonly setLoadingImportFeatureFlag = this.updater((state, isLoadingImportFeatureFlag: boolean) => ({ + ...state, + isLoadingImportFeatureFlag, + })); + + readonly setImportResults = this.updater((state, importResults: { fileName: string; error: string | null }[]) => ({ + ...state, + importResults, + })); + + readonly setValidationErrors = this.updater((state, validationErrors: ValidateFeatureFlagError[]) => ({ + ...state, + validationErrors, + })); + + // effects + + // Effect for Import Feature Flags + readonly importFeatureFlags = this.effect((featureFlagFiles$: Observable<{ files: IFeatureFlagFile[] }>) => { + return featureFlagFiles$.pipe( + tap(() => this.setLoading(true)), + switchMap((featureFlagFiles) => + this.featureFlagsDataService.importFeatureFlag(featureFlagFiles).pipe( + tap({ + next: (importResults: { fileName: string; error: string | null }[]) => { + this.setImportResults(importResults); + this.setLoading(false); + this.featureFlagsService.fetchFeatureFlags(true); + }, + error: (error) => { + console.log('Error importing feature flags', error); + // this.setError(error.message || 'An error occurred'); + this.setLoading(false); + }, + }) + ) + ) + ); + }); + + readonly importFeatureFlagList = this.effect( + ( + params$: Observable<{ + fileData: IFeatureFlagFile[]; + flagId: string; + listType: FEATURE_FLAG_LIST_FILTER_MODE; + }> + ) => { + return params$.pipe( + tap(() => this.setLoadingImportFeatureFlag(true)), + switchMap(({ fileData, flagId, listType }) => + this.featureFlagsDataService.importFeatureFlagList(fileData, flagId, listType).pipe( + tap({ + next: (importResults: { fileName: string; error: string | null }[]) => { + this.setImportResults(importResults); + this.setLoadingImportFeatureFlag(false); + }, + error: (error) => { + console.error('Error importing feature flag list:', error); + this.setLoadingImportFeatureFlag(false); + }, + }) + ) + ) + ); + } + ); + + readonly validateFeatureFlags = this.effect((featureFlagFiles$: Observable) => { + return featureFlagFiles$.pipe( + tap(() => this.setLoading(true)), + switchMap((files) => + this.featureFlagsDataService.validateFeatureFlag({ files }).pipe( + tap({ + next: (validationErrors: ValidateFeatureFlagError[]) => { + this.setValidationErrors(validationErrors); + this.setLoading(false); + }, + error: (error) => { + console.error('Error during validation:', error); + this.setLoading(false); + }, + }) + ) + ) + ); + }); + + readonly validateFeatureFlagList = this.effect( + ( + params$: Observable<{ + fileData: IFeatureFlagFile[]; + flagId: string; + listType: FEATURE_FLAG_LIST_FILTER_MODE; + }> + ) => { + return params$.pipe( + tap(() => this.setLoading(true)), + switchMap(({ fileData, flagId, listType }) => + this.featureFlagsDataService.validateFeatureFlagList(fileData, flagId, listType).pipe( + tap({ + next: (validationErrors: ValidateFeatureFlagError[]) => { + this.setValidationErrors(validationErrors); + this.setLoading(false); + }, + error: (error) => { + console.error('Error validating feature flag list:', error); + this.setLoading(false); + }, + }) + ) + ) + ); + } + ); +} diff --git a/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.html b/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.html index e73b2d57e5..63439c7eb5 100644 --- a/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.html +++ b/frontend/projects/upgrade/src/app/features/dashboard/feature-flags/modals/import-feature-flag-modal/import-feature-flag-modal.component.html @@ -7,8 +7,8 @@ (primaryActionBtnClicked)="importFiles()" >
- - + + (); fileValidationErrors: ValidateFeatureFlagError[] = []; fileData: IFeatureFlagFile[] = []; - uploadedFileCount = new BehaviorSubject(0); - isLoadingImportFeatureFlag$ = this.featureFlagsService.isLoadingImportFeatureFlag$; - isImportActionBtnDisabled$: Observable = combineLatest([ - this.uploadedFileCount, - this.isLoadingImportFeatureFlag$, - ]).pipe(map(([uploadedCount, isLoading]) => isLoading || uploadedCount === 0)); + uploadedFileCount = signal(0); + isLoadingImportFeatureFlag$ = this.featureFlagStore.isLoadingImportFeatureFlag; + isImportActionBtnDisabled$ = computed(() => { + const uploadedCount = this.uploadedFileCount(); + const isLoading = this.isLoadingImportFeatureFlag$(); + return isLoading || uploadedCount === 0; + }); constructor( @Inject(MAT_DIALOG_DATA) public data: CommonModalConfig, - public featureFlagsService: FeatureFlagsService, - public featureFlagsDataService: FeatureFlagsDataService, public dialogRef: MatDialogRef, - private notificationService: NotificationService - ) {} + private notificationService: NotificationService, + private featureFlagStore: FeatureFlagsStore + ) { + effect( + () => { + if (this.featureFlagStore.importResults().length > 0) { + this.showNotification(this.featureFlagStore.importResults()); + } + if (this.featureFlagStore.validationErrors().length > 0) { + this.checkValidation(this.featureFlagStore.validationErrors()); + } + }, + { allowSignalWrites: true } + ); + } async handleFilesSelected(event) { if (event.length > 0) { this.isImportActionBtnDisabled.next(false); - this.featureFlagsService.setIsLoadingImportFeatureFlag(true); + this.featureFlagStore.setLoadingImportFeatureFlag(true); } - this.uploadedFileCount.next(event.length); + this.uploadedFileCount.set(event.length); this.fileValidationErrors = []; this.fileData = []; @@ -81,30 +93,22 @@ export class ImportFeatureFlagModalComponent { }) ); - await this.checkValidation(this.fileData); + if (this.data.params.modelType === MODEL_TYPE.FEATURE_FLAG) { + this.featureFlagStore.validateFeatureFlags(this.fileData); + } else if (this.data.params.modelType === MODEL_TYPE.LIST) { + this.featureFlagStore.validateFeatureFlagList({ + fileData: this.fileData, + flagId: this.data.params.flagId, + listType: this.data.params.listType, + }); + } } - async checkValidation(files: IFeatureFlagFile[]) { + async checkValidation(validationErrors: ValidateFeatureFlagError[]) { try { - let validationErrors: ValidateFeatureFlagError[]; - - if (this.data.title === 'Import Feature Flag') { - validationErrors = (await firstValueFrom( - this.featureFlagsDataService.validateFeatureFlag({ files: files }) - )) as ValidateFeatureFlagError[]; - } else if (this.data.title === 'Import List') { - validationErrors = (await firstValueFrom( - this.featureFlagsDataService.validateFeatureFlagList( - files, - this.data.params.flagId, - this.data.params.listType - ) - )) as ValidateFeatureFlagError[]; - } - this.fileValidationErrors = validationErrors.filter((data) => data.compatibilityType != null) || []; this.fileValidationErrorDataSource.data = this.fileValidationErrors; - this.featureFlagsService.setIsLoadingImportFeatureFlag(false); + this.featureFlagStore.setLoadingImportFeatureFlag(false); if (this.fileValidationErrors.length > 0) { this.fileValidationErrors.forEach((error) => { @@ -115,8 +119,9 @@ export class ImportFeatureFlagModalComponent { } } catch (error) { console.error('Error during validation:', error); - this.featureFlagsService.setIsLoadingImportFeatureFlag(false); + this.featureFlagStore.setLoadingImportFeatureFlag(false); } + this.featureFlagStore.setValidationErrors([]); } toggleExpand() { @@ -126,25 +131,18 @@ export class ImportFeatureFlagModalComponent { async importFiles() { try { this.isImportActionBtnDisabled.next(true); - let importResult: importError[]; - - if (this.data.title === 'Import Feature Flag') { - importResult = (await firstValueFrom( - this.featureFlagsDataService.importFeatureFlag({ files: this.fileData }) - )) as importError[]; - } else if (this.data.title === 'Import List') { - importResult = (await firstValueFrom( - this.featureFlagsDataService.importFeatureFlagList( - this.fileData, - this.data.params.flagId, - this.data.params.listType - ) - )) as importError[]; + + if (this.data.params.modelType === MODEL_TYPE.FEATURE_FLAG) { + this.featureFlagStore.importFeatureFlags({ files: this.fileData }); + } else if (this.data.params.modelType === MODEL_TYPE.LIST) { + this.featureFlagStore.importFeatureFlagList({ + fileData: this.fileData, + flagId: this.data.params.flagId, + listType: this.data.params.listType, + }); } - this.showNotification(importResult); this.isImportActionBtnDisabled.next(false); - this.uploadedFileCount.next(0); this.fileData = []; } catch (error) { console.error('Error during import:', error); @@ -159,7 +157,6 @@ export class ImportFeatureFlagModalComponent { if (importSuccessFiles.length > 0) { importSuccessMsg = `Successfully imported ${importSuccessFiles.length} file/s: ${importSuccessFiles.join(', ')}`; this.closeModal(); - this.featureFlagsService.fetchFeatureFlags(true); } this.notificationService.showSuccess(importSuccessMsg); @@ -168,6 +165,8 @@ export class ImportFeatureFlagModalComponent { importFailedFiles.forEach((data) => { this.notificationService.showError(`Failed to import ${data.fileName}: ${data.error}`); }); + + this.featureFlagStore.setImportResults([]); } closeModal() { diff --git a/frontend/projects/upgrade/src/app/shared/services/common-dialog.service.ts b/frontend/projects/upgrade/src/app/shared/services/common-dialog.service.ts index ef2fbfb47c..78c440cf23 100644 --- a/frontend/projects/upgrade/src/app/shared/services/common-dialog.service.ts +++ b/frontend/projects/upgrade/src/app/shared/services/common-dialog.service.ts @@ -6,6 +6,7 @@ import { ImportFeatureFlagModalComponent } from '../../features/dashboard/featur import { UpsertFeatureFlagModalComponent } from '../../features/dashboard/feature-flags/modals/upsert-feature-flag-modal/upsert-feature-flag-modal.component'; import { UpsertPrivateSegmentListModalComponent } from '../../features/dashboard/segments/modals/upsert-private-segment-list-modal/upsert-private-segment-list-modal.component'; import { + MODEL_TYPE, UPSERT_PRIVATE_SEGMENT_LIST_ACTION, UpsertPrivateSegmentListParams, } from '../../core/segments/store/segments.model'; @@ -353,18 +354,18 @@ export class DialogService { } openImportFeatureFlagModal() { - return this.openImportModal('Import Feature Flag', null, null); + return this.openImportModal('Import Feature Flag', null, null, MODEL_TYPE.FEATURE_FLAG); } openImportFeatureFlagIncludeListModal(flagId: string) { - return this.openImportModal('Import List', FEATURE_FLAG_LIST_FILTER_MODE.INCLUSION, flagId); + return this.openImportModal('Import List', FEATURE_FLAG_LIST_FILTER_MODE.INCLUSION, flagId, MODEL_TYPE.LIST); } openImportFeatureFlagExcludeListModal(flagId: string) { - return this.openImportModal('Import List', FEATURE_FLAG_LIST_FILTER_MODE.EXCLUSION, flagId); + return this.openImportModal('Import List', FEATURE_FLAG_LIST_FILTER_MODE.EXCLUSION, flagId, MODEL_TYPE.LIST); } - openImportModal(title: string, listType: FEATURE_FLAG_LIST_FILTER_MODE, flagId: string) { + openImportModal(title: string, listType: FEATURE_FLAG_LIST_FILTER_MODE, flagId: string, modelType: MODEL_TYPE) { const commonModalConfig: CommonModalConfig = { title: title, primaryActionBtnLabel: 'Import', @@ -373,6 +374,7 @@ export class DialogService { params: { listType: listType, flagId: flagId, + modelType: modelType, }, };