[AAE-7241] fix eslint warnings for Extensions project (#7491)

* fix eslint warnings for Extensions project

* fix production mode compilation
This commit is contained in:
Denys Vuika
2022-02-08 12:05:33 +00:00
committed by GitHub
parent 8a03e7a2e7
commit 8048cbeb21
17 changed files with 109 additions and 134 deletions

View File

@@ -20,18 +20,7 @@
"eslint-plugin-rxjs" "eslint-plugin-rxjs"
], ],
"rules": { "rules": {
"jsdoc/newline-after-description": "warn", "no-underscore-dangle": ["error", { "allowAfterThis": true }],
"@typescript-eslint/naming-convention": "warn",
"@typescript-eslint/consistent-type-assertions": "warn",
"@typescript-eslint/prefer-for-of": "warn",
"no-underscore-dangle": "warn",
"no-shadow": "warn",
"quote-props": "warn",
"object-shorthand": "warn",
"prefer-const": "warn",
"arrow-body-style": "warn",
"@angular-eslint/no-output-native": "warn",
"space-before-function-paren": "warn",
"@angular-eslint/component-selector": [ "@angular-eslint/component-selector": [
"error", "error",

View File

@@ -93,7 +93,7 @@ describe('DynamicExtensionComponent', () => {
component.ngOnChanges({}); component.ngOnChanges({});
fixture.detectChanges(); fixture.detectChanges();
expect((<any> componentFactoryResolver.resolveComponentFactory).calls.count()).toBe(1); expect((componentFactoryResolver.resolveComponentFactory as any).calls.count()).toBe(1);
}); });
it('should pass through the data', () => { it('should pass through the data', () => {

View File

@@ -63,6 +63,13 @@ export class DynamicExtensionComponent implements OnChanges, OnDestroy {
this.proxy('ngOnChanges', changes); this.proxy('ngOnChanges', changes);
} }
ngOnDestroy() {
if (this.componentCreated()) {
this.componentRef.destroy();
this.componentRef = null;
}
}
private loadComponent() { private loadComponent() {
const componentType = this.extensions.getComponentById<ExtensionComponent>(this.id); const componentType = this.extensions.getComponentById<ExtensionComponent>(this.id);
if (componentType) { if (componentType) {
@@ -76,13 +83,6 @@ export class DynamicExtensionComponent implements OnChanges, OnDestroy {
} }
} }
ngOnDestroy() {
if (this.componentCreated()) {
this.componentRef.destroy();
this.componentRef = null;
}
}
private updateInstance() { private updateInstance() {
if (this.componentCreated()) { if (this.componentCreated()) {
this.componentRef.instance.data = this.data; this.componentRef.instance.data = this.data;

View File

@@ -17,6 +17,7 @@
import { ExtensionElement } from './extension-element'; import { ExtensionElement } from './extension-element';
// eslint-disable-next-line no-shadow
export enum ContentActionType { export enum ContentActionType {
default = 'default', default = 'default',
button = 'button', button = 'button',
@@ -36,13 +37,13 @@ export interface ContentActionRef extends ExtensionElement {
data?: any; data?: any;
color?: string; color?: string;
actions?: { actions?: {
click?: string;
[key: string]: string; [key: string]: string;
click?: string;
}; };
rules?: { rules?: {
[key: string]: string;
enabled?: string; enabled?: string;
visible?: string; visible?: string;
[key: string]: string;
}; };
} }

View File

@@ -45,8 +45,8 @@ describe('Extension Utils', () => {
}); });
it('should not process special properties starting with $', () => { it('should not process special properties starting with $', () => {
const obj1 = { '$id': 'uid', aHello: 1 }; const obj1 = { $id: 'uid', aHello: 1 };
const obj2 = { '$schema': 'schema-id', bWorld: 2 }; const obj2 = { $schema: 'schema-id', bWorld: 2 };
const result = mergeObjects(obj1, obj2); const result = mergeObjects(obj1, obj2);

View File

@@ -17,7 +17,7 @@
import { ContentActionRef, ContentActionType } from './action.extensions'; import { ContentActionRef, ContentActionType } from './action.extensions';
export function getValue(target: any, key: string): any { export const getValue = (target: any, key: string): any => {
if (!target) { if (!target) {
return undefined; return undefined;
} }
@@ -42,27 +42,25 @@ export function getValue(target: any, key: string): any {
} while (keys.length); } while (keys.length);
return target; return target;
} };
export function filterEnabled(entry: { disabled?: boolean }): boolean { export const filterEnabled = (entry: { disabled?: boolean }): boolean => !entry.disabled;
return !entry.disabled;
}
export function sortByOrder( export const sortByOrder = (
a: { order?: number | undefined }, a: { order?: number | undefined },
b: { order?: number | undefined } b: { order?: number | undefined }
) { ) => {
const left = a.order === undefined ? Number.MAX_SAFE_INTEGER : a.order; const left = a.order === undefined ? Number.MAX_SAFE_INTEGER : a.order;
const right = b.order === undefined ? Number.MAX_SAFE_INTEGER : b.order; const right = b.order === undefined ? Number.MAX_SAFE_INTEGER : b.order;
return left - right; return left - right;
} };
export function reduceSeparators( export const reduceSeparators = (
acc: ContentActionRef[], acc: ContentActionRef[],
el: ContentActionRef, el: ContentActionRef,
i: number, i: number,
arr: ContentActionRef[] arr: ContentActionRef[]
): ContentActionRef[] { ): ContentActionRef[] => {
// remove leading separator // remove leading separator
if (i === 0) { if (i === 0) {
if (arr[i].type === ContentActionType.separator) { if (arr[i].type === ContentActionType.separator) {
@@ -88,21 +86,21 @@ export function reduceSeparators(
} }
return acc.concat(el); return acc.concat(el);
} };
export function reduceEmptyMenus( export const reduceEmptyMenus = (
acc: ContentActionRef[], acc: ContentActionRef[],
el: ContentActionRef el: ContentActionRef
): ContentActionRef[] { ): ContentActionRef[] => {
if (el.type === ContentActionType.menu) { if (el.type === ContentActionType.menu) {
if ((el.children || []).length === 0) { if ((el.children || []).length === 0) {
return acc; return acc;
} }
} }
return acc.concat(el); return acc.concat(el);
} };
export function mergeObjects(...objects: any[]): any { export const mergeObjects = (...objects: any[]): any => {
const result = {}; const result = {};
objects.forEach((source) => { objects.forEach((source) => {
@@ -129,9 +127,9 @@ export function mergeObjects(...objects: any[]): any {
}); });
return result; return result;
} };
export function mergeArrays(left: any[], right: any[]): any[] { export const mergeArrays = (left: any[], right: any[]): any[] => {
const result = []; const result = [];
const map = {}; const map = {};
@@ -155,4 +153,4 @@ export function mergeArrays(left: any[], right: any[]): any[] {
}); });
return Object.keys(map).map((key) => map[key]).concat(result); return Object.keys(map).map((key) => map[key]).concat(result);
} };

View File

@@ -23,7 +23,7 @@ export interface SidebarTabRef extends ExtensionElement {
icon?: string; icon?: string;
rules?: { rules?: {
visible?: string;
[key: string]: string; [key: string]: string;
visible?: string;
}; };
} }

View File

@@ -22,7 +22,7 @@ export interface ViewerExtensionRef extends ExtensionElement {
component: string; component: string;
rules?: { rules?: {
visible?: string;
[key: string]: string; [key: string]: string;
visible?: string;
}; };
} }

View File

@@ -21,7 +21,7 @@ import { RuleParameter } from '../config/rule.extensions';
describe('Core Evaluators', () => { describe('Core Evaluators', () => {
const context: any = { const context: any = {
getEvaluator(key: string) { getEvaluator: (key: string) => {
switch (key) { switch (key) {
case 'positive': case 'positive':
return () => true; return () => true;

View File

@@ -17,7 +17,7 @@
import { RuleContext, RuleParameter } from '../config/rule.extensions'; import { RuleContext, RuleParameter } from '../config/rule.extensions';
export function not(context: RuleContext, ...args: RuleParameter[]): boolean { export const not = (context: RuleContext, ...args: RuleParameter[]): boolean => {
if (!args || args.length === 0) { if (!args || args.length === 0) {
return false; return false;
} }
@@ -31,9 +31,9 @@ export function not(context: RuleContext, ...args: RuleParameter[]): boolean {
} }
return !evaluator(context, ...(arg.parameters || [])); return !evaluator(context, ...(arg.parameters || []));
}); });
} };
export function every(context: RuleContext, ...args: RuleParameter[]): boolean { export const every = (context: RuleContext, ...args: RuleParameter[]): boolean => {
if (!args || args.length === 0) { if (!args || args.length === 0) {
return false; return false;
} }
@@ -47,9 +47,9 @@ export function every(context: RuleContext, ...args: RuleParameter[]): boolean {
} }
return evaluator(context, ...(arg.parameters || [])); return evaluator(context, ...(arg.parameters || []));
}); });
} };
export function some(context: RuleContext, ...args: RuleParameter[]): boolean { export const some = (context: RuleContext, ...args: RuleParameter[]): boolean => {
if (!args || args.length === 0) { if (!args || args.length === 0) {
return false; return false;
} }
@@ -63,4 +63,4 @@ export function some(context: RuleContext, ...args: RuleParameter[]): boolean {
} }
return evaluator(context, ...(arg.parameters || [])); return evaluator(context, ...(arg.parameters || []));
}); });
} };

View File

@@ -24,9 +24,8 @@ import { ViewerExtensionRef } from '../config/viewer.extensions';
providedIn: 'root' providedIn: 'root'
}) })
export class AppExtensionServiceMock { export class AppExtensionServiceMock {
private _references = new BehaviorSubject<ExtensionRef[]>([]);
references$: Observable<ExtensionRef[]>; references$: Observable<ExtensionRef[]>;
private _references = new BehaviorSubject<ExtensionRef[]>([]);
constructor() { constructor() {
this.references$ = this._references.asObservable(); this.references$ = this._references.asObservable();
@@ -35,5 +34,4 @@ export class AppExtensionServiceMock {
getViewerExtensions(): ViewerExtensionRef[] { getViewerExtensions(): ViewerExtensionRef[] {
return []; return [];
} }
} }

View File

@@ -26,9 +26,8 @@ import { DocumentListPresetRef } from '../config/document-list.extensions';
providedIn: 'root' providedIn: 'root'
}) })
export class AppExtensionService { export class AppExtensionService {
private _references = new BehaviorSubject<ExtensionRef[]>([]);
references$: Observable<ExtensionRef[]>; references$: Observable<ExtensionRef[]>;
private _references = new BehaviorSubject<ExtensionRef[]>([]);
constructor(protected extensionService: ExtensionService) { constructor(protected extensionService: ExtensionService) {
this.references$ = this._references.asObservable(); this.references$ = this._references.asObservable();
@@ -46,13 +45,14 @@ export class AppExtensionService {
const references = (config.$references || []) const references = (config.$references || [])
.filter((entry) => typeof entry === 'object') .filter((entry) => typeof entry === 'object')
.map((entry) => <ExtensionRef> entry); .map((entry) => entry as ExtensionRef);
this._references.next(references); this._references.next(references);
} }
/** /**
* Provides a collection of document list columns for the particular preset. * Provides a collection of document list columns for the particular preset.
* The result is filtered by the **disabled** state. * The result is filtered by the **disabled** state.
*
* @param key Preset key. * @param key Preset key.
*/ */
getDocumentListPreset(key: string): DocumentListPresetRef[] { getDocumentListPreset(key: string): DocumentListPresetRef[] {

View File

@@ -79,38 +79,6 @@ export class ExtensionLoaderService {
}); });
} }
protected getMetadata(config: ExtensionConfig): ExtensionRef {
const result: any = {};
Object
.keys(config)
.filter((key) => key.startsWith('$'))
.forEach((key) => {
result[key] = config[key];
});
return result;
}
protected loadConfig(
url: string,
order: number
): Promise<{ order: number; config: ExtensionConfig }> {
return new Promise((resolve) => {
this.http.get<ExtensionConfig>(url).subscribe(
(config) => {
resolve({
order,
config
});
},
() => {
resolve(null);
}
);
});
}
/** /**
* Retrieves configuration elements. * Retrieves configuration elements.
* Filters element by **enabled** and **order** attributes. * Filters element by **enabled** and **order** attributes.
@@ -161,6 +129,38 @@ export class ExtensionLoaderService {
return []; return [];
} }
protected getMetadata(config: ExtensionConfig): ExtensionRef {
const result: any = {};
Object
.keys(config)
.filter((key) => key.startsWith('$'))
.forEach((key) => {
result[key] = config[key];
});
return result;
}
protected loadConfig(
url: string,
order: number
): Promise<{ order: number; config: ExtensionConfig }> {
return new Promise((resolve) => {
this.http.get<ExtensionConfig>(url).subscribe(
(config) => {
resolve({
order,
config
});
},
() => {
resolve(null);
}
);
});
}
protected setActionDefaults(action: ContentActionRef): ContentActionRef { protected setActionDefaults(action: ContentActionRef): ContentActionRef {
if (action) { if (action) {
action.type = action.type || ContentActionType.default; action.type = action.type || ContentActionType.default;

View File

@@ -47,10 +47,7 @@ describe('ExtensionService', () => {
}); });
it('should load and setup a config', async () => { it('should load and setup a config', async () => {
spyOn(loader, 'load').and.callFake(() => { spyOn(loader, 'load').and.callFake(() => Promise.resolve(blankConfig));
return Promise.resolve(blankConfig);
});
spyOn(service, 'setup').and.stub(); spyOn(service, 'setup').and.stub();
await service.load(); await service.load();
@@ -82,8 +79,8 @@ describe('ExtensionService', () => {
const evaluator2 = () => false; const evaluator2 = () => false;
service.setEvaluators({ service.setEvaluators({
'eval1': evaluator1, eval1: evaluator1,
'eval2': evaluator2 eval2: evaluator2
}); });
expect(service.getEvaluator('eval1')).toBe(evaluator1); expect(service.getEvaluator('eval1')).toBe(evaluator1);
@@ -100,7 +97,7 @@ describe('ExtensionService', () => {
service.setEvaluators({ service.setEvaluators({
'core.every': evaluator1, 'core.every': evaluator1,
'eval2': evaluator2 eval2: evaluator2
}); });
expect(service.getEvaluator('core.every')).toBe(evaluator1); expect(service.getEvaluator('core.every')).toBe(evaluator1);
@@ -111,7 +108,7 @@ describe('ExtensionService', () => {
const positive = () => true; const positive = () => true;
service.setEvaluators({ service.setEvaluators({
'positive': positive positive
}); });
let evaluator = service.getEvaluator('positive'); let evaluator = service.getEvaluator('positive');
@@ -136,8 +133,8 @@ describe('ExtensionService', () => {
const guard2: any = {}; const guard2: any = {};
service.setAuthGuards({ service.setAuthGuards({
'auth1': guard1, auth1: guard1,
'auth2': guard2 auth2: guard2
}); });
registered = service.getAuthGuards(['auth1', 'auth2']); registered = service.getAuthGuards(['auth1', 'auth2']);
@@ -151,13 +148,13 @@ describe('ExtensionService', () => {
const guard2: any = {}; const guard2: any = {};
service.setAuthGuards({ service.setAuthGuards({
'auth': guard1 auth: guard1
}); });
expect(service.getAuthGuards(['auth'])).toEqual([guard1]); expect(service.getAuthGuards(['auth'])).toEqual([guard1]);
service.setAuthGuards({ service.setAuthGuards({
'auth': guard2 auth: guard2
}); });
expect(service.getAuthGuards(['auth'])).toEqual([guard2]); expect(service.getAuthGuards(['auth'])).toEqual([guard2]);
@@ -167,7 +164,7 @@ describe('ExtensionService', () => {
const guard1: any = {}; const guard1: any = {};
service.setAuthGuards({ service.setAuthGuards({
'auth': guard1 auth: guard1
}); });
service.setAuthGuards(null); service.setAuthGuards(null);
@@ -184,7 +181,7 @@ describe('ExtensionService', () => {
const component: any = {}; const component: any = {};
service.setComponents({ service.setComponents({
'component1': component component1: component
}); });
expect(service.getComponentById('component1')).toBe(component); expect(service.getComponentById('component1')).toBe(component);
@@ -195,13 +192,13 @@ describe('ExtensionService', () => {
const component2: any = {}; const component2: any = {};
service.setComponents({ service.setComponents({
'component': component1 component: component1
}); });
expect(service.getComponentById('component')).toBe(component1); expect(service.getComponentById('component')).toBe(component1);
service.setComponents({ service.setComponents({
'component': component2 component: component2
}); });
expect(service.getComponentById('component')).toBe(component2); expect(service.getComponentById('component')).toBe(component2);
@@ -211,7 +208,7 @@ describe('ExtensionService', () => {
const component: any = {}; const component: any = {};
service.setComponents({ service.setComponents({
'component1': component component1: component
}); });
expect(service.getComponentById('component1')).toBe(component); expect(service.getComponentById('component1')).toBe(component);
@@ -266,9 +263,7 @@ describe('ExtensionService', () => {
}); });
const context: any = { const context: any = {
getEvaluator(key: string) { getEvaluator: (key: string) => service.getEvaluator(key)
return service.getEvaluator(key);
}
}; };
const result = service.evaluateRule('test.condition', context); const result = service.evaluateRule('test.condition', context);
@@ -277,9 +272,7 @@ describe('ExtensionService', () => {
it('should evaluate missing condition as [false]', () => { it('should evaluate missing condition as [false]', () => {
const context: any = { const context: any = {
getEvaluator(key: string) { getEvaluator: (key: string) => service.getEvaluator(key)
return service.getEvaluator(key);
}
}; };
const result = service.evaluateRule('missing.condition', context); const result = service.evaluateRule('missing.condition', context);
@@ -308,9 +301,7 @@ describe('ExtensionService', () => {
}); });
const context: any = { const context: any = {
getEvaluator(key: string) { getEvaluator: (key: string) => service.getEvaluator(key)
return service.getEvaluator(key);
}
}; };
const result = service.evaluateRule('test.rule', context); const result = service.evaluateRule('test.rule', context);
@@ -327,9 +318,7 @@ describe('ExtensionService', () => {
service.setup(blankConfig); service.setup(blankConfig);
const context: any = { const context: any = {
getEvaluator(key: string) { getEvaluator: (key: string) => service.getEvaluator(key)
return service.getEvaluator(key);
}
}; };
const result = service.evaluateRule('test.rule', context); const result = service.evaluateRule('test.rule', context);
@@ -352,9 +341,7 @@ describe('ExtensionService', () => {
service.setup(blankConfig); service.setup(blankConfig);
const context: any = { const context: any = {
getEvaluator(key: string) { getEvaluator: (key: string) => service.getEvaluator(key)
return service.getEvaluator(key);
}
}; };
const result = service.evaluateRule('test.rule', context); const result = service.evaluateRule('test.rule', context);

View File

@@ -25,32 +25,31 @@ import * as core from '../evaluators/core.evaluators';
import { ComponentRegisterService } from './component-register.service'; import { ComponentRegisterService } from './component-register.service';
import { RuleService } from './rule.service'; import { RuleService } from './rule.service';
import { ExtensionElement } from '../config/extension-element'; import { ExtensionElement } from '../config/extension-element';
import { BehaviorSubject } from 'rxjs'; import { BehaviorSubject, Observable } from 'rxjs';
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
export function extensionJsonsFactory() { export function extensionJsonsFactory() {
return []; return [];
} };
export const EXTENSION_JSONS = new InjectionToken<string[][]>('extension-jsons', { export const EXTENSION_JSONS = new InjectionToken<string[][]>('extension-jsons', {
providedIn: 'root', providedIn: 'root',
factory: extensionJsonsFactory factory: extensionJsonsFactory
}); });
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
export function provideExtensionConfig(jsons: string[]) { export function provideExtensionConfig(jsons: string[]) {
return { return {
provide: EXTENSION_JSONS, provide: EXTENSION_JSONS,
useValue: jsons, useValue: jsons,
multi: true multi: true
}; };
} };
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class ExtensionService { export class ExtensionService {
protected config: ExtensionConfig = null;
configPath = 'assets/app.extensions.json'; configPath = 'assets/app.extensions.json';
pluginsPath = 'assets/plugins'; pluginsPath = 'assets/plugins';
@@ -59,8 +58,10 @@ export class ExtensionService {
features: Array<any> = []; features: Array<any> = [];
authGuards: { [key: string]: Type<any> } = {}; authGuards: { [key: string]: Type<any> } = {};
setup$: Observable<ExtensionConfig>;
protected config: ExtensionConfig = null;
protected onSetup$ = new BehaviorSubject<ExtensionConfig>(this.config); protected onSetup$ = new BehaviorSubject<ExtensionConfig>(this.config);
setup$ = this.onSetup$.asObservable();
constructor( constructor(
protected loader: ExtensionLoaderService, protected loader: ExtensionLoaderService,
@@ -68,6 +69,7 @@ export class ExtensionService {
protected ruleService: RuleService, protected ruleService: RuleService,
@Inject(EXTENSION_JSONS) protected extensionJsons: string[] @Inject(EXTENSION_JSONS) protected extensionJsons: string[]
) { ) {
this.setup$ = this.onSetup$.asObservable();
} }
/** /**

View File

@@ -36,6 +36,7 @@ export class RuleService {
/** /**
* Adds one or more new rule evaluators to the existing set. * Adds one or more new rule evaluators to the existing set.
*
* @param values The new evaluators to add * @param values The new evaluators to add
*/ */
setEvaluators(values: { [key: string]: RuleEvaluator }) { setEvaluators(values: { [key: string]: RuleEvaluator }) {
@@ -46,6 +47,7 @@ export class RuleService {
/** /**
* Retrieves a rule using its ID value. * Retrieves a rule using its ID value.
*
* @param id The ID value to look for * @param id The ID value to look for
* @returns The rule or null if not found * @returns The rule or null if not found
*/ */
@@ -55,21 +57,21 @@ export class RuleService {
/** /**
* Retrieves a RuleEvaluator function using its key name. * Retrieves a RuleEvaluator function using its key name.
*
* @param key Key name to look for * @param key Key name to look for
* @returns RuleEvaluator or null if not found * @returns RuleEvaluator or null if not found
*/ */
getEvaluator(key: string): RuleEvaluator { getEvaluator(key: string): RuleEvaluator {
if (key && key.startsWith('!')) { if (key && key.startsWith('!')) {
const fn = this.evaluators[key.substring(1)]; const fn = this.evaluators[key.substring(1)];
return (context: RuleContext, ...args: RuleParameter[]): boolean => { return (context: RuleContext, ...args: RuleParameter[]): boolean => !fn(context, ...args);
return !fn(context, ...args);
};
} }
return this.evaluators[key]; return this.evaluators[key];
} }
/** /**
* Evaluates a rule. * Evaluates a rule.
*
* @param ruleId ID of the rule to evaluate * @param ruleId ID of the rule to evaluate
* @param context Custom rule execution context. * @param context Custom rule execution context.
* @returns True if the rule passed, false otherwise * @returns True if the rule passed, false otherwise

View File

@@ -17,6 +17,4 @@
import { AppExtensionService } from './app-extension.service'; import { AppExtensionService } from './app-extension.service';
export function setupExtensions(appExtensionService: AppExtensionService) { export const setupExtensions = (appExtensionService: AppExtensionService) => () => appExtensionService.load();
return () => appExtensionService.load();
}