mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-09-10 14:11:42 +00:00
AAE-32587 new custom screen registration api (#11120)
This commit is contained in:
@@ -200,7 +200,8 @@ module.exports = {
|
|||||||
files: ['*.spec.ts'],
|
files: ['*.spec.ts'],
|
||||||
plugins: ['@alfresco/eslint-angular'],
|
plugins: ['@alfresco/eslint-angular'],
|
||||||
rules: {
|
rules: {
|
||||||
'@alfresco/eslint-angular/no-angular-material-selectors': 'error'
|
'@alfresco/eslint-angular/no-angular-material-selectors': 'error',
|
||||||
|
'@angular-eslint/component-class-suffix': 'off'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -84,6 +84,13 @@
|
|||||||
"@angular-eslint/prefer-standalone": "off"
|
"@angular-eslint/prefer-standalone": "off"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.spec.ts"],
|
||||||
|
"plugins": ["@alfresco/eslint-angular"],
|
||||||
|
"rules": {
|
||||||
|
"@angular-eslint/component-class-suffix": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"files": ["*.html"],
|
"files": ["*.html"],
|
||||||
"extends": ["plugin:@nx/angular-template"],
|
"extends": ["plugin:@nx/angular-template"],
|
||||||
|
@@ -16,10 +16,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { CommonModule } from '@angular/common';
|
|
||||||
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { ScreenRenderingService } from '../../../services/public-api';
|
import { ScreenRenderingService } from '../../services/screen-rendering.service';
|
||||||
import { TaskScreenCloudComponent } from './screen-cloud.component';
|
import { TaskScreenCloudComponent } from './screen-cloud.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -31,8 +30,7 @@ import { TaskScreenCloudComponent } from './screen-cloud.component';
|
|||||||
<div class="adf-cloud-test-container-rootProcessInstanceId">{{ rootProcessInstanceId }}</div>
|
<div class="adf-cloud-test-container-rootProcessInstanceId">{{ rootProcessInstanceId }}</div>
|
||||||
<button class="adf-cloud-test-container-complete-btn" (click)="onComplete()">complete</button>
|
<button class="adf-cloud-test-container-complete-btn" (click)="onComplete()">complete</button>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`
|
||||||
imports: [CommonModule]
|
|
||||||
})
|
})
|
||||||
class TestComponent {
|
class TestComponent {
|
||||||
@Input() taskId = '';
|
@Input() taskId = '';
|
||||||
@@ -59,7 +57,7 @@ class TestComponent {
|
|||||||
(taskCompleted)="onTaskCompleted()"
|
(taskCompleted)="onTaskCompleted()"
|
||||||
/>
|
/>
|
||||||
`,
|
`,
|
||||||
imports: [CommonModule, TaskScreenCloudComponent]
|
imports: [TaskScreenCloudComponent]
|
||||||
})
|
})
|
||||||
class TestWrapperComponent {
|
class TestWrapperComponent {
|
||||||
@Input() screenId = '';
|
@Input() screenId = '';
|
||||||
|
@@ -17,9 +17,9 @@
|
|||||||
|
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { Component, ComponentRef, DestroyRef, EventEmitter, inject, Input, OnInit, Output, ViewChild, ViewContainerRef } from '@angular/core';
|
import { Component, ComponentRef, DestroyRef, EventEmitter, inject, Input, OnInit, Output, ViewChild, ViewContainerRef } from '@angular/core';
|
||||||
import { ScreenRenderingService } from '../../../services/public-api';
|
import { ScreenRenderingService } from '../../services/screen-rendering.service';
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
import { UserTaskCustomUi } from '../../models/screen-cloud.model';
|
import { UserTaskCustomUi } from './screen-cloud.model';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { MatCheckboxChange } from '@angular/material/checkbox';
|
import { MatCheckboxChange } from '@angular/material/checkbox';
|
||||||
|
|
||||||
|
@@ -15,4 +15,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './models/screen-cloud.model';
|
export * from './components/screen-cloud/screen-cloud.model';
|
||||||
|
export * from './services/screen-rendering.service';
|
||||||
|
export * from './services/provide-screen';
|
||||||
|
@@ -0,0 +1,50 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2025 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { InjectionToken, Provider, Type } from '@angular/core';
|
||||||
|
|
||||||
|
export interface CustomScreen {
|
||||||
|
key: string;
|
||||||
|
component: Type<any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injection token for custom screens.
|
||||||
|
* This token can be used to inject custom screen components into the application.
|
||||||
|
* It allows for multiple screen components to be registered and injected.
|
||||||
|
*/
|
||||||
|
export const APP_CUSTOM_SCREEN_TOKEN = new InjectionToken<CustomScreen>('Injection token for custom screens.');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a custom screen component to be used in the application.
|
||||||
|
* This function allows you to register a custom screen component that can be injected
|
||||||
|
* into the application using the `APP_CUSTOM_SCREEN_TOKEN`.
|
||||||
|
*
|
||||||
|
* @param key - A unique key to identify the screen component.
|
||||||
|
* @param component - The screen component to be registered.
|
||||||
|
* @returns A provider that can be used in the Angular dependency injection system.
|
||||||
|
*/
|
||||||
|
export function provideScreen(key: string, component: Type<any>): Provider {
|
||||||
|
return {
|
||||||
|
provide: APP_CUSTOM_SCREEN_TOKEN,
|
||||||
|
multi: true,
|
||||||
|
useValue: {
|
||||||
|
key,
|
||||||
|
component
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@@ -0,0 +1,123 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2025 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { ScreenRenderingService } from './screen-rendering.service';
|
||||||
|
import { APP_CUSTOM_SCREEN_TOKEN, provideScreen } from './provide-screen';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: '<div>Test Component 1</div>'
|
||||||
|
})
|
||||||
|
class TestComponent1 {}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: '<div>Test Component 2</div>'
|
||||||
|
})
|
||||||
|
class TestComponent2 {}
|
||||||
|
|
||||||
|
describe('ScreenRenderingService', () => {
|
||||||
|
let service: ScreenRenderingService;
|
||||||
|
|
||||||
|
describe('without custom screens', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(ScreenRenderingService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle empty custom screens array', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
expect(() => service).not.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with custom screens', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [provideScreen('test-screen-1', TestComponent1), provideScreen('test-screen-2', TestComponent2)]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created with custom screens', () => {
|
||||||
|
const service = TestBed.inject(ScreenRenderingService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should register custom screens on initialization', () => {
|
||||||
|
const spy = spyOn(ScreenRenderingService.prototype, 'setComponentTypeResolver');
|
||||||
|
TestBed.inject(ScreenRenderingService);
|
||||||
|
|
||||||
|
expect(spy).toHaveBeenCalledTimes(2);
|
||||||
|
expect(spy).toHaveBeenCalledWith('test-screen-1', jasmine.any(Function), true);
|
||||||
|
expect(spy).toHaveBeenCalledWith('test-screen-2', jasmine.any(Function), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should register component resolvers that return correct components', () => {
|
||||||
|
const resolverCalls: any[] = [];
|
||||||
|
spyOn(ScreenRenderingService.prototype, 'setComponentTypeResolver').and.callFake((key, resolver, override) => {
|
||||||
|
resolverCalls.push({ key, resolver: resolver({ type: key }), override });
|
||||||
|
});
|
||||||
|
TestBed.inject(ScreenRenderingService);
|
||||||
|
|
||||||
|
expect(resolverCalls).toEqual([
|
||||||
|
{ key: 'test-screen-1', resolver: TestComponent1, override: true },
|
||||||
|
{ key: 'test-screen-2', resolver: TestComponent2, override: true }
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with single custom screen', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [provideScreen('single-screen', TestComponent1)]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle single custom screen', () => {
|
||||||
|
const spy = spyOn(ScreenRenderingService.prototype, 'setComponentTypeResolver');
|
||||||
|
TestBed.inject(ScreenRenderingService);
|
||||||
|
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(spy).toHaveBeenCalledWith('single-screen', jasmine.any(Function), true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with null custom screens', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: APP_CUSTOM_SCREEN_TOKEN,
|
||||||
|
useValue: null,
|
||||||
|
multi: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle null custom screens gracefully', () => {
|
||||||
|
expect(() => {
|
||||||
|
service = TestBed.inject(ScreenRenderingService);
|
||||||
|
}).not.toThrow();
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,67 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2025 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DynamicComponentMapper } from '@alfresco/adf-core';
|
||||||
|
import { inject, Injectable } from '@angular/core';
|
||||||
|
import { APP_CUSTOM_SCREEN_TOKEN, CustomScreen } from './provide-screen';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for managing and rendering custom screen components.
|
||||||
|
*
|
||||||
|
* Custom screens can be registered using the {@link provideScreen} helper function
|
||||||
|
* and the {@link APP_CUSTOM_SCREEN_TOKEN} injection token.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* // Register a custom screen in your Angular module providers:
|
||||||
|
* import { provideScreen, ScreenRenderingService } from '@alfresco/adf-process-services-cloud';
|
||||||
|
*
|
||||||
|
* @Component({
|
||||||
|
* template: '<div>My Custom Screen</div>'
|
||||||
|
* })
|
||||||
|
* class MyCustomScreenComponent {}
|
||||||
|
*
|
||||||
|
* @NgModule({
|
||||||
|
* providers: [
|
||||||
|
* provideScreen('my-custom-screen', MyCustomScreenComponent)
|
||||||
|
* ]
|
||||||
|
* })
|
||||||
|
* export class MyModule {}
|
||||||
|
*
|
||||||
|
* // The custom screen can now be resolved and rendered by ScreenRenderingService.
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ScreenRenderingService extends DynamicComponentMapper {
|
||||||
|
private customScreens = inject<CustomScreen[]>(APP_CUSTOM_SCREEN_TOKEN, { optional: true }) || [];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.registerCustomScreens();
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerCustomScreens() {
|
||||||
|
if (this.customScreens && this.customScreens.length > 0) {
|
||||||
|
this.customScreens.forEach((screen) => {
|
||||||
|
if (!screen) return; // Skip null or undefined screens
|
||||||
|
this.setComponentTypeResolver(screen.key, () => screen.component, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -21,7 +21,6 @@ export * from './form-fields.interfaces';
|
|||||||
export * from './local-preference-cloud.service';
|
export * from './local-preference-cloud.service';
|
||||||
export * from './notification-cloud.service';
|
export * from './notification-cloud.service';
|
||||||
export * from './preference-cloud.interface';
|
export * from './preference-cloud.interface';
|
||||||
export * from './screen-rendering.service';
|
|
||||||
export * from './task-list-cloud.service.interface';
|
export * from './task-list-cloud.service.interface';
|
||||||
export * from './user-preference-cloud.service';
|
export * from './user-preference-cloud.service';
|
||||||
export * from './variable-mapper.sevice';
|
export * from './variable-mapper.sevice';
|
||||||
|
@@ -1,32 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Copyright © 2005-2025 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { TestBed } from '@angular/core/testing';
|
|
||||||
import { ScreenRenderingService } from './screen-rendering.service';
|
|
||||||
|
|
||||||
describe('ScreenRenderingService', () => {
|
|
||||||
let service: ScreenRenderingService;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({});
|
|
||||||
service = TestBed.inject(ScreenRenderingService);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be created', () => {
|
|
||||||
expect(service).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,24 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Copyright © 2005-2025 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { DynamicComponentMapper } from '@alfresco/adf-core';
|
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root'
|
|
||||||
})
|
|
||||||
export class ScreenRenderingService extends DynamicComponentMapper {}
|
|
Reference in New Issue
Block a user