diff --git a/angular.json b/angular.json index 8eefa7620..37fafef6a 100644 --- a/angular.json +++ b/angular.json @@ -566,7 +566,8 @@ "production": { "tsConfig": "projects/aca-folder-rules/tsconfig.lib.prod.json" } - } + }, + "defaultConfiguration": "production" }, "test": { "builder": "@angular-devkit/build-angular:karma", diff --git a/projects/aca-folder-rules/ng-package.json b/projects/aca-folder-rules/ng-package.json new file mode 100644 index 000000000..9945adeca --- /dev/null +++ b/projects/aca-folder-rules/ng-package.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/aca-folder-rules", + "lib": { + "entryFile": "src/public-api.ts" + } +} diff --git a/projects/aca-folder-rules/package.json b/projects/aca-folder-rules/package.json new file mode 100644 index 000000000..42b198345 --- /dev/null +++ b/projects/aca-folder-rules/package.json @@ -0,0 +1,25 @@ +{ + "name": "aca-folder-rules", + "version": "0.0.1", + "peerDependencies": { + "@angular/common": "^14.1.0", + "@angular/core": "^14.1.0", + "@alfresco/adf-core": "6.0.0-A.1-37376", + "@alfresco/adf-content-services": "6.0.0-A.1-37376", + "@alfresco/adf-extensions": "6.0.0-A.1-37376", + "@alfresco/aca-shared": "0.0.1", + "@alfresco/js-api": "5.2.0", + "@angular/animations": "14.1.2", + "@angular/cdk": "14.1.2", + "@angular/flex-layout": "^14.0.0-beta.40", + "@angular/forms": "14.1.2", + "@angular/material": "14.1.2", + "@ngx-translate/core": "^14.0.0", + "rxjs": "6.6.6", + "tslib": "^2.0.0", + "zone.js": "0.11.8" + }, + "dependencies": { + "tslib": "^2.3.0" + } +} diff --git a/projects/aca-folder-rules/tsconfig.lib.prod.json b/projects/aca-folder-rules/tsconfig.lib.prod.json index 5615c27df..e93bb96b3 100644 --- a/projects/aca-folder-rules/tsconfig.lib.prod.json +++ b/projects/aca-folder-rules/tsconfig.lib.prod.json @@ -2,7 +2,12 @@ { "extends": "./tsconfig.lib.json", "compilerOptions": { - "declarationMap": false + "declarationMap": false, + "paths": { + "@alfresco/aca-shared": ["dist/aca-shared"], + "@alfresco/aca-shared/store": ["dist/aca-shared/store"], + "@alfresco/aca-shared/rules": ["dist/aca-shared/rules"] + } }, "angularCompilerOptions": { "enableIvy": false diff --git a/projects/aca-shared/ng-package.json b/projects/aca-shared/ng-package.json new file mode 100644 index 000000000..1139324cb --- /dev/null +++ b/projects/aca-shared/ng-package.json @@ -0,0 +1,6 @@ +{ + "dest": "../../dist/aca-shared", + "lib": { + "entryFile": "src/public-api.ts" + } +} diff --git a/projects/aca-shared/package.json b/projects/aca-shared/package.json new file mode 100644 index 000000000..0778a821c --- /dev/null +++ b/projects/aca-shared/package.json @@ -0,0 +1,28 @@ +{ + "name": "@alfresco/aca-shared", + "version": "0.0.1", + "commit": "", + "license": "LGPL-3.0", + "scripts": {}, + "peerDependencies": { + "@alfresco/adf-content-services": "6.0.0-A.1-37376", + "@alfresco/adf-core": "6.0.0-A.1-37376", + "@alfresco/adf-extensions": "6.0.0-A.1-37376", + "@alfresco/js-api": "5.2.0", + "@angular/animations": "14.1.2", + "@angular/cdk": "14.1.2", + "@angular/common": "14.1.2", + "@angular/compiler": "14.1.2", + "@angular/core": "14.1.2", + "@angular/flex-layout": "^14.0.0-beta.40", + "@angular/forms": "14.1.2", + "@angular/material": "14.1.2", + "@ngrx/effects": "^14.2.0", + "@ngrx/router-store": "^14.2.0", + "@ngrx/store": "^14.2.0", + "@ngx-translate/core": "^14.0.0", + "rxjs": "6.6.6", + "tslib": "^2.0.0", + "zone.js": "0.11.8" + } + } diff --git a/projects/aca-shared/rules/src/app.rules.spec.ts b/projects/aca-shared/rules/src/app.rules.spec.ts index 8e801fe12..519e934a3 100644 --- a/projects/aca-shared/rules/src/app.rules.spec.ts +++ b/projects/aca-shared/rules/src/app.rules.spec.ts @@ -26,8 +26,23 @@ import * as app from './app.rules'; import { TestRuleContext } from './test-rule-context'; import { NodeEntry } from '@alfresco/js-api'; +import { getFileExtension } from './app.rules'; describe('app.evaluators', () => { + describe('getFileExtension', () => { + it('should return no extension when input is null', () => { + expect(getFileExtension(null)).toBe(null); + }); + + it('should extract file extension', () => { + expect(getFileExtension('test.docx')).toBe('docx'); + }); + + it('should not extract file extension', () => { + expect(getFileExtension('unknown')).toBe(null); + }); + }); + describe('canDownloadSelection', () => { it('should return [false] if selection is empty', () => { const context = new TestRuleContext(); diff --git a/projects/aca-shared/rules/src/app.rules.ts b/projects/aca-shared/rules/src/app.rules.ts index dcd82f748..f4a1cc405 100644 --- a/projects/aca-shared/rules/src/app.rules.ts +++ b/projects/aca-shared/rules/src/app.rules.ts @@ -25,11 +25,61 @@ import { AppConfigService } from '@alfresco/adf-core'; import { RuleContext } from '@alfresco/adf-extensions'; -import { getFileExtension, supportedExtensions } from '@alfresco/adf-office-services-ext'; import * as navigation from './navigation.rules'; import * as repository from './repository.rules'; import { isAdmin } from './user.rules'; +/* cspell:disable */ +export const supportedExtensions = { + doc: 'ms-word', + docx: 'ms-word', + docm: 'ms-word', + dot: 'ms-word', + dotx: 'ms-word', + dotm: 'ms-word', + rtf: 'ms-word', + xls: 'ms-excel', + xlsx: 'ms-excel', + xlsb: 'ms-excel', + xlsm: 'ms-excel', + xlt: 'ms-excel', + xltx: 'ms-excel', + xltm: 'ms-excel', + xlam: 'ms-excel', + ppt: 'ms-powerpoint', + pptx: 'ms-powerpoint', + pot: 'ms-powerpoint', + potx: 'ms-powerpoint', + potm: 'ms-powerpoint', + pptm: 'ms-powerpoint', + pps: 'ms-powerpoint', + ppsx: 'ms-powerpoint', + ppam: 'ms-powerpoint', + ppsm: 'ms-powerpoint', + sldx: 'ms-powerpoint', + sldm: 'ms-powerpoint', + vsd: 'ms-visio', + vss: 'ms-visio', + vst: 'ms-visio', + vsdx: 'ms-visio', + vsdm: 'ms-visio', + vssx: 'ms-visio', + vssm: 'ms-visio', + vstx: 'ms-visio', + vstm: 'ms-visio' +}; +/* cspell:enable */ + +export function getFileExtension(fileName: string): string | null { + if (fileName) { + const match = fileName.match(/\.([^\./\?\#]+)($|\?|\#)/); + + return match ? match[1] : null; + } + + return null; +} + export interface AcaRuleContext extends RuleContext { withCredentials: boolean; appConfig: AppConfigService; @@ -257,7 +307,7 @@ export function canUpdateSelectedNode(context: RuleContext): boolean { if (context.selection && !context.selection.isEmpty) { const node = context.selection.first; - if (node.entry.isFile && hasLockedFiles(context)) { + if (node?.entry.isFile && hasLockedFiles(context)) { return false; } @@ -329,8 +379,8 @@ export const isWriteLocked = (context: RuleContext): boolean => */ export const isUserWriteLockOwner = (context: RuleContext): boolean => isWriteLocked(context) && - 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'] && + context.selection.file?.entry.properties['cm:lockOwner'].id === context.profile.id; /** * Checks if user can lock selected file. @@ -344,7 +394,7 @@ export const canLockFile = (context: RuleContext): boolean => !isWriteLocked(con */ export function canUnlockFile(context: RuleContext): boolean { const { file } = context.selection; - return isWriteLocked(context) && (context.permissions.check(file.entry, ['delete']) || isUserWriteLockOwner(context)); + return isWriteLocked(context) && (context.permissions.check(file?.entry, ['delete']) || isUserWriteLockOwner(context)); } /** @@ -475,7 +525,7 @@ export const canShowLogout = (context: AcaRuleContext): boolean => !context.with * @param context Rule execution context */ export const isLibraryManager = (context: RuleContext): boolean => - hasLibrarySelected(context) && context.selection.library.entry && context.selection.library.entry.role === 'SiteManager'; + hasLibrarySelected(context) && context.selection.library?.entry.role === 'SiteManager'; /** * Checks if the preview button for search results can be showed diff --git a/projects/aca-shared/src/lib/services/app.service.ts b/projects/aca-shared/src/lib/services/app.service.ts index c364acf12..0dd7e2472 100644 --- a/projects/aca-shared/src/lib/services/app.service.ts +++ b/projects/aca-shared/src/lib/services/app.service.ts @@ -52,7 +52,7 @@ import { SetUserProfileAction, SnackbarErrorAction, ResetSelectionAction -} from '../../../store/src/public-api'; +} from '@alfresco/aca-shared/store'; import { ContentApiService } from './content-api.service'; import { RouterExtensionService } from './router.extension.service'; import { Store } from '@ngrx/store'; diff --git a/projects/aca-shared/store/src/actions/library.actions.ts b/projects/aca-shared/store/src/actions/library.actions.ts index 69cff9a4e..763cffffe 100644 --- a/projects/aca-shared/store/src/actions/library.actions.ts +++ b/projects/aca-shared/store/src/actions/library.actions.ts @@ -25,7 +25,7 @@ import { Action } from '@ngrx/store'; import { SiteBody } from '@alfresco/js-api'; -import { ModalConfiguration } from '@alfresco/aca-shared'; +import { ModalConfiguration } from '../models/modal-configuration'; export enum LibraryActionTypes { Delete = 'DELETE_LIBRARY', diff --git a/projects/aca-shared/store/src/actions/node.actions.ts b/projects/aca-shared/store/src/actions/node.actions.ts index eca093b9b..af1bf2392 100644 --- a/projects/aca-shared/store/src/actions/node.actions.ts +++ b/projects/aca-shared/store/src/actions/node.actions.ts @@ -25,7 +25,7 @@ import { Action } from '@ngrx/store'; import { MinimalNodeEntity } from '@alfresco/js-api'; -import { ModalConfiguration } from '@alfresco/aca-shared'; +import { ModalConfiguration } from '../models/modal-configuration'; export enum NodeActionTypes { SetSelection = 'SET_SELECTED_NODES', diff --git a/projects/aca-shared/store/src/actions/upload.actions.ts b/projects/aca-shared/store/src/actions/upload.actions.ts index a9975f407..5c14d07c8 100644 --- a/projects/aca-shared/store/src/actions/upload.actions.ts +++ b/projects/aca-shared/store/src/actions/upload.actions.ts @@ -24,7 +24,7 @@ */ import { Action } from '@ngrx/store'; -import { ModalConfiguration } from '@alfresco/aca-shared'; +import { ModalConfiguration } from '../models/modal-configuration'; export enum UploadActionTypes { UploadFiles = 'UPLOAD_FILES', diff --git a/projects/aca-shared/store/src/models/modal-configuration.ts b/projects/aca-shared/store/src/models/modal-configuration.ts new file mode 100644 index 000000000..0a5182153 --- /dev/null +++ b/projects/aca-shared/store/src/models/modal-configuration.ts @@ -0,0 +1,3 @@ +export interface ModalConfiguration { + focusedElementOnCloseSelector?: string; +} diff --git a/projects/aca-shared/tsconfig.lib.json b/projects/aca-shared/tsconfig.lib.json index 3a8d66dfe..305be1100 100644 --- a/projects/aca-shared/tsconfig.lib.json +++ b/projects/aca-shared/tsconfig.lib.json @@ -14,9 +14,7 @@ "importHelpers": true, "types": [], "lib": ["dom", "es2018"], - "paths": { - "@alfresco/aca-shared/*": ["./*"] - } + "paths": {} }, "angularCompilerOptions": { "skipTemplateCodegen": true, diff --git a/projects/adf-office-services-ext/src/lib/aos-extension.service.ts b/projects/adf-office-services-ext/src/lib/aos-extension.service.ts index 7673a0aea..b617fc2cd 100644 --- a/projects/adf-office-services-ext/src/lib/aos-extension.service.ts +++ b/projects/adf-office-services-ext/src/lib/aos-extension.service.ts @@ -27,12 +27,16 @@ import { AppConfigService, AuthenticationService, NotificationService } from '@alfresco/adf-core'; import { Injectable } from '@angular/core'; import { MinimalNodeEntryEntity } from '@alfresco/js-api'; -import { supportedExtensions, getFileExtension } from './utils'; +import { getFileExtension, supportedExtensions } from '@alfresco/aca-shared/rules'; + +export interface IAosEditOnlineService { + onActionEditOnlineAos(node: MinimalNodeEntryEntity): void; +} @Injectable({ providedIn: 'root' }) -export class AosEditOnlineService { +export class AosEditOnlineService implements IAosEditOnlineService { constructor( private alfrescoAuthenticationService: AuthenticationService, private appConfigService: AppConfigService, diff --git a/projects/adf-office-services-ext/src/lib/effects/aos.effects.spec.ts b/projects/adf-office-services-ext/src/lib/effects/aos.effects.spec.ts new file mode 100755 index 000000000..1e1037072 --- /dev/null +++ b/projects/adf-office-services-ext/src/lib/effects/aos.effects.spec.ts @@ -0,0 +1,72 @@ +/*! + * @license + * Alfresco Example Content Application + * + * Copyright (C) 2005 - 2020 Alfresco Software Limited + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +import { MinimalNodeEntryEntity } from '@alfresco/js-api'; +import { TestBed } from '@angular/core/testing'; +import { provideMockActions } from '@ngrx/effects/testing'; +import { Observable, of } from 'rxjs'; +import { AosAction } from '../actions/aos.actions'; +import { AosEditOnlineService, IAosEditOnlineService } from '../aos-extension.service'; +import { AosEffects } from './aos.effects'; + +class AosEditOnlineServiceMock implements IAosEditOnlineService { + onActionEditOnlineAos(_node: MinimalNodeEntryEntity): void {} +} + +describe('AosEffects', () => { + let aosActions$: Observable; + let effects: AosEffects; + let aosEditOnlineServiceMock: AosEditOnlineServiceMock; + + beforeEach(() => { + aosActions$ = new Observable(); + + TestBed.configureTestingModule({ + providers: [ + { + provide: AosEditOnlineService, + useClass: AosEditOnlineServiceMock + }, + provideMockActions(() => aosActions$), + AosEffects + ] + }); + + effects = TestBed.inject(AosEffects); + aosEditOnlineServiceMock = TestBed.inject(AosEditOnlineService); + }); + + it('should call onActionEditOnlineAos on AOS_ACTION', () => { + const onActionEditOnlineAosSpy = spyOn(aosEditOnlineServiceMock, 'onActionEditOnlineAos'); + + const payload = new MinimalNodeEntryEntity(); + const action = new AosAction(payload); + aosActions$ = of(action); + + effects.openOffice$.subscribe(); + + expect(onActionEditOnlineAosSpy).toHaveBeenCalledWith(payload); + }); +}); diff --git a/projects/adf-office-services-ext/src/lib/utils.spec.ts b/projects/adf-office-services-ext/src/lib/utils.spec.ts deleted file mode 100644 index d11bfa753..000000000 --- a/projects/adf-office-services-ext/src/lib/utils.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -/*! - * @license - * Alfresco Example Content Application - * - * Copyright (C) 2005 - 2020 Alfresco Software Limited - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -import { getFileExtension } from './utils'; - -describe('utils', () => { - it('should return no extension when input is null', () => { - expect(getFileExtension(null)).toBe(null); - }); - - it('should extract file extension', () => { - expect(getFileExtension('test.docx')).toBe('docx'); - }); - - it('should not extract file extension', () => { - expect(getFileExtension('unknown')).toBe(null); - }); -}); diff --git a/projects/adf-office-services-ext/src/lib/utils.ts b/projects/adf-office-services-ext/src/lib/utils.ts deleted file mode 100644 index fdd826d90..000000000 --- a/projects/adf-office-services-ext/src/lib/utils.ts +++ /dev/null @@ -1,73 +0,0 @@ -/*! - * @license - * Alfresco Example Content Application - * - * Copyright (C) 2005 - 2020 Alfresco Software Limited - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -/* cspell:disable */ -export const supportedExtensions = { - doc: 'ms-word', - docx: 'ms-word', - docm: 'ms-word', - dot: 'ms-word', - dotx: 'ms-word', - dotm: 'ms-word', - rtf: 'ms-word', - xls: 'ms-excel', - xlsx: 'ms-excel', - xlsb: 'ms-excel', - xlsm: 'ms-excel', - xlt: 'ms-excel', - xltx: 'ms-excel', - xltm: 'ms-excel', - xlam: 'ms-excel', - ppt: 'ms-powerpoint', - pptx: 'ms-powerpoint', - pot: 'ms-powerpoint', - potx: 'ms-powerpoint', - potm: 'ms-powerpoint', - pptm: 'ms-powerpoint', - pps: 'ms-powerpoint', - ppsx: 'ms-powerpoint', - ppam: 'ms-powerpoint', - ppsm: 'ms-powerpoint', - sldx: 'ms-powerpoint', - sldm: 'ms-powerpoint', - vsd: 'ms-visio', - vss: 'ms-visio', - vst: 'ms-visio', - vsdx: 'ms-visio', - vsdm: 'ms-visio', - vssx: 'ms-visio', - vssm: 'ms-visio', - vstx: 'ms-visio', - vstm: 'ms-visio' -}; -/* cspell:enable */ - -export function getFileExtension(fileName: string): string { - if (fileName) { - const match = fileName.match(/\.([^\./\?\#]+)($|\?|\#)/); - return match ? match[1] : null; - } - return null; -} diff --git a/projects/adf-office-services-ext/src/public-api.ts b/projects/adf-office-services-ext/src/public-api.ts index 2f1422629..c91e4788c 100644 --- a/projects/adf-office-services-ext/src/public-api.ts +++ b/projects/adf-office-services-ext/src/public-api.ts @@ -26,6 +26,5 @@ export * from './lib/aos-extension.service'; export * from './lib/actions/aos.actions'; export * from './lib/effects/aos.effects'; -export * from './lib/utils'; export * from './lib/aos-extension.module';