[AAE-7101] - Introduced Eslint to ACA and added some fix to avoid errors (#2424)

* Conversion to ESlint

* Fixed ESLINT for ACA

* [AAE-6638] - typo in eslint file

* [AAE-6638] - attempt to fix problem on linting

* Check caching to improve lint speed

* Improved eslint for content-app

* Added new cache

* Remove cache file

* Removed eslintcache

* Attempt to make eslint run on travis

* Slow ng lint on travis

* Fixed eslint error
This commit is contained in:
Vito 2022-02-09 08:40:04 +00:00 committed by GitHub
parent fde64be498
commit 23262d0949
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
72 changed files with 3979 additions and 702 deletions

11
.eslintignore Normal file
View File

@ -0,0 +1,11 @@
node_modules
e2e-output
dist
coverage
.github
.travis
.vscode
scripts
src/assets/i18n
/angular.json
docs/**/*.md

142
.eslintrc.json Normal file
View File

@ -0,0 +1,142 @@
{
"root": true,
"ignorePatterns": [
"projects/**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"createDefaultProgram": true
},
"extends": [
"plugin:@angular-eslint/ng-cli-compat",
"plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
"plugin:@angular-eslint/template/process-inline-templates"
],
"plugins": [
"eslint-plugin-react",
"eslint-plugin-rxjs",
"eslint-plugin-unicorn",
"prettier"
],
"rules": {
"prettier/prettier": "error",
"no-shadow": "off",
"@typescript-eslint/no-shadow": "error",
"prefer-arrow/prefer-arrow-functions": [
"warn",
{
"disallowPrototype": true,
"singleReturnOnly": true,
"classPropertiesAllowed": false
}
],
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": [
"app",
"aca",
"adf"
],
"style": "kebab-case"
}
],
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "aca",
"style": "camelCase"
}
],
"@angular-eslint/no-host-metadata-property": "off",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/member-ordering": "off",
"@typescript-eslint/explicit-member-accessibility": [
"off",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/member-delimiter-style": [
"off",
{
"multiline": {
"delimiter": "none",
"requireLast": true
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
],
"@typescript-eslint/semi": [
"off",
null
],
"@typescript-eslint/naming-convention":[
"error",
{
"selector": "enum",
"format": ["PascalCase"]
}
],
"@typescript-eslint/type-annotation-spacing": "off",
"arrow-parents": [
"off",
"always"
],
"brace-style": [
"off",
"off"
],
"eol-last": "off",
"id-blacklist": "off",
"id-match": "off",
"linebreak-style": "off",
"max-len": "off",
"new-parens": "off",
"newline-per-chained-call": "off",
"no-duplicate-imports": "error",
"no-extra-semi": "off",
"no-irregular-whitespace": "off",
"no-return-await": "error",
"no-underscore-dangle": "off",
"quote-props": "off",
"react/jsx-curly-spacing": "off",
"react/jsx-equals-spacing": "off",
"react/jsx-wrap-multilines": "off",
"rxjs/no-create": "error",
"rxjs/no-subject-unsubscribe": "error",
"rxjs/no-subject-value": "error",
"rxjs/no-unsafe-takeuntil": "error",
"space-before-function-paren": "off",
"space-in-parens": [
"off",
"never"
],
"unicorn/filename-case": "error"
}
},
{
"files": [
"*.html"
],
"extends": [
"plugin:@angular-eslint/template/recommended"
],
"rules": {
"@angular-eslint/template/no-autofocus": "error",
"@angular-eslint/template/no-negated-async": "off",
"@angular-eslint/template/no-positive-tabindex": "error"
}
}
]
}

1
.gitignore vendored
View File

@ -40,6 +40,7 @@ testem.log
/typings /typings
/www /www
.env .env
.eslintcache
# e2e # e2e
/e2e/*.map /e2e/*.map

View File

@ -266,16 +266,15 @@
} }
}, },
"lint": { "lint": {
"builder": "@angular-devkit/build-angular:tslint", "builder": "@angular-eslint/builder:lint",
"options": { "options": {
"tsConfig": [ "lintFilePatterns": [
"app/tsconfig.app.json", "app/**/*.ts",
"app/tsconfig.spec.json" "app/**/*.html"
], ],
"exclude": [ "cache": true,
"**/node_modules/**", "cacheLocation": ".eslintcache",
"package.json" "ignorePath": ".eslintignore"
]
} }
} }
} }
@ -307,15 +306,15 @@
} }
}, },
"lint": { "lint": {
"builder": "@angular-devkit/build-angular:tslint", "builder": "@angular-eslint/builder:lint",
"options": { "options": {
"tsConfig": [ "lintFilePatterns": [
"e2e/tsconfig.e2e.json" "e2e/**/*.ts",
"e2e/**/*.html"
], ],
"exclude": [ "cache": true,
"**/node_modules/**", "cacheLocation": ".eslintcache",
"package.json" "ignorePath": ".eslintignore"
]
} }
} }
} }
@ -347,15 +346,15 @@
} }
}, },
"lint": { "lint": {
"builder": "@angular-devkit/build-angular:tslint", "builder": "@angular-eslint/builder:lint",
"options": { "options": {
"tsConfig": [ "lintFilePatterns": [
"projects/adf-office-services-ext/tsconfig.lib.json", "projects/adf-office-services-ext/**/*.ts",
"projects/adf-office-services-ext/tsconfig.spec.json" "projects/adf-office-services-ext/**/*.html"
], ],
"exclude": [ "cache": true,
"**/node_modules/**" "cacheLocation": ".eslintcache",
] "ignorePath": ".eslintignore"
} }
} }
} }
@ -387,15 +386,15 @@
} }
}, },
"lint": { "lint": {
"builder": "@angular-devkit/build-angular:tslint", "builder": "@angular-eslint/builder:lint",
"options": { "options": {
"tsConfig": [ "lintFilePatterns": [
"projects/aca-shared/tsconfig.lib.json", "projects/aca-shared/**/*.ts",
"projects/aca-shared/tsconfig.spec.json" "projects/aca-shared/**/*.html"
], ],
"exclude": [ "cache": true,
"**/node_modules/**" "cacheLocation": ".eslintcache",
] "ignorePath": ".eslintignore"
} }
} }
} }
@ -433,15 +432,15 @@
} }
}, },
"lint": { "lint": {
"builder": "@angular-devkit/build-angular:tslint", "builder": "@angular-eslint/builder:lint",
"options": { "options": {
"tsConfig": [ "lintFilePatterns": [
"projects/aca-about/tsconfig.lib.json", "projects/aca-about/**/*.ts",
"projects/aca-about/tsconfig.spec.json" "projects/aca-about/**/*.html"
], ],
"exclude": [ "cache": true,
"**/node_modules/**" "cacheLocation": ".eslintcache",
] "ignorePath": ".eslintignore"
} }
} }
} }
@ -473,15 +472,15 @@
} }
}, },
"lint": { "lint": {
"builder": "@angular-devkit/build-angular:tslint", "builder": "@angular-eslint/builder:lint",
"options": { "options": {
"tsConfig": [ "lintFilePatterns": [
"projects/aca-settings/tsconfig.lib.json", "projects/aca-settings/**/*.ts",
"projects/aca-settings/tsconfig.spec.json" "projects/aca-settings/**/*.html"
], ],
"exclude": [ "cache": true,
"**/node_modules/**" "cacheLocation": ".eslintcache",
] "ignorePath": ".eslintignore"
} }
} }
} }

118
app/.eslintrc.json Normal file
View File

@ -0,0 +1,118 @@
{
"extends": "../.eslintrc.json",
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"project": [
"app/tsconfig.app.json",
"app/tsconfig.spec.json"
],
"createDefaultProgram": true
},
"plugins": [
"eslint-plugin-react",
"eslint-plugin-rxjs",
"eslint-plugin-unicorn"
],
"rules": {
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": [
"app",
"aca",
"adf"
],
"style": "kebab-case"
}
],
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "aca",
"style": "camelCase"
}
],
"@angular-eslint/no-host-metadata-property": "off",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/explicit-member-accessibility": [
"off",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/member-delimiter-style": [
"off",
{
"multiline": {
"delimiter": "none",
"requireLast": true
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
],
"@typescript-eslint/semi": [
"off",
null
],
"@typescript-eslint/type-annotation-spacing": "off",
"arrow-parens": [
"off",
"always"
],
"brace-style": [
"off",
"off"
],
"eol-last": "off",
"id-blacklist": "off",
"id-match": "off",
"linebreak-style": "off",
"max-len": "off",
"new-parens": "off",
"newline-per-chained-call": "off",
"no-duplicate-imports": "error",
"no-extra-semi": "off",
"no-irregular-whitespace": "off",
"no-return-await": "error",
"no-underscore-dangle": "off",
"quote-props": "off",
"react/jsx-curly-spacing": "off",
"react/jsx-equals-spacing": "off",
"react/jsx-wrap-multilines": "off",
"rxjs/no-create": "error",
"rxjs/no-subject-unsubscribe": "error",
"rxjs/no-subject-value": "error",
"rxjs/no-unsafe-takeuntil": "error",
"space-before-function-paren": "off",
"space-in-parens": [
"off",
"never"
],
"unicorn/filename-case": "error"
}
},
{
"files": [
"*.html"
],
"rules": {
"@angular-eslint/template/no-autofocus": "error",
"@angular-eslint/template/no-negated-async": "off",
"@angular-eslint/template/no-positive-tabindex": "error"
}
}
]
}

View File

@ -90,7 +90,7 @@ export class AppComponent implements OnInit, OnDestroy {
} }
this.router.navigate(['/login'], { this.router.navigate(['/login'], {
queryParams: { redirectUrl: redirectUrl } queryParams: { redirectUrl }
}); });
} }
} }

View File

@ -57,7 +57,7 @@ export class OutsideEventDirective implements OnInit, OnDestroy {
if (el.classList.contains(className)) { if (el.classList.contains(className)) {
return true; return true;
} }
// tslint:disable-next-line:curly // eslint-disable-next-line curly
while ((el = el.parentElement) && !el.classList.contains(className)); while ((el = el.parentElement) && !el.classList.contains(className));
return !!el; return !!el;
} }

View File

@ -59,9 +59,7 @@ describe('CustomNameColumnComponent', () => {
id: 'nodeId' id: 'nodeId'
} }
}, },
getValue(key: string) { getValue: (key: string) => key
return key;
}
} }
}; };
@ -79,9 +77,7 @@ describe('CustomNameColumnComponent', () => {
id: 'nodeId' id: 'nodeId'
} }
}, },
getValue(key: string) { getValue: (key: string) => key
return key;
}
} }
}; };
@ -100,9 +96,7 @@ describe('CustomNameColumnComponent', () => {
properties: { 'cm:lockType': 'WRITE_LOCK' } properties: { 'cm:lockType': 'WRITE_LOCK' }
} }
}, },
getValue(key: string) { getValue: (key: string) => key
return key;
}
} }
}; };

View File

@ -69,9 +69,7 @@ export class CustomNameColumnComponent extends NameColumnComponent implements On
this.actions$ this.actions$
.pipe( .pipe(
ofType<any>(NodeActionTypes.EditOffline), ofType<any>(NodeActionTypes.EditOffline),
filter((val) => { filter((val) => this.node.entry.id === val.payload.entry.id),
return this.node.entry.id === val.payload.entry.id;
}),
takeUntil(this.onDestroy$$) takeUntil(this.onDestroy$$)
) )
.subscribe(() => { .subscribe(() => {

View File

@ -75,9 +75,7 @@ export class FavoritesComponent extends PageComponent implements OnInit {
const { isFolder, id } = favorite; const { isFolder, id } = favorite;
// TODO: rework as it will fail on non-English setups // TODO: rework as it will fail on non-English setups
const isSitePath = (path: PathInfo): boolean => { const isSitePath = (path: PathInfo): boolean => path && path.elements && path.elements.some(({ name }: PathElementEntity) => name === 'Sites');
return path && path.elements && path.elements.some(({ name }: PathElementEntity) => name === 'Sites');
};
if (isFolder) { if (isFolder) {
this.contentApi this.contentApi

View File

@ -250,9 +250,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
} }
onContentCopied(nodes: MinimalNodeEntity[]) { onContentCopied(nodes: MinimalNodeEntity[]) {
const newNode = nodes.find((node) => { const newNode = nodes.find((node) => node && node.entry && node.entry.parentId === this.getParentNodeId());
return node && node.entry && node.entry.parentId === this.getParentNodeId();
});
if (newNode) { if (newNode) {
this.reload(this.selectedNode); this.reload(this.selectedNode);
} }
@ -265,9 +263,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
if (node && node.path && node.path.elements) { if (node && node.path && node.path.elements) {
const elements = node.path.elements; const elements = node.path.elements;
this.nodePath = elements.map((pathElement) => { this.nodePath = elements.map((pathElement) => Object.assign({}, pathElement));
return Object.assign({}, pathElement);
});
if (elements.length > 1) { if (elements.length > 1) {
if (elements[1].name === 'User Homes') { if (elements[1].name === 'User Homes') {

View File

@ -75,9 +75,7 @@ describe('AppHeaderComponent', () => {
] ]
}); });
store.select.and.callFake((memoizeFn) => { store.select.and.callFake((memoizeFn) => of(memoizeFn({ app })));
return of(memoizeFn({ app }));
});
fixture = TestBed.createComponent(AppHeaderComponent); fixture = TestBed.createComponent(AppHeaderComponent);
component = fixture.componentInstance; component = fixture.componentInstance;

View File

@ -46,7 +46,7 @@ import {
} from '@alfresco/aca-shared/store'; } from '@alfresco/aca-shared/store';
import { isLocked, isLibrary, AppExtensionService } from '@alfresco/aca-shared'; import { isLocked, isLibrary, AppExtensionService } from '@alfresco/aca-shared';
/* tslint:disable:directive-class-suffix */ /* eslint-disable @angular-eslint/directive-class-suffix */
@Directive() @Directive()
export abstract class PageComponent implements OnInit, OnDestroy, OnChanges { export abstract class PageComponent implements OnInit, OnDestroy, OnChanges {
onDestroy$: Subject<boolean> = new Subject<boolean>(); onDestroy$: Subject<boolean> = new Subject<boolean>();
@ -74,11 +74,7 @@ export abstract class PageComponent implements OnInit, OnDestroy, OnChanges {
ngOnInit() { ngOnInit() {
this.sharedPreviewUrl$ = this.store.select(getSharedUrl); this.sharedPreviewUrl$ = this.store.select(getSharedUrl);
this.infoDrawerOpened$ = this.store.select(isInfoDrawerOpened).pipe( this.infoDrawerOpened$ = this.store.select(isInfoDrawerOpened).pipe(map((infoDrawerState) => !this.isOutletPreviewUrl() && infoDrawerState));
map((infoDrawerState) => {
return !this.isOutletPreviewUrl() && infoDrawerState;
})
);
this.documentDisplayMode$ = this.store.select(getDocumentDisplayMode); this.documentDisplayMode$ = this.store.select(getDocumentDisplayMode);

View File

@ -167,6 +167,7 @@ export class PreviewComponent extends PageComponent implements OnInit, OnDestroy
/** /**
* Loads the particular node into the Viewer * Loads the particular node into the Viewer
*
* @param id Unique identifier for the Node to display * @param id Unique identifier for the Node to display
*/ */
async displayNode(id: string) { async displayNode(id: string) {
@ -206,6 +207,7 @@ export class PreviewComponent extends PageComponent implements OnInit, OnDestroy
/** /**
* Handles the visibility change of the Viewer component. * Handles the visibility change of the Viewer component.
*
* @param isVisible Indicator whether Viewer is visible or hidden. * @param isVisible Indicator whether Viewer is visible or hidden.
*/ */
onVisibilityChanged(isVisible: boolean): void { onVisibilityChanged(isVisible: boolean): void {
@ -253,6 +255,7 @@ export class PreviewComponent extends PageComponent implements OnInit, OnDestroy
/** /**
* Generates a node preview route based on folder and node IDs. * Generates a node preview route based on folder and node IDs.
*
* @param folderId Folder ID * @param folderId Folder ID
* @param nodeId Node ID * @param nodeId Node ID
*/ */
@ -272,6 +275,7 @@ export class PreviewComponent extends PageComponent implements OnInit, OnDestroy
/** /**
* Retrieves nearest node information for the given node and folder. * Retrieves nearest node information for the given node and folder.
*
* @param nodeId Unique identifier of the document node * @param nodeId Unique identifier of the document node
* @param folderId Unique identifier of the containing folder node. * @param folderId Unique identifier of the containing folder node.
*/ */
@ -304,6 +308,7 @@ export class PreviewComponent extends PageComponent implements OnInit, OnDestroy
/** /**
* Retrieves a list of node identifiers for the folder and data source. * Retrieves a list of node identifiers for the folder and data source.
*
* @param source Data source name. Allowed values are: personal-files, libraries, favorites, shared, recent-files. * @param source Data source name. Allowed values are: personal-files, libraries, favorites, shared, recent-files.
* @param folderId Containing folder node identifier for 'personal-files' and 'libraries' sources. * @param folderId Containing folder node identifier for 'personal-files' and 'libraries' sources.
*/ */
@ -425,6 +430,7 @@ export class PreviewComponent extends PageComponent implements OnInit, OnDestroy
/** /**
* Get the root field name from the property path. * Get the root field name from the property path.
* Example: 'property1.some.child.property' => 'property1' * Example: 'property1.some.child.property' => 'property1'
*
* @param path Property path * @param path Property path
*/ */
getRootField(path: string) { getRootField(path: string) {

View File

@ -43,7 +43,7 @@ export class SearchInputControlComponent implements OnDestroy {
/** Emitted when the search is submitted pressing ENTER button. /** Emitted when the search is submitted pressing ENTER button.
* The search term is provided as value of the event. * The search term is provided as value of the event.
*/ */
// tslint:disable-next-line: no-output-native // eslint-disable-next-line @angular-eslint/no-output-native
@Output() @Output()
submit: EventEmitter<any> = new EventEmitter(); submit: EventEmitter<any> = new EventEmitter();

View File

@ -29,7 +29,7 @@ import { Store } from '@ngrx/store';
import { AppStore } from '@alfresco/aca-shared/store'; import { AppStore } from '@alfresco/aca-shared/store';
@Directive({ @Directive({
/* tslint:disable-next-line */ /* eslint-disable-next-line */
selector: '[action]', selector: '[action]',
exportAs: 'action' exportAs: 'action'
}) })

View File

@ -59,9 +59,7 @@ export class ExpansionPanelDirective implements OnInit, OnDestroy {
hasActiveLinks() { hasActiveLinks() {
if (this.acaExpansionPanel && this.acaExpansionPanel.children) { if (this.acaExpansionPanel && this.acaExpansionPanel.children) {
return this.acaExpansionPanel.children.some((child) => { return this.acaExpansionPanel.children.some((child) => this.router.url.startsWith(child.url || child.action.payload));
return this.router.url.startsWith(child.url || child.action.payload);
});
} }
return false; return false;
} }

View File

@ -58,9 +58,7 @@ export class MenuPanelDirective implements OnInit, OnDestroy {
hasActiveLinks() { hasActiveLinks() {
if (this.acaMenuPanel && this.acaMenuPanel.children) { if (this.acaMenuPanel && this.acaMenuPanel.children) {
return this.acaMenuPanel.children.some((child) => { return this.acaMenuPanel.children.some((child) => this.router.url.startsWith(child.url || child.action.payload));
return this.router.url.startsWith(child.url || child.action.payload);
});
} }
return false; return false;
} }

View File

@ -70,7 +70,7 @@ describe('ToggleFavoriteComponent', () => {
}); });
it('should not dispatch reload if route is not specified', () => { it('should not dispatch reload if route is not specified', () => {
component.data = "['/reload_on_this_route']"; component.data = '["/reload_on_this_route"]';
router.url = '/somewhere_over_the_rainbow'; router.url = '/somewhere_over_the_rainbow';
fixture.detectChanges(); fixture.detectChanges();
@ -80,7 +80,7 @@ describe('ToggleFavoriteComponent', () => {
}); });
it('should dispatch reload if route is specified', () => { it('should dispatch reload if route is specified', () => {
component.data = "['/reload_on_this_route']"; component.data = '["/reload_on_this_route"]';
router.url = '/reload_on_this_route'; router.url = '/reload_on_this_route';
fixture.detectChanges(); fixture.detectChanges();

View File

@ -33,16 +33,6 @@ describe('TrashcanComponent', () => {
let fixture: ComponentFixture<TrashcanComponent>; let fixture: ComponentFixture<TrashcanComponent>;
let component: TrashcanComponent; let component: TrashcanComponent;
let alfrescoApi: AlfrescoApiService; let alfrescoApi: AlfrescoApiService;
let page;
beforeEach(() => {
page = {
list: {
entries: [{ entry: { id: 1 } }, { entry: { id: 2 } }],
pagination: { data: 'data' }
}
};
});
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -63,7 +53,9 @@ describe('TrashcanComponent', () => {
} as any; } as any;
}); });
beforeEach(() => { it('should perform at least a test otherwise karma will complain', async () => {
spyOn(component['nodesApi'], 'getDeletedNodes').and.returnValue(Promise.resolve(page)); fixture.detectChanges();
await fixture.whenStable();
expect(fixture.nativeElement.querySelector('adf-document-list')).not.toBeNull();
}); });
}); });

View File

@ -268,6 +268,7 @@ export class AppViewerComponent implements OnInit, OnDestroy {
/** /**
* Retrieves nearest node information for the given node and folder. * Retrieves nearest node information for the given node and folder.
*
* @param nodeId Unique identifier of the document node * @param nodeId Unique identifier of the document node
* @param folderId Unique identifier of the containing folder node. * @param folderId Unique identifier of the containing folder node.
*/ */
@ -300,6 +301,7 @@ export class AppViewerComponent implements OnInit, OnDestroy {
/** /**
* Retrieves a list of node identifiers for the folder and data source. * Retrieves a list of node identifiers for the folder and data source.
*
* @param source Data source name. Allowed values are: personal-files, libraries, favorites, shared, recent-files. * @param source Data source name. Allowed values are: personal-files, libraries, favorites, shared, recent-files.
* @param folderId Containing folder node identifier for 'personal-files' and 'libraries' sources. * @param folderId Containing folder node identifier for 'personal-files' and 'libraries' sources.
*/ */
@ -395,6 +397,7 @@ export class AppViewerComponent implements OnInit, OnDestroy {
/** /**
* Get the root field name from the property path. * Get the root field name from the property path.
* Example: 'property1.some.child.property' => 'property1' * Example: 'property1.some.child.property' => 'property1'
*
* @param path Property path * @param path Property path
*/ */
getRootField(path: string) { getRootField(path: string) {

View File

@ -33,9 +33,7 @@ import { CreateFromTemplate } from '@alfresco/aca-shared/store';
import { Node } from '@alfresco/js-api'; import { Node } from '@alfresco/js-api';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
function text(length: number) { const text = (length: number) => new Array(length).fill(Math.random().toString().substring(2, 3)).join('');
return new Array(length).fill(Math.random().toString().substring(2, 3)).join('');
}
describe('CreateFileFromTemplateDialogComponent', () => { describe('CreateFileFromTemplateDialogComponent', () => {
let fixture: ComponentFixture<CreateFromTemplateDialogComponent>; let fixture: ComponentFixture<CreateFromTemplateDialogComponent>;

View File

@ -80,8 +80,8 @@ export class CreateFromTemplateDialogComponent implements OnInit {
} }
private forbidSpecialCharacters({ value }: FormControl): ValidationErrors | null { private forbidSpecialCharacters({ value }: FormControl): ValidationErrors | null {
const specialCharacters: RegExp = /([\*\"\<\>\\\/\?\:\|])/; const specialCharacters = /([\*\"\<\>\\\/\?\:\|])/;
const isValid: boolean = !specialCharacters.test(value); const isValid = !specialCharacters.test(value);
return isValid return isValid
? null ? null
@ -102,7 +102,7 @@ export class CreateFromTemplateDialogComponent implements OnInit {
private forbidOnlySpaces({ value }: FormControl): ValidationErrors | null { private forbidOnlySpaces({ value }: FormControl): ValidationErrors | null {
if (value.length) { if (value.length) {
const isValid: boolean = !!(value || '').trim(); const isValid = !!(value || '').trim();
return isValid return isValid
? null ? null

View File

@ -55,7 +55,7 @@ import { LogoutComponent } from '../components/common/logout/logout.component';
import { AppExtensionService, ExtensionsDataLoaderGuard } from '@alfresco/aca-shared'; import { AppExtensionService, ExtensionsDataLoaderGuard } from '@alfresco/aca-shared';
import { PreviewComponent } from '../components/preview/preview.component'; import { PreviewComponent } from '../components/preview/preview.component';
export function setupExtensions(service: AppExtensionService): Function { export function setupExtensions(service: AppExtensionService): () => void {
return () => service.load(); return () => service.load();
} }

View File

@ -886,9 +886,7 @@ describe('ContentManagementService', () => {
describe('Permanent Delete', () => { describe('Permanent Delete', () => {
beforeEach(() => { beforeEach(() => {
spyOn(dialog, 'open').and.returnValue({ spyOn(dialog, 'open').and.returnValue({
afterClosed() { afterClosed: () => of(true)
return of(true);
}
} as MatDialogRef<MatDialog>); } as MatDialogRef<MatDialog>);
}); });
@ -1378,9 +1376,7 @@ describe('ContentManagementService', () => {
const node = { entry: { id: '1', name: 'name1' } } as any; const node = { entry: { id: '1', name: 'name1' } } as any;
spyOn(contentApi, 'getNodeInfo').and.returnValue(of({} as Node)); spyOn(contentApi, 'getNodeInfo').and.returnValue(of({} as Node));
spyOn(dialog, 'open').and.returnValue({ spyOn(dialog, 'open').and.returnValue({
afterClosed() { afterClosed: () => of(null)
return of(null);
}
} as MatDialogRef<MatDialog>); } as MatDialogRef<MatDialog>);
store.dispatch(new ShareNodeAction(node)); store.dispatch(new ShareNodeAction(node));
@ -1395,9 +1391,7 @@ describe('ContentManagementService', () => {
} as any; } as any;
spyOn(contentApi, 'getNodeInfo').and.returnValue(of({} as Node)); spyOn(contentApi, 'getNodeInfo').and.returnValue(of({} as Node));
spyOn(dialog, 'open').and.returnValue({ spyOn(dialog, 'open').and.returnValue({
afterClosed() { afterClosed: () => of(null)
return of(null);
}
} as MatDialogRef<MatDialog>); } as MatDialogRef<MatDialog>);
store.dispatch(new ShareNodeAction(node)); store.dispatch(new ShareNodeAction(node));
@ -1410,9 +1404,7 @@ describe('ContentManagementService', () => {
const node = { entry: { id: '1', name: 'name1' } } as NodeEntry; const node = { entry: { id: '1', name: 'name1' } } as NodeEntry;
spyOn(store, 'dispatch').and.callThrough(); spyOn(store, 'dispatch').and.callThrough();
spyOn(dialog, 'open').and.returnValue({ spyOn(dialog, 'open').and.returnValue({
afterClosed() { afterClosed: () => of(null)
return of(null);
}
} as MatDialogRef<MatDialog>); } as MatDialogRef<MatDialog>);
store.dispatch(new ShareNodeAction(node)); store.dispatch(new ShareNodeAction(node));

View File

@ -135,22 +135,6 @@ export class ContentManagementService {
} }
} }
private openVersionManagerDialog(node: any) {
// workaround Shared
if (node.isFile || node.nodeId) {
const dialogRef = this.dialogRef.open(NodeVersionsDialogComponent, {
data: { node, showVersionsOnly: true, title: 'VERSION.DIALOG_ADF.TITLE' } as NodeVersionDialogData,
panelClass: 'adf-version-manager-dialog-panel',
width: '630px'
});
dialogRef.componentInstance.refreshEvent.subscribe(() => {
this.store.dispatch(new ReloadDocumentListAction());
});
} else {
this.store.dispatch(new SnackbarErrorAction('APP.MESSAGES.ERRORS.PERMISSION'));
}
}
manageAspects(node: any) { manageAspects(node: any) {
if (node && node.entry) { if (node && node.entry) {
// shared and favorite // shared and favorite
@ -166,15 +150,6 @@ export class ContentManagementService {
} }
} }
private openAspectListDialog(node: any) {
// workaround Shared
if (node.isFile || node.id) {
this.nodeAspectService.updateNodeAspects(node.id);
} else {
this.store.dispatch(new SnackbarErrorAction('APP.MESSAGES.ERRORS.PERMISSION'));
}
}
versionUpdateDialog(node, file) { versionUpdateDialog(node, file) {
this.contentApi.getNodeVersions(node.id).subscribe(({ list }) => { this.contentApi.getNodeVersions(node.id).subscribe(({ list }) => {
this.dialogRef.open(NodeVersionsDialogComponent, { this.dialogRef.open(NodeVersionsDialogComponent, {
@ -226,7 +201,7 @@ export class ContentManagementService {
createFolder(parentNodeId: string) { createFolder(parentNodeId: string) {
const dialogInstance = this.dialogRef.open(FolderDialogComponent, { const dialogInstance = this.dialogRef.open(FolderDialogComponent, {
data: { data: {
parentNodeId: parentNodeId, parentNodeId,
createTitle: undefined, createTitle: undefined,
nodeType: 'cm:folder' nodeType: 'cm:folder'
}, },
@ -435,6 +410,66 @@ export class ContentManagementService {
); );
} }
moveNodes(nodes: Array<MinimalNodeEntity>) {
const permissionForMove = '!';
zip(this.nodeActionsService.moveNodes(nodes, permissionForMove), this.nodeActionsService.contentMoved).subscribe(
(result) => {
const [operationResult, moveResponse] = result;
this.showMoveMessage(nodes, operationResult, moveResponse);
this.store.dispatch(new ReloadDocumentListAction());
},
(error) => {
this.showMoveMessage(nodes, error);
}
);
}
getErrorMessage(errorObject: { message: any }): string {
let i18nMessageString = 'APP.MESSAGES.ERRORS.GENERIC';
try {
const {
error: { statusCode }
} = JSON.parse(errorObject.message);
if (statusCode === 409) {
i18nMessageString = 'APP.MESSAGES.ERRORS.NODE_MOVE';
} else if (statusCode === 403) {
i18nMessageString = 'APP.MESSAGES.ERRORS.PERMISSION';
}
} catch (err) {
/* Do nothing, keep the original message */
}
return i18nMessageString;
}
getNodeInfo(): Observable<MinimalNodeEntryEntity> {
return this.store.select(getAppSelection).pipe(
take(1),
mergeMap(({ file }) => {
const id = (file as any).entry.nodeId || (file as any).entry.guid;
if (!id) {
return of(file.entry);
} else {
return this.contentApi.getNodeInfo(id);
}
})
);
}
unlockNode(node: NodeEntry): Promise<void | NodeEntry> {
return this.contentApi.unlockNode(node.entry.id).catch(() => {
this.store.dispatch(
new SnackbarErrorAction('APP.MESSAGES.ERRORS.UNLOCK_NODE', {
fileName: node.entry.name
})
);
});
}
private showCopyMessage(info: any, nodes: Array<MinimalNodeEntity>, newItems?: Array<MinimalNodeEntity>) { private showCopyMessage(info: any, nodes: Array<MinimalNodeEntity>, newItems?: Array<MinimalNodeEntity>) {
const numberOfCopiedItems = newItems ? newItems.length : 0; const numberOfCopiedItems = newItems ? newItems.length : 0;
const failedItems = nodes.length - numberOfCopiedItems; const failedItems = nodes.length - numberOfCopiedItems;
@ -513,29 +548,38 @@ export class ContentManagementService {
); );
} }
moveNodes(nodes: Array<MinimalNodeEntity>) { private openVersionManagerDialog(node: any) {
const permissionForMove = '!'; // workaround Shared
if (node.isFile || node.nodeId) {
zip(this.nodeActionsService.moveNodes(nodes, permissionForMove), this.nodeActionsService.contentMoved).subscribe( const dialogRef = this.dialogRef.open(NodeVersionsDialogComponent, {
(result) => { data: { node, showVersionsOnly: true, title: 'VERSION.DIALOG_ADF.TITLE' } as NodeVersionDialogData,
const [operationResult, moveResponse] = result; panelClass: 'adf-version-manager-dialog-panel',
this.showMoveMessage(nodes, operationResult, moveResponse); width: '630px'
});
dialogRef.componentInstance.refreshEvent.subscribe(() => {
this.store.dispatch(new ReloadDocumentListAction()); this.store.dispatch(new ReloadDocumentListAction());
}, });
(error) => { } else {
this.showMoveMessage(nodes, error); this.store.dispatch(new SnackbarErrorAction('APP.MESSAGES.ERRORS.PERMISSION'));
} }
); }
private openAspectListDialog(node: any) {
// workaround Shared
if (node.isFile || node.id) {
this.nodeAspectService.updateNodeAspects(node.id);
} else {
this.store.dispatch(new SnackbarErrorAction('APP.MESSAGES.ERRORS.PERMISSION'));
}
} }
private undoMoveNodes(moveResponse, selectionParentId: string) { private undoMoveNodes(moveResponse, selectionParentId: string) {
const movedNodes = moveResponse && moveResponse['succeeded'] ? moveResponse['succeeded'] : []; const movedNodes = moveResponse && moveResponse['succeeded'] ? moveResponse['succeeded'] : [];
const partiallyMovedNodes = moveResponse && moveResponse['partiallySucceeded'] ? moveResponse['partiallySucceeded'] : []; const partiallyMovedNodes = moveResponse && moveResponse['partiallySucceeded'] ? moveResponse['partiallySucceeded'] : [];
const restoreDeletedNodesBatch = this.nodeActionsService.moveDeletedEntries.map((folderEntry) => { const restoreDeletedNodesBatch = this.nodeActionsService.moveDeletedEntries.map((folderEntry) =>
return this.contentApi.restoreNode(folderEntry.nodeId || folderEntry.id).pipe(map((node) => node.entry)); this.contentApi.restoreNode(folderEntry.nodeId || folderEntry.id).pipe(map((node) => node.entry))
}); );
zip(...restoreDeletedNodesBatch, of(null)) zip(...restoreDeletedNodesBatch, of(null))
.pipe( .pipe(
@ -627,20 +671,18 @@ export class ContentManagementService {
const { id, name } = item; const { id, name } = item;
return this.contentApi.restoreNode(id).pipe( return this.contentApi.restoreNode(id).pipe(
map(() => { map(() => ({
return { id,
id, name,
name, status: 1
status: 1 })),
}; catchError(() =>
}), of({
catchError(() => {
return of({
id, id,
name, name,
status: 0 status: 0
}); })
}) )
); );
} }
@ -707,13 +749,13 @@ export class ContentManagementService {
id, id,
name name
})), })),
catchError(() => { catchError(() =>
return of({ of({
status: 0, status: 0,
id, id,
name name
}); })
}) )
); );
} }
@ -878,20 +920,18 @@ export class ContentManagementService {
const id = node.entry.nodeId || node.entry.id; const id = node.entry.nodeId || node.entry.id;
return this.contentApi.deleteNode(id).pipe( return this.contentApi.deleteNode(id).pipe(
map(() => { map(() => ({
return { id,
id, name,
name, status: 1
status: 1 })),
}; catchError(() =>
}), of({
catchError(() => {
return of({
id, id,
name, name,
status: 0 status: 0
}); })
}) )
); );
} }
@ -1003,48 +1043,4 @@ export class ContentManagementService {
.onAction() .onAction()
.subscribe(() => this.undoMoveNodes(moveResponse, initialParentId)); .subscribe(() => this.undoMoveNodes(moveResponse, initialParentId));
} }
getErrorMessage(errorObject: { message: any }): string {
let i18nMessageString = 'APP.MESSAGES.ERRORS.GENERIC';
try {
const {
error: { statusCode }
} = JSON.parse(errorObject.message);
if (statusCode === 409) {
i18nMessageString = 'APP.MESSAGES.ERRORS.NODE_MOVE';
} else if (statusCode === 403) {
i18nMessageString = 'APP.MESSAGES.ERRORS.PERMISSION';
}
} catch (err) {
/* Do nothing, keep the original message */
}
return i18nMessageString;
}
getNodeInfo(): Observable<MinimalNodeEntryEntity> {
return this.store.select(getAppSelection).pipe(
take(1),
mergeMap(({ file }) => {
const id = (file as any).entry.nodeId || (file as any).entry.guid;
if (!id) {
return of(file.entry);
} else {
return this.contentApi.getNodeInfo(id);
}
})
);
}
unlockNode(node: NodeEntry): Promise<void | NodeEntry> {
return this.contentApi.unlockNode(node.entry.id).catch(() => {
this.store.dispatch(
new SnackbarErrorAction('APP.MESSAGES.ERRORS.UNLOCK_NODE', {
fileName: node.entry.name
})
);
});
}
} }

View File

@ -70,9 +70,10 @@ describe('NodeActionsService', () => {
let dialog: MatDialog; let dialog: MatDialog;
const helper = { const helper = {
fakeCopyNode: (isForbidden: boolean = false, nameExistingOnDestination?: string) => { fakeCopyNode:
return (_entryId, options) => { (isForbidden: boolean = false, nameExistingOnDestination?: string) =>
return new Promise((resolve, reject) => { (_entryId, options) =>
new Promise((resolve, reject) => {
if (isForbidden) { if (isForbidden) {
reject(permissionError); reject(permissionError);
} else if (nameExistingOnDestination && options && options.name === nameExistingOnDestination) { } else if (nameExistingOnDestination && options && options.name === nameExistingOnDestination) {
@ -80,21 +81,18 @@ describe('NodeActionsService', () => {
} else { } else {
resolve(''); resolve('');
} }
}); }),
}; fakeGetNodeChildren:
}, (familyNodes: { parentNodeId: string; nodeChildren: any[] }[], isForbidden: boolean = false) =>
fakeGetNodeChildren: (familyNodes: { parentNodeId: string; nodeChildren: any[] }[], isForbidden: boolean = false) => { (parentId) =>
return (parentId) => { new Promise((resolve, reject) => {
return new Promise((resolve, reject) => {
if (isForbidden) { if (isForbidden) {
reject(permissionError); reject(permissionError);
} else { } else {
const node = familyNodes.filter((familyNode) => familyNode.parentNodeId === parentId); const node = familyNodes.filter((familyNode) => familyNode.parentNodeId === parentId);
resolve({ list: { entries: node[0].nodeChildren } } || emptyChildrenList); resolve({ list: { entries: node[0].nodeChildren } } || emptyChildrenList);
} }
}); })
};
}
}; };
beforeEach(() => { beforeEach(() => {
@ -184,7 +182,7 @@ describe('NodeActionsService', () => {
}); });
describe('doBatchOperation', () => { describe('doBatchOperation', () => {
it("should throw error if 'contentEntities' required parameter is missing", (done) => { it('should throw error if "contentEntities" required parameter is missing', (done) => {
const contentEntities = undefined; const contentEntities = undefined;
const doCopyBatchOperation = service.copyNodes(contentEntities).asObservable(); const doCopyBatchOperation = service.copyNodes(contentEntities).asObservable();
@ -201,7 +199,7 @@ describe('NodeActionsService', () => {
}); });
}); });
it("should throw error if 'contentEntities' is not an array of entry entities", (done) => { it('should throw error if "contentEntities" is not an array of entry entities', (done) => {
const contentEntities = [new TestNode(), {}]; const contentEntities = [new TestNode(), {}];
const doCopyBatchOperation = service.copyNodes(contentEntities).asObservable(); const doCopyBatchOperation = service.copyNodes(contentEntities).asObservable();
@ -218,7 +216,7 @@ describe('NodeActionsService', () => {
}); });
}); });
it("should throw error if an entry in 'contentEntities' does not have id nor nodeId property", (done) => { it('should throw error if an entry in "contentEntities" does not have id nor nodeId property', (done) => {
const contentEntities = [new TestNode(), { entry: {} }]; const contentEntities = [new TestNode(), { entry: {} }];
const doCopyBatchOperation = service.copyNodes(contentEntities).asObservable(); const doCopyBatchOperation = service.copyNodes(contentEntities).asObservable();
@ -235,7 +233,7 @@ describe('NodeActionsService', () => {
}); });
}); });
it("should not throw error if entry in 'contentEntities' does not have id, but has nodeId property", () => { it('should not throw error if entry in "contentEntities" does not have id, but has nodeId property', () => {
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }]; const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
const subject = new Subject<MinimalNodeEntryEntity[]>(); const subject = new Subject<MinimalNodeEntryEntity[]>();
@ -324,9 +322,7 @@ describe('NodeActionsService', () => {
destinationFolder = new TestNode(folderDestinationId); destinationFolder = new TestNode(folderDestinationId);
translationService = TestBed.inject(TranslationService); translationService = TestBed.inject(TranslationService);
spyOn(translationService, 'instant').and.callFake((key) => { spyOn(translationService, 'instant').and.callFake((key) => key);
return key;
});
}); });
it('should be called', () => { it('should be called', () => {

View File

@ -198,7 +198,7 @@ export class NodeActionsService {
this.isSitesDestinationAvailable = false; this.isSitesDestinationAvailable = false;
const data: ContentNodeSelectorComponentData = { const data: ContentNodeSelectorComponentData = {
selectionMode: 'single', selectionMode: 'single',
title: title, title,
currentFolderId: currentParentFolderId, currentFolderId: currentParentFolderId,
actionName: action, actionName: action,
dropdownHideMyFiles: true, dropdownHideMyFiles: true,
@ -463,9 +463,7 @@ export class NodeActionsService {
let newDestinationFolder; let newDestinationFolder;
return this.documentListService.moveNode(contentEntryId, selectionId).pipe( return this.documentListService.moveNode(contentEntryId, selectionId).pipe(
map((itemMoved) => { map((itemMoved) => ({ itemMoved, initialParentId })),
return { itemMoved, initialParentId };
}),
catchError((err) => { catchError((err) => {
let errStatusCode; let errStatusCode;
try { try {
@ -516,13 +514,11 @@ export class NodeActionsService {
const initialParentId = this.getEntryParentId(contentEntry); const initialParentId = this.getEntryParentId(contentEntry);
return this.documentListService.moveNode(contentEntryId, selectionId).pipe( return this.documentListService.moveNode(contentEntryId, selectionId).pipe(
map((itemMoved) => { map((itemMoved) => ({ itemMoved, initialParentId })),
return { itemMoved, initialParentId }; catchError((err) =>
}),
catchError((err) => {
// do not throw error, to be able to show message in case of partial move of files // do not throw error, to be able to show message in case of partial move of files
return of(err); of(err)
}) )
); );
} }
@ -539,9 +535,7 @@ export class NodeActionsService {
matchedNodes.next(null); matchedNodes.next(null);
} }
}, },
(err) => { (err) => matchedNodes.error(err)
return matchedNodes.error(err);
}
); );
return matchedNodes; return matchedNodes;
} }

View File

@ -185,7 +185,7 @@ describe('TemplateEffects', () => {
})); }));
it('should resolve error with current node value when updateNode api fails', fakeAsync(() => { it('should resolve error with current node value when updateNode api fails', fakeAsync(() => {
const test_node = { const TEST_NODE = {
entry: { entry: {
id: 'test-node-id', id: 'test-node-id',
properties: { properties: {
@ -194,7 +194,7 @@ describe('TemplateEffects', () => {
} }
} }
} as NodeEntry; } as NodeEntry;
copyNodeSpy.and.returnValue(of(test_node)); copyNodeSpy.and.returnValue(of(TEST_NODE));
updateNodeSpy.and.returnValue( updateNodeSpy.and.returnValue(
Promise.reject({ Promise.reject({
@ -202,10 +202,10 @@ describe('TemplateEffects', () => {
}) })
); );
store.dispatch(new CreateFromTemplate(test_node.entry)); store.dispatch(new CreateFromTemplate(TEST_NODE.entry));
tick(); tick();
expect(store.dispatch['calls'].mostRecent().args[0]).toEqual(new CreateFromTemplateSuccess(test_node.entry)); expect(store.dispatch['calls'].mostRecent().args[0]).toEqual(new CreateFromTemplateSuccess(TEST_NODE.entry));
})); }));
it('should close dialog on create template success', fakeAsync(() => { it('should close dialog on create template success', fakeAsync(() => {
@ -215,9 +215,9 @@ describe('TemplateEffects', () => {
})); }));
it('should should reload content on create template success', fakeAsync(() => { it('should should reload content on create template success', fakeAsync(() => {
const test_node = { id: 'test-node-id' } as Node; const TEST_NODE = { id: 'test-node-id' } as Node;
store.dispatch(new CreateFromTemplateSuccess(test_node)); store.dispatch(new CreateFromTemplateSuccess(TEST_NODE));
tick(); tick();
expect(appHookService.reload.next).toHaveBeenCalledWith(test_node); expect(appHookService.reload.next).toHaveBeenCalledWith(TEST_NODE);
})); }));
}); });

View File

@ -90,9 +90,7 @@ export class TemplateEffects {
this.store this.store
.select(getCurrentFolder) .select(getCurrentFolder)
.pipe( .pipe(
switchMap((folder) => { switchMap((folder) => this.copyNode(action.payload, folder.id)),
return this.copyNode(action.payload, folder.id);
}),
take(1) take(1)
) )
.subscribe((node: NodeEntry | null) => { .subscribe((node: NodeEntry | null) => {
@ -134,9 +132,7 @@ export class TemplateEffects {
} }
}) })
), ),
catchError((error) => { catchError((error) => this.handleError(error))
return this.handleError(error);
})
); );
} }

View File

@ -46,9 +46,7 @@ describe('UploadEffects', () => {
}); });
zone = TestBed.inject(NgZone); zone = TestBed.inject(NgZone);
spyOn(zone, 'run').and.callFake((fn: () => any) => { spyOn(zone, 'run').and.callFake((fn: () => any) => fn());
return fn();
});
contentManagementService = TestBed.inject(ContentManagementService); contentManagementService = TestBed.inject(ContentManagementService);
store = TestBed.inject(Store); store = TestBed.inject(Store);

View File

@ -139,13 +139,14 @@ export class UploadEffects {
.subscribe((node) => { .subscribe((node) => {
if (node && node.id) { if (node && node.id) {
const input = event.currentTarget as HTMLInputElement; const input = event.currentTarget as HTMLInputElement;
const files = FileUtils.toFileArray(input.files).map((file: any) => { const files = FileUtils.toFileArray(input.files).map(
return new FileModel(file, { (file: any) =>
parentId: node.id, new FileModel(file, {
path: (file.webkitRelativePath || '').replace(/\/[^\/]*$/, ''), parentId: node.id,
nodeType: 'cm:content' path: (file.webkitRelativePath || '').replace(/\/[^\/]*$/, ''),
}); nodeType: 'cm:content'
}); })
);
this.uploadQueue(files); this.uploadQueue(files);
event.target.value = ''; event.target.value = '';

View File

@ -42,12 +42,10 @@ import { Store, createSelector } from '@ngrx/store';
import { AppExtensionService } from '@alfresco/aca-shared'; import { AppExtensionService } from '@alfresco/aca-shared';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
export const fileToPreview = createSelector(getAppSelection, getCurrentFolder, (selection, folder) => { export const fileToPreview = createSelector(getAppSelection, getCurrentFolder, (selection, folder) => ({
return { selection,
selection, folder
folder }));
};
});
@Injectable() @Injectable()
export class ViewerEffects { export class ViewerEffects {

View File

@ -177,12 +177,10 @@ function showInfoDrawerPreview(state: AppState) {
return newState; return newState;
} }
function toggleDocumentDisplayMode(state: AppState) { const toggleDocumentDisplayMode = (state: AppState) => ({
return { ...state,
...state, documentDisplayMode: state.documentDisplayMode === 'list' ? 'gallery' : 'list'
documentDisplayMode: state.documentDisplayMode === 'list' ? 'gallery' : 'list' });
};
}
function updateSelectedNodes(state: AppState, action: SetSelectedNodesAction): AppState { function updateSelectedNodes(state: AppState, action: SetSelectedNodesAction): AppState {
const newState = { ...state }; const newState = { ...state };
@ -201,10 +199,11 @@ function updateSelectedNodes(state: AppState, action: SetSelectedNodesAction): A
last = nodes[nodes.length - 1]; last = nodes[nodes.length - 1];
if (nodes.length === 1) { if (nodes.length === 1) {
file = nodes.find((entity: any) => { file = nodes.find(
// workaround Shared (entity: any) =>
return !!(entity.entry.isFile || entity.entry.nodeId || entity.entry.sharedByUser); // workaround Shared
}); !!(entity.entry.isFile || entity.entry.nodeId || entity.entry.sharedByUser)
);
folder = nodes.find((entity: any) => entity.entry.isFolder); folder = nodes.find((entity: any) => entity.entry.isFolder);
} }
} }
@ -232,26 +231,20 @@ function updateSelectedNodes(state: AppState, action: SetSelectedNodesAction): A
return newState; return newState;
} }
function setInfoDrawer(state: AppState, action: SetInfoDrawerStateAction) { const setInfoDrawer = (state: AppState, action: SetInfoDrawerStateAction) => ({
return { ...state,
...state, infoDrawerOpened: action.payload
infoDrawerOpened: action.payload });
};
}
function setInfoDrawerPreview(state: AppState, action: SetInfoDrawerPreviewStateAction) { const setInfoDrawerPreview = (state: AppState, action: SetInfoDrawerPreviewStateAction) => ({
return { ...state,
...state, infoDrawerPreview: action.payload
infoDrawerPreview: action.payload });
};
}
function setInfoDrawerAspect(state: AppState, action: SetInfoDrawerMetadataAspectAction) { const setInfoDrawerAspect = (state: AppState, action: SetInfoDrawerMetadataAspectAction) => ({
return { ...state,
...state, infoDrawerMetadataAspect: action.payload
infoDrawerMetadataAspect: action.payload });
};
}
function updateRepositoryStatus(state: AppState, action: SetRepositoryInfoAction) { function updateRepositoryStatus(state: AppState, action: SetRepositoryInfoAction) {
const newState = { ...state }; const newState = { ...state };

View File

@ -77,27 +77,17 @@ import { BehaviorSubject, Observable, of } from 'rxjs';
provide: DiscoveryApiService, provide: DiscoveryApiService,
useValue: { useValue: {
ecmProductInfo$: new BehaviorSubject<RepositoryInfo>(null), ecmProductInfo$: new BehaviorSubject<RepositoryInfo>(null),
getEcmProductInfo(): Observable<RepositoryInfo> { getEcmProductInfo: (): Observable<RepositoryInfo> => of(new RepositoryInfo({ version: '10.0.0' }))
return of(new RepositoryInfo({ version: '10.0.0' }));
}
} }
}, },
{ {
provide: AuthenticationService, provide: AuthenticationService,
useValue: { useValue: {
isEcmLoggedIn(): boolean { isEcmLoggedIn: (): boolean => true,
return true; getRedirect: (): string => null,
},
getRedirect(): string {
return null;
},
setRedirect() {}, setRedirect() {},
isOauth(): boolean { isOauth: (): boolean => false,
return false; isOAuthWithoutSilentLogin: (): boolean => false
},
isOAuthWithoutSilentLogin(): boolean {
return false;
}
} }
} }
] ]

View File

@ -28,14 +28,12 @@ import { ContentActionRef, ContentActionType } from '@alfresco/adf-extensions';
export const ACTION_TITLE = 'ACTION_TITLE'; export const ACTION_TITLE = 'ACTION_TITLE';
export const ACTION_CLICK = 'ACTION_CLICK'; export const ACTION_CLICK = 'ACTION_CLICK';
export const getContentActionRef = (): ContentActionRef => { export const getContentActionRef = (): ContentActionRef => ({
return { id: 'id',
id: 'id', type: ContentActionType.button,
type: ContentActionType.button, title: ACTION_TITLE,
title: ACTION_TITLE, disabled: false,
disabled: false, actions: {
actions: { click: ACTION_CLICK
click: ACTION_CLICK }
} });
};
};

View File

@ -23,7 +23,7 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/ */
// This file is required by karma.conf.js and loads recursively all the .spec and framework files // This file is required by __karma__.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/long-stack-trace-zone'; import 'zone.js/dist/long-stack-trace-zone';
import 'zone.js/dist/proxy.js'; import 'zone.js/dist/proxy.js';
@ -38,7 +38,7 @@ import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@ang
declare const __karma__: any; declare const __karma__: any;
declare const require: any; declare const require: any;
// Prevent Karma from running prematurely. // Prevent __karma__ from running prematurely.
__karma__.loaded = function () {}; __karma__.loaded = function () {};
// First, initialize the Angular testing environment. // First, initialize the Angular testing environment.
@ -47,5 +47,5 @@ getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDyn
const context = require.context('./', true, /\.spec\.ts$/); const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules. // And load the modules.
context.keys().map(context); context.keys().map(context);
// Finally, start Karma to run the tests. // Finally, start __karma__ to run the tests.
__karma__.start(); __karma__.start();

View File

@ -24,7 +24,7 @@
*/ */
/* SystemJS module definition */ /* SystemJS module definition */
declare var module: NodeModule; // declare let module: NodeModule;
interface NodeModule { interface NodeModule {
id: string; id: string;
} }

117
e2e/.eslintrc.json Normal file
View File

@ -0,0 +1,117 @@
{
"extends": "../.eslintrc.json",
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"project": [
"e2e/tsconfig.e2e.json"
],
"createDefaultProgram": true
},
"plugins": [
"eslint-plugin-react",
"eslint-plugin-rxjs",
"eslint-plugin-unicorn"
],
"rules": {
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": [
"app",
"aca",
"adf"
],
"style": "kebab-case"
}
],
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "aca",
"style": "camelCase"
}
],
"@angular-eslint/no-host-metadata-property": "off",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/explicit-member-accessibility": [
"off",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/member-delimiter-style": [
"off",
{
"multiline": {
"delimiter": "none",
"requireLast": true
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
],
"@typescript-eslint/semi": [
"off",
null
],
"@typescript-eslint/type-annotation-spacing": "off",
"arrow-parens": [
"off",
"always"
],
"brace-style": [
"off",
"off"
],
"eol-last": "off",
"id-blacklist": "off",
"id-match": "off",
"linebreak-style": "off",
"max-len": "off",
"new-parens": "off",
"newline-per-chained-call": "off",
"no-duplicate-imports": "error",
"no-extra-semi": "off",
"no-irregular-whitespace": "off",
"no-return-await": "error",
"no-underscore-dangle": "off",
"quote-props": "off",
"react/jsx-curly-spacing": "off",
"react/jsx-equals-spacing": "off",
"react/jsx-wrap-multilines": "off",
"rxjs/no-create": "error",
"rxjs/no-subject-unsubscribe": "error",
"rxjs/no-subject-value": "error",
"rxjs/no-unsafe-takeuntil": "error",
"space-before-function-paren": "off",
"space-in-parens": [
"off",
"never"
],
"unicorn/filename-case": "error"
}
},
{
"files": [
"*.html"
],
"rules": {
"@angular-eslint/template/no-autofocus": "error",
"@angular-eslint/template/no-negated-async": "off",
"@angular-eslint/template/no-positive-tabindex": "error"
}
}
]
}

View File

@ -132,6 +132,4 @@ export async function checkViewerActions(item: string, expectedToolbarPrimary: s
const toRemove = ['Close', 'Previous File', 'Next File', 'View details']; const toRemove = ['Close', 'Previous File', 'Next File', 'View details'];
function removeClosePreviousNextOldInfo(actions: string[]): string[] { const removeClosePreviousNextOldInfo = (actions: string[]): string[] => actions.filter((elem) => !toRemove.includes(elem));
return actions.filter((elem) => !toRemove.includes(elem));
}

View File

@ -477,7 +477,7 @@ describe('Copy content', () => {
})); }));
}); });
async function copyFile(fileName: string, location: string = '', destination: string, doBefore?: Function) { async function copyFile(fileName: string, location: string = '', destination: string, doBefore?: () => void) {
if (doBefore) { if (doBefore) {
await doBefore(); await doBefore();
} }
@ -497,7 +497,7 @@ describe('Copy content', () => {
expect(await dataTable.isItemPresent(fileName)).toBe(true, `${fileName} not present in ${destination} folder`); expect(await dataTable.isItemPresent(fileName)).toBe(true, `${fileName} not present in ${destination} folder`);
} }
async function copyFolderWithContent(folderName: string, location: string = '', destination: string, doBefore?: Function) { async function copyFolderWithContent(folderName: string, location: string = '', destination: string, doBefore?: () => void) {
if (doBefore) { if (doBefore) {
await doBefore(); await doBefore();
} }
@ -521,7 +521,7 @@ describe('Copy content', () => {
expect(await dataTable.isItemPresent(fileInFolder)).toBe(true, `${fileInFolder} is not present in ${folderName} folder in ${destination}`); expect(await dataTable.isItemPresent(fileInFolder)).toBe(true, `${fileInFolder} is not present in ${folderName} folder in ${destination}`);
} }
async function copyMultipleItems(items: string[], location: string = '', destination: string, doBefore?: Function) { async function copyMultipleItems(items: string[], location: string = '', destination: string, doBefore?: () => void) {
if (doBefore) { if (doBefore) {
await doBefore(); await doBefore();
} }
@ -543,7 +543,7 @@ describe('Copy content', () => {
expect(await dataTable.isItemPresent(items[1])).toBe(true, `${items[1]} not present in ${destination} folder`); expect(await dataTable.isItemPresent(items[1])).toBe(true, `${items[1]} not present in ${destination} folder`);
} }
async function copyFileWithNameThatAlreadyExists(fileName: string, location: string = '', destination: string, doBefore?: Function) { async function copyFileWithNameThatAlreadyExists(fileName: string, location: string = '', destination: string, doBefore?: () => void) {
if (doBefore) { if (doBefore) {
await doBefore(); await doBefore();
} }
@ -563,7 +563,7 @@ describe('Copy content', () => {
expect(await dataTable.isItemPresent(fileName)).toBe(true, `${fileName}.txt not present in ${destination} folder`); expect(await dataTable.isItemPresent(fileName)).toBe(true, `${fileName}.txt not present in ${destination} folder`);
} }
async function copyFolderWithNameThatAlreadyExists(folderName: string, location: string = '', destination: string, doBefore?: Function) { async function copyFolderWithNameThatAlreadyExists(folderName: string, location: string = '', destination: string, doBefore?: () => void) {
if (doBefore) { if (doBefore) {
await doBefore(); await doBefore();
} }
@ -586,7 +586,7 @@ describe('Copy content', () => {
expect(await dataTable.isItemPresent(file3InFolder)).toBe(true, `${file3InFolder} not present in ${destination} folder in ${folderName}`); expect(await dataTable.isItemPresent(file3InFolder)).toBe(true, `${file3InFolder} not present in ${destination} folder in ${folderName}`);
} }
async function copyItemsIntoLibrary(items: string[], location: string = '', destination: string, doBefore?: Function) { async function copyItemsIntoLibrary(items: string[], location: string = '', destination: string, doBefore?: () => void) {
if (doBefore) { if (doBefore) {
await doBefore(); await doBefore();
} }
@ -616,7 +616,7 @@ describe('Copy content', () => {
} }
} }
async function copyLockedFile(fileName: string, location: string = '', destination: string, doBefore?: Function) { async function copyLockedFile(fileName: string, location: string = '', destination: string, doBefore?: () => void) {
if (doBefore) { if (doBefore) {
await doBefore(); await doBefore();
} }
@ -639,7 +639,7 @@ describe('Copy content', () => {
expect(await apis.user.nodes.isFileLockedByName(fileName, destinationId)).toBe(false, `${fileName} is locked in ${destination}`); expect(await apis.user.nodes.isFileLockedByName(fileName, destinationId)).toBe(false, `${fileName} is locked in ${destination}`);
} }
async function copyFolderThatContainsLockedFile(folderName: string, location: string = '', destination: string, doBefore?: Function) { async function copyFolderThatContainsLockedFile(folderName: string, location: string = '', destination: string, doBefore?: () => void) {
if (doBefore) { if (doBefore) {
await doBefore(); await doBefore();
} }
@ -671,7 +671,7 @@ describe('Copy content', () => {
).toBe(false, `${fileLockedInFolder} is locked in ${destination}`); ).toBe(false, `${fileLockedInFolder} is locked in ${destination}`);
} }
async function undoCopyFile(fileName: string, location: string = '', destination: string, doBefore?: Function) { async function undoCopyFile(fileName: string, location: string = '', destination: string, doBefore?: () => void) {
if (doBefore) { if (doBefore) {
await doBefore(); await doBefore();
} }
@ -694,7 +694,7 @@ describe('Copy content', () => {
expect(await dataTable.isEmpty()).toBe(true, 'Trash is not empty'); expect(await dataTable.isEmpty()).toBe(true, 'Trash is not empty');
} }
async function undoCopyFolder(folderName: string, location: string = '', destination: string, doBefore?: Function) { async function undoCopyFolder(folderName: string, location: string = '', destination: string, doBefore?: () => void) {
if (doBefore) { if (doBefore) {
await doBefore(); await doBefore();
} }
@ -717,7 +717,7 @@ describe('Copy content', () => {
expect(await dataTable.isEmpty()).toBe(true, 'Trash is not empty'); expect(await dataTable.isEmpty()).toBe(true, 'Trash is not empty');
} }
async function undoCopyFileWithExistingName(fileName: string, location: string = '', destination: string, doBefore?: Function) { async function undoCopyFileWithExistingName(fileName: string, location: string = '', destination: string, doBefore?: () => void) {
if (doBefore) { if (doBefore) {
await doBefore(); await doBefore();
} }
@ -744,7 +744,7 @@ describe('Copy content', () => {
expect(await dataTable.isEmpty()).toBe(true, 'Trash is not empty'); expect(await dataTable.isEmpty()).toBe(true, 'Trash is not empty');
} }
async function undoCopyFolderWithExistingName(folderName: string, location: string = '', destination: string, doBefore?: Function) { async function undoCopyFolderWithExistingName(folderName: string, location: string = '', destination: string, doBefore?: () => void) {
if (doBefore) { if (doBefore) {
await doBefore(); await doBefore();
} }

View File

@ -124,7 +124,8 @@ describe('Move content', () => {
const existingFile = `existing-${Utils.random()}`; const existingFile = `existing-${Utils.random()}`;
const existingFolder = `existing-${Utils.random()}`; const existingFolder = `existing-${Utils.random()}`;
let existingId1, existingId2; let existingId1;
let existingId2;
const file2InFolder = `file2InFolder-${Utils.random()}.txt`; const file2InFolder = `file2InFolder-${Utils.random()}.txt`;
const file3InFolder = `file3InFolder-${Utils.random()}.txt`; const file3InFolder = `file3InFolder-${Utils.random()}.txt`;
@ -551,7 +552,8 @@ describe('Move content', () => {
let existingFileId; let existingFileId;
const existingFolder = `existing-${Utils.random()}`; const existingFolder = `existing-${Utils.random()}`;
let existingId1, existingId2; let existingId1;
let existingId2;
const file2InFolder = `file2InFolder-${Utils.random()}.txt`; const file2InFolder = `file2InFolder-${Utils.random()}.txt`;
const file3InFolder = `file3InFolder-${Utils.random()}.txt`; const file3InFolder = `file3InFolder-${Utils.random()}.txt`;

View File

@ -32,25 +32,25 @@ describe('Extensions - Info Drawer', () => {
const file = `file-${Utils.random()}.txt`; const file = `file-${Utils.random()}.txt`;
let fileId: string; let fileId: string;
const properties_tab = { const PROPERTIES_TAB = {
order: 1, order: 1,
title: 'MY PROPERTIES' title: 'MY PROPERTIES'
}; };
const custom_tab = { const CUSTOM_TAB = {
order: 2, order: 2,
icon: 'mood', icon: 'mood',
title: 'MY CUSTOM TITLE', title: 'MY CUSTOM TITLE',
component: 'app.toolbar.toggleFavorite' component: 'app.toolbar.toggleFavorite'
}; };
const no_title_tab = { const NO_TITLE_TAB = {
order: 3, order: 3,
icon: 'check_circle', icon: 'check_circle',
title: '' title: ''
}; };
const comments_tab = { const COMMENTS_TAB = {
title: 'COMMENTS' title: 'COMMENTS'
}; };
@ -94,9 +94,9 @@ describe('Extensions - Info Drawer', () => {
await BrowserActions.click(page.toolbar.viewDetailsButton); await BrowserActions.click(page.toolbar.viewDetailsButton);
await infoDrawer.waitForInfoDrawerToOpen(); await infoDrawer.waitForInfoDrawerToOpen();
const val = await infoDrawer.getTabTitle(custom_tab.order); const val = await infoDrawer.getTabTitle(CUSTOM_TAB.order);
expect(await infoDrawer.isTabPresent(custom_tab.title)).toBe(true, `${custom_tab.title} tab is not present`); expect(await infoDrawer.isTabPresent(CUSTOM_TAB.title)).toBe(true, `${CUSTOM_TAB.title} tab is not present`);
expect(val.trim()).toEqual(`${custom_tab.icon}\n${custom_tab.title}`.trim()); expect(val.trim()).toEqual(`${CUSTOM_TAB.icon}\n${CUSTOM_TAB.title}`.trim());
}); });
it('[C284647] Remove existing tab', async () => { it('[C284647] Remove existing tab', async () => {
@ -104,7 +104,7 @@ describe('Extensions - Info Drawer', () => {
await BrowserActions.click(page.toolbar.viewDetailsButton); await BrowserActions.click(page.toolbar.viewDetailsButton);
await infoDrawer.waitForInfoDrawerToOpen(); await infoDrawer.waitForInfoDrawerToOpen();
expect(await infoDrawer.isTabPresent(comments_tab.title)).toBe(false, `${comments_tab.title} tab should not be present!`); expect(await infoDrawer.isTabPresent(COMMENTS_TAB.title)).toBe(false, `${COMMENTS_TAB.title} tab should not be present!`);
}); });
it('[C284648] Change tab title', async () => { it('[C284648] Change tab title', async () => {
@ -112,8 +112,8 @@ describe('Extensions - Info Drawer', () => {
await BrowserActions.click(page.toolbar.viewDetailsButton); await BrowserActions.click(page.toolbar.viewDetailsButton);
await infoDrawer.waitForInfoDrawerToOpen(); await infoDrawer.waitForInfoDrawerToOpen();
expect(await infoDrawer.isTabPresent(properties_tab.title)).toBe(true, `${properties_tab.title} tab is not present`); expect(await infoDrawer.isTabPresent(PROPERTIES_TAB.title)).toBe(true, `${PROPERTIES_TAB.title} tab is not present`);
expect(await infoDrawer.getTabTitle(properties_tab.order)).toEqual(properties_tab.title); expect(await infoDrawer.getTabTitle(PROPERTIES_TAB.order)).toEqual(PROPERTIES_TAB.title);
}); });
it('[C284649] Tab with icon and no title', async () => { it('[C284649] Tab with icon and no title', async () => {
@ -121,8 +121,8 @@ describe('Extensions - Info Drawer', () => {
await BrowserActions.click(page.toolbar.viewDetailsButton); await BrowserActions.click(page.toolbar.viewDetailsButton);
await infoDrawer.waitForInfoDrawerToOpen(); await infoDrawer.waitForInfoDrawerToOpen();
expect(await infoDrawer.isTabPresent(no_title_tab.title)).toBe(true, `${no_title_tab.title} tab is not present`); expect(await infoDrawer.isTabPresent(NO_TITLE_TAB.title)).toBe(true, `${NO_TITLE_TAB.title} tab is not present`);
expect((await infoDrawer.getTabTitle(no_title_tab.order)).trim()).toEqual(`${no_title_tab.icon}`.trim()); expect((await infoDrawer.getTabTitle(NO_TITLE_TAB.order)).trim()).toEqual(`${NO_TITLE_TAB.icon}`.trim());
}); });
it('[C284651] Insert new component in tab', async () => { it('[C284651] Insert new component in tab', async () => {
@ -130,9 +130,9 @@ describe('Extensions - Info Drawer', () => {
await BrowserActions.click(page.toolbar.viewDetailsButton); await BrowserActions.click(page.toolbar.viewDetailsButton);
await infoDrawer.waitForInfoDrawerToOpen(); await infoDrawer.waitForInfoDrawerToOpen();
expect(await infoDrawer.isTabDisplayed(custom_tab.title)).toBe(true, `${custom_tab.title} tab is not displayed`); expect(await infoDrawer.isTabDisplayed(CUSTOM_TAB.title)).toBe(true, `${CUSTOM_TAB.title} tab is not displayed`);
await infoDrawer.clickTab(custom_tab.title); await infoDrawer.clickTab(CUSTOM_TAB.title);
expect(await infoDrawer.getComponentIdOfTab()).toEqual(custom_tab.component); expect(await infoDrawer.getComponentIdOfTab()).toEqual(CUSTOM_TAB.component);
}); });
}); });

View File

@ -42,7 +42,7 @@ describe('Extensions - Metadata presets', () => {
let fileId: string; let fileId: string;
const properties_tab = { const PROPERTIES_TAB = {
title: 'Properties', title: 'Properties',
component: 'app.components.tabs.metadata' component: 'app.components.tabs.metadata'
}; };
@ -91,7 +91,7 @@ describe('Extensions - Metadata presets', () => {
await BrowserActions.click(page.toolbar.viewDetailsButton); await BrowserActions.click(page.toolbar.viewDetailsButton);
await infoDrawer.waitForInfoDrawerToOpen(); await infoDrawer.waitForInfoDrawerToOpen();
await infoDrawer.clickTab(properties_tab.title); await infoDrawer.clickTab(PROPERTIES_TAB.title);
await BrowserActions.click(metadataCard.expandButton); await BrowserActions.click(metadataCard.expandButton);
await metadataCard.waitForFirstExpansionPanel(); await metadataCard.waitForFirstExpansionPanel();

View File

@ -30,13 +30,13 @@ describe('Extensions - Viewer', () => {
const username = `user-${Utils.random()}`; const username = `user-${Utils.random()}`;
const pdfFile = { const pdfFile = {
file_name: FILES.pdfFile, fileName: FILES.pdfFile,
component: 'app.components.tabs.metadata' component: 'app.components.tabs.metadata'
}; };
let pdfFileId: string; let pdfFileId: string;
const docxFile = { const docxFile = {
file_name: FILES.docxFile, fileName: FILES.docxFile,
component: 'app.components.tabs.comments' component: 'app.components.tabs.comments'
}; };
let docxFileId: string; let docxFileId: string;
@ -76,8 +76,8 @@ describe('Extensions - Viewer', () => {
beforeAll(async (done) => { beforeAll(async (done) => {
await adminApiActions.createUser({ username }); await adminApiActions.createUser({ username });
pdfFileId = (await apis.user.upload.uploadFile(pdfFile.file_name)).entry.id; pdfFileId = (await apis.user.upload.uploadFile(pdfFile.fileName)).entry.id;
docxFileId = (await apis.user.upload.uploadFile(docxFile.file_name)).entry.id; docxFileId = (await apis.user.upload.uploadFile(docxFile.fileName)).entry.id;
await loginPage.load(); await loginPage.load();
await Utils.setSessionStorageFromConfig(EXTENSIBILITY_CONFIGS.VIEWER); await Utils.setSessionStorageFromConfig(EXTENSIBILITY_CONFIGS.VIEWER);
@ -102,13 +102,13 @@ describe('Extensions - Viewer', () => {
describe('content', () => { describe('content', () => {
it('[C284659] Insert new component in a content viewer', async () => { it('[C284659] Insert new component in a content viewer', async () => {
await page.dataTable.doubleClickOnRowByName(pdfFile.file_name); await page.dataTable.doubleClickOnRowByName(pdfFile.fileName);
expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened');
expect(await viewer.isCustomContentPresent()).toBe(true, 'Custom content is not present'); expect(await viewer.isCustomContentPresent()).toBe(true, 'Custom content is not present');
expect(await viewer.getComponentIdOfView()).toEqual(pdfFile.component); expect(await viewer.getComponentIdOfView()).toEqual(pdfFile.component);
await BrowserActions.click(viewer.closeButton); await BrowserActions.click(viewer.closeButton);
await page.dataTable.doubleClickOnRowByName(docxFile.file_name); await page.dataTable.doubleClickOnRowByName(docxFile.fileName);
expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened');
expect(await viewer.isCustomContentPresent()).toBe(true, 'Custom content is not present'); expect(await viewer.isCustomContentPresent()).toBe(true, 'Custom content is not present');
expect(await viewer.getComponentIdOfView()).toEqual(docxFile.component); expect(await viewer.getComponentIdOfView()).toEqual(docxFile.component);
@ -117,7 +117,7 @@ describe('Extensions - Viewer', () => {
describe('toolbar actions', () => { describe('toolbar actions', () => {
it('[C286416] Add a new action in the toolbar', async () => { it('[C286416] Add a new action in the toolbar', async () => {
await page.dataTable.doubleClickOnRowByName(pdfFile.file_name); await page.dataTable.doubleClickOnRowByName(pdfFile.fileName);
expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened');
expect(await toolbar.isButtonPresent(customAction.title)).toBe(true, 'Custom action is not present'); expect(await toolbar.isButtonPresent(customAction.title)).toBe(true, 'Custom action is not present');
@ -126,14 +126,14 @@ describe('Extensions - Viewer', () => {
}); });
it('[C286417] Modify title of action from toolbar', async () => { it('[C286417] Modify title of action from toolbar', async () => {
await page.dataTable.doubleClickOnRowByName(pdfFile.file_name); await page.dataTable.doubleClickOnRowByName(pdfFile.fileName);
expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened');
expect(await BrowserActions.getAttribute(toolbar.getButtonById(downloadButton.id), 'title')).toEqual(downloadButton.title); expect(await BrowserActions.getAttribute(toolbar.getButtonById(downloadButton.id), 'title')).toEqual(downloadButton.title);
}); });
it('[C286419] Remove action from toolbar', async () => { it('[C286419] Remove action from toolbar', async () => {
await page.dataTable.doubleClickOnRowByName(pdfFile.file_name); await page.dataTable.doubleClickOnRowByName(pdfFile.fileName);
expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened');
expect(await toolbar.isPrintPresent()).toBe(false, 'Print button is still displayed'); expect(await toolbar.isPrintPresent()).toBe(false, 'Print button is still displayed');
@ -142,7 +142,7 @@ describe('Extensions - Viewer', () => {
describe('toolbar More actions menu', () => { describe('toolbar More actions menu', () => {
it('[C286420] Add a new action', async () => { it('[C286420] Add a new action', async () => {
await page.dataTable.doubleClickOnRowByName(pdfFile.file_name); await page.dataTable.doubleClickOnRowByName(pdfFile.fileName);
expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened');
await toolbar.openMoreMenu(); await toolbar.openMoreMenu();
@ -152,7 +152,7 @@ describe('Extensions - Viewer', () => {
}); });
it('[C286421] Modify title of action from More actions menu', async () => { it('[C286421] Modify title of action from More actions menu', async () => {
await page.dataTable.doubleClickOnRowByName(pdfFile.file_name); await page.dataTable.doubleClickOnRowByName(pdfFile.fileName);
expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened');
await toolbar.openMoreMenu(); await toolbar.openMoreMenu();
@ -160,7 +160,7 @@ describe('Extensions - Viewer', () => {
}); });
it('[C286423] Remove action from More actions menu', async () => { it('[C286423] Remove action from More actions menu', async () => {
await page.dataTable.doubleClickOnRowByName(pdfFile.file_name); await page.dataTable.doubleClickOnRowByName(pdfFile.fileName);
expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened');
await toolbar.openMoreMenu(); await toolbar.openMoreMenu();

2601
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -62,6 +62,11 @@
"@angular-custom-builders/lite-serve": "^0.2.3", "@angular-custom-builders/lite-serve": "^0.2.3",
"@angular-devkit/build-angular": "^0.1002.0", "@angular-devkit/build-angular": "^0.1002.0",
"@angular-devkit/build-ng-packagr": "^0.1002.0", "@angular-devkit/build-ng-packagr": "^0.1002.0",
"@angular-eslint/builder": "1.2.0",
"@angular-eslint/eslint-plugin": "1.2.0",
"@angular-eslint/eslint-plugin-template": "1.2.0",
"@angular-eslint/schematics": "1.2.0",
"@angular-eslint/template-parser": "1.2.0",
"@angular/cli": "^10.1.4", "@angular/cli": "^10.1.4",
"@angular/compiler-cli": "10.0.4", "@angular/compiler-cli": "10.0.4",
"@angular/language-service": "11.0.8", "@angular/language-service": "11.0.8",
@ -71,6 +76,8 @@
"@types/node": "^14.14.12", "@types/node": "^14.14.12",
"@types/selenium-webdriver": "^4.0.9", "@types/selenium-webdriver": "^4.0.9",
"@types/superagent": "^4.1.10", "@types/superagent": "^4.1.10",
"@typescript-eslint/eslint-plugin": "4.3.0",
"@typescript-eslint/parser": "4.3.0",
"adf-tslint-rules": "0.0.7", "adf-tslint-rules": "0.0.7",
"ajv-cli": "^4.2.0", "ajv-cli": "^4.2.0",
"browser-sync": "^2.27.7", "browser-sync": "^2.27.7",
@ -82,6 +89,14 @@
"dotenv": "8.2.0", "dotenv": "8.2.0",
"dotenv-expand": "5.1.0", "dotenv-expand": "5.1.0",
"envsub": "^4.0.7", "envsub": "^4.0.7",
"eslint": "^7.6.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jsdoc": "30.7.6",
"eslint-plugin-prefer-arrow": "1.2.2",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "latest",
"eslint-plugin-rxjs": "latest",
"eslint-plugin-unicorn": "latest",
"http-server": "^14.1.0", "http-server": "^14.1.0",
"husky": "^7.0.2", "husky": "^7.0.2",
"inquirer": "^8.1.5", "inquirer": "^8.1.5",
@ -98,7 +113,7 @@
"lite-server": "^2.4.0", "lite-server": "^2.4.0",
"ng-packagr": "^10.1.2", "ng-packagr": "^10.1.2",
"node-stream-zip": "^1.14.0", "node-stream-zip": "^1.14.0",
"prettier": "^2.1.2", "prettier": "2.5.1",
"protractor": "~7.0.0", "protractor": "~7.0.0",
"protractor-retry-angular-cli": "^2.0.2", "protractor-retry-angular-cli": "^2.0.2",
"protractor-screenshoter-plugin": "0.10.3", "protractor-screenshoter-plugin": "0.10.3",
@ -108,7 +123,7 @@
"selenium-webdriver": "^4.1.1", "selenium-webdriver": "^4.1.1",
"ts-node": "^10.2.1", "ts-node": "^10.2.1",
"tsconfig-paths": "3.12.0", "tsconfig-paths": "3.12.0",
"tslint": "~6.1.0", "tslint": "^6.1.3",
"tslint-config-prettier": "^1.18.0", "tslint-config-prettier": "^1.18.0",
"tslint-plugin-prettier": "^2.3.0", "tslint-plugin-prettier": "^2.3.0",
"typescript": "3.9.8", "typescript": "3.9.8",

View File

@ -0,0 +1,124 @@
{
"extends": "../../.eslintrc.json",
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"project": [
"projects/aca-about/tsconfig.lib.json",
"projects/aca-about/tsconfig.spec.json"
],
"createDefaultProgram": true
},
"plugins": [
"eslint-plugin-react",
"eslint-plugin-rxjs",
"eslint-plugin-unicorn"
],
"rules": {
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": [
"lib",
"aca",
"app",
"adf"
],
"style": "kebab-case"
}
],
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": [
"lib",
"aca",
"app",
"adf"
],
"style": "camelCase"
}
],
"@angular-eslint/no-host-metadata-property": "off",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/explicit-member-accessibility": [
"off",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/member-delimiter-style": [
"off",
{
"multiline": {
"delimiter": "none",
"requireLast": true
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
],
"@typescript-eslint/semi": [
"off",
null
],
"@typescript-eslint/type-annotation-spacing": "off",
"arrow-parens": [
"off",
"always"
],
"brace-style": [
"off",
"off"
],
"eol-last": "off",
"id-blacklist": "off",
"id-match": "off",
"linebreak-style": "off",
"max-len": "off",
"new-parens": "off",
"newline-per-chained-call": "off",
"no-duplicate-imports": "error",
"no-extra-semi": "off",
"no-irregular-whitespace": "off",
"no-return-await": "error",
"no-underscore-dangle": "off",
"quote-props": "off",
"react/jsx-curly-spacing": "off",
"react/jsx-equals-spacing": "off",
"react/jsx-wrap-multilines": "off",
"rxjs/no-create": "error",
"rxjs/no-subject-unsubscribe": "error",
"rxjs/no-subject-value": "error",
"rxjs/no-unsafe-takeuntil": "error",
"space-before-function-paren": "off",
"space-in-parens": [
"off",
"never"
],
"unicorn/filename-case": "error"
}
},
{
"files": [
"*.html"
],
"rules": {
"@angular-eslint/template/no-autofocus": "error",
"@angular-eslint/template/no-negated-async": "off",
"@angular-eslint/template/no-positive-tabindex": "error"
}
}
]
}

View File

@ -1,17 +0,0 @@
{
"extends": "../../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
["lib", "aca", "app", "adf"],
"camelCase"
],
"component-selector": [
true,
"element",
["lib", "aca", "app", "adf"],
"kebab-case"
]
}
}

View File

@ -0,0 +1,124 @@
{
"extends": "../../.eslintrc.json",
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"project": [
"projects/aca-settings/tsconfig.lib.json",
"projects/aca-settings/tsconfig.spec.json"
],
"createDefaultProgram": true
},
"plugins": [
"eslint-plugin-react",
"eslint-plugin-rxjs",
"eslint-plugin-unicorn"
],
"rules": {
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": [
"lib",
"aca",
"app",
"adf"
],
"style": "kebab-case"
}
],
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": [
"lib",
"aca",
"app",
"adf"
],
"style": "camelCase"
}
],
"@angular-eslint/no-host-metadata-property": "off",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/explicit-member-accessibility": [
"off",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/member-delimiter-style": [
"off",
{
"multiline": {
"delimiter": "none",
"requireLast": true
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
],
"@typescript-eslint/semi": [
"off",
null
],
"@typescript-eslint/type-annotation-spacing": "off",
"arrow-parens": [
"off",
"always"
],
"brace-style": [
"off",
"off"
],
"eol-last": "off",
"id-blacklist": "off",
"id-match": "off",
"linebreak-style": "off",
"max-len": "off",
"new-parens": "off",
"newline-per-chained-call": "off",
"no-duplicate-imports": "error",
"no-extra-semi": "off",
"no-irregular-whitespace": "off",
"no-return-await": "error",
"no-underscore-dangle": "off",
"quote-props": "off",
"react/jsx-curly-spacing": "off",
"react/jsx-equals-spacing": "off",
"react/jsx-wrap-multilines": "off",
"rxjs/no-create": "error",
"rxjs/no-subject-unsubscribe": "error",
"rxjs/no-subject-value": "error",
"rxjs/no-unsafe-takeuntil": "error",
"space-before-function-paren": "off",
"space-in-parens": [
"off",
"never"
],
"unicorn/filename-case": "error"
}
},
{
"files": [
"*.html"
],
"rules": {
"@angular-eslint/template/no-autofocus": "error",
"@angular-eslint/template/no-negated-async": "off",
"@angular-eslint/template/no-positive-tabindex": "error"
}
}
]
}

View File

@ -1,17 +0,0 @@
{
"extends": "../../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
["lib", "aca", "app", "adf"],
"camelCase"
],
"component-selector": [
true,
"element",
["lib", "aca", "app", "adf"],
"kebab-case"
]
}
}

View File

@ -0,0 +1,114 @@
{
"extends": "../../.eslintrc.json",
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"project": [
"projects/aca-shared/tsconfig.lib.json",
"projects/aca-shared/tsconfig.spec.json"
],
"createDefaultProgram": true
},
"plugins": [
"eslint-plugin-react",
"eslint-plugin-rxjs",
"eslint-plugin-unicorn"
],
"rules": {
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": ["aca", "adf", "app"],
"style": "kebab-case"
}
],
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": ["aca", "adf", "app"],
"style": "camelCase"
}
],
"@angular-eslint/no-host-metadata-property": "off",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/explicit-member-accessibility": [
"off",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/member-delimiter-style": [
"off",
{
"multiline": {
"delimiter": "none",
"requireLast": true
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
],
"@typescript-eslint/semi": [
"off",
null
],
"@typescript-eslint/type-annotation-spacing": "off",
"arrow-parens": [
"off",
"always"
],
"brace-style": [
"off",
"off"
],
"eol-last": "off",
"id-blacklist": "off",
"id-match": "off",
"linebreak-style": "off",
"max-len": "off",
"new-parens": "off",
"newline-per-chained-call": "off",
"no-duplicate-imports": "error",
"no-extra-semi": "off",
"no-irregular-whitespace": "off",
"no-return-await": "error",
"no-underscore-dangle": "off",
"quote-props": "off",
"react/jsx-curly-spacing": "off",
"react/jsx-equals-spacing": "off",
"react/jsx-wrap-multilines": "off",
"rxjs/no-create": "error",
"rxjs/no-subject-unsubscribe": "error",
"rxjs/no-subject-value": "error",
"rxjs/no-unsafe-takeuntil": "error",
"space-before-function-paren": "off",
"space-in-parens": [
"off",
"never"
],
"unicorn/filename-case": "error"
}
},
{
"files": [
"*.html"
],
"rules": {
"@angular-eslint/template/no-autofocus": "error",
"@angular-eslint/template/no-negated-async": "off",
"@angular-eslint/template/no-positive-tabindex": "error"
}
}
]
}

View File

@ -35,11 +35,11 @@ export interface AcaRuleContext extends RuleContext {
/** /**
* Checks if user can copy selected node. * Checks if user can copy selected node.
* JSON ref: `app.canCopyNode` * JSON ref: `app.canCopyNode`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function canCopyNode(context: RuleContext): boolean { export const canCopyNode = (context: RuleContext): boolean =>
return [hasSelection(context), navigation.isNotTrashcan(context), navigation.isNotLibraries(context)].every(Boolean); [hasSelection(context), navigation.isNotTrashcan(context), navigation.isNotLibraries(context)].every(Boolean);
}
/** /**
* Checks if user can mark selected nodes as **Favorite**. * Checks if user can mark selected nodes as **Favorite**.
@ -73,29 +73,24 @@ export function canRemoveFavorite(context: RuleContext): boolean {
* Checks if user can share selected file. * Checks if user can share selected file.
* JSON ref: `app.selection.file.canShare` * JSON ref: `app.selection.file.canShare`
*/ */
export function canShareFile(context: RuleContext): boolean { export const canShareFile = (context: RuleContext): boolean =>
return [context.selection.file, navigation.isNotTrashcan(context), repository.hasQuickShareEnabled(context), !isShared(context)].every(Boolean); [context.selection.file, navigation.isNotTrashcan(context), repository.hasQuickShareEnabled(context), !isShared(context)].every(Boolean);
}
/** /**
* Checks if user can perform "Join" or "Cancel Join Request" on a library. * Checks if user can perform "Join" or "Cancel Join Request" on a library.
* JSON ref: `canToggleJoinLibrary` * JSON ref: `canToggleJoinLibrary`
*/ */
export function canToggleJoinLibrary(context: RuleContext): boolean { export const canToggleJoinLibrary = (context: RuleContext): boolean =>
return ( [hasLibrarySelected(context), !isPrivateLibrary(context), hasNoLibraryRole(context)].every(Boolean) ||
[hasLibrarySelected(context), !isPrivateLibrary(context), hasNoLibraryRole(context)].every(Boolean) || [hasLibrarySelected(context), isPrivateLibrary(context), hasNoLibraryRole(context), isAdmin(context)].every(Boolean);
[hasLibrarySelected(context), isPrivateLibrary(context), hasNoLibraryRole(context), isAdmin(context)].every(Boolean)
);
}
/** /**
* Checks if user can edit the selected folder. * Checks if user can edit the selected folder.
* JSON ref: `canEditFolder` * JSON ref: `canEditFolder`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function canEditFolder(context: RuleContext): boolean { export const canEditFolder = (context: RuleContext): boolean => [canUpdateSelectedFolder(context), navigation.isNotTrashcan(context)].every(Boolean);
return [canUpdateSelectedFolder(context), navigation.isNotTrashcan(context)].every(Boolean);
}
/** /**
* Checks if the selected file is already shared. * Checks if the selected file is already shared.
@ -166,9 +161,7 @@ export function canUnshareNodes(context: RuleContext): boolean {
* Checks if user selected anything. * Checks if user selected anything.
* JSON ref: `app.selection.notEmpty` * JSON ref: `app.selection.notEmpty`
*/ */
export function hasSelection(context: RuleContext): boolean { export const hasSelection = (context: RuleContext): boolean => !context.selection.isEmpty;
return !context.selection.isEmpty;
}
/** /**
* Checks if user can create a new folder with current path. * Checks if user can create a new folder with current path.
@ -200,9 +193,7 @@ export function canUpload(context: RuleContext): boolean {
*/ */
export function canDownloadSelection(context: RuleContext): boolean { export function canDownloadSelection(context: RuleContext): boolean {
if (!context.selection.isEmpty && navigation.isNotTrashcan(context)) { if (!context.selection.isEmpty && navigation.isNotTrashcan(context)) {
return context.selection.nodes.every((node: any) => { return context.selection.nodes.every((node: any) => node.entry && (node.entry.isFile || node.entry.isFolder || !!node.entry.nodeId));
return node.entry && (node.entry.isFile || node.entry.isFolder || !!node.entry.nodeId);
});
} }
return false; return false;
} }
@ -211,17 +202,13 @@ export function canDownloadSelection(context: RuleContext): boolean {
* Checks if user has selected a folder. * Checks if user has selected a folder.
* JSON ref: `app.selection.folder` * JSON ref: `app.selection.folder`
*/ */
export function hasFolderSelected(context: RuleContext): boolean { export const hasFolderSelected = (context: RuleContext): boolean => !!context.selection.folder;
return !!context.selection.folder;
}
/** /**
* Checks if user has selected a library (site). * Checks if user has selected a library (site).
* JSON ref: `app.selection.library` * JSON ref: `app.selection.library`
*/ */
export function hasLibrarySelected(context: RuleContext): boolean { export const hasLibrarySelected = (context: RuleContext): boolean => !!context.selection.library;
return !!context.selection.library;
}
/** /**
* Checks if user has selected a **private** library (site) * Checks if user has selected a **private** library (site)
@ -245,17 +232,13 @@ export function hasLibraryRole(context: RuleContext): boolean {
* Checks if the selected library has no **role** property defined. * Checks if the selected library has no **role** property defined.
* JSON ref: `app.selection.hasNoLibraryRole` * JSON ref: `app.selection.hasNoLibraryRole`
*/ */
export function hasNoLibraryRole(context: RuleContext): boolean { export const hasNoLibraryRole = (context: RuleContext): boolean => !hasLibraryRole(context);
return !hasLibraryRole(context);
}
/** /**
* Checks if user has selected a file. * Checks if user has selected a file.
* JSON ref: `app.selection.file` * JSON ref: `app.selection.file`
*/ */
export function hasFileSelected(context: RuleContext): boolean { export const hasFileSelected = (context: RuleContext): boolean => !!(context && context.selection && context.selection.file);
return !!(context && context.selection && context.selection.file);
}
/** /**
* Checks if user can update the first selected node. * Checks if user can update the first selected node.
@ -319,8 +302,8 @@ export function hasLockedFiles(context: RuleContext): boolean {
* Checks if the selected file has **write** or **read-only** locks specified. * Checks if the selected file has **write** or **read-only** locks specified.
* JSON ref: `app.selection.file.isLocked` * JSON ref: `app.selection.file.isLocked`
*/ */
export function isWriteLocked(context: RuleContext): boolean { export const isWriteLocked = (context: RuleContext): boolean =>
return !!( !!(
context && context &&
context.selection && context.selection &&
context.selection.file && context.selection.file &&
@ -329,28 +312,22 @@ export function isWriteLocked(context: RuleContext): boolean {
(context.selection.file.entry.properties['cm:lockType'] === 'WRITE_LOCK' || (context.selection.file.entry.properties['cm:lockType'] === 'WRITE_LOCK' ||
context.selection.file.entry.properties['cm:lockType'] === 'READ_ONLY_LOCK') context.selection.file.entry.properties['cm:lockType'] === 'READ_ONLY_LOCK')
); );
}
/** /**
* Checks if the selected file has **write** or **read-only** locks specified, * Checks if the selected file has **write** or **read-only** locks specified,
* and that current user is the owner of the lock. * and that current user is the owner of the lock.
* JSON ref: `app.selection.file.isLockOwner` * JSON ref: `app.selection.file.isLockOwner`
*/ */
export function isUserWriteLockOwner(context: RuleContext): boolean { export const isUserWriteLockOwner = (context: RuleContext): boolean =>
return ( isWriteLocked(context) &&
isWriteLocked(context) && context.selection.file.entry.properties['cm:lockOwner'] &&
context.selection.file.entry.properties['cm:lockOwner'] && context.selection.file.entry.properties['cm:lockOwner'].id === context.profile.id;
context.selection.file.entry.properties['cm:lockOwner'].id === context.profile.id
);
}
/** /**
* Checks if user can lock selected file. * Checks if user can lock selected file.
* JSON ref: `app.selection.file.canLock` * JSON ref: `app.selection.file.canLock`
*/ */
export function canLockFile(context: RuleContext): boolean { export const canLockFile = (context: RuleContext): boolean => !isWriteLocked(context) && canUpdateSelectedNode(context);
return !isWriteLocked(context) && canUpdateSelectedNode(context);
}
/** /**
* Checks if user can unlock selected file. * Checks if user can unlock selected file.
@ -380,131 +357,124 @@ export function canUploadVersion(context: RuleContext): boolean {
/** /**
* Checks if user has trashcan item selected. * Checks if user has trashcan item selected.
* JSON ref: `isTrashcanItemSelected` * JSON ref: `isTrashcanItemSelected`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function isTrashcanItemSelected(context: RuleContext): boolean { export const isTrashcanItemSelected = (context: RuleContext): boolean => [navigation.isTrashcan(context), hasSelection(context)].every(Boolean);
return [navigation.isTrashcan(context), hasSelection(context)].every(Boolean);
}
/** /**
* Checks if user can view the file. * Checks if user can view the file.
* JSON ref: `canViewFile` * JSON ref: `canViewFile`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function canViewFile(context: RuleContext): boolean { export const canViewFile = (context: RuleContext): boolean => [hasFileSelected(context), navigation.isNotTrashcan(context)].every(Boolean);
return [hasFileSelected(context), navigation.isNotTrashcan(context)].every(Boolean);
}
/** /**
* Checks if user can **Leave** selected library. * Checks if user can **Leave** selected library.
* JSON ref: `canLeaveLibrary` * JSON ref: `canLeaveLibrary`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function canLeaveLibrary(context: RuleContext): boolean { export const canLeaveLibrary = (context: RuleContext): boolean => [hasLibrarySelected(context), hasLibraryRole(context)].every(Boolean);
return [hasLibrarySelected(context), hasLibraryRole(context)].every(Boolean);
}
/** /**
* Checks if user can toggle shared link mode. * Checks if user can toggle shared link mode.
* JSON ref: `canToggleSharedLink` * JSON ref: `canToggleSharedLink`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function canToggleSharedLink(context: RuleContext): boolean { export const canToggleSharedLink = (context: RuleContext): boolean =>
return [hasFileSelected(context), [canShareFile(context), isShared(context)].some(Boolean)].every(Boolean); [hasFileSelected(context), [canShareFile(context), isShared(context)].some(Boolean)].every(Boolean);
}
/** /**
* Checks if user can show **Info Drawer** for the selected node. * Checks if user can show **Info Drawer** for the selected node.
* JSON ref: `canShowInfoDrawer` * JSON ref: `canShowInfoDrawer`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function canShowInfoDrawer(context: RuleContext): boolean { export const canShowInfoDrawer = (context: RuleContext): boolean =>
return [hasSelection(context), navigation.isNotLibraries(context), navigation.isNotTrashcan(context)].every(Boolean); [hasSelection(context), navigation.isNotLibraries(context), navigation.isNotTrashcan(context)].every(Boolean);
}
/** /**
* Checks if user can manage file versions for the selected node. * Checks if user can manage file versions for the selected node.
* JSON ref: `canManageFileVersions` * JSON ref: `canManageFileVersions`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function canManageFileVersions(context: RuleContext): boolean { export const canManageFileVersions = (context: RuleContext): boolean =>
return [hasFileSelected(context), navigation.isNotTrashcan(context), !hasLockedFiles(context)].every(Boolean); [hasFileSelected(context), navigation.isNotTrashcan(context), !hasLockedFiles(context)].every(Boolean);
}
/** /**
* Checks if user can edit aspects for the selected node. * Checks if user can edit aspects for the selected node.
* JSON ref: `canEditAspects` * JSON ref: `canEditAspects`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function canEditAspects(context: RuleContext): boolean { export const canEditAspects = (context: RuleContext): boolean =>
return [ [
!isMultiselection(context), !isMultiselection(context),
canUpdateSelectedNode(context), canUpdateSelectedNode(context),
!isWriteLocked(context), !isWriteLocked(context),
navigation.isNotTrashcan(context), navigation.isNotTrashcan(context),
repository.isMajorVersionAvailable(context, '7') repository.isMajorVersionAvailable(context, '7')
].every(Boolean); ].every(Boolean);
}
/** /**
* Checks if user can manage permissions for the selected node. * Checks if user can manage permissions for the selected node.
* JSON ref: `canManagePermissions` * JSON ref: `canManagePermissions`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function canManagePermissions(context: RuleContext): boolean { export const canManagePermissions = (context: RuleContext): boolean =>
return [canUpdateSelectedNode(context), navigation.isNotTrashcan(context)].every(Boolean); [canUpdateSelectedNode(context), navigation.isNotTrashcan(context)].every(Boolean);
}
/** /**
* Checks if user can toggle **Edit Offline** mode for selected node. * Checks if user can toggle **Edit Offline** mode for selected node.
* JSON ref: `canToggleEditOffline` * JSON ref: `canToggleEditOffline`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function canToggleEditOffline(context: RuleContext): boolean { export const canToggleEditOffline = (context: RuleContext): boolean =>
return [hasFileSelected(context), navigation.isNotTrashcan(context), canLockFile(context) || canUnlockFile(context)].every(Boolean); [hasFileSelected(context), navigation.isNotTrashcan(context), canLockFile(context) || canUnlockFile(context)].every(Boolean);
}
/** /**
* @deprecated Uses workarounds for for recent files and search api issues. * @deprecated Uses workarounds for for recent files and search api issues.
* Checks if user can toggle **Favorite** state for a node. * Checks if user can toggle **Favorite** state for a node.
* @param context Rule execution context * @param context Rule execution context
*/ */
export function canToggleFavorite(context: RuleContext): boolean { export const canToggleFavorite = (context: RuleContext): boolean =>
return [ [
[canAddFavorite(context), canRemoveFavorite(context)].some(Boolean), [canAddFavorite(context), canRemoveFavorite(context)].some(Boolean),
[navigation.isRecentFiles(context), navigation.isSharedFiles(context), navigation.isSearchResults(context), navigation.isFavorites(context)].some( [navigation.isRecentFiles(context), navigation.isSharedFiles(context), navigation.isSearchResults(context), navigation.isFavorites(context)].some(
Boolean Boolean
) )
].every(Boolean); ].every(Boolean);
}
/** /**
* Checks if application should render logout option. * Checks if application should render logout option.
* JSON ref: `canShowLogout` * JSON ref: `canShowLogout`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function canShowLogout(context: AcaRuleContext): boolean { export const canShowLogout = (context: AcaRuleContext): boolean => !context.withCredentials;
return !context.withCredentials;
}
/** /**
* Checks if user is library manager * Checks if user is library manager
* JSON ref: `isLibraryManager` * JSON ref: `isLibraryManager`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function isLibraryManager(context: RuleContext): boolean { export const isLibraryManager = (context: RuleContext): boolean =>
return hasLibrarySelected(context) && context.selection.library.entry && context.selection.library.entry.role === 'SiteManager'; hasLibrarySelected(context) && context.selection.library.entry && context.selection.library.entry.role === 'SiteManager';
}
/** /**
* Checks if the preview button for search results can be showed * Checks if the preview button for search results can be showed
* JSON ref: `canInfoPreview` * JSON ref: `canInfoPreview`
*
* @param context Rule execution context * @param context Rule execution context
*/ */
export function canInfoPreview(context: RuleContext): boolean { export const canInfoPreview = (context: RuleContext): boolean =>
return navigation.isSearchResults(context) && !isMultiselection(context) && !hasFolderSelected(context) && !navigation.isPreview(context); navigation.isSearchResults(context) && !isMultiselection(context) && !hasFolderSelected(context) && !navigation.isPreview(context);
}
export function showInfoSelectionButton(context: RuleContext): boolean { export const showInfoSelectionButton = (context: RuleContext): boolean => navigation.isSearchResults(context) && !navigation.isPreview(context);
return navigation.isSearchResults(context) && !navigation.isPreview(context);
}

View File

@ -47,9 +47,7 @@ export function isFavorites(context: RuleContext): boolean {
* Checks if the activated route is not **Favorites**. * Checks if the activated route is not **Favorites**.
* JSON ref: `app.navigation.isNotFavorites` * JSON ref: `app.navigation.isNotFavorites`
*/ */
export function isNotFavorites(context: RuleContext): boolean { export const isNotFavorites = (context: RuleContext): boolean => !isFavorites(context);
return !isFavorites(context);
}
/** /**
* Checks if a **Shared Files** route is activated. * Checks if a **Shared Files** route is activated.
@ -64,9 +62,7 @@ export function isSharedFiles(context: RuleContext): boolean {
* Checks if the activated route is not **Shared Files**. * Checks if the activated route is not **Shared Files**.
* JSON ref: `app.navigation.isNotSharedFiles` * JSON ref: `app.navigation.isNotSharedFiles`
*/ */
export function isNotSharedFiles(context: RuleContext): boolean { export const isNotSharedFiles = (context: RuleContext): boolean => !isSharedFiles(context);
return !isSharedFiles(context);
}
/** /**
* Checks if a **Trashcan** route is activated. * Checks if a **Trashcan** route is activated.
@ -81,9 +77,7 @@ export function isTrashcan(context: RuleContext): boolean {
* Checks if the activated route is not **Trashcan**. * Checks if the activated route is not **Trashcan**.
* JSON ref: `app.navigation.isNotTrashcan` * JSON ref: `app.navigation.isNotTrashcan`
*/ */
export function isNotTrashcan(context: RuleContext): boolean { export const isNotTrashcan = (context: RuleContext): boolean => !isTrashcan(context);
return !isTrashcan(context);
}
/** /**
* Checks if a **Personal Files** route is activated. * Checks if a **Personal Files** route is activated.
@ -116,9 +110,7 @@ export function isLibraries(context: RuleContext): boolean {
* Checks if the activated route is neither **Libraries** nor **Library Search Results**. * Checks if the activated route is neither **Libraries** nor **Library Search Results**.
* JSON ref: `app.navigation.isNotLibraries` * JSON ref: `app.navigation.isNotLibraries`
*/ */
export function isNotLibraries(context: RuleContext): boolean { export const isNotLibraries = (context: RuleContext): boolean => !isLibraries(context);
return !isLibraries(context);
}
/** /**
* Checks if a **Recent Files** route is activated. * Checks if a **Recent Files** route is activated.
@ -133,16 +125,16 @@ export function isRecentFiles(context: RuleContext): boolean {
* Checks if the activated route is not **Recent Files**. * Checks if the activated route is not **Recent Files**.
* JSON ref: `app.navigation.isNotRecentFiles` * JSON ref: `app.navigation.isNotRecentFiles`
*/ */
export function isNotRecentFiles(context: RuleContext): boolean { export const isNotRecentFiles = (context: RuleContext): boolean => !isRecentFiles(context);
return !isRecentFiles(context);
}
/** /**
* Checks if a **Search Results** route is activated. * Checks if a **Search Results** route is activated.
* JSON ref: `app.navigation.isSearchResults` * JSON ref: `app.navigation.isSearchResults`
*/ */
export function isSearchResults(context: RuleContext /*, export function isSearchResults(
...args: RuleParameter[]*/): boolean { context: RuleContext /*,
...args: RuleParameter[]*/
): boolean {
const { url } = context.navigation; const { url } = context.navigation;
return url && url.startsWith('/search'); return url && url.startsWith('/search');
} }
@ -151,9 +143,7 @@ export function isSearchResults(context: RuleContext /*,
* Checks if the activated route is not **Search Results**. * Checks if the activated route is not **Search Results**.
* JSON ref: `app.navigation.isNotSearchResults` * JSON ref: `app.navigation.isNotSearchResults`
*/ */
export function isNotSearchResults(context: RuleContext): boolean { export const isNotSearchResults = (context: RuleContext): boolean => !isSearchResults(context);
return !isSearchResults(context);
}
/** /**
* Checks if a **Shared Preview** route is activated. * Checks if a **Shared Preview** route is activated.

View File

@ -29,9 +29,7 @@ import { RuleContext } from '@alfresco/adf-extensions';
* Checks if the quick share repository option is enabled or not. * Checks if the quick share repository option is enabled or not.
* JSON ref: `repository.isQuickShareEnabled` * JSON ref: `repository.isQuickShareEnabled`
*/ */
export function hasQuickShareEnabled(context: RuleContext): boolean { export const hasQuickShareEnabled = (context: RuleContext): boolean => context.repository.status.isQuickShareEnabled;
return context.repository.status.isQuickShareEnabled;
}
export function isMajorVersionAvailable(context: RuleContext, versionNumber: string): boolean { export function isMajorVersionAvailable(context: RuleContext, versionNumber: string): boolean {
const majorVersion = context.repository.version?.major ? parseInt(context.repository.version.major, 10) : 0; const majorVersion = context.repository.version?.major ? parseInt(context.repository.version.major, 10) : 0;

View File

@ -29,6 +29,4 @@ import { RuleContext } from '@alfresco/adf-extensions';
* Checks if user is admin. * Checks if user is admin.
* JSON ref: `user.isAdmin` * JSON ref: `user.isAdmin`
*/ */
export function isAdmin(context: RuleContext): boolean { export const isAdmin = (context: RuleContext): boolean => context.profile.isAdmin;
return context.profile.isAdmin;
}

View File

@ -122,9 +122,7 @@ describe('ExtensionsDataLoaderGuard', () => {
it('should call canActivate only once', () => { it('should call canActivate only once', () => {
const subject1 = new Subject<true>(); const subject1 = new Subject<true>();
const extensionLoaders = { const extensionLoaders = {
fct1: function () { fct1: () => subject1.asObservable()
return subject1.asObservable();
}
}; };
const extensionLoaderSpy = spyOn(extensionLoaders, 'fct1').and.callThrough(); const extensionLoaderSpy = spyOn(extensionLoaders, 'fct1').and.callThrough();
const guard = new ExtensionsDataLoaderGuard([extensionLoaders.fct1]); const guard = new ExtensionsDataLoaderGuard([extensionLoaders.fct1]);

View File

@ -30,9 +30,7 @@ import { tap, map, catchError } from 'rxjs/operators';
export type ExtensionLoaderCallback = (route: ActivatedRouteSnapshot) => Observable<boolean>; export type ExtensionLoaderCallback = (route: ActivatedRouteSnapshot) => Observable<boolean>;
export function DefaultExtensionLoaderFactory() { export const DefaultExtensionLoaderFactory = () => [];
return [];
}
export const EXTENSION_DATA_LOADERS = new InjectionToken<ExtensionLoaderCallback[]>('EXTENSION_DATA_LOADERS', { export const EXTENSION_DATA_LOADERS = new InjectionToken<ExtensionLoaderCallback[]>('EXTENSION_DATA_LOADERS', {
providedIn: 'root', providedIn: 'root',
@ -64,9 +62,9 @@ export class ExtensionsDataLoaderGuard implements CanActivate {
map(() => true), map(() => true),
tap(() => (this.invoked = true)), tap(() => (this.invoked = true)),
catchError((e) => { catchError((e) => {
// tslint:disable-next-line // eslint-disable-next-line no-console
console.error('Some of the extension data loader guards has been errored.'); console.error('Some of the extension data loader guards has been errored.');
// tslint:disable-next-line // eslint-disable-next-line no-console
console.error(e); console.error(e);
return of(true); return of(true);
}) })

View File

@ -37,7 +37,7 @@ export class ContextActionsDirective implements OnInit, OnDestroy {
private execute$: Subject<any> = new Subject(); private execute$: Subject<any> = new Subject();
onDestroy$: Subject<boolean> = new Subject<boolean>(); onDestroy$: Subject<boolean> = new Subject<boolean>();
// tslint:disable-next-line:no-input-rename // eslint-disable-next-line
@Input('acaContextEnable') @Input('acaContextEnable')
enabled = true; enabled = true;
@ -93,7 +93,7 @@ export class ContextActionsDirective implements OnInit, OnDestroy {
if (el.classList.contains(className)) { if (el.classList.contains(className)) {
return el; return el;
} }
// tslint:disable-next-line:curly // eslint-disable-next-line curly
while ((el = el.parentElement) && !el.classList.contains(className)); while ((el = el.parentElement) && !el.classList.contains(className));
return el; return el;
} }

View File

@ -35,9 +35,7 @@ export class AlfrescoOfficeExtensionService {
this.appConfigService.onLoad this.appConfigService.onLoad
.pipe( .pipe(
take(1), take(1),
map((appConfig) => { map((appConfig) => appConfig.plugins && appConfig.plugins.aosPlugin)
return appConfig.plugins && appConfig.plugins.aosPlugin;
})
) )
.subscribe((aosPlugin) => { .subscribe((aosPlugin) => {
if (aosPlugin) { if (aosPlugin) {

View File

@ -218,67 +218,65 @@ export class AppExtensionService implements RuleContext {
getApplicationNavigation(elements): Array<NavBarGroupRef> { getApplicationNavigation(elements): Array<NavBarGroupRef> {
return elements return elements
.filter((group) => this.filterVisible(group)) .filter((group) => this.filterVisible(group))
.map((group) => { .map((group) => ({
return { ...group,
...group, items: (group.items || [])
items: (group.items || []) .filter((entry) => !entry.disabled)
.filter((entry) => !entry.disabled) .filter((item) => this.filterVisible(item))
.filter((item) => this.filterVisible(item)) .sort(sortByOrder)
.sort(sortByOrder) .map((item) => {
.map((item) => { if (item.children && item.children.length > 0) {
if (item.children && item.children.length > 0) { item.children = item.children
item.children = item.children .filter((entry) => !entry.disabled)
.filter((entry) => !entry.disabled) .filter((child) => this.filterVisible(child))
.filter((child) => this.filterVisible(child)) .sort(sortByOrder)
.sort(sortByOrder) .map((child) => {
.map((child) => { if (child.component) {
if (child.component) { return {
return { ...child
...child };
}; }
}
if (!child.click) {
const childRouteRef = this.extensions.getRouteById(child.route);
const childUrl = `/${childRouteRef ? childRouteRef.path : child.route}`;
return {
...child,
url: childUrl
};
}
if (!child.click) {
const childRouteRef = this.extensions.getRouteById(child.route);
const childUrl = `/${childRouteRef ? childRouteRef.path : child.route}`;
return { return {
...child, ...child,
action: child.click url: childUrl
}; };
}); }
return { return {
...item ...child,
}; action: child.click
} };
});
if (item.component) {
return { ...item };
}
if (!item.click) {
const routeRef = this.extensions.getRouteById(item.route);
const url = `/${routeRef ? routeRef.path : item.route}`;
return {
...item,
url
};
}
return { return {
...item, ...item
action: item.click
}; };
}) }
.reduce(reduceEmptyMenus, [])
}; if (item.component) {
}); return { ...item };
}
if (!item.click) {
const routeRef = this.extensions.getRouteById(item.route);
const url = `/${routeRef ? routeRef.path : item.route}`;
return {
...item,
url
};
}
return {
...item,
action: item.click
};
})
.reduce(reduceEmptyMenus, [])
}));
} }
loadContentMetadata(config: ExtensionConfig): any { loadContentMetadata(config: ExtensionConfig): any {

View File

@ -124,6 +124,7 @@ export class ContentApiService {
/** /**
* Moves a node to the trashcan. * Moves a node to the trashcan.
*
* @param nodeId ID of the target node * @param nodeId ID of the target node
* @param options Optional parameters supported by JS-API * @param options Optional parameters supported by JS-API
* @returns Empty result that notifies when the deletion is complete * @returns Empty result that notifies when the deletion is complete
@ -134,6 +135,7 @@ export class ContentApiService {
/** /**
* Gets the stored information about a node. * Gets the stored information about a node.
*
* @param nodeId ID of the target node * @param nodeId ID of the target node
* @param options Optional parameters supported by JS-API * @param options Optional parameters supported by JS-API
* @returns Node information * @returns Node information
@ -170,6 +172,7 @@ export class ContentApiService {
/** /**
* Gets the items contained in a folder node. * Gets the items contained in a folder node.
*
* @param nodeId ID of the target node * @param nodeId ID of the target node
* @param options Optional parameters supported by JS-API * @param options Optional parameters supported by JS-API
* @returns List of child items from the folder * @returns List of child items from the folder
@ -208,6 +211,7 @@ export class ContentApiService {
/** /**
* Gets information about a user identified by their username. * Gets information about a user identified by their username.
*
* @param personId ID of the target user * @param personId ID of the target user
* @param options Api options * @param options Api options
* @returns User information * @returns User information
@ -230,6 +234,7 @@ export class ContentApiService {
/** /**
* Gets product information for Content Services. * Gets product information for Content Services.
*
* @returns ProductVersionModel containing product details * @returns ProductVersionModel containing product details
*/ */
getRepositoryInformation(): Observable<DiscoveryEntry> { getRepositoryInformation(): Observable<DiscoveryEntry> {
@ -253,19 +258,17 @@ export class ContentApiService {
...opts, ...opts,
where: '(EXISTS(target/site))' where: '(EXISTS(target/site))'
}).pipe( }).pipe(
map((response: FavoritePaging) => { map((response: FavoritePaging) => ({
return { list: {
list: { entries: response.list.entries.map(({ entry }: any) => {
entries: response.list.entries.map(({ entry }: any) => { entry.target.site.createdAt = entry.createdAt;
entry.target.site.createdAt = entry.createdAt; return {
return { entry: entry.target.site
entry: entry.target.site };
}; }),
}), pagination: response.list.pagination
pagination: response.list.pagination }
} }))
};
})
); );
} }

View File

@ -35,8 +35,13 @@ describe('RouterExtensionService', () => {
let extensionService: ExtensionService; let extensionService: ExtensionService;
let service: RouterExtensionService; let service: RouterExtensionService;
let router: Router; let router: Router;
let component1, component2, component3, layoutComponent; let component1;
let guard1, guard2, guard3; let component2;
let component3;
let layoutComponent;
let guard1;
let guard2;
let guard3;
beforeEach(() => { beforeEach(() => {
component1 = { name: 'component-1' }; component1 = { name: 'component-1' };
@ -97,17 +102,15 @@ describe('RouterExtensionService', () => {
}); });
describe('getApplicationRoutes', () => { describe('getApplicationRoutes', () => {
function getDummyRoute(overrides) { const getDummyRoute = (overrides) => ({
return { id: 'aca:routes/about',
id: 'aca:routes/about', path: 'ext/about',
path: 'ext/about', component: 'ext:components/about',
component: 'ext:components/about', layout: 'aca:layouts/main',
layout: 'aca:layouts/main', auth: ['aca:auth'],
auth: ['aca:auth'], data: { title: 'Custom About' },
data: { title: 'Custom About' }, ...overrides
...overrides });
};
}
it('should calculate path properly', () => { it('should calculate path properly', () => {
extensionService.routes = [getDummyRoute({ path: 'aca:routes/about' })]; extensionService.routes = [getDummyRoute({ path: 'aca:routes/about' })];

View File

@ -68,14 +68,12 @@ export class RouterExtensionService {
parentRoute: route.parentRoute, parentRoute: route.parentRoute,
children: [ children: [
...(route['children'] ...(route['children']
? route['children'].map(({ path, component, outlet, data }) => { ? route['children'].map(({ path, component, outlet, data }) => ({
return { path,
path, outlet,
outlet, data,
data, component: this.getComponentById(component)
component: this.getComponentById(component) }))
};
})
: []), : []),
{ {
path: '', path: '',
@ -87,7 +85,7 @@ export class RouterExtensionService {
}); });
} }
private getComponentById(id: string): Type<{}> { private getComponentById(id: string): Type<unknown> {
return this.extensions.getComponentById(id); return this.extensions.getComponentById(id);
} }

View File

@ -33,7 +33,7 @@ export enum SnackbarActionTypes {
export interface SnackbarAction extends Action { export interface SnackbarAction extends Action {
payload: string; payload: string;
params?: Object; params?: any;
userAction?: SnackbarUserAction; userAction?: SnackbarUserAction;
duration: number; duration: number;
} }
@ -48,7 +48,7 @@ export class SnackbarInfoAction implements SnackbarAction {
userAction?: SnackbarUserAction; userAction?: SnackbarUserAction;
duration = 4000; duration = 4000;
constructor(public payload: string, public params?: Object) {} constructor(public payload: string, public params?: any) {}
} }
export class SnackbarWarningAction implements SnackbarAction { export class SnackbarWarningAction implements SnackbarAction {
@ -57,7 +57,7 @@ export class SnackbarWarningAction implements SnackbarAction {
userAction?: SnackbarUserAction; userAction?: SnackbarUserAction;
duration = 4000; duration = 4000;
constructor(public payload: string, public params?: Object) {} constructor(public payload: string, public params?: any) {}
} }
export class SnackbarErrorAction implements SnackbarAction { export class SnackbarErrorAction implements SnackbarAction {
@ -66,5 +66,5 @@ export class SnackbarErrorAction implements SnackbarAction {
userAction?: SnackbarUserAction; userAction?: SnackbarUserAction;
duration = 4000; duration = 4000;
constructor(public payload: string, public params?: Object) {} constructor(public payload: string, public params?: any) {}
} }

View File

@ -75,7 +75,7 @@ export class SnackbarEffects {
const snackBarRef = this.snackBar.open(message, actionName, { const snackBarRef = this.snackBar.open(message, actionName, {
duration: action.duration || 4000, duration: action.duration || 4000,
panelClass: panelClass panelClass
}); });
if (action.userAction) { if (action.userAction) {
@ -85,7 +85,7 @@ export class SnackbarEffects {
} }
} }
private translate(message: string, params?: Object): string { private translate(message: string, params?: any): string {
return this.translationService.instant(message, params); return this.translationService.instant(message, params);
} }
} }

View File

@ -49,26 +49,22 @@ export const isQuickShareEnabled = createSelector(getRepositoryStatus, (info) =>
export const isAdmin = createSelector(selectApp, (state) => state.user.isAdmin); export const isAdmin = createSelector(selectApp, (state) => state.user.isAdmin);
export const getFileUploadingDialog = createSelector(selectApp, (state) => state.fileUploadingDialog); export const getFileUploadingDialog = createSelector(selectApp, (state) => state.fileUploadingDialog);
export const getSideNavState = createSelector(getAppSelection, getNavigationState, (selection, navigation) => { export const getSideNavState = createSelector(getAppSelection, getNavigationState, (selection, navigation) => ({
return { selection,
selection, navigation
navigation }));
};
});
export const getRuleContext = createSelector( export const getRuleContext = createSelector(
getAppSelection, getAppSelection,
getNavigationState, getNavigationState,
getUserProfile, getUserProfile,
getRepositoryStatus, getRepositoryStatus,
(selection, navigation, profile, repository) => { (selection, navigation, profile, repository) => ({
return { selection,
selection, navigation,
navigation, profile,
profile, repository
repository })
};
}
); );
export const infoDrawerMetadataAspect = createSelector(selectApp, (state) => state.infoDrawerMetadataAspect); export const infoDrawerMetadataAspect = createSelector(selectApp, (state) => state.infoDrawerMetadataAspect);

View File

@ -1,7 +0,0 @@
{
"extends": "../../tslint.json",
"rules": {
"directive-selector": [true, "attribute", "aca", "app", "camelCase"],
"component-selector": [true, "element", "aca", "app", "kebab-case"]
}
}

View File

@ -0,0 +1,114 @@
{
"extends": "../../.eslintrc.json",
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"project": [
"projects/adf-office-services-ext/tsconfig.lib.json",
"projects/adf-office-services-ext/tsconfig.spec.json"
],
"createDefaultProgram": true
},
"plugins": [
"eslint-plugin-react",
"eslint-plugin-rxjs",
"eslint-plugin-unicorn"
],
"rules": {
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "lib",
"style": "kebab-case"
}
],
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "lib",
"style": "camelCase"
}
],
"@angular-eslint/no-host-metadata-property": "off",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/explicit-member-accessibility": [
"off",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/member-delimiter-style": [
"off",
{
"multiline": {
"delimiter": "none",
"requireLast": true
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
],
"@typescript-eslint/semi": [
"off",
null
],
"@typescript-eslint/type-annotation-spacing": "off",
"arrow-parens": [
"off",
"always"
],
"brace-style": [
"off",
"off"
],
"eol-last": "off",
"id-blacklist": "off",
"id-match": "off",
"linebreak-style": "off",
"max-len": "off",
"new-parens": "off",
"newline-per-chained-call": "off",
"no-duplicate-imports": "error",
"no-extra-semi": "off",
"no-irregular-whitespace": "off",
"no-return-await": "error",
"no-underscore-dangle": "off",
"quote-props": "off",
"react/jsx-curly-spacing": "off",
"react/jsx-equals-spacing": "off",
"react/jsx-wrap-multilines": "off",
"rxjs/no-create": "error",
"rxjs/no-subject-unsubscribe": "error",
"rxjs/no-subject-value": "error",
"rxjs/no-unsafe-takeuntil": "error",
"space-before-function-paren": "off",
"space-in-parens": [
"off",
"never"
],
"unicorn/filename-case": "error"
}
},
{
"files": [
"*.html"
],
"rules": {
"@angular-eslint/template/no-autofocus": "error",
"@angular-eslint/template/no-negated-async": "off",
"@angular-eslint/template/no-positive-tabindex": "error"
}
}
]
}

View File

@ -109,11 +109,11 @@ export class AosEditOnlineService {
if (!this.isWindows() && !this.isMacOs()) { if (!this.isWindows() && !this.isMacOs()) {
this.notificationService.openSnackMessage('Only supported for Windows and Mac', 3000); this.notificationService.openSnackMessage('Only supported for Windows and Mac', 3000);
} else { } else {
this.aos_tryToLaunchOfficeByMsProtocolHandler(protocolHandler, url); this.aosTryToLaunchOfficeByMsProtocolHandler(protocolHandler, url);
} }
} }
private aos_tryToLaunchOfficeByMsProtocolHandler(protocolHandler: string, url: string) { private aosTryToLaunchOfficeByMsProtocolHandler(protocolHandler: string, url: string) {
const protocolUrl = protocolHandler + ':ofe%7Cu%7C' + url; const protocolUrl = protocolHandler + ':ofe%7Cu%7C' + url;
const iframe = document.createElement('iframe'); const iframe = document.createElement('iframe');

View File

@ -30,9 +30,7 @@ describe('evaluators', () => {
it('should return [false] if using SSO', () => { it('should return [false] if using SSO', () => {
const context: any = { const context: any = {
auth: { auth: {
isOauth() { isOauth: () => true
return true;
}
} }
}; };

View File

@ -1,17 +0,0 @@
{
"extends": "../../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"lib",
"camelCase"
],
"component-selector": [
true,
"element",
"lib",
"kebab-case"
]
}
}