From a939547f9f135e4fff8c2b28c82e63a9cc60af01 Mon Sep 17 00:00:00 2001 From: Mykyta Maliarchuk Date: Wed, 7 Aug 2024 14:01:04 +0200 Subject: [PATCH] [ACS-8001] hide under the feature flag --- .../content-metadata-card.component.spec.ts | 6 +++-- .../content-metadata.component.spec.ts | 11 +++++++--- .../content-metadata.component.ts | 22 ++++++++++++++----- .../src/lib/content.module.ts | 13 +++++++++-- lib/core/api/src/lib/types.ts | 2 +- .../providers/dummy-feature-flags.provider.ts | 5 +++-- .../src/lib/app-config/app-config.loader.ts | 2 +- lib/core/src/lib/pipes/user-like.interface.ts | 2 +- lib/core/src/lib/prediction/feature-flag.ts | 20 +++++++++++++++++ lib/core/src/lib/prediction/public-api.ts | 1 + .../properties-viewer.widget.spec.ts | 8 ++++++- .../properties-viewer.widget.spec.ts | 9 ++++++-- 12 files changed, 80 insertions(+), 21 deletions(-) create mode 100644 lib/core/src/lib/prediction/feature-flag.ts diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts b/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts index 9e7e5b6234b..9aa653352b1 100644 --- a/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts +++ b/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts @@ -26,7 +26,7 @@ import { NodeAspectService } from '../../../aspect-list/services/node-aspect.ser import { ContentMetadataService } from '../../services/content-metadata.service'; import { AllowableOperationsEnum } from '../../../common/models/allowable-operations.enum'; import { of } from 'rxjs'; -import { AlfrescoApiService, AlfrescoApiServiceMock, AuthModule, PipeModule, TranslationMock, TranslationService } from '@alfresco/adf-core'; +import { AlfrescoApiService, AlfrescoApiServiceMock, AuthModule, PipeModule, TranslationMock, TranslationService, CONTENT_ENRICHMENT } from '@alfresco/adf-core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { HttpClientModule } from '@angular/common/http'; import { versionCompatibilityFactory } from '../../../version-compatibility/version-compatibility-factory'; @@ -37,6 +37,7 @@ import { MatTooltipModule } from '@angular/material/tooltip'; import { CategoryService } from '../../../category'; import { TagService } from '../../../tag'; import { PropertyDescriptorsService } from '../../public-api'; +import { provideMockFeatureFlags } from '@alfresco/adf-core/feature-flags'; describe('ContentMetadataCardComponent', () => { let component: ContentMetadataCardComponent; @@ -72,7 +73,8 @@ describe('ContentMetadataCardComponent', () => { useFactory: versionCompatibilityFactory, deps: [VersionCompatibilityService], multi: true - } + }, + provideMockFeatureFlags({[CONTENT_ENRICHMENT.EXPERIENCE_INSIGHT]: true}) ] }); fixture = TestBed.createComponent(ContentMetadataCardComponent); diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts index 1634d4c4ade..f9c097190f7 100644 --- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts +++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts @@ -45,7 +45,8 @@ import { TranslationService, UpdateNotification, PredictionService, - PredictionStatusUpdate + PredictionStatusUpdate, + CONTENT_ENRICHMENT } from '@alfresco/adf-core'; import { NodesApiService } from '../../../common/services/nodes-api.service'; import { EMPTY, of, throwError, Subject } from 'rxjs'; @@ -70,6 +71,7 @@ import { MatProgressBarModule } from '@angular/material/progress-bar'; import { MatTooltipModule } from '@angular/material/tooltip'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { MatChipHarness } from '@angular/material/chips/testing'; +import { provideMockFeatureFlags } from '@alfresco/adf-core/feature-flags'; describe('ContentMetadataComponent', () => { let component: ContentMetadataComponent; @@ -239,7 +241,8 @@ describe('ContentMetadataComponent', () => { getPredictions: () => EMPTY, predictionStatusUpdated$: new Subject() } - } + }, + provideMockFeatureFlags({[CONTENT_ENRICHMENT.EXPERIENCE_INSIGHT]: true}) ] }); fixture = TestBed.createComponent(ContentMetadataComponent); @@ -1807,7 +1810,9 @@ describe('ContentMetadataComponent', () => { }); it('should call onPredictionStatusChanged when prediction status has changed', () => { - const onPredictionStatusChangedSpy = spyOn(updateService, 'onPredictionStatusChanged'); + const updatedNode = { ...node, name: 'new test name' }; + const onPredictionStatusChangedSpy = spyOn(updateService, 'onPredictionStatusChanged').and.stub(); + spyOn(nodesApiService, 'getNode').and.returnValue(of(updatedNode)); const notification = { key: 'test:test', previousValue: 'previous value' }; component.ngOnInit(); predictionService.predictionStatusUpdated$.next(notification); diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.ts b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.ts index 20aab7e0b94..bf944f09dac 100644 --- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.ts +++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core'; +import { Component, Inject, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core'; import { Category, CategoryEntry, CategoryLinkBody, CategoryPaging, Node, TagBody, TagEntry, TagPaging, Prediction, ReviewStatus } from '@alfresco/js-api'; import { forkJoin, Observable, of, Subject, zip } from 'rxjs'; import { @@ -26,8 +26,10 @@ import { NotificationService, PredictionService, TranslationService, - UpdateNotification + UpdateNotification, + CONTENT_ENRICHMENT } from '@alfresco/adf-core'; +import { FeaturesServiceToken, IFeaturesService } from '@alfresco/adf-core/feature-flags'; import { ContentMetadataService } from '../../services/content-metadata.service'; import { CardViewGroup, PresetConfig, ContentMetadataCustomPanel, ContentMetadataPanel } from '../../interfaces/content-metadata.interfaces'; import { catchError, debounceTime, map, takeUntil } from 'rxjs/operators'; @@ -161,6 +163,7 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { changedProperties = {}; hasMetadataChanged = false; + isContentEnrichmentFlagOn = false; assignedCategories: Category[] = []; categories: Category[] = []; categoriesManagementMode = CategoriesManagementMode.ASSIGN; @@ -182,7 +185,8 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { private categoryService: CategoryService, private contentService: ContentService, private notificationService: NotificationService, - private predictionService: PredictionService + private predictionService: PredictionService, + @Inject(FeaturesServiceToken) private readonly featuresService: IFeaturesService ) { this.copyToClipboardAction = this.appConfig.get('content-metadata.copy-to-clipboard-action'); this.multiValueSeparator = this.appConfig.get('content-metadata.multi-value-pipe-separator') || DEFAULT_SEPARATOR; @@ -190,6 +194,12 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { } ngOnInit() { + this.featuresService.isOn$(CONTENT_ENRICHMENT.EXPERIENCE_INSIGHT).pipe( + takeUntil(this.onDestroy$) + ).subscribe((isOn) => { + this.isContentEnrichmentFlagOn = isOn; + }); + this.cardViewContentUpdateService.itemUpdated$ .pipe(debounceTime(500), takeUntil(this.onDestroy$)) .subscribe((updatedNode: UpdateNotification) => { @@ -203,7 +213,7 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { this.loadProperties(node); }); - if (this.displayPredictions) { + if (this.isContentEnrichmentFlagOn && this.displayPredictions) { this.predictionService.predictionStatusUpdated$.pipe(takeUntil(this.onDestroy$)).subscribe(({ key, previousValue }) => { this.cardViewContentUpdateService.onPredictionStatusChanged([{ key, previousValue }]); this.nodesApiService @@ -424,7 +434,7 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { ) .subscribe((result: any) => { if (result) { - if (this.displayPredictions) { + if (this.isContentEnrichmentFlagOn && this.displayPredictions) { this.cardViewContentUpdateService.onPredictionStatusChanged( Object.keys(this.changedProperties['properties']).map((key) => ({ key })) ); @@ -471,7 +481,7 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { requests['groupedProperties'] = this.contentMetadataService.getGroupedProperties(node, this.preset); } - if (this.displayPredictions) { + if (this.isContentEnrichmentFlagOn && this.displayPredictions) { requests['predictions'] = this.loadPredictionsForNode(this.node.id); } diff --git a/lib/content-services/src/lib/content.module.ts b/lib/content-services/src/lib/content.module.ts index e4ab61c6f90..bea51a0b6de 100644 --- a/lib/content-services/src/lib/content.module.ts +++ b/lib/content-services/src/lib/content.module.ts @@ -47,6 +47,7 @@ import { NewVersionUploaderDialogComponent } from './new-version-uploader'; import { VersionCompatibilityDirective } from './version-compatibility'; import { CONTENT_UPLOAD_DIRECTIVES } from './upload'; import { TreeViewComponent } from './tree-view'; +import { provideDebugFeatureFlags, provideDummyFeatureFlags } from '@alfresco/adf-core/feature-flags'; @NgModule({ imports: [ @@ -109,7 +110,9 @@ import { TreeViewComponent } from './tree-view'; ] }) export class ContentModule { - static forRoot(): ModuleWithProviders { + static forRoot( + devTools = false + ): ModuleWithProviders { return { ngModule: ContentModule, providers: [ @@ -126,7 +129,13 @@ export class ContentModule { useFactory: contentAuthLoaderFactory, deps: [ContentAuthLoaderService], multi: true - } + }, + ...provideDummyFeatureFlags(), + ...(devTools + ? provideDebugFeatureFlags({ + storageKey: 'content-feature-flags' + }) + : []) ] }; } diff --git a/lib/core/api/src/lib/types.ts b/lib/core/api/src/lib/types.ts index 3df78a41746..0fd85a5cae7 100644 --- a/lib/core/api/src/lib/types.ts +++ b/lib/core/api/src/lib/types.ts @@ -17,6 +17,6 @@ export interface Dictionary { [key: string]: T; -}; +} export type Constructor = new (...args: any[]) => T; diff --git a/lib/core/feature-flags/src/lib/providers/dummy-feature-flags.provider.ts b/lib/core/feature-flags/src/lib/providers/dummy-feature-flags.provider.ts index ed333531434..dae309b706b 100644 --- a/lib/core/feature-flags/src/lib/providers/dummy-feature-flags.provider.ts +++ b/lib/core/feature-flags/src/lib/providers/dummy-feature-flags.provider.ts @@ -18,7 +18,7 @@ import { IsFlagsOverrideOn } from '../guards/is-flags-override-on.guard'; import { IsFeatureOn } from '../guards/is-feature-on.guard'; import { IsFeatureOff } from '../guards/is-feature-off.guard'; -import { FeaturesServiceToken, FlagsOverrideToken } from '../interfaces/features.interface'; +import { FeaturesServiceToken, FlagsOverrideToken, OverridableFeaturesServiceToken } from '../interfaces/features.interface'; import { DummyFeaturesService } from '../services/dummy-features.service'; /** @@ -28,7 +28,8 @@ import { DummyFeaturesService } from '../services/dummy-features.service'; */ export function provideDummyFeatureFlags() { return [ - { provide: FeaturesServiceToken, useClass: DummyFeaturesService }, + { provide: OverridableFeaturesServiceToken, useClass: DummyFeaturesService }, + { provide: FeaturesServiceToken, useExisting: OverridableFeaturesServiceToken }, { provide: FlagsOverrideToken, useValue: false }, IsFeatureOn, IsFeatureOff, diff --git a/lib/core/src/lib/app-config/app-config.loader.ts b/lib/core/src/lib/app-config/app-config.loader.ts index 1744729a593..9df72f13e88 100644 --- a/lib/core/src/lib/app-config/app-config.loader.ts +++ b/lib/core/src/lib/app-config/app-config.loader.ts @@ -45,4 +45,4 @@ export function loadAppConfig( }); }; return () => appConfigService.load(init); -}; +} diff --git a/lib/core/src/lib/pipes/user-like.interface.ts b/lib/core/src/lib/pipes/user-like.interface.ts index 4e6daf35bec..c7d0fc722c6 100644 --- a/lib/core/src/lib/pipes/user-like.interface.ts +++ b/lib/core/src/lib/pipes/user-like.interface.ts @@ -20,4 +20,4 @@ export interface UserLike { firstName?: string; lastName?: string; email?: string; -}; +} diff --git a/lib/core/src/lib/prediction/feature-flag.ts b/lib/core/src/lib/prediction/feature-flag.ts new file mode 100644 index 00000000000..c0c0dd2e960 --- /dev/null +++ b/lib/core/src/lib/prediction/feature-flag.ts @@ -0,0 +1,20 @@ +/*! + * @license + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export enum CONTENT_ENRICHMENT { + EXPERIENCE_INSIGHT = 'content-enrichment-with-experience-insight' +} diff --git a/lib/core/src/lib/prediction/public-api.ts b/lib/core/src/lib/prediction/public-api.ts index 4a47573a5cd..266c0d63b1f 100644 --- a/lib/core/src/lib/prediction/public-api.ts +++ b/lib/core/src/lib/prediction/public-api.ts @@ -17,3 +17,4 @@ export * from './services'; export * from './interfaces/prediction-status-update.interface'; +export * from './feature-flag'; diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/properties-viewer/properties-viewer-wrapper/properties-viewer.widget.spec.ts b/lib/process-services-cloud/src/lib/form/components/widgets/properties-viewer/properties-viewer-wrapper/properties-viewer.widget.spec.ts index 4bb0210d254..acd176ba94a 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/properties-viewer/properties-viewer-wrapper/properties-viewer.widget.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/properties-viewer/properties-viewer-wrapper/properties-viewer.widget.spec.ts @@ -21,6 +21,8 @@ import { ProcessServiceCloudTestingModule } from '../../../../../testing/process import { of } from 'rxjs'; import { fakeNodeWithProperties } from '../../../../mocks/attach-file-cloud-widget.mock'; import { NodesApiService, BasicPropertiesService } from '@alfresco/adf-content-services'; +import { provideMockFeatureFlags } from '@alfresco/adf-core/feature-flags'; +import { CONTENT_ENRICHMENT } from '@alfresco/adf-core'; describe('PropertiesViewerWidgetComponent', () => { let component: PropertiesViewerWrapperComponent; @@ -30,7 +32,11 @@ describe('PropertiesViewerWidgetComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [ProcessServiceCloudTestingModule], - providers: [NodesApiService, { provide: BasicPropertiesService, useValue: { getProperties: () => [] } }] + providers: [ + NodesApiService, + { provide: BasicPropertiesService, useValue: { getProperties: () => [] } }, + provideMockFeatureFlags({[CONTENT_ENRICHMENT.EXPERIENCE_INSIGHT]: false}) + ] }); fixture = TestBed.createComponent(PropertiesViewerWrapperComponent); component = fixture.componentInstance; diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/properties-viewer/properties-viewer.widget.spec.ts b/lib/process-services-cloud/src/lib/form/components/widgets/properties-viewer/properties-viewer.widget.spec.ts index 51e33185377..eea2ebec2a4 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/properties-viewer/properties-viewer.widget.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/properties-viewer/properties-viewer.widget.spec.ts @@ -16,13 +16,14 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { FormFieldModel, FormModel } from '@alfresco/adf-core'; +import { CONTENT_ENRICHMENT, FormFieldModel, FormModel } from '@alfresco/adf-core'; import { PropertiesViewerWidgetComponent } from './properties-viewer.widget'; import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module'; import { fakeNodeWithProperties } from '../../../mocks/attach-file-cloud-widget.mock'; import { PropertiesViewerWrapperComponent } from './properties-viewer-wrapper/properties-viewer-wrapper.component'; import { NodesApiService, BasicPropertiesService } from '@alfresco/adf-content-services'; import { of } from 'rxjs'; +import { provideMockFeatureFlags } from '@alfresco/adf-core/feature-flags'; describe('PropertiesViewerWidgetComponent', () => { let widget: PropertiesViewerWidgetComponent; @@ -49,7 +50,11 @@ describe('PropertiesViewerWidgetComponent', () => { TestBed.configureTestingModule({ imports: [ProcessServiceCloudTestingModule], declarations: [PropertiesViewerWrapperComponent], - providers: [NodesApiService, { provide: BasicPropertiesService, useValue: { getProperties: () => [] } }] + providers: [ + NodesApiService, + { provide: BasicPropertiesService, useValue: { getProperties: () => [] } }, + provideMockFeatureFlags({[CONTENT_ENRICHMENT.EXPERIENCE_INSIGHT]: false}) + ] }); fixture = TestBed.createComponent(PropertiesViewerWidgetComponent); nodesApiService = TestBed.inject(NodesApiService);