[ACS-8001] hide under the feature flag

This commit is contained in:
Mykyta Maliarchuk
2024-08-07 14:01:04 +02:00
parent 10462855b4
commit a939547f9f
12 changed files with 80 additions and 21 deletions

View File

@@ -26,7 +26,7 @@ import { NodeAspectService } from '../../../aspect-list/services/node-aspect.ser
import { ContentMetadataService } from '../../services/content-metadata.service'; import { ContentMetadataService } from '../../services/content-metadata.service';
import { AllowableOperationsEnum } from '../../../common/models/allowable-operations.enum'; import { AllowableOperationsEnum } from '../../../common/models/allowable-operations.enum';
import { of } from 'rxjs'; 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 { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http';
import { versionCompatibilityFactory } from '../../../version-compatibility/version-compatibility-factory'; import { versionCompatibilityFactory } from '../../../version-compatibility/version-compatibility-factory';
@@ -37,6 +37,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
import { CategoryService } from '../../../category'; import { CategoryService } from '../../../category';
import { TagService } from '../../../tag'; import { TagService } from '../../../tag';
import { PropertyDescriptorsService } from '../../public-api'; import { PropertyDescriptorsService } from '../../public-api';
import { provideMockFeatureFlags } from '@alfresco/adf-core/feature-flags';
describe('ContentMetadataCardComponent', () => { describe('ContentMetadataCardComponent', () => {
let component: ContentMetadataCardComponent; let component: ContentMetadataCardComponent;
@@ -72,7 +73,8 @@ describe('ContentMetadataCardComponent', () => {
useFactory: versionCompatibilityFactory, useFactory: versionCompatibilityFactory,
deps: [VersionCompatibilityService], deps: [VersionCompatibilityService],
multi: true multi: true
} },
provideMockFeatureFlags({[CONTENT_ENRICHMENT.EXPERIENCE_INSIGHT]: true})
] ]
}); });
fixture = TestBed.createComponent(ContentMetadataCardComponent); fixture = TestBed.createComponent(ContentMetadataCardComponent);

View File

@@ -45,7 +45,8 @@ import {
TranslationService, TranslationService,
UpdateNotification, UpdateNotification,
PredictionService, PredictionService,
PredictionStatusUpdate PredictionStatusUpdate,
CONTENT_ENRICHMENT
} from '@alfresco/adf-core'; } from '@alfresco/adf-core';
import { NodesApiService } from '../../../common/services/nodes-api.service'; import { NodesApiService } from '../../../common/services/nodes-api.service';
import { EMPTY, of, throwError, Subject } from 'rxjs'; 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 { MatTooltipModule } from '@angular/material/tooltip';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatChipHarness } from '@angular/material/chips/testing'; import { MatChipHarness } from '@angular/material/chips/testing';
import { provideMockFeatureFlags } from '@alfresco/adf-core/feature-flags';
describe('ContentMetadataComponent', () => { describe('ContentMetadataComponent', () => {
let component: ContentMetadataComponent; let component: ContentMetadataComponent;
@@ -239,7 +241,8 @@ describe('ContentMetadataComponent', () => {
getPredictions: () => EMPTY, getPredictions: () => EMPTY,
predictionStatusUpdated$: new Subject<PredictionStatusUpdate>() predictionStatusUpdated$: new Subject<PredictionStatusUpdate>()
} }
} },
provideMockFeatureFlags({[CONTENT_ENRICHMENT.EXPERIENCE_INSIGHT]: true})
] ]
}); });
fixture = TestBed.createComponent(ContentMetadataComponent); fixture = TestBed.createComponent(ContentMetadataComponent);
@@ -1807,7 +1810,9 @@ describe('ContentMetadataComponent', () => {
}); });
it('should call onPredictionStatusChanged when prediction status has changed', () => { 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' }; const notification = { key: 'test:test', previousValue: 'previous value' };
component.ngOnInit(); component.ngOnInit();
predictionService.predictionStatusUpdated$.next(notification); predictionService.predictionStatusUpdated$.next(notification);

View File

@@ -15,7 +15,7 @@
* limitations under the License. * 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 { Category, CategoryEntry, CategoryLinkBody, CategoryPaging, Node, TagBody, TagEntry, TagPaging, Prediction, ReviewStatus } from '@alfresco/js-api';
import { forkJoin, Observable, of, Subject, zip } from 'rxjs'; import { forkJoin, Observable, of, Subject, zip } from 'rxjs';
import { import {
@@ -26,8 +26,10 @@ import {
NotificationService, NotificationService,
PredictionService, PredictionService,
TranslationService, TranslationService,
UpdateNotification UpdateNotification,
CONTENT_ENRICHMENT
} from '@alfresco/adf-core'; } from '@alfresco/adf-core';
import { FeaturesServiceToken, IFeaturesService } from '@alfresco/adf-core/feature-flags';
import { ContentMetadataService } from '../../services/content-metadata.service'; import { ContentMetadataService } from '../../services/content-metadata.service';
import { CardViewGroup, PresetConfig, ContentMetadataCustomPanel, ContentMetadataPanel } from '../../interfaces/content-metadata.interfaces'; import { CardViewGroup, PresetConfig, ContentMetadataCustomPanel, ContentMetadataPanel } from '../../interfaces/content-metadata.interfaces';
import { catchError, debounceTime, map, takeUntil } from 'rxjs/operators'; import { catchError, debounceTime, map, takeUntil } from 'rxjs/operators';
@@ -161,6 +163,7 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy {
changedProperties = {}; changedProperties = {};
hasMetadataChanged = false; hasMetadataChanged = false;
isContentEnrichmentFlagOn = false;
assignedCategories: Category[] = []; assignedCategories: Category[] = [];
categories: Category[] = []; categories: Category[] = [];
categoriesManagementMode = CategoriesManagementMode.ASSIGN; categoriesManagementMode = CategoriesManagementMode.ASSIGN;
@@ -182,7 +185,8 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy {
private categoryService: CategoryService, private categoryService: CategoryService,
private contentService: ContentService, private contentService: ContentService,
private notificationService: NotificationService, private notificationService: NotificationService,
private predictionService: PredictionService private predictionService: PredictionService,
@Inject(FeaturesServiceToken) private readonly featuresService: IFeaturesService
) { ) {
this.copyToClipboardAction = this.appConfig.get<boolean>('content-metadata.copy-to-clipboard-action'); this.copyToClipboardAction = this.appConfig.get<boolean>('content-metadata.copy-to-clipboard-action');
this.multiValueSeparator = this.appConfig.get<string>('content-metadata.multi-value-pipe-separator') || DEFAULT_SEPARATOR; this.multiValueSeparator = this.appConfig.get<string>('content-metadata.multi-value-pipe-separator') || DEFAULT_SEPARATOR;
@@ -190,6 +194,12 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy {
} }
ngOnInit() { ngOnInit() {
this.featuresService.isOn$(CONTENT_ENRICHMENT.EXPERIENCE_INSIGHT).pipe(
takeUntil(this.onDestroy$)
).subscribe((isOn) => {
this.isContentEnrichmentFlagOn = isOn;
});
this.cardViewContentUpdateService.itemUpdated$ this.cardViewContentUpdateService.itemUpdated$
.pipe(debounceTime(500), takeUntil(this.onDestroy$)) .pipe(debounceTime(500), takeUntil(this.onDestroy$))
.subscribe((updatedNode: UpdateNotification) => { .subscribe((updatedNode: UpdateNotification) => {
@@ -203,7 +213,7 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy {
this.loadProperties(node); this.loadProperties(node);
}); });
if (this.displayPredictions) { if (this.isContentEnrichmentFlagOn && this.displayPredictions) {
this.predictionService.predictionStatusUpdated$.pipe(takeUntil(this.onDestroy$)).subscribe(({ key, previousValue }) => { this.predictionService.predictionStatusUpdated$.pipe(takeUntil(this.onDestroy$)).subscribe(({ key, previousValue }) => {
this.cardViewContentUpdateService.onPredictionStatusChanged([{ key, previousValue }]); this.cardViewContentUpdateService.onPredictionStatusChanged([{ key, previousValue }]);
this.nodesApiService this.nodesApiService
@@ -424,7 +434,7 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy {
) )
.subscribe((result: any) => { .subscribe((result: any) => {
if (result) { if (result) {
if (this.displayPredictions) { if (this.isContentEnrichmentFlagOn && this.displayPredictions) {
this.cardViewContentUpdateService.onPredictionStatusChanged( this.cardViewContentUpdateService.onPredictionStatusChanged(
Object.keys(this.changedProperties['properties']).map((key) => ({ key })) 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); requests['groupedProperties'] = this.contentMetadataService.getGroupedProperties(node, this.preset);
} }
if (this.displayPredictions) { if (this.isContentEnrichmentFlagOn && this.displayPredictions) {
requests['predictions'] = this.loadPredictionsForNode(this.node.id); requests['predictions'] = this.loadPredictionsForNode(this.node.id);
} }

View File

@@ -47,6 +47,7 @@ import { NewVersionUploaderDialogComponent } from './new-version-uploader';
import { VersionCompatibilityDirective } from './version-compatibility'; import { VersionCompatibilityDirective } from './version-compatibility';
import { CONTENT_UPLOAD_DIRECTIVES } from './upload'; import { CONTENT_UPLOAD_DIRECTIVES } from './upload';
import { TreeViewComponent } from './tree-view'; import { TreeViewComponent } from './tree-view';
import { provideDebugFeatureFlags, provideDummyFeatureFlags } from '@alfresco/adf-core/feature-flags';
@NgModule({ @NgModule({
imports: [ imports: [
@@ -109,7 +110,9 @@ import { TreeViewComponent } from './tree-view';
] ]
}) })
export class ContentModule { export class ContentModule {
static forRoot(): ModuleWithProviders<ContentModule> { static forRoot(
devTools = false
): ModuleWithProviders<ContentModule> {
return { return {
ngModule: ContentModule, ngModule: ContentModule,
providers: [ providers: [
@@ -126,7 +129,13 @@ export class ContentModule {
useFactory: contentAuthLoaderFactory, useFactory: contentAuthLoaderFactory,
deps: [ContentAuthLoaderService], deps: [ContentAuthLoaderService],
multi: true multi: true
} },
...provideDummyFeatureFlags(),
...(devTools
? provideDebugFeatureFlags({
storageKey: 'content-feature-flags'
})
: [])
] ]
}; };
} }

View File

@@ -17,6 +17,6 @@
export interface Dictionary<T> { export interface Dictionary<T> {
[key: string]: T; [key: string]: T;
}; }
export type Constructor<T> = new (...args: any[]) => T; export type Constructor<T> = new (...args: any[]) => T;

View File

@@ -18,7 +18,7 @@
import { IsFlagsOverrideOn } from '../guards/is-flags-override-on.guard'; import { IsFlagsOverrideOn } from '../guards/is-flags-override-on.guard';
import { IsFeatureOn } from '../guards/is-feature-on.guard'; import { IsFeatureOn } from '../guards/is-feature-on.guard';
import { IsFeatureOff } from '../guards/is-feature-off.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'; import { DummyFeaturesService } from '../services/dummy-features.service';
/** /**
@@ -28,7 +28,8 @@ import { DummyFeaturesService } from '../services/dummy-features.service';
*/ */
export function provideDummyFeatureFlags() { export function provideDummyFeatureFlags() {
return [ return [
{ provide: FeaturesServiceToken, useClass: DummyFeaturesService }, { provide: OverridableFeaturesServiceToken, useClass: DummyFeaturesService },
{ provide: FeaturesServiceToken, useExisting: OverridableFeaturesServiceToken },
{ provide: FlagsOverrideToken, useValue: false }, { provide: FlagsOverrideToken, useValue: false },
IsFeatureOn, IsFeatureOn,
IsFeatureOff, IsFeatureOff,

View File

@@ -45,4 +45,4 @@ export function loadAppConfig(
}); });
}; };
return () => appConfigService.load(init); return () => appConfigService.load(init);
}; }

View File

@@ -20,4 +20,4 @@ export interface UserLike {
firstName?: string; firstName?: string;
lastName?: string; lastName?: string;
email?: string; email?: string;
}; }

View File

@@ -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'
}

View File

@@ -17,3 +17,4 @@
export * from './services'; export * from './services';
export * from './interfaces/prediction-status-update.interface'; export * from './interfaces/prediction-status-update.interface';
export * from './feature-flag';

View File

@@ -21,6 +21,8 @@ import { ProcessServiceCloudTestingModule } from '../../../../../testing/process
import { of } from 'rxjs'; import { of } from 'rxjs';
import { fakeNodeWithProperties } from '../../../../mocks/attach-file-cloud-widget.mock'; import { fakeNodeWithProperties } from '../../../../mocks/attach-file-cloud-widget.mock';
import { NodesApiService, BasicPropertiesService } from '@alfresco/adf-content-services'; 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', () => { describe('PropertiesViewerWidgetComponent', () => {
let component: PropertiesViewerWrapperComponent; let component: PropertiesViewerWrapperComponent;
@@ -30,7 +32,11 @@ describe('PropertiesViewerWidgetComponent', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule], imports: [ProcessServiceCloudTestingModule],
providers: [NodesApiService, { provide: BasicPropertiesService, useValue: { getProperties: () => [] } }] providers: [
NodesApiService,
{ provide: BasicPropertiesService, useValue: { getProperties: () => [] } },
provideMockFeatureFlags({[CONTENT_ENRICHMENT.EXPERIENCE_INSIGHT]: false})
]
}); });
fixture = TestBed.createComponent(PropertiesViewerWrapperComponent); fixture = TestBed.createComponent(PropertiesViewerWrapperComponent);
component = fixture.componentInstance; component = fixture.componentInstance;

View File

@@ -16,13 +16,14 @@
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; 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 { PropertiesViewerWidgetComponent } from './properties-viewer.widget';
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module'; import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { fakeNodeWithProperties } from '../../../mocks/attach-file-cloud-widget.mock'; import { fakeNodeWithProperties } from '../../../mocks/attach-file-cloud-widget.mock';
import { PropertiesViewerWrapperComponent } from './properties-viewer-wrapper/properties-viewer-wrapper.component'; import { PropertiesViewerWrapperComponent } from './properties-viewer-wrapper/properties-viewer-wrapper.component';
import { NodesApiService, BasicPropertiesService } from '@alfresco/adf-content-services'; import { NodesApiService, BasicPropertiesService } from '@alfresco/adf-content-services';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { provideMockFeatureFlags } from '@alfresco/adf-core/feature-flags';
describe('PropertiesViewerWidgetComponent', () => { describe('PropertiesViewerWidgetComponent', () => {
let widget: PropertiesViewerWidgetComponent; let widget: PropertiesViewerWidgetComponent;
@@ -49,7 +50,11 @@ describe('PropertiesViewerWidgetComponent', () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ProcessServiceCloudTestingModule], imports: [ProcessServiceCloudTestingModule],
declarations: [PropertiesViewerWrapperComponent], declarations: [PropertiesViewerWrapperComponent],
providers: [NodesApiService, { provide: BasicPropertiesService, useValue: { getProperties: () => [] } }] providers: [
NodesApiService,
{ provide: BasicPropertiesService, useValue: { getProperties: () => [] } },
provideMockFeatureFlags({[CONTENT_ENRICHMENT.EXPERIENCE_INSIGHT]: false})
]
}); });
fixture = TestBed.createComponent(PropertiesViewerWidgetComponent); fixture = TestBed.createComponent(PropertiesViewerWidgetComponent);
nodesApiService = TestBed.inject(NodesApiService); nodesApiService = TestBed.inject(NodesApiService);