mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-24 17:31:52 +00:00
shared library (#1080)
* shared project scaffold * rules package * move evaluators to shared lib * add rxjs peer dependency * use dedicated material namespaces * create store package, move actions * move selectors to shared library * move generic effects to shared lib * move routing extensions * minor code reorg * fix unit tests * move content-api service * move permission service * update tests * update plint config * move page layout * css variables * use dedicated css property * move generic error component to shared lib * fix test
This commit is contained in:
24
projects/aca-shared/README.md
Normal file
24
projects/aca-shared/README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# AcaShared
|
||||
|
||||
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.2.0.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name --project aca-shared` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project aca-shared`.
|
||||
> Note: Don't forget to add `--project aca-shared` or else it will be added to the default project in your `angular.json` file.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build aca-shared` to build the project. The build artifacts will be stored in the `dist/` directory.
|
||||
|
||||
## Publishing
|
||||
|
||||
After building your library with `ng build aca-shared`, go to the dist folder `cd dist/aca-shared` and run `npm publish`.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test aca-shared` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
32
projects/aca-shared/karma.conf.js
Normal file
32
projects/aca-shared/karma.conf.js
Normal file
@@ -0,0 +1,32 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
],
|
||||
client: {
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(__dirname, '../../coverage/aca-shared'),
|
||||
reports: ['html', 'lcovonly'],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true
|
||||
});
|
||||
};
|
17
projects/aca-shared/ng-package.json
Normal file
17
projects/aca-shared/ng-package.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "../../dist/@alfresco/aca-shared",
|
||||
"lib": {
|
||||
"entryFile": "src/public-api.ts",
|
||||
"umdModuleIds": {
|
||||
"rxjs": "rxjs",
|
||||
"@alfresco/js-api": "@alfresco/js-api",
|
||||
"@alfresco/adf-core": "@alfresco/adf-core",
|
||||
"@alfresco/adf-extensions": "@alfresco/adf-extensions",
|
||||
"@ngrx/store": "@ngrx/store",
|
||||
"@ngrx/effects": "@ngrx/effects",
|
||||
"@angular/material": "@angular/material",
|
||||
"@ngx-translate/core": "@ngx-translate/core"
|
||||
}
|
||||
}
|
||||
}
|
15
projects/aca-shared/package.json
Normal file
15
projects/aca-shared/package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "@alfresco/aca-shared",
|
||||
"version": "1.8.0",
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^7.2.0",
|
||||
"@angular/core": "^7.2.0",
|
||||
"@angular/material": "^7.3.7",
|
||||
"@ngrx/effects": "^7.4.0",
|
||||
"@ngrx/store": "^7.4.0",
|
||||
"@alfresco/adf-extensions": "^3.1.0",
|
||||
"@alfresco/js-api": "^3.1.0",
|
||||
"rxjs": "^6.4.0",
|
||||
"@ngx-translate/core": "^11.0.1"
|
||||
}
|
||||
}
|
3
projects/aca-shared/rules/package.json
Normal file
3
projects/aca-shared/rules/package.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"ngPackage": {}
|
||||
}
|
365
projects/aca-shared/rules/src/app.rules.spec.ts
Normal file
365
projects/aca-shared/rules/src/app.rules.spec.ts
Normal file
@@ -0,0 +1,365 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as app from './app.rules';
|
||||
|
||||
describe('app.evaluators', () => {
|
||||
describe('isWriteLocked', () => {
|
||||
it('should return [true] if lock type is set', () => {
|
||||
const context: any = {
|
||||
selection: {
|
||||
file: {
|
||||
entry: {
|
||||
properties: {
|
||||
'cm:lockType': 'WRITE_LOCK'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isWriteLocked(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if lock type is not set', () => {
|
||||
const context: any = {
|
||||
selection: {
|
||||
file: {
|
||||
entry: {
|
||||
properties: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isWriteLocked(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return [false] if selection not present', () => {
|
||||
const context: any = {};
|
||||
|
||||
expect(app.isWriteLocked(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasLockedFiles', () => {
|
||||
it('should return [false] if selection not present', () => {
|
||||
const context: any = {};
|
||||
expect(app.hasLockedFiles(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return [false] if nodes not present', () => {
|
||||
const context: any = {
|
||||
selection: {
|
||||
nodes: null
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.hasLockedFiles(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return [false] if no files selected', () => {
|
||||
const context: any = {
|
||||
selection: {
|
||||
nodes: [
|
||||
{
|
||||
entry: {
|
||||
isFile: false
|
||||
}
|
||||
},
|
||||
{
|
||||
entry: {
|
||||
isFile: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.hasLockedFiles(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return [true] when one of files is locked', () => {
|
||||
const context: any = {
|
||||
selection: {
|
||||
nodes: [
|
||||
{
|
||||
entry: {
|
||||
isFile: true,
|
||||
isLocked: true
|
||||
}
|
||||
},
|
||||
{
|
||||
entry: {
|
||||
isFile: true,
|
||||
isLocked: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.hasLockedFiles(context)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return [true] when one of files has readonly lock', () => {
|
||||
const context: any = {
|
||||
selection: {
|
||||
nodes: [
|
||||
{
|
||||
entry: {
|
||||
isFile: true,
|
||||
isLocked: false
|
||||
}
|
||||
},
|
||||
{
|
||||
entry: {
|
||||
isFile: true,
|
||||
isLocked: false,
|
||||
properties: {
|
||||
'cm:lockType': 'READ_ONLY_LOCK'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.hasLockedFiles(context)).toBe(true);
|
||||
});
|
||||
|
||||
describe('canUpdateSelectedNode', () => {
|
||||
it('should return [false] if selection not preset', () => {
|
||||
const context: any = {};
|
||||
|
||||
expect(app.canUpdateSelectedNode(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return [false] if selection is empty', () => {
|
||||
const context: any = {
|
||||
selection: {
|
||||
isEmpty: true
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.canUpdateSelectedNode(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return [false] if first selection is not a file', () => {
|
||||
const context: any = {
|
||||
permissions: {
|
||||
check: () => false
|
||||
},
|
||||
selection: {
|
||||
isEmpty: false,
|
||||
first: {
|
||||
entry: {
|
||||
isFile: false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.canUpdateSelectedNode(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return [false] if the file is locked', () => {
|
||||
const context: any = {
|
||||
permissions: {
|
||||
check: () => true
|
||||
},
|
||||
selection: {
|
||||
isEmpty: false,
|
||||
nodes: [
|
||||
{
|
||||
entry: {
|
||||
isFile: true,
|
||||
isLocked: true
|
||||
}
|
||||
}
|
||||
],
|
||||
first: {
|
||||
entry: {
|
||||
isFile: true,
|
||||
isLocked: true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.canUpdateSelectedNode(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should evaluate allowable operation for the file', () => {
|
||||
const context: any = {
|
||||
permissions: {
|
||||
check: () => true
|
||||
},
|
||||
selection: {
|
||||
isEmpty: false,
|
||||
nodes: [
|
||||
{
|
||||
entry: {
|
||||
isFile: true,
|
||||
allowableOperationsOnTarget: []
|
||||
}
|
||||
}
|
||||
],
|
||||
first: {
|
||||
entry: {
|
||||
isFile: true,
|
||||
allowableOperationsOnTarget: []
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.canUpdateSelectedNode(context)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('canUploadVersion', () => {
|
||||
it('should return [true] if user has locked it previously', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/personal-files'
|
||||
},
|
||||
profile: {
|
||||
id: 'user1'
|
||||
},
|
||||
selection: {
|
||||
file: {
|
||||
entry: {
|
||||
properties: {
|
||||
'cm:lockType': 'WRITE_LOCK',
|
||||
'cm:lockOwner': {
|
||||
id: 'user1'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.canUploadVersion(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if other user has locked it previously', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/personal-files'
|
||||
},
|
||||
profile: {
|
||||
id: 'user2'
|
||||
},
|
||||
selection: {
|
||||
file: {
|
||||
entry: {
|
||||
properties: {
|
||||
'cm:lockType': 'WRITE_LOCK',
|
||||
'cm:lockOwner': {
|
||||
id: 'user1'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.canUploadVersion(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should check the [update] operation when no write lock present', () => {
|
||||
let checked = false;
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/personal-files'
|
||||
},
|
||||
permissions: {
|
||||
check: () => (checked = true)
|
||||
},
|
||||
selection: {
|
||||
file: {},
|
||||
isEmpty: false,
|
||||
nodes: [
|
||||
{
|
||||
entry: {
|
||||
isFile: true
|
||||
}
|
||||
}
|
||||
],
|
||||
first: {
|
||||
entry: {
|
||||
isFile: true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.canUploadVersion(context)).toBe(true);
|
||||
expect(checked).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [true] if route is `/favorites`', () => {
|
||||
const context: any = {
|
||||
selection: {
|
||||
file: {}
|
||||
},
|
||||
navigation: {
|
||||
url: '/favorites'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.canUploadVersion(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [true] if route is `/favorites`', () => {
|
||||
const context: any = {
|
||||
selection: {
|
||||
file: {}
|
||||
},
|
||||
navigation: {
|
||||
url: '/favorites'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.canUploadVersion(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [true] if route is `/shared`', () => {
|
||||
const context: any = {
|
||||
selection: {
|
||||
file: {}
|
||||
},
|
||||
navigation: {
|
||||
url: '/shared'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.canUploadVersion(context)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
528
projects/aca-shared/rules/src/app.rules.ts
Normal file
528
projects/aca-shared/rules/src/app.rules.ts
Normal file
@@ -0,0 +1,528 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { RuleContext } from '@alfresco/adf-extensions';
|
||||
import * as navigation from './navigation.rules';
|
||||
import * as repository from './repository.rules';
|
||||
|
||||
/**
|
||||
* Checks if user can copy selected node.
|
||||
* JSON ref: `app.canCopyNode`
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canCopyNode(context: RuleContext): boolean {
|
||||
return [
|
||||
hasSelection(context),
|
||||
navigation.isNotTrashcan(context),
|
||||
navigation.isNotLibraries(context)
|
||||
].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can mark selected nodes as **Favorite**.
|
||||
* JSON ref: `app.selection.canAddFavorite`
|
||||
*/
|
||||
export function canAddFavorite(context: RuleContext): boolean {
|
||||
if (!context.selection.isEmpty) {
|
||||
if (
|
||||
navigation.isFavorites(context) ||
|
||||
navigation.isLibraries(context) ||
|
||||
navigation.isTrashcan(context)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return context.selection.nodes.some(node => !node.entry.isFavorite);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can un-mark selected nodes as **Favorite**.
|
||||
* JSON ref: `app.selection.canRemoveFavorite`
|
||||
*/
|
||||
export function canRemoveFavorite(context: RuleContext): boolean {
|
||||
if (!context.selection.isEmpty && !navigation.isTrashcan(context)) {
|
||||
if (navigation.isFavorites(context)) {
|
||||
return true;
|
||||
}
|
||||
return context.selection.nodes.every(node => node.entry.isFavorite);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can share selected file.
|
||||
* JSON ref: `app.selection.file.canShare`
|
||||
*/
|
||||
export function canShareFile(context: RuleContext): boolean {
|
||||
return [
|
||||
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.
|
||||
* JSON ref: `canToggleJoinLibrary`
|
||||
*/
|
||||
export function canToggleJoinLibrary(context: RuleContext): boolean {
|
||||
return [
|
||||
hasLibrarySelected(context),
|
||||
!isPrivateLibrary(context),
|
||||
hasNoLibraryRole(context)
|
||||
].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can edit the selected folder.
|
||||
* JSON ref: `canEditFolder`
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canEditFolder(context: RuleContext): boolean {
|
||||
return [
|
||||
canUpdateSelectedFolder(context),
|
||||
navigation.isNotTrashcan(context)
|
||||
].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the selected file is already shared.
|
||||
* JSON ref: `app.selection.file.isShared`
|
||||
*/
|
||||
export function isShared(context: RuleContext): boolean {
|
||||
if (navigation.isSharedFiles(context) && !context.selection.isEmpty) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
(navigation.isNotTrashcan(context),
|
||||
!context.selection.isEmpty && context.selection.file)
|
||||
) {
|
||||
return !!(
|
||||
context.selection.file.entry &&
|
||||
context.selection.file.entry.properties &&
|
||||
context.selection.file.entry.properties['qshare:sharedId']
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can delete selected nodes.
|
||||
* JSON ref: `app.selection.canDelete`
|
||||
*/
|
||||
export function canDeleteSelection(context: RuleContext): boolean {
|
||||
if (
|
||||
navigation.isNotTrashcan(context) &&
|
||||
navigation.isNotLibraries(context) &&
|
||||
navigation.isNotSearchResults(context) &&
|
||||
!context.selection.isEmpty
|
||||
) {
|
||||
if (hasLockedFiles(context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// temp workaround for Search api
|
||||
if (navigation.isFavorites(context)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (navigation.isPreview(context)) {
|
||||
return context.permissions.check(context.selection.nodes, ['delete']);
|
||||
}
|
||||
|
||||
// workaround for Shared Files
|
||||
if (navigation.isSharedFiles(context)) {
|
||||
return context.permissions.check(context.selection.nodes, ['delete'], {
|
||||
target: 'allowableOperationsOnTarget'
|
||||
});
|
||||
}
|
||||
|
||||
return context.permissions.check(context.selection.nodes, ['delete']);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can un-share selected nodes.
|
||||
* JSON ref: `app.selection.canUnshare`
|
||||
*/
|
||||
export function canUnshareNodes(context: RuleContext): boolean {
|
||||
if (!context.selection.isEmpty) {
|
||||
return context.permissions.check(context.selection.nodes, ['delete'], {
|
||||
target: 'allowableOperationsOnTarget'
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user selected anything.
|
||||
* JSON ref: `app.selection.notEmpty`
|
||||
*/
|
||||
export function hasSelection(context: RuleContext): boolean {
|
||||
return !context.selection.isEmpty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can create a new folder with current path.
|
||||
* JSON ref: `app.navigation.folder.canCreate`
|
||||
*/
|
||||
export function canCreateFolder(context: RuleContext): boolean {
|
||||
const { currentFolder } = context.navigation;
|
||||
if (currentFolder) {
|
||||
return context.permissions.check(currentFolder, ['create']);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can upload content to current folder.
|
||||
* JSON ref: `app.navigation.folder.canUpload`
|
||||
*/
|
||||
export function canUpload(context: RuleContext): boolean {
|
||||
const { currentFolder } = context.navigation;
|
||||
if (currentFolder) {
|
||||
return context.permissions.check(currentFolder, ['create']);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can download selected nodes (either files or folders).
|
||||
* JSON ref: `app.selection.canDownload`
|
||||
*/
|
||||
export function canDownloadSelection(context: RuleContext): boolean {
|
||||
if (!context.selection.isEmpty && navigation.isNotTrashcan(context)) {
|
||||
return context.selection.nodes.every((node: any) => {
|
||||
return (
|
||||
node.entry &&
|
||||
(node.entry.isFile || node.entry.isFolder || !!node.entry.nodeId)
|
||||
);
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user has selected a folder.
|
||||
* JSON ref: `app.selection.folder`
|
||||
*/
|
||||
export function hasFolderSelected(context: RuleContext): boolean {
|
||||
const folder = context.selection.folder;
|
||||
return folder ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user has selected a library (site).
|
||||
* JSON ref: `app.selection.library`
|
||||
*/
|
||||
export function hasLibrarySelected(context: RuleContext): boolean {
|
||||
const library = context.selection.library;
|
||||
return library ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user has selected a **private** library (site)
|
||||
* JSON ref: `app.selection.isPrivateLibrary`
|
||||
*/
|
||||
export function isPrivateLibrary(context: RuleContext): boolean {
|
||||
const library = context.selection.library;
|
||||
return library
|
||||
? !!(
|
||||
library.entry &&
|
||||
library.entry.visibility &&
|
||||
library.entry.visibility === 'PRIVATE'
|
||||
)
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the selected library has a **role** property defined.
|
||||
* JSON ref: `app.selection.hasLibraryRole`
|
||||
*/
|
||||
export function hasLibraryRole(context: RuleContext): boolean {
|
||||
const library = context.selection.library;
|
||||
return library ? !!(library.entry && library.entry.role) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the selected library has no **role** property defined.
|
||||
* JSON ref: `app.selection.hasNoLibraryRole`
|
||||
*/
|
||||
export function hasNoLibraryRole(context: RuleContext): boolean {
|
||||
return !hasLibraryRole(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user has selected a file.
|
||||
* JSON ref: `app.selection.file`
|
||||
*/
|
||||
export function hasFileSelected(context: RuleContext): boolean {
|
||||
if (context && context.selection && context.selection.file) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can update the first selected node.
|
||||
* JSON ref: `app.selection.first.canUpdate`
|
||||
*/
|
||||
export function canUpdateSelectedNode(context: RuleContext): boolean {
|
||||
if (context.selection && !context.selection.isEmpty) {
|
||||
const node = context.selection.first;
|
||||
|
||||
if (node.entry.isFile && hasLockedFiles(context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return context.permissions.check(node, ['update']);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can update the first selected folder.
|
||||
* JSON ref: `app.selection.folder.canUpdate`
|
||||
*/
|
||||
export function canUpdateSelectedFolder(context: RuleContext): boolean {
|
||||
const { folder } = context.selection;
|
||||
if (folder) {
|
||||
return (
|
||||
// workaround for Favorites Api
|
||||
navigation.isFavorites(context) ||
|
||||
context.permissions.check(folder.entry, ['update'])
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user has selected a **locked** file node.
|
||||
* JSON ref: `app.selection.file.isLocked`
|
||||
*/
|
||||
export function hasLockedFiles(context: RuleContext): boolean {
|
||||
if (context && context.selection && context.selection.nodes) {
|
||||
return context.selection.nodes.some(node => {
|
||||
if (!node.entry.isFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
node.entry.isLocked ||
|
||||
(node.entry.properties &&
|
||||
node.entry.properties['cm:lockType'] === 'READ_ONLY_LOCK')
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the selected file has **write** or **read-only** locks specified.
|
||||
* JSON ref: `app.selection.file.isLocked`
|
||||
*/
|
||||
export function isWriteLocked(context: RuleContext): boolean {
|
||||
return !!(
|
||||
context &&
|
||||
context.selection &&
|
||||
context.selection.file &&
|
||||
context.selection.file.entry &&
|
||||
context.selection.file.entry.properties &&
|
||||
(context.selection.file.entry.properties['cm:lockType'] === 'WRITE_LOCK' ||
|
||||
context.selection.file.entry.properties['cm:lockType'] ===
|
||||
'READ_ONLY_LOCK')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the selected file has **write** or **read-only** locks specified,
|
||||
* and that current user is the owner of the lock.
|
||||
* JSON ref: `app.selection.file.isLockOwner`
|
||||
*/
|
||||
export function isUserWriteLockOwner(context: RuleContext): boolean {
|
||||
return (
|
||||
isWriteLocked(context) &&
|
||||
(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.
|
||||
* JSON ref: `app.selection.file.canLock`
|
||||
*/
|
||||
export function canLockFile(context: RuleContext): boolean {
|
||||
return !isWriteLocked(context) && canUpdateSelectedNode(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can unlock selected file.
|
||||
* JSON ref: `app.selection.file.canLock`
|
||||
*/
|
||||
export function canUnlockFile(context: RuleContext): boolean {
|
||||
const { file } = context.selection;
|
||||
return (
|
||||
isWriteLocked(context) &&
|
||||
(context.permissions.check(file.entry, ['delete']) ||
|
||||
isUserWriteLockOwner(context))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can upload a new version of the file.
|
||||
* JSON ref: `app.selection.file.canUploadVersion`
|
||||
*/
|
||||
export function canUploadVersion(context: RuleContext): boolean {
|
||||
if (navigation.isFavorites(context) || navigation.isSharedFiles(context)) {
|
||||
return hasFileSelected(context);
|
||||
}
|
||||
|
||||
return [
|
||||
hasFileSelected(context),
|
||||
navigation.isNotTrashcan(context),
|
||||
isWriteLocked(context)
|
||||
? isUserWriteLockOwner(context)
|
||||
: canUpdateSelectedNode(context)
|
||||
].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user has trashcan item selected.
|
||||
* JSON ref: `isTrashcanItemSelected`
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function isTrashcanItemSelected(context: RuleContext): boolean {
|
||||
return [navigation.isTrashcan(context), hasSelection(context)].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can view the file.
|
||||
* JSON ref: `canViewFile`
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canViewFile(context: RuleContext): boolean {
|
||||
return [hasFileSelected(context), navigation.isNotTrashcan(context)].every(
|
||||
Boolean
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can **Leave** selected library.
|
||||
* JSON ref: `canLeaveLibrary`
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canLeaveLibrary(context: RuleContext): boolean {
|
||||
return [hasLibrarySelected(context), hasLibraryRole(context)].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can toggle shared link mode.
|
||||
* JSON ref: `canToggleSharedLink`
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canToggleSharedLink(context: RuleContext): boolean {
|
||||
return [
|
||||
hasFileSelected(context),
|
||||
[canShareFile(context), isShared(context)].some(Boolean)
|
||||
].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can show **Info Drawer** for the selected node.
|
||||
* JSON ref: `canShowInfoDrawer`
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canShowInfoDrawer(context: RuleContext): boolean {
|
||||
return [
|
||||
hasSelection(context),
|
||||
navigation.isNotLibraries(context),
|
||||
navigation.isNotTrashcan(context)
|
||||
].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can manage file versions for the selected node.
|
||||
* JSON ref: `canManageFileVersions`
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canManageFileVersions(context: RuleContext): boolean {
|
||||
return [
|
||||
hasFileSelected(context),
|
||||
navigation.isNotTrashcan(context),
|
||||
!hasLockedFiles(context)
|
||||
].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can manage permissions for the selected node.
|
||||
* JSON ref: `canManagePermissions`
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canManagePermissions(context: RuleContext): boolean {
|
||||
return [
|
||||
canUpdateSelectedNode(context),
|
||||
navigation.isNotTrashcan(context)
|
||||
].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can toggle **Edit Offline** mode for selected node.
|
||||
* JSON ref: `canToggleEditOffline`
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canToggleEditOffline(context: RuleContext): boolean {
|
||||
return [
|
||||
hasFileSelected(context),
|
||||
navigation.isNotTrashcan(context),
|
||||
navigation.isNotFavorites(context) ||
|
||||
navigation.isFavoritesPreview(context),
|
||||
navigation.isNotSharedFiles(context) || navigation.isSharedPreview(context),
|
||||
canLockFile(context) || canUnlockFile(context)
|
||||
].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Uses workarounds for for recent files and search api issues.
|
||||
* Checks if user can toggle **Favorite** state for a node.
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canToggleFavorite(context: RuleContext): boolean {
|
||||
return [
|
||||
[canAddFavorite(context), canRemoveFavorite(context)].some(Boolean),
|
||||
[
|
||||
navigation.isRecentFiles(context),
|
||||
navigation.isSharedFiles(context),
|
||||
navigation.isSearchResults(context),
|
||||
navigation.isFavorites(context)
|
||||
].some(Boolean)
|
||||
].every(Boolean);
|
||||
}
|
338
projects/aca-shared/rules/src/navigation.rules.spec.ts
Normal file
338
projects/aca-shared/rules/src/navigation.rules.spec.ts
Normal file
@@ -0,0 +1,338 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as app from './navigation.rules';
|
||||
|
||||
describe('navigation.evaluators', () => {
|
||||
describe('isPreview', () => {
|
||||
it('should return [true] if url contains `/preview/`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: 'path/preview/id'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isPreview(context)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isFavorites', () => {
|
||||
it('should return [true] if url contains `/favorites`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/favorites/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isFavorites(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if `/favorites` url contains `/preview/`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/favorites/preview/'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isFavorites(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNotFavorites', () => {
|
||||
it('should return [true] if url is not `/favorites`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/some/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotFavorites(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url starts with `/favorites`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/favorites/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotFavorites(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSharedFiles', () => {
|
||||
it('should return [true] if path starts with `/shared`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/shared/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isSharedFiles(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if `/shared` url contains `/preview/`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/shared/preview/'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isSharedFiles(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNotSharedFiles', () => {
|
||||
it('should return [true] if path does not contain `/shared`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/some/path/'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotSharedFiles(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if path contains `/shared`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/shared/path/'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotSharedFiles(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isTrashcan', () => {
|
||||
it('should return [true] if url starts with `/trashcan`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/trashcan'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isTrashcan(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url does not start with `/trashcan`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path/trashcan'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isTrashcan(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNotTrashcan', () => {
|
||||
it('should return [true] if url does not start with `/trashcan`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path/trashcan'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotTrashcan(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url does start with `/trashcan`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/trashcan'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotTrashcan(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isPersonalFiles', () => {
|
||||
it('should return [true] if url starts with `/personal-files`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/personal-files'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isPersonalFiles(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url does not start with `/personal-files`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path/personal-files'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isPersonalFiles(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isLibraries', () => {
|
||||
it('should return [true] if url ends with `/libraries`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path/libraries'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isLibraries(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [true] if url starts with `/search-libraries`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/search-libraries/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isLibraries(context)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNotLibraries', () => {
|
||||
it('should return [true] if url does not end with `/libraries`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/libraries/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotLibraries(context)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isRecentFiles', () => {
|
||||
it('should return [true] if url starts with `/recent-files`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/recent-files'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isRecentFiles(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url does not start with `/recent-files`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path/recent-files'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isRecentFiles(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSearchResults', () => {
|
||||
it('should return [true] if url starts with `/search`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/search'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isSearchResults(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url does not start with `/search`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path/search'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isSearchResults(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSharedPreview', () => {
|
||||
it('should return [true] if url starts with `/shared/preview/`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/shared/preview/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isSharedPreview(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url does not start with `/shared/preview/`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path/shared/preview/'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isSharedPreview(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isFavoritesPreview', () => {
|
||||
it('should return [true] if url starts with `/favorites/preview/`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/favorites/preview/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isFavoritesPreview(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url does not start with `/favorites/preview/`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path/favorites/preview/'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isFavoritesPreview(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSharedFileViewer', () => {
|
||||
it('should return [true] if url starts with `/preview/s/`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/preview/s/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isSharedFileViewer(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url does not start with `/preview/s/`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path/preview/s/'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isSharedFileViewer(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
187
projects/aca-shared/rules/src/navigation.rules.ts
Normal file
187
projects/aca-shared/rules/src/navigation.rules.ts
Normal file
@@ -0,0 +1,187 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { RuleContext } from '@alfresco/adf-extensions';
|
||||
|
||||
/**
|
||||
* Checks if a Preview route is activated.
|
||||
* JSON ref: `app.navigation.isPreview`
|
||||
*/
|
||||
export function isPreview(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url && (url.includes('/preview/') || url.includes('/view/'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Favorites** route is activated.
|
||||
* JSON ref: `app.navigation.isFavorites`
|
||||
*/
|
||||
export function isFavorites(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url && url.startsWith('/favorites') && !isPreview(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the activated route is not **Favorites**.
|
||||
* JSON ref: `app.navigation.isNotFavorites`
|
||||
*/
|
||||
export function isNotFavorites(context: RuleContext): boolean {
|
||||
return !isFavorites(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Shared Files** route is activated.
|
||||
* JSON ref: `app.navigation.isSharedFiles`
|
||||
*/
|
||||
export function isSharedFiles(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url && url.startsWith('/shared') && !isPreview(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the activated route is not **Shared Files**.
|
||||
* JSON ref: `app.navigation.isNotSharedFiles`
|
||||
*/
|
||||
export function isNotSharedFiles(context: RuleContext): boolean {
|
||||
return !isSharedFiles(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Trashcan** route is activated.
|
||||
* JSON ref: `app.navigation.isTrashcan`
|
||||
*/
|
||||
export function isTrashcan(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url && url.startsWith('/trashcan');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the activated route is not **Trashcan**.
|
||||
* JSON ref: `app.navigation.isNotTrashcan`
|
||||
*/
|
||||
export function isNotTrashcan(context: RuleContext): boolean {
|
||||
return !isTrashcan(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Personal Files** route is activated.
|
||||
* JSON ref: `app.navigation.isPersonalFiles`
|
||||
*/
|
||||
export function isPersonalFiles(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url && url.startsWith('/personal-files');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Library Files** route is activated.
|
||||
* JSON ref: `app.navigation.isLibraryFiles`
|
||||
*/
|
||||
export function isLibraryFiles(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url && url.startsWith('/libraries');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Library Files** or **Library Search Result** route is activated.
|
||||
* JSON ref: `app.navigation.isLibraryFiles`
|
||||
*/
|
||||
export function isLibraries(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return (
|
||||
url && (url.endsWith('/libraries') || url.startsWith('/search-libraries'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the activated route is neither **Libraries** nor **Library Search Results**.
|
||||
* JSON ref: `app.navigation.isNotLibraries`
|
||||
*/
|
||||
export function isNotLibraries(context: RuleContext): boolean {
|
||||
return !isLibraries(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Recent Files** route is activated.
|
||||
* JSON ref: `app.navigation.isRecentFiles`
|
||||
*/
|
||||
export function isRecentFiles(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url && url.startsWith('/recent-files');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the activated route is not **Recent Files**.
|
||||
* JSON ref: `app.navigation.isNotRecentFiles`
|
||||
*/
|
||||
export function isNotRecentFiles(context: RuleContext): boolean {
|
||||
return !isRecentFiles(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Search Results** route is activated.
|
||||
* JSON ref: `app.navigation.isSearchResults`
|
||||
*/
|
||||
export function isSearchResults(
|
||||
context: RuleContext /*,
|
||||
...args: RuleParameter[]*/
|
||||
): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url && url.startsWith('/search');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the activated route is not **Search Results**.
|
||||
* JSON ref: `app.navigation.isNotSearchResults`
|
||||
*/
|
||||
export function isNotSearchResults(context: RuleContext): boolean {
|
||||
return !isSearchResults(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Shared Preview** route is activated.
|
||||
* JSON ref: `app.navigation.isSharedPreview`
|
||||
*/
|
||||
export function isSharedPreview(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url && url.startsWith('/shared/preview/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Favorites Preview** route is activated.
|
||||
* JSON ref: `app.navigation.isFavoritesPreview`
|
||||
*/
|
||||
export function isFavoritesPreview(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url && url.startsWith('/favorites/preview/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Shared File Preview** route is activated.
|
||||
* JSON ref: `app.navigation.isFavoritesPreview`
|
||||
*/
|
||||
export function isSharedFileViewer(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url && url.startsWith('/preview/s/');
|
||||
}
|
28
projects/aca-shared/rules/src/public_api.ts
Normal file
28
projects/aca-shared/rules/src/public_api.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export * from './app.rules';
|
||||
export * from './navigation.rules';
|
||||
export * from './repository.rules';
|
34
projects/aca-shared/rules/src/repository.rules.ts
Normal file
34
projects/aca-shared/rules/src/repository.rules.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { RuleContext } from '@alfresco/adf-extensions';
|
||||
|
||||
/**
|
||||
* Checks if the quick share repository option is enabled or not.
|
||||
* JSON ref: `repository.isQuickShareEnabled`
|
||||
*/
|
||||
export function hasQuickShareEnabled(context: RuleContext): boolean {
|
||||
return context.repository.status.isQuickShareEnabled;
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
<mat-icon>ic_error</mat-icon>
|
||||
<p class="generic-error__title">
|
||||
{{ text | translate }}
|
||||
</p>
|
@@ -0,0 +1,22 @@
|
||||
.aca-generic-error {
|
||||
color: var(--theme-text-color, rgba(0, 0, 0, 0.54));
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
&__title {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
color: var(--theme-warn-color, #f44336);
|
||||
direction: rtl;
|
||||
font-size: 52px;
|
||||
height: 52px;
|
||||
width: 52px;
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { GenericErrorComponent } from './generic-error.component';
|
||||
|
||||
describe('GenericErrorComponent', () => {
|
||||
it('should be defined', () => {
|
||||
expect(GenericErrorComponent).toBeDefined();
|
||||
});
|
||||
});
|
@@ -0,0 +1,44 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
ViewEncapsulation,
|
||||
ChangeDetectionStrategy,
|
||||
Input
|
||||
} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-generic-error',
|
||||
templateUrl: './generic-error.component.html',
|
||||
styleUrls: ['./generic-error.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { class: 'aca-generic-error' }
|
||||
})
|
||||
export class GenericErrorComponent {
|
||||
@Input()
|
||||
text = 'APP.MESSAGES.ERRORS.MISSING_CONTENT';
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { GenericErrorComponent } from './generic-error.component';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, MatIconModule, TranslateModule.forChild()],
|
||||
declarations: [GenericErrorComponent],
|
||||
exports: [GenericErrorComponent]
|
||||
})
|
||||
export class GenericErrorModule {}
|
@@ -0,0 +1,47 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
ViewEncapsulation,
|
||||
ChangeDetectionStrategy,
|
||||
Input,
|
||||
HostBinding
|
||||
} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-page-layout-content',
|
||||
template: `
|
||||
<ng-content></ng-content>
|
||||
`,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { class: 'aca-page-layout-content' }
|
||||
})
|
||||
export class PageLayoutContentComponent {
|
||||
@Input()
|
||||
@HostBinding('class.scrollable')
|
||||
scrollable = false;
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
ViewEncapsulation,
|
||||
ChangeDetectionStrategy
|
||||
} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-page-layout-error',
|
||||
template: `
|
||||
<ng-content></ng-content>
|
||||
`,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { class: 'aca-page-layout-error' }
|
||||
})
|
||||
export class PageLayoutErrorComponent {}
|
@@ -0,0 +1,39 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
ViewEncapsulation,
|
||||
ChangeDetectionStrategy
|
||||
} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-page-layout-header',
|
||||
template: '<ng-content></ng-content>',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { class: 'aca-page-layout-header' }
|
||||
})
|
||||
export class PageLayoutHeaderComponent {}
|
@@ -0,0 +1,3 @@
|
||||
<ng-content select="aca-page-layout-header"></ng-content>
|
||||
<ng-content select="aca-page-layout-error" *ngIf="hasError"></ng-content>
|
||||
<ng-content select="aca-page-layout-content" *ngIf="!hasError"></ng-content>
|
@@ -0,0 +1,44 @@
|
||||
@import '../../styles/mixins.scss';
|
||||
|
||||
.aca-page-layout {
|
||||
@include flex-column;
|
||||
|
||||
.aca-page-layout-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 0 0 65px;
|
||||
flex-basis: 48px;
|
||||
background: #fafafa;
|
||||
border-bottom: 1px solid var(--theme-border-color, rgba(0, 0, 0, 0.07));
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.aca-page-layout-content {
|
||||
@include flex-row;
|
||||
}
|
||||
|
||||
.aca-page-layout-error {
|
||||
@include flex-row;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
@include flex-column;
|
||||
border-right: 1px solid var(--theme-border-color, rgba(0, 0, 0, 0.07));
|
||||
}
|
||||
|
||||
.scrollable {
|
||||
overflow: auto !important;
|
||||
|
||||
.main-content {
|
||||
overflow: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
display: block;
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
max-width: 350px;
|
||||
width: 350px;
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
ViewEncapsulation,
|
||||
ChangeDetectionStrategy,
|
||||
Input
|
||||
} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-page-layout',
|
||||
templateUrl: 'page-layout.component.html',
|
||||
styleUrls: ['./page-layout.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: { class: 'aca-page-layout' },
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class PageLayoutComponent {
|
||||
@Input()
|
||||
hasError = false;
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { PageLayoutContentComponent } from './page-layout-content.component';
|
||||
import { PageLayoutErrorComponent } from './page-layout-error.component';
|
||||
import { PageLayoutHeaderComponent } from './page-layout-header.component';
|
||||
import { PageLayoutComponent } from './page-layout.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
declarations: [
|
||||
PageLayoutContentComponent,
|
||||
PageLayoutErrorComponent,
|
||||
PageLayoutHeaderComponent,
|
||||
PageLayoutComponent
|
||||
],
|
||||
exports: [
|
||||
PageLayoutContentComponent,
|
||||
PageLayoutErrorComponent,
|
||||
PageLayoutHeaderComponent,
|
||||
PageLayoutComponent
|
||||
]
|
||||
})
|
||||
export class PageLayoutModule {}
|
@@ -0,0 +1,86 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { AppRouteReuseStrategy } from './app.routes.strategy';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
describe('AppRouteReuseStrategy', () => {
|
||||
let appRouteReuse: AppRouteReuseStrategy;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [AppRouteReuseStrategy]
|
||||
});
|
||||
|
||||
appRouteReuse = TestBed.get(AppRouteReuseStrategy);
|
||||
});
|
||||
|
||||
it('should allow detach if route is configured to be reused', () => {
|
||||
const route = <any>{
|
||||
routeConfig: {
|
||||
data: {
|
||||
reuse: true
|
||||
},
|
||||
path: 'tested-path'
|
||||
}
|
||||
};
|
||||
expect(appRouteReuse.shouldDetach(<any>route)).toBe(true);
|
||||
});
|
||||
|
||||
it('should store on routeCache', () => {
|
||||
const route = <any>{
|
||||
url: [],
|
||||
routeConfig: {
|
||||
data: {
|
||||
reuse: true
|
||||
},
|
||||
path: 'tested-path',
|
||||
component: {}
|
||||
},
|
||||
firstChild: null,
|
||||
children: []
|
||||
};
|
||||
appRouteReuse.store(route, { route: {} });
|
||||
expect(appRouteReuse.shouldAttach(<any>route)).toBe(true);
|
||||
});
|
||||
|
||||
it('should clear routeCache on resetCache', () => {
|
||||
const route = <any>{
|
||||
url: [],
|
||||
routeConfig: {
|
||||
data: {
|
||||
reuse: true
|
||||
},
|
||||
path: 'tested-path',
|
||||
component: {}
|
||||
},
|
||||
firstChild: null,
|
||||
children: []
|
||||
};
|
||||
appRouteReuse.store(route, { route: {} });
|
||||
appRouteReuse.resetCache();
|
||||
expect(appRouteReuse.shouldAttach(<any>route)).toBe(false);
|
||||
});
|
||||
});
|
142
projects/aca-shared/src/lib/routing/app.routes.strategy.ts
Normal file
142
projects/aca-shared/src/lib/routing/app.routes.strategy.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
RouteReuseStrategy,
|
||||
DetachedRouteHandle,
|
||||
ActivatedRouteSnapshot
|
||||
} from '@angular/router';
|
||||
import { ComponentRef } from '@angular/core';
|
||||
|
||||
interface RouteData {
|
||||
reuse: boolean;
|
||||
}
|
||||
|
||||
interface RouteInfo {
|
||||
handle: DetachedRouteHandle;
|
||||
data: RouteData;
|
||||
}
|
||||
|
||||
export class AppRouteReuseStrategy implements RouteReuseStrategy {
|
||||
private routeCache = new Map<string, RouteInfo>();
|
||||
|
||||
resetCache() {
|
||||
this.routeCache.forEach(value => {
|
||||
this.deactivateComponent(value.handle);
|
||||
});
|
||||
this.routeCache.clear();
|
||||
}
|
||||
|
||||
private deactivateComponent(handle: DetachedRouteHandle): void {
|
||||
if (!handle) {
|
||||
return;
|
||||
}
|
||||
const componentRef: ComponentRef<any> = handle['componentRef'];
|
||||
if (componentRef) {
|
||||
componentRef.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
shouldReuseRoute(
|
||||
future: ActivatedRouteSnapshot,
|
||||
curr: ActivatedRouteSnapshot
|
||||
): boolean {
|
||||
const ret = future.routeConfig === curr.routeConfig;
|
||||
if (ret) {
|
||||
this.addRedirectsRecursively(future); // update redirects
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
shouldDetach(route: ActivatedRouteSnapshot): boolean {
|
||||
const data = this.getRouteData(route);
|
||||
return data && data.reuse;
|
||||
}
|
||||
|
||||
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
|
||||
const url = this.getFullRouteUrl(route);
|
||||
const data = this.getRouteData(route);
|
||||
this.routeCache.set(url, { handle, data });
|
||||
this.addRedirectsRecursively(route);
|
||||
}
|
||||
|
||||
shouldAttach(route: ActivatedRouteSnapshot): boolean {
|
||||
const url = this.getFullRouteUrl(route);
|
||||
return this.routeCache.has(url);
|
||||
}
|
||||
|
||||
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
|
||||
const url = this.getFullRouteUrl(route);
|
||||
const data = this.getRouteData(route);
|
||||
return data && data.reuse && this.routeCache.has(url)
|
||||
? this.routeCache.get(url).handle
|
||||
: null;
|
||||
}
|
||||
|
||||
private addRedirectsRecursively(route: ActivatedRouteSnapshot): void {
|
||||
const config = route.routeConfig;
|
||||
if (config) {
|
||||
if (!config.loadChildren) {
|
||||
const routeFirstChild = route.firstChild;
|
||||
const routeFirstChildUrl = routeFirstChild
|
||||
? this.getRouteUrlPaths(routeFirstChild).join('/')
|
||||
: '';
|
||||
const childConfigs = config.children;
|
||||
if (childConfigs) {
|
||||
const childConfigWithRedirect = childConfigs.find(
|
||||
c => c.path === '' && !!c.redirectTo
|
||||
);
|
||||
if (childConfigWithRedirect) {
|
||||
childConfigWithRedirect.redirectTo = routeFirstChildUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
route.children.forEach(childRoute =>
|
||||
this.addRedirectsRecursively(childRoute)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private getFullRouteUrl(route: ActivatedRouteSnapshot): string {
|
||||
return this.getFullRouteUrlPaths(route)
|
||||
.filter(Boolean)
|
||||
.join('/');
|
||||
}
|
||||
|
||||
private getFullRouteUrlPaths(route: ActivatedRouteSnapshot): string[] {
|
||||
const paths = this.getRouteUrlPaths(route);
|
||||
return route.parent
|
||||
? [...this.getFullRouteUrlPaths(route.parent), ...paths]
|
||||
: paths;
|
||||
}
|
||||
|
||||
private getRouteUrlPaths(route: ActivatedRouteSnapshot): string[] {
|
||||
return route.url.map(urlSegment => urlSegment.path);
|
||||
}
|
||||
|
||||
private getRouteData(route: ActivatedRouteSnapshot): RouteData {
|
||||
return route.routeConfig && (route.routeConfig.data as RouteData);
|
||||
}
|
||||
}
|
54
projects/aca-shared/src/lib/routing/shared.guard.ts
Normal file
54
projects/aca-shared/src/lib/routing/shared.guard.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CanActivate } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppStore, isQuickShareEnabled } from '@alfresco/aca-shared/store';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AppSharedRuleGuard implements CanActivate {
|
||||
isQuickShareEnabled$: Observable<boolean>;
|
||||
|
||||
constructor(store: Store<AppStore>) {
|
||||
this.isQuickShareEnabled$ = store.select(isQuickShareEnabled);
|
||||
}
|
||||
|
||||
canActivate(
|
||||
_: ActivatedRouteSnapshot
|
||||
): Observable<boolean> | Promise<boolean> | boolean {
|
||||
return this.isQuickShareEnabled$;
|
||||
}
|
||||
|
||||
canActivateChild(
|
||||
route: ActivatedRouteSnapshot
|
||||
): Observable<boolean> | Promise<boolean> | boolean {
|
||||
return this.canActivate(route);
|
||||
}
|
||||
}
|
96
projects/aca-shared/src/lib/services/app.service.spec.ts
Normal file
96
projects/aca-shared/src/lib/services/app.service.spec.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { AppService } from './app.service';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { AuthenticationService, AppConfigService } from '@alfresco/adf-core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { AppRouteReuseStrategy } from '../routing/app.routes.strategy';
|
||||
|
||||
describe('AppService', () => {
|
||||
let service: AppService;
|
||||
let auth: AuthenticationService;
|
||||
let routeReuse: AppRouteReuseStrategy;
|
||||
let appConfig: AppConfigService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [HttpClientModule],
|
||||
providers: [
|
||||
AppRouteReuseStrategy,
|
||||
{
|
||||
provide: AuthenticationService,
|
||||
useValue: {
|
||||
onLogin: new Subject<any>(),
|
||||
onLogout: new Subject<any>(),
|
||||
isLoggedIn: () => false
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
routeReuse = TestBed.get(AppRouteReuseStrategy);
|
||||
auth = TestBed.get(AuthenticationService);
|
||||
appConfig = TestBed.get(AppConfigService);
|
||||
spyOn(routeReuse, 'resetCache').and.stub();
|
||||
|
||||
service = new AppService(auth, appConfig, routeReuse);
|
||||
});
|
||||
|
||||
it('should be ready if [withCredentials] mode is used', done => {
|
||||
appConfig.config = {
|
||||
auth: {
|
||||
withCredentials: true
|
||||
}
|
||||
};
|
||||
|
||||
const instance = new AppService(auth, appConfig, routeReuse);
|
||||
expect(instance.withCredentials).toBeTruthy();
|
||||
|
||||
instance.ready$.subscribe(() => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should reset route cache on login', async () => {
|
||||
auth.onLogin.next();
|
||||
await expect(routeReuse.resetCache).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should reset route cache on logout', async () => {
|
||||
auth.onLogout.next();
|
||||
await expect(routeReuse.resetCache).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should be ready after login', async () => {
|
||||
let isReady = false;
|
||||
service.ready$.subscribe(value => {
|
||||
isReady = value;
|
||||
});
|
||||
auth.onLogin.next();
|
||||
await expect(<any>isReady).toEqual(true);
|
||||
});
|
||||
});
|
64
projects/aca-shared/src/lib/services/app.service.ts
Normal file
64
projects/aca-shared/src/lib/services/app.service.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Injectable, Inject } from '@angular/core';
|
||||
import { AuthenticationService, AppConfigService } from '@alfresco/adf-core';
|
||||
import { Observable, BehaviorSubject } from 'rxjs';
|
||||
import { RouteReuseStrategy } from '@angular/router';
|
||||
import { AppRouteReuseStrategy } from '../routing/app.routes.strategy';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AppService {
|
||||
private ready: BehaviorSubject<boolean>;
|
||||
ready$: Observable<boolean>;
|
||||
|
||||
/**
|
||||
* Whether `withCredentials` mode is enabled.
|
||||
* Usually means that `Kerberos` mode is used.
|
||||
*/
|
||||
get withCredentials(): boolean {
|
||||
return this.config.get<boolean>('auth.withCredentials', false);
|
||||
}
|
||||
|
||||
constructor(
|
||||
auth: AuthenticationService,
|
||||
private config: AppConfigService,
|
||||
@Inject(RouteReuseStrategy) routeStrategy: AppRouteReuseStrategy
|
||||
) {
|
||||
this.ready = new BehaviorSubject(auth.isLoggedIn() || this.withCredentials);
|
||||
this.ready$ = this.ready.asObservable();
|
||||
|
||||
auth.onLogin.subscribe(() => {
|
||||
routeStrategy.resetCache();
|
||||
this.ready.next(true);
|
||||
});
|
||||
|
||||
auth.onLogout.subscribe(() => {
|
||||
routeStrategy.resetCache();
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ContentApiService } from './content-api.service';
|
||||
|
||||
describe('ContentApiService', () => {
|
||||
it('should be defined', () => {
|
||||
expect(ContentApiService).toBeDefined();
|
||||
});
|
||||
});
|
293
projects/aca-shared/src/lib/services/content-api.service.ts
Normal file
293
projects/aca-shared/src/lib/services/content-api.service.ts
Normal file
@@ -0,0 +1,293 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AlfrescoApiService, UserPreferencesService } from '@alfresco/adf-core';
|
||||
import { Observable, from } from 'rxjs';
|
||||
import {
|
||||
MinimalNodeEntity,
|
||||
NodePaging,
|
||||
Node,
|
||||
DeletedNodesPaging,
|
||||
PersonEntry,
|
||||
NodeEntry,
|
||||
DiscoveryEntry,
|
||||
FavoritePaging,
|
||||
SharedLinkPaging,
|
||||
SearchRequest,
|
||||
ResultSetPaging,
|
||||
SiteBody,
|
||||
SiteEntry,
|
||||
FavoriteBody,
|
||||
FavoriteEntry
|
||||
} from '@alfresco/js-api';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ContentApiService {
|
||||
constructor(
|
||||
private api: AlfrescoApiService,
|
||||
private preferences: UserPreferencesService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Moves a node to the trashcan.
|
||||
* @param nodeId ID of the target node
|
||||
* @param options Optional parameters supported by JS-API
|
||||
* @returns Empty result that notifies when the deletion is complete
|
||||
*/
|
||||
deleteNode(
|
||||
nodeId: string,
|
||||
options: { permanent?: boolean } = {}
|
||||
): Observable<void> {
|
||||
return from(this.api.nodesApi.deleteNode(nodeId, options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the stored information about a node.
|
||||
* @param nodeId ID of the target node
|
||||
* @param options Optional parameters supported by JS-API
|
||||
* @returns Node information
|
||||
*/
|
||||
getNode(nodeId: string, options: any = {}): Observable<MinimalNodeEntity> {
|
||||
const defaults = {
|
||||
include: ['path', 'properties', 'allowableOperations', 'permissions']
|
||||
};
|
||||
const queryOptions = Object.assign(defaults, options);
|
||||
|
||||
return from(this.api.nodesApi.getNode(nodeId, queryOptions));
|
||||
}
|
||||
|
||||
getNodeInfo(nodeId: string, options?: any): Observable<Node> {
|
||||
const defaults = {
|
||||
include: ['isFavorite', 'allowableOperations']
|
||||
};
|
||||
const queryOptions = Object.assign(defaults, options || {});
|
||||
|
||||
return from(this.api.nodesApi.getNodeInfo(nodeId, queryOptions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the items contained in a folder node.
|
||||
* @param nodeId ID of the target node
|
||||
* @param options Optional parameters supported by JS-API
|
||||
* @returns List of child items from the folder
|
||||
*/
|
||||
getNodeChildren(nodeId: string, options: any = {}): Observable<NodePaging> {
|
||||
const defaults = {
|
||||
maxItems: this.preferences.paginationSize,
|
||||
skipCount: 0,
|
||||
include: [
|
||||
'isLocked',
|
||||
'path',
|
||||
'properties',
|
||||
'allowableOperations',
|
||||
'permissions'
|
||||
]
|
||||
};
|
||||
const queryOptions = Object.assign(defaults, options);
|
||||
|
||||
return from(this.api.nodesApi.getNodeChildren(nodeId, queryOptions));
|
||||
}
|
||||
|
||||
deleteSharedLink(linkId: string): Observable<any> {
|
||||
return from(this.api.sharedLinksApi.deleteSharedLink(linkId));
|
||||
}
|
||||
|
||||
getDeletedNodes(options: any = {}): Observable<DeletedNodesPaging> {
|
||||
const defaults = {
|
||||
include: ['path']
|
||||
};
|
||||
const queryOptions = Object.assign(defaults, options);
|
||||
|
||||
return from(this.api.nodesApi.getDeletedNodes(queryOptions));
|
||||
}
|
||||
|
||||
restoreNode(nodeId: string): Observable<MinimalNodeEntity> {
|
||||
return from(this.api.nodesApi.restoreNode(nodeId));
|
||||
}
|
||||
|
||||
purgeDeletedNode(nodeId: string): Observable<any> {
|
||||
return from(this.api.nodesApi.purgeDeletedNode(nodeId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information about a user identified by their username.
|
||||
* @param personId ID of the target user
|
||||
* @returns User information
|
||||
*/
|
||||
getPerson(
|
||||
personId: string,
|
||||
options?: { fields?: Array<string> }
|
||||
): Observable<PersonEntry> {
|
||||
return from(this.api.peopleApi.getPerson(personId, options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a node to destination node
|
||||
*
|
||||
* @param nodeId The id of the node to be copied
|
||||
* @param targetParentId The id of the folder-node where the node have to be copied to
|
||||
* @param name The new name for the copy that would be added on the destination folder
|
||||
*/
|
||||
copyNode(
|
||||
nodeId: string,
|
||||
targetParentId: string,
|
||||
name?: string,
|
||||
opts?: { include?: Array<string>; fields?: Array<string> }
|
||||
): Observable<NodeEntry> {
|
||||
return from(
|
||||
this.api.nodesApi.copyNode(nodeId, { targetParentId, name }, opts)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets product information for Content Services.
|
||||
* @returns ProductVersionModel containing product details
|
||||
*/
|
||||
getRepositoryInformation(): Observable<DiscoveryEntry> {
|
||||
return from(
|
||||
this.api.getInstance().discovery.discoveryApi.getRepositoryInformation()
|
||||
);
|
||||
}
|
||||
|
||||
getFavorites(
|
||||
personId: string,
|
||||
opts?: {
|
||||
skipCount?: number;
|
||||
maxItems?: number;
|
||||
where?: string;
|
||||
fields?: Array<string>;
|
||||
}
|
||||
): Observable<FavoritePaging> {
|
||||
return from(this.api.favoritesApi.getFavorites(personId, opts));
|
||||
}
|
||||
|
||||
getFavoriteLibraries(
|
||||
personId: string = '-me-',
|
||||
opts?: any
|
||||
): Observable<FavoritePaging> {
|
||||
return this.getFavorites(personId, {
|
||||
...opts,
|
||||
where: '(EXISTS(target/site))'
|
||||
}).pipe(
|
||||
map((response: FavoritePaging) => {
|
||||
return {
|
||||
list: {
|
||||
entries: response.list.entries.map(({ entry }: any) => {
|
||||
entry.target.site.createdAt = entry.createdAt;
|
||||
return {
|
||||
entry: entry.target.site
|
||||
};
|
||||
}),
|
||||
pagination: response.list.pagination
|
||||
}
|
||||
};
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
findSharedLinks(opts?: any): Observable<SharedLinkPaging> {
|
||||
return from(this.api.sharedLinksApi.findSharedLinks(opts));
|
||||
}
|
||||
|
||||
getSharedLinkContent(sharedId: string, attachment?: boolean): string {
|
||||
return this.api.contentApi.getSharedLinkContentUrl(sharedId, attachment);
|
||||
}
|
||||
|
||||
search(request: SearchRequest): Observable<ResultSetPaging> {
|
||||
return from(this.api.searchApi.search(request));
|
||||
}
|
||||
|
||||
getContentUrl(nodeId: string, attachment?: boolean): string {
|
||||
return this.api.contentApi.getContentUrl(nodeId, attachment);
|
||||
}
|
||||
|
||||
deleteSite(siteId?: string, opts?: { permanent?: boolean }): Observable<any> {
|
||||
return from(this.api.sitesApi.deleteSite(siteId, opts));
|
||||
}
|
||||
|
||||
leaveSite(siteId?: string): Observable<any> {
|
||||
return from(this.api.sitesApi.removeSiteMember(siteId, '-me-'));
|
||||
}
|
||||
|
||||
createSite(
|
||||
siteBody: SiteBody,
|
||||
opts?: {
|
||||
fields?: Array<string>;
|
||||
skipConfiguration?: boolean;
|
||||
skipAddToFavorites?: boolean;
|
||||
}
|
||||
): Observable<SiteEntry> {
|
||||
return from(this.api.sitesApi.createSite(siteBody, opts));
|
||||
}
|
||||
|
||||
getSite(
|
||||
siteId?: string,
|
||||
opts?: { relations?: Array<string>; fields?: Array<string> }
|
||||
): Observable<SiteEntry> {
|
||||
return from(this.api.sitesApi.getSite(siteId, opts));
|
||||
}
|
||||
|
||||
updateLibrary(siteId: string, siteBody: SiteBody): Observable<SiteEntry> {
|
||||
return from(this.api.sitesApi.updateSite(siteId, siteBody));
|
||||
}
|
||||
|
||||
addFavorite(nodes: Array<MinimalNodeEntity>): Observable<FavoriteEntry> {
|
||||
const payload: FavoriteBody[] = nodes.map(node => {
|
||||
const { isFolder, nodeId, id } = <any>node.entry;
|
||||
const siteId = node.entry['guid'];
|
||||
const type = siteId ? 'site' : isFolder ? 'folder' : 'file';
|
||||
const guid = siteId || nodeId || id;
|
||||
|
||||
return {
|
||||
target: {
|
||||
[type]: {
|
||||
guid
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return from(this.api.favoritesApi.addFavorite('-me-', <any>payload));
|
||||
}
|
||||
|
||||
removeFavorite(nodes: Array<MinimalNodeEntity>): Observable<any> {
|
||||
return from(
|
||||
Promise.all(
|
||||
nodes.map((node: any) => {
|
||||
const id = node.entry.nodeId || node.entry.id;
|
||||
return this.api.favoritesApi.removeFavoriteSite('-me-', id);
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
unlockNode(nodeId: string, opts?: any) {
|
||||
return this.api.nodesApi.unlockNode(nodeId, opts);
|
||||
}
|
||||
}
|
@@ -0,0 +1,226 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { NodePermissionService } from './node-permission.service';
|
||||
|
||||
describe('NodePermissionService', () => {
|
||||
let permission: NodePermissionService;
|
||||
|
||||
beforeEach(() => {
|
||||
permission = new NodePermissionService();
|
||||
});
|
||||
|
||||
it('should return false when source is null', () => {
|
||||
const source = null;
|
||||
|
||||
expect(permission.check(source, ['update'])).toBe(false);
|
||||
});
|
||||
|
||||
describe('Multiple source permission', () => {
|
||||
it('should return true when source has allowableOperations permission', () => {
|
||||
const source = [
|
||||
{ entry: { allowableOperations: ['update'] } },
|
||||
{ entry: { allowableOperations: ['update'] } },
|
||||
{ entry: { allowableOperations: ['update'] } }
|
||||
];
|
||||
|
||||
expect(permission.check(source, ['update'])).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when source has allowableOperationsOnTarget permission', () => {
|
||||
const source = [
|
||||
{ entry: { allowableOperationsOnTarget: ['update'] } },
|
||||
{ entry: { allowableOperationsOnTarget: ['update'] } },
|
||||
{ entry: { allowableOperationsOnTarget: ['update'] } }
|
||||
];
|
||||
|
||||
expect(
|
||||
permission.check(source, ['update'], {
|
||||
target: 'allowableOperationsOnTarget'
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when source does not have allowableOperations permission', () => {
|
||||
const source = [
|
||||
{ entry: { allowableOperations: ['update'] } },
|
||||
{ entry: { allowableOperations: ['update'] } },
|
||||
{ entry: { allowableOperations: ['delete'] } }
|
||||
];
|
||||
|
||||
expect(
|
||||
permission.check(source, ['update'], {
|
||||
target: 'allowableOperationsOnTarget'
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when source does not have allowableOperationsOnTarget permission', () => {
|
||||
const source = [
|
||||
{ entry: { allowableOperationsOnTarget: ['update'] } },
|
||||
{ entry: { allowableOperationsOnTarget: ['update'] } },
|
||||
{ entry: { allowableOperationsOnTarget: ['delete'] } }
|
||||
];
|
||||
|
||||
expect(
|
||||
permission.check(source, ['update'], {
|
||||
target: 'allowableOperationsOnTarget'
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true when source has `OR` allowableOperations permission', () => {
|
||||
const source = [
|
||||
{ entry: { allowableOperations: ['update', 'delete'] } },
|
||||
{ entry: { allowableOperations: ['update', 'create'] } },
|
||||
{ entry: { allowableOperations: ['update', 'updatePermissions'] } }
|
||||
];
|
||||
|
||||
expect(permission.check(source, ['update', 'create'])).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when source has `AND` allowableOperations permission', () => {
|
||||
const source = [
|
||||
{ entry: { allowableOperations: ['update', 'delete', 'other'] } },
|
||||
{ entry: { allowableOperations: ['update', 'create', 'other'] } },
|
||||
{
|
||||
entry: {
|
||||
allowableOperations: ['update', 'updatePermissions', 'other']
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
expect(
|
||||
permission.check(source, ['update', 'other'], { operation: 'AND' })
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when source has no `AND` allowableOperations permission', () => {
|
||||
const source = [
|
||||
{ entry: { allowableOperations: ['update', 'delete', 'other'] } },
|
||||
{ entry: { allowableOperations: ['update', 'create', 'other'] } },
|
||||
{
|
||||
entry: {
|
||||
allowableOperations: ['update', 'updatePermissions', 'other']
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
expect(
|
||||
permission.check(source, ['update', 'bogus'], { operation: 'AND' })
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when source has no allowableOperations', () => {
|
||||
const source = [
|
||||
{ entry: { allowableOperations: [] } },
|
||||
{ entry: { allowableOperations: [] } },
|
||||
{ entry: { allowableOperations: ['update'] } }
|
||||
];
|
||||
|
||||
expect(permission.check(source, ['update'])).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when source has no allowableOperations property', () => {
|
||||
const source = [
|
||||
{ entry: {} },
|
||||
{ entry: {} },
|
||||
{ entry: { allowableOperations: ['update'] } }
|
||||
];
|
||||
|
||||
expect(permission.check(source, ['update'])).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Single source permission', () => {
|
||||
it('should return true when source has allowableOperations permission', () => {
|
||||
const source = { entry: { allowableOperations: ['update'] } };
|
||||
|
||||
expect(permission.check(source, ['update'])).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when source has allowableOperationsOnTarget permission', () => {
|
||||
const source = { entry: { allowableOperationsOnTarget: ['update'] } };
|
||||
|
||||
expect(
|
||||
permission.check(source, ['update'], {
|
||||
target: 'allowableOperationsOnTarget'
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when source does not have allowableOperations permission', () => {
|
||||
const source = { entry: { allowableOperations: ['delete'] } };
|
||||
|
||||
expect(permission.check(source, ['update'])).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when source does not have allowableOperationsOnTarget permission', () => {
|
||||
const source = { entry: { allowableOperationsOnTarget: ['delete'] } };
|
||||
|
||||
expect(
|
||||
permission.check(source, ['update'], {
|
||||
target: 'allowableOperationsOnTarget'
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true when source has `OR` allowableOperations permission', () => {
|
||||
const source = { entry: { allowableOperations: ['update'] } };
|
||||
|
||||
expect(permission.check(source, ['update', 'create'])).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true when source has `AND` allowableOperations permission', () => {
|
||||
const source = { entry: { allowableOperations: ['update', 'other'] } };
|
||||
|
||||
expect(
|
||||
permission.check(source, ['update', 'other'], { operation: 'AND' })
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when source has no `AND` allowableOperations permission', () => {
|
||||
const source = {
|
||||
entry: { allowableOperations: ['update', 'updatePermissions', 'other'] }
|
||||
};
|
||||
|
||||
expect(
|
||||
permission.check(source, ['update', 'bogus'], { operation: 'AND' })
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when source has no allowableOperations', () => {
|
||||
const source = { entry: { allowableOperations: [] } };
|
||||
|
||||
expect(permission.check(source, ['update'])).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when source has no allowableOperations property', () => {
|
||||
const source = { entry: {} };
|
||||
|
||||
expect(permission.check(source, ['update'])).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
120
projects/aca-shared/src/lib/services/node-permission.service.ts
Normal file
120
projects/aca-shared/src/lib/services/node-permission.service.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { NodePermissions } from '@alfresco/adf-extensions';
|
||||
import { Node, SharedLink, SharedLinkEntry, NodeEntry } from '@alfresco/js-api';
|
||||
|
||||
export type PermissionSource = NodeEntry | SharedLinkEntry | Node;
|
||||
|
||||
export interface PermissionOptions {
|
||||
target?: string;
|
||||
operation?: string;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class NodePermissionService implements NodePermissions {
|
||||
static DEFAULT_OPERATION = 'OR';
|
||||
|
||||
private defaultOptions: PermissionOptions = {
|
||||
operation: NodePermissionService.DEFAULT_OPERATION,
|
||||
target: null
|
||||
};
|
||||
|
||||
check(
|
||||
source: PermissionSource | PermissionSource[],
|
||||
permissions: string[],
|
||||
options?: PermissionOptions
|
||||
): boolean {
|
||||
const opts = Object.assign({}, this.defaultOptions, options || {});
|
||||
|
||||
if (!source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Array.isArray(source)) {
|
||||
source = source.filter(item => item);
|
||||
|
||||
if (source.length > 0) {
|
||||
return source.every(node =>
|
||||
this.isOperationAllowed(node, permissions, opts)
|
||||
);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return this.isOperationAllowed(source, permissions, opts);
|
||||
}
|
||||
}
|
||||
|
||||
private isOperationAllowed(
|
||||
node: PermissionSource,
|
||||
permissions: string[],
|
||||
options: PermissionOptions
|
||||
): boolean {
|
||||
const allowableOperations = this.getAllowableOperations(
|
||||
node,
|
||||
options.target
|
||||
);
|
||||
|
||||
if (allowableOperations.length) {
|
||||
if (options.operation === NodePermissionService.DEFAULT_OPERATION) {
|
||||
return permissions.some(permission =>
|
||||
allowableOperations.includes(permission)
|
||||
);
|
||||
} else {
|
||||
return permissions.every(permission =>
|
||||
allowableOperations.includes(permission)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private getAllowableOperations(
|
||||
node: PermissionSource,
|
||||
property?: string
|
||||
): string[] {
|
||||
let entry: Node | SharedLink;
|
||||
|
||||
if ('entry' in node) {
|
||||
entry = node.entry;
|
||||
} else {
|
||||
entry = node;
|
||||
}
|
||||
|
||||
if (property) {
|
||||
return entry[property] || [];
|
||||
}
|
||||
|
||||
if ('allowableOperationsOnTarget' in entry) {
|
||||
return entry.allowableOperationsOnTarget || [];
|
||||
} else {
|
||||
return entry.allowableOperations || [];
|
||||
}
|
||||
}
|
||||
}
|
39
projects/aca-shared/src/lib/shared.module.ts
Normal file
39
projects/aca-shared/src/lib/shared.module.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||
import { ContentApiService } from './services/content-api.service';
|
||||
import { NodePermissionService } from './services/node-permission.service';
|
||||
import { AppService } from './services/app.service';
|
||||
|
||||
@NgModule({})
|
||||
export class SharedModule {
|
||||
static forRoot(): ModuleWithProviders {
|
||||
return {
|
||||
ngModule: SharedModule,
|
||||
providers: [ContentApiService, NodePermissionService, AppService]
|
||||
};
|
||||
}
|
||||
}
|
16
projects/aca-shared/src/lib/styles/mixins.scss
Normal file
16
projects/aca-shared/src/lib/styles/mixins.scss
Normal file
@@ -0,0 +1,16 @@
|
||||
@mixin flex-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
@mixin flex-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
42
projects/aca-shared/src/public-api.ts
Normal file
42
projects/aca-shared/src/public-api.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export * from './lib/components/page-layout/page-layout-content.component';
|
||||
export * from './lib/components/page-layout/page-layout-error.component';
|
||||
export * from './lib/components/page-layout/page-layout-header.component';
|
||||
export * from './lib/components/page-layout/page-layout.component';
|
||||
export * from './lib/components/page-layout/page-layout.module';
|
||||
|
||||
export * from './lib/routing/app.routes.strategy';
|
||||
export * from './lib/routing/shared.guard';
|
||||
|
||||
export * from './lib/services/app.service';
|
||||
export * from './lib/services/content-api.service';
|
||||
export * from './lib/services/node-permission.service';
|
||||
|
||||
export * from './lib/components/generic-error/generic-error.component';
|
||||
export * from './lib/components/generic-error/generic-error.module';
|
||||
|
||||
export * from './lib/shared.module';
|
3
projects/aca-shared/store/package.json
Normal file
3
projects/aca-shared/store/package.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"ngPackage": {}
|
||||
}
|
107
projects/aca-shared/store/src/actions/app.actions.ts
Normal file
107
projects/aca-shared/store/src/actions/app.actions.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Action } from '@ngrx/store';
|
||||
import { Node, Person, Group, RepositoryInfo } from '@alfresco/js-api';
|
||||
import { AppState } from '../states/app.state';
|
||||
|
||||
export enum AppActionTypes {
|
||||
SetInitialState = 'SET_INITIAL_STATE',
|
||||
SetLanguagePicker = 'SET_LANGUAGE_PICKER',
|
||||
SetCurrentFolder = 'SET_CURRENT_FOLDER',
|
||||
SetCurrentUrl = 'SET_CURRENT_URL',
|
||||
SetUserProfile = 'SET_USER_PROFILE',
|
||||
SetRepositoryInfo = 'SET_REPOSITORY_INFO',
|
||||
ToggleInfoDrawer = 'TOGGLE_INFO_DRAWER',
|
||||
ToggleDocumentDisplayMode = 'TOGGLE_DOCUMENT_DISPLAY_MODE',
|
||||
Logout = 'LOGOUT',
|
||||
ReloadDocumentList = 'RELOAD_DOCUMENT_LIST',
|
||||
SetInfoDrawerState = 'SET_INFO_DRAWER_STATE',
|
||||
CloseModalDialogs = 'CLOSE_MODAL_DIALOGS'
|
||||
}
|
||||
|
||||
export class SetInitialStateAction implements Action {
|
||||
readonly type = AppActionTypes.SetInitialState;
|
||||
|
||||
constructor(public payload: AppState) {}
|
||||
}
|
||||
|
||||
export class SetLanguagePickerAction implements Action {
|
||||
readonly type = AppActionTypes.SetLanguagePicker;
|
||||
|
||||
constructor(public payload: boolean) {}
|
||||
}
|
||||
|
||||
export class SetCurrentFolderAction implements Action {
|
||||
readonly type = AppActionTypes.SetCurrentFolder;
|
||||
|
||||
constructor(public payload: Node) {}
|
||||
}
|
||||
|
||||
export class SetCurrentUrlAction implements Action {
|
||||
readonly type = AppActionTypes.SetCurrentUrl;
|
||||
|
||||
constructor(public payload: string) {}
|
||||
}
|
||||
|
||||
export class SetUserProfileAction implements Action {
|
||||
readonly type = AppActionTypes.SetUserProfile;
|
||||
|
||||
constructor(public payload: { person: Person; groups: Group[] }) {}
|
||||
}
|
||||
|
||||
export class ToggleInfoDrawerAction implements Action {
|
||||
readonly type = AppActionTypes.ToggleInfoDrawer;
|
||||
}
|
||||
|
||||
export class ToggleDocumentDisplayMode implements Action {
|
||||
readonly type = AppActionTypes.ToggleDocumentDisplayMode;
|
||||
}
|
||||
|
||||
export class LogoutAction implements Action {
|
||||
readonly type = AppActionTypes.Logout;
|
||||
}
|
||||
|
||||
export class ReloadDocumentListAction implements Action {
|
||||
readonly type = AppActionTypes.ReloadDocumentList;
|
||||
|
||||
constructor(public payload?: any) {}
|
||||
}
|
||||
|
||||
export class SetInfoDrawerStateAction implements Action {
|
||||
readonly type = AppActionTypes.SetInfoDrawerState;
|
||||
|
||||
constructor(public payload: boolean) {}
|
||||
}
|
||||
|
||||
export class CloseModalDialogsAction implements Action {
|
||||
readonly type = AppActionTypes.CloseModalDialogs;
|
||||
}
|
||||
|
||||
export class SetRepositoryInfoAction implements Action {
|
||||
readonly type = AppActionTypes.SetRepositoryInfo;
|
||||
|
||||
constructor(public payload: RepositoryInfo) {}
|
||||
}
|
63
projects/aca-shared/store/src/actions/library.actions.ts
Normal file
63
projects/aca-shared/store/src/actions/library.actions.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Action } from '@ngrx/store';
|
||||
import { SiteBody } from '@alfresco/js-api';
|
||||
|
||||
export enum LibraryActionTypes {
|
||||
Delete = 'DELETE_LIBRARY',
|
||||
Create = 'CREATE_LIBRARY',
|
||||
Navigate = 'NAVIGATE_LIBRARY',
|
||||
Update = 'UPDATE_LIBRARY',
|
||||
Leave = 'LEAVE_LIBRARY'
|
||||
}
|
||||
|
||||
export class DeleteLibraryAction implements Action {
|
||||
readonly type = LibraryActionTypes.Delete;
|
||||
|
||||
constructor(public payload?: string) {}
|
||||
}
|
||||
|
||||
export class CreateLibraryAction implements Action {
|
||||
readonly type = LibraryActionTypes.Create;
|
||||
}
|
||||
|
||||
export class NavigateLibraryAction implements Action {
|
||||
readonly type = LibraryActionTypes.Navigate;
|
||||
|
||||
constructor(public payload?: string) {}
|
||||
}
|
||||
|
||||
export class UpdateLibraryAction implements Action {
|
||||
readonly type = LibraryActionTypes.Update;
|
||||
|
||||
constructor(public payload?: SiteBody) {}
|
||||
}
|
||||
|
||||
export class LeaveLibraryAction implements Action {
|
||||
readonly type = LibraryActionTypes.Leave;
|
||||
|
||||
constructor(public payload?: string) {}
|
||||
}
|
163
projects/aca-shared/store/src/actions/node.actions.ts
Normal file
163
projects/aca-shared/store/src/actions/node.actions.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Action } from '@ngrx/store';
|
||||
import { MinimalNodeEntity } from '@alfresco/js-api';
|
||||
|
||||
export enum NodeActionTypes {
|
||||
SetSelection = 'SET_SELECTED_NODES',
|
||||
Delete = 'DELETE_NODES',
|
||||
UndoDelete = 'UNDO_DELETE_NODES',
|
||||
RestoreDeleted = 'RESTORE_DELETED_NODES',
|
||||
PurgeDeleted = 'PURGE_DELETED_NODES',
|
||||
Download = 'DOWNLOAD_NODES',
|
||||
CreateFolder = 'CREATE_FOLDER',
|
||||
EditFolder = 'EDIT_FOLDER',
|
||||
Share = 'SHARE_NODE',
|
||||
Unshare = 'UNSHARE_NODES',
|
||||
Copy = 'COPY_NODES',
|
||||
Move = 'MOVE_NODES',
|
||||
ManagePermissions = 'MANAGE_PERMISSIONS',
|
||||
PrintFile = 'PRINT_FILE',
|
||||
ManageVersions = 'MANAGE_VERSIONS',
|
||||
EditOffline = 'EDIT_OFFLINE',
|
||||
UnlockForWriting = 'UNLOCK_WRITE_LOCK',
|
||||
AddFavorite = 'ADD_FAVORITE',
|
||||
RemoveFavorite = 'REMOVE_FAVORITE'
|
||||
}
|
||||
|
||||
export class SetSelectedNodesAction implements Action {
|
||||
readonly type = NodeActionTypes.SetSelection;
|
||||
|
||||
constructor(public payload: MinimalNodeEntity[] = []) {}
|
||||
}
|
||||
|
||||
export class DeleteNodesAction implements Action {
|
||||
readonly type = NodeActionTypes.Delete;
|
||||
|
||||
constructor(public payload: MinimalNodeEntity[] = []) {}
|
||||
}
|
||||
|
||||
export class UndoDeleteNodesAction implements Action {
|
||||
readonly type = NodeActionTypes.UndoDelete;
|
||||
|
||||
constructor(public payload: any[] = []) {}
|
||||
}
|
||||
|
||||
export class RestoreDeletedNodesAction implements Action {
|
||||
readonly type = NodeActionTypes.RestoreDeleted;
|
||||
|
||||
constructor(public payload: Array<MinimalNodeEntity>) {}
|
||||
}
|
||||
|
||||
export class PurgeDeletedNodesAction implements Action {
|
||||
readonly type = NodeActionTypes.PurgeDeleted;
|
||||
|
||||
constructor(public payload: Array<MinimalNodeEntity>) {}
|
||||
}
|
||||
|
||||
export class DownloadNodesAction implements Action {
|
||||
readonly type = NodeActionTypes.Download;
|
||||
|
||||
constructor(public payload: MinimalNodeEntity[] = []) {}
|
||||
}
|
||||
|
||||
export class CreateFolderAction implements Action {
|
||||
readonly type = NodeActionTypes.CreateFolder;
|
||||
|
||||
constructor(public payload: string) {}
|
||||
}
|
||||
|
||||
export class EditFolderAction implements Action {
|
||||
readonly type = NodeActionTypes.EditFolder;
|
||||
|
||||
constructor(public payload: MinimalNodeEntity) {}
|
||||
}
|
||||
|
||||
export class ShareNodeAction implements Action {
|
||||
readonly type = NodeActionTypes.Share;
|
||||
|
||||
constructor(public payload: MinimalNodeEntity) {}
|
||||
}
|
||||
|
||||
export class UnshareNodesAction implements Action {
|
||||
readonly type = NodeActionTypes.Unshare;
|
||||
|
||||
constructor(public payload: Array<MinimalNodeEntity>) {}
|
||||
}
|
||||
|
||||
export class CopyNodesAction implements Action {
|
||||
readonly type = NodeActionTypes.Copy;
|
||||
|
||||
constructor(public payload: Array<MinimalNodeEntity>) {}
|
||||
}
|
||||
|
||||
export class MoveNodesAction implements Action {
|
||||
readonly type = NodeActionTypes.Move;
|
||||
|
||||
constructor(public payload: Array<MinimalNodeEntity>) {}
|
||||
}
|
||||
|
||||
export class ManagePermissionsAction implements Action {
|
||||
readonly type = NodeActionTypes.ManagePermissions;
|
||||
|
||||
constructor(public payload: MinimalNodeEntity) {}
|
||||
}
|
||||
|
||||
export class PrintFileAction implements Action {
|
||||
readonly type = NodeActionTypes.PrintFile;
|
||||
|
||||
constructor(public payload: MinimalNodeEntity) {}
|
||||
}
|
||||
|
||||
export class ManageVersionsAction implements Action {
|
||||
readonly type = NodeActionTypes.ManageVersions;
|
||||
|
||||
constructor(public payload: MinimalNodeEntity) {}
|
||||
}
|
||||
|
||||
export class EditOfflineAction implements Action {
|
||||
readonly type = NodeActionTypes.EditOffline;
|
||||
|
||||
constructor(public payload: any) {}
|
||||
}
|
||||
|
||||
export class UnlockWriteAction implements Action {
|
||||
readonly type = NodeActionTypes.UnlockForWriting;
|
||||
|
||||
constructor(public payload: any) {}
|
||||
}
|
||||
|
||||
export class AddFavoriteAction implements Action {
|
||||
readonly type = NodeActionTypes.AddFavorite;
|
||||
|
||||
constructor(public payload: Array<MinimalNodeEntity>) {}
|
||||
}
|
||||
|
||||
export class RemoveFavoriteAction implements Action {
|
||||
readonly type = NodeActionTypes.RemoveFavorite;
|
||||
|
||||
constructor(public payload: Array<MinimalNodeEntity>) {}
|
||||
}
|
58
projects/aca-shared/store/src/actions/router.actions.ts
Normal file
58
projects/aca-shared/store/src/actions/router.actions.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Action } from '@ngrx/store';
|
||||
import { MinimalNodeEntity } from '@alfresco/js-api';
|
||||
|
||||
export enum RouterActionTypes {
|
||||
NavigateUrl = 'NAVIGATE_URL',
|
||||
NavigateRoute = 'NAVIGATE_ROUTE',
|
||||
NavigateFolder = 'NAVIGATE_FOLDER',
|
||||
NavigateParentFolder = 'NAVIGATE_PARENT_FOLDER'
|
||||
}
|
||||
|
||||
export class NavigateUrlAction implements Action {
|
||||
readonly type = RouterActionTypes.NavigateUrl;
|
||||
|
||||
constructor(public payload: string) {}
|
||||
}
|
||||
|
||||
export class NavigateRouteAction implements Action {
|
||||
readonly type = RouterActionTypes.NavigateRoute;
|
||||
|
||||
constructor(public payload: any[]) {}
|
||||
}
|
||||
|
||||
export class NavigateToFolder implements Action {
|
||||
readonly type = RouterActionTypes.NavigateFolder;
|
||||
|
||||
constructor(public payload: MinimalNodeEntity) {}
|
||||
}
|
||||
|
||||
export class NavigateToParentFolder implements Action {
|
||||
readonly type = RouterActionTypes.NavigateParentFolder;
|
||||
|
||||
constructor(public payload: MinimalNodeEntity) {}
|
||||
}
|
54
projects/aca-shared/store/src/actions/search.actions.ts
Normal file
54
projects/aca-shared/store/src/actions/search.actions.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Action } from '@ngrx/store';
|
||||
import { SearchOptionModel } from '../models/search-option.model';
|
||||
|
||||
export enum SearchActionTypes {
|
||||
SearchByTerm = 'SEARCH_BY_TERM',
|
||||
ToggleFilter = 'TOGGLE_SEARCH_FILTER',
|
||||
ShowFilter = 'SHOW_SEARCH_FILTER',
|
||||
HideFilter = 'HIDE_SEARCH_FILTER'
|
||||
}
|
||||
|
||||
export class SearchByTermAction implements Action {
|
||||
readonly type = SearchActionTypes.SearchByTerm;
|
||||
constructor(
|
||||
public payload: string,
|
||||
public searchOptions?: SearchOptionModel[]
|
||||
) {}
|
||||
}
|
||||
|
||||
export class ToggleSearchFilterAction implements Action {
|
||||
readonly type = SearchActionTypes.ToggleFilter;
|
||||
}
|
||||
|
||||
export class ShowSearchFilterAction implements Action {
|
||||
readonly type = SearchActionTypes.ShowFilter;
|
||||
}
|
||||
|
||||
export class HideSearchFilterAction implements Action {
|
||||
readonly type = SearchActionTypes.HideFilter;
|
||||
}
|
70
projects/aca-shared/store/src/actions/snackbar.actions.ts
Normal file
70
projects/aca-shared/store/src/actions/snackbar.actions.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Action } from '@ngrx/store';
|
||||
|
||||
export enum SnackbarActionTypes {
|
||||
Info = 'SNACKBAR_INFO',
|
||||
Warning = 'SNACKBAR_WARNING',
|
||||
Error = 'SNACKBAR_ERROR'
|
||||
}
|
||||
|
||||
export interface SnackbarAction extends Action {
|
||||
payload: string;
|
||||
params?: Object;
|
||||
userAction?: SnackbarUserAction;
|
||||
duration: number;
|
||||
}
|
||||
|
||||
export class SnackbarUserAction {
|
||||
constructor(public title: string, public action: Action) {}
|
||||
}
|
||||
|
||||
export class SnackbarInfoAction implements SnackbarAction {
|
||||
readonly type = SnackbarActionTypes.Info;
|
||||
|
||||
userAction?: SnackbarUserAction;
|
||||
duration = 4000;
|
||||
|
||||
constructor(public payload: string, public params?: Object) {}
|
||||
}
|
||||
|
||||
export class SnackbarWarningAction implements SnackbarAction {
|
||||
readonly type = SnackbarActionTypes.Warning;
|
||||
|
||||
userAction?: SnackbarUserAction;
|
||||
duration = 4000;
|
||||
|
||||
constructor(public payload: string, public params?: Object) {}
|
||||
}
|
||||
|
||||
export class SnackbarErrorAction implements SnackbarAction {
|
||||
readonly type = SnackbarActionTypes.Error;
|
||||
|
||||
userAction?: SnackbarUserAction;
|
||||
duration = 4000;
|
||||
|
||||
constructor(public payload: string, public params?: Object) {}
|
||||
}
|
48
projects/aca-shared/store/src/actions/upload.actions.ts
Normal file
48
projects/aca-shared/store/src/actions/upload.actions.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Action } from '@ngrx/store';
|
||||
|
||||
export enum UploadActionTypes {
|
||||
UploadFiles = 'UPLOAD_FILES',
|
||||
UploadFolder = 'UPLOAD_FOLDER',
|
||||
UploadFileVersion = 'UPLOAD_FILE_VERSION'
|
||||
}
|
||||
|
||||
export class UploadFilesAction implements Action {
|
||||
readonly type = UploadActionTypes.UploadFiles;
|
||||
|
||||
constructor(public payload: any) {}
|
||||
}
|
||||
|
||||
export class UploadFolderAction implements Action {
|
||||
readonly type = UploadActionTypes.UploadFolder;
|
||||
|
||||
constructor(public payload: any) {}
|
||||
}
|
||||
|
||||
export class UploadFileVersionAction implements Action {
|
||||
readonly type = UploadActionTypes.UploadFileVersion;
|
||||
}
|
51
projects/aca-shared/store/src/actions/viewer.actions.ts
Normal file
51
projects/aca-shared/store/src/actions/viewer.actions.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Action } from '@ngrx/store';
|
||||
import { MinimalNodeEntity } from '@alfresco/js-api';
|
||||
|
||||
export enum ViewerActionTypes {
|
||||
ViewFile = 'VIEW_FILE',
|
||||
ViewNode = 'VIEW_NODE',
|
||||
FullScreen = 'FULLSCREEN_VIEWER'
|
||||
}
|
||||
|
||||
export class ViewFileAction implements Action {
|
||||
readonly type = ViewerActionTypes.ViewFile;
|
||||
|
||||
constructor(public payload: MinimalNodeEntity, public parentId?: string) {}
|
||||
}
|
||||
|
||||
export class ViewNodeAction implements Action {
|
||||
readonly type = ViewerActionTypes.ViewNode;
|
||||
|
||||
constructor(public nodeId: string, public location?: string) {}
|
||||
}
|
||||
|
||||
export class FullscreenViewerAction implements Action {
|
||||
readonly type = ViewerActionTypes.FullScreen;
|
||||
|
||||
constructor(public payload: MinimalNodeEntity) {}
|
||||
}
|
44
projects/aca-shared/store/src/effects/dialog.effects.ts
Normal file
44
projects/aca-shared/store/src/effects/dialog.effects.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Effect, Actions, ofType } from '@ngrx/effects';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import {
|
||||
CloseModalDialogsAction,
|
||||
AppActionTypes
|
||||
} from '../actions/app.actions';
|
||||
|
||||
@Injectable()
|
||||
export class DialogEffects {
|
||||
constructor(private actions$: Actions, private matDialog: MatDialog) {}
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
closeAll$ = this.actions$.pipe(
|
||||
ofType<CloseModalDialogsAction>(AppActionTypes.CloseModalDialogs),
|
||||
map(() => this.matDialog.closeAll())
|
||||
);
|
||||
}
|
151
projects/aca-shared/store/src/effects/router.effects.ts
Normal file
151
projects/aca-shared/store/src/effects/router.effects.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Actions, Effect, ofType } from '@ngrx/effects';
|
||||
import { MinimalNodeEntryEntity, PathInfoEntity } from '@alfresco/js-api';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppStore } from '../states/app.state';
|
||||
import {
|
||||
NavigateUrlAction,
|
||||
RouterActionTypes,
|
||||
NavigateRouteAction,
|
||||
NavigateToFolder,
|
||||
NavigateToParentFolder
|
||||
} from '../actions/router.actions';
|
||||
import { SnackbarErrorAction } from '../actions/snackbar.actions';
|
||||
|
||||
@Injectable()
|
||||
export class RouterEffects {
|
||||
constructor(
|
||||
private store: Store<AppStore>,
|
||||
private actions$: Actions,
|
||||
private router: Router
|
||||
) {}
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
navigateUrl$ = this.actions$.pipe(
|
||||
ofType<NavigateUrlAction>(RouterActionTypes.NavigateUrl),
|
||||
map(action => {
|
||||
if (action.payload) {
|
||||
this.router.navigateByUrl(action.payload);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
navigateRoute$ = this.actions$.pipe(
|
||||
ofType<NavigateRouteAction>(RouterActionTypes.NavigateRoute),
|
||||
map(action => {
|
||||
this.router.navigate(action.payload);
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
navigateToFolder$ = this.actions$.pipe(
|
||||
ofType<NavigateToFolder>(RouterActionTypes.NavigateFolder),
|
||||
map(action => {
|
||||
if (action.payload && action.payload.entry) {
|
||||
this.navigateToFolder(action.payload.entry);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
navigateToParentFolder$ = this.actions$.pipe(
|
||||
ofType<NavigateToParentFolder>(RouterActionTypes.NavigateParentFolder),
|
||||
map(action => {
|
||||
if (action.payload && action.payload.entry) {
|
||||
this.navigateToParentFolder(action.payload.entry);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
private navigateToFolder(node: MinimalNodeEntryEntity) {
|
||||
let link: any[] = null;
|
||||
const { path, id } = node;
|
||||
|
||||
if (path && path.name && path.elements) {
|
||||
const isLibraryPath = this.isLibraryContent(<PathInfoEntity>path);
|
||||
|
||||
const parent = path.elements[path.elements.length - 1];
|
||||
const area = isLibraryPath ? '/libraries' : '/personal-files';
|
||||
|
||||
if (!isLibraryPath) {
|
||||
link = [area, id];
|
||||
} else {
|
||||
// parent.id could be 'Site' folder or child as 'documentLibrary'
|
||||
link = [area, parent.name === 'Sites' ? {} : id];
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.router.navigate(link);
|
||||
}, 10);
|
||||
} else {
|
||||
this.router.navigate(['/personal-files', node.id]);
|
||||
}
|
||||
}
|
||||
|
||||
private navigateToParentFolder(node: MinimalNodeEntryEntity) {
|
||||
let link: any[] = null;
|
||||
const { path } = node;
|
||||
|
||||
if (path && path.name && path.elements) {
|
||||
const isLibraryPath = this.isLibraryContent(<PathInfoEntity>path);
|
||||
|
||||
const parent = path.elements[path.elements.length - 1];
|
||||
const area = isLibraryPath ? '/libraries' : '/personal-files';
|
||||
|
||||
if (!isLibraryPath) {
|
||||
link = [area, parent.id];
|
||||
} else {
|
||||
// parent.id could be 'Site' folder or child as 'documentLibrary'
|
||||
link = [area, parent.name === 'Sites' ? {} : parent.id];
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.router.navigate(link);
|
||||
}, 10);
|
||||
} else {
|
||||
this.store.dispatch(
|
||||
new SnackbarErrorAction('APP.MESSAGES.ERRORS.CANNOT_NAVIGATE_LOCATION')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private isLibraryContent(path: PathInfoEntity): boolean {
|
||||
if (
|
||||
path &&
|
||||
path.elements.length >= 2 &&
|
||||
path.elements[1].name === 'Sites'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
97
projects/aca-shared/store/src/effects/snackbar.effects.ts
Normal file
97
projects/aca-shared/store/src/effects/snackbar.effects.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { TranslationService } from '@alfresco/adf-core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { Actions, Effect, ofType } from '@ngrx/effects';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { AppStore } from '../states/app.state';
|
||||
import {
|
||||
SnackbarInfoAction,
|
||||
SnackbarActionTypes,
|
||||
SnackbarWarningAction,
|
||||
SnackbarErrorAction,
|
||||
SnackbarAction
|
||||
} from '../actions/snackbar.actions';
|
||||
|
||||
@Injectable()
|
||||
export class SnackbarEffects {
|
||||
constructor(
|
||||
private store: Store<AppStore>,
|
||||
private actions$: Actions,
|
||||
private snackBar: MatSnackBar,
|
||||
private translationService: TranslationService
|
||||
) {}
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
infoEffect = this.actions$.pipe(
|
||||
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
|
||||
map((action: SnackbarInfoAction) => {
|
||||
this.showSnackBar(action, 'info-snackbar');
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
warningEffect = this.actions$.pipe(
|
||||
ofType<SnackbarWarningAction>(SnackbarActionTypes.Warning),
|
||||
map((action: SnackbarWarningAction) => {
|
||||
this.showSnackBar(action, 'warning-snackbar');
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
errorEffect = this.actions$.pipe(
|
||||
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
|
||||
map((action: SnackbarErrorAction) => {
|
||||
this.showSnackBar(action, 'error-snackbar');
|
||||
})
|
||||
);
|
||||
|
||||
private showSnackBar(action: SnackbarAction, panelClass: string) {
|
||||
const message = this.translate(action.payload, action.params);
|
||||
|
||||
let actionName: string = null;
|
||||
if (action.userAction) {
|
||||
actionName = this.translate(action.userAction.title);
|
||||
}
|
||||
|
||||
const snackBarRef = this.snackBar.open(message, actionName, {
|
||||
duration: action.duration || 4000,
|
||||
panelClass: panelClass
|
||||
});
|
||||
|
||||
if (action.userAction) {
|
||||
snackBarRef.onAction().subscribe(() => {
|
||||
this.store.dispatch(action.userAction.action);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private translate(message: string, params?: Object): string {
|
||||
return this.translationService.instant(message, params);
|
||||
}
|
||||
}
|
36
projects/aca-shared/store/src/models/delete-status.model.ts
Normal file
36
projects/aca-shared/store/src/models/delete-status.model.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export interface DeleteStatus {
|
||||
success: any[];
|
||||
fail: any[];
|
||||
someFailed: boolean;
|
||||
someSucceeded: boolean;
|
||||
oneFailed: boolean;
|
||||
oneSucceeded: boolean;
|
||||
allSucceeded: boolean;
|
||||
allFailed: boolean;
|
||||
reset(): void;
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export interface DeletedNodeInfo {
|
||||
id: string;
|
||||
name: string;
|
||||
status: number;
|
||||
}
|
32
projects/aca-shared/store/src/models/node-info.model.ts
Normal file
32
projects/aca-shared/store/src/models/node-info.model.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export interface NodeInfo {
|
||||
parentId?: string;
|
||||
id: string;
|
||||
name: string;
|
||||
isFile?: boolean;
|
||||
isFolder?: boolean;
|
||||
}
|
37
projects/aca-shared/store/src/models/search-option.model.ts
Normal file
37
projects/aca-shared/store/src/models/search-option.model.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export enum SearchOptionIds {
|
||||
Files = 'content',
|
||||
Folders = 'folder',
|
||||
Libraries = 'libraries'
|
||||
}
|
||||
|
||||
export interface SearchOptionModel {
|
||||
id: SearchOptionIds;
|
||||
key: string;
|
||||
value: boolean;
|
||||
shouldDisable(): boolean;
|
||||
}
|
48
projects/aca-shared/store/src/public_api.ts
Normal file
48
projects/aca-shared/store/src/public_api.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export * from './actions/app.actions';
|
||||
export * from './actions/library.actions';
|
||||
export * from './actions/node.actions';
|
||||
export * from './actions/router.actions';
|
||||
export * from './actions/search.actions';
|
||||
export * from './actions/snackbar.actions';
|
||||
export * from './actions/upload.actions';
|
||||
export * from './actions/viewer.actions';
|
||||
|
||||
export * from './effects/dialog.effects';
|
||||
export * from './effects/router.effects';
|
||||
export * from './effects/snackbar.effects';
|
||||
|
||||
export * from './models/delete-status.model';
|
||||
export * from './models/deleted-node-info.model';
|
||||
export * from './models/node-info.model';
|
||||
export * from './models/search-option.model';
|
||||
|
||||
export * from './selectors/app.selectors';
|
||||
|
||||
export * from './states/app.state';
|
||||
|
||||
export * from './store.module';
|
130
projects/aca-shared/store/src/selectors/app.selectors.ts
Normal file
130
projects/aca-shared/store/src/selectors/app.selectors.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { AppStore } from '../states/app.state';
|
||||
import { createSelector } from '@ngrx/store';
|
||||
|
||||
export const selectApp = (state: AppStore) => state.app;
|
||||
|
||||
export const getHeaderColor = createSelector(
|
||||
selectApp,
|
||||
state => state.headerColor
|
||||
);
|
||||
|
||||
export const getAppName = createSelector(
|
||||
selectApp,
|
||||
state => state.appName
|
||||
);
|
||||
|
||||
export const getLogoPath = createSelector(
|
||||
selectApp,
|
||||
state => state.logoPath
|
||||
);
|
||||
|
||||
export const getLanguagePickerState = createSelector(
|
||||
selectApp,
|
||||
state => state.languagePicker
|
||||
);
|
||||
|
||||
export const getUserProfile = createSelector(
|
||||
selectApp,
|
||||
state => state.user
|
||||
);
|
||||
|
||||
export const getCurrentFolder = createSelector(
|
||||
selectApp,
|
||||
state => state.navigation.currentFolder
|
||||
);
|
||||
|
||||
export const getAppSelection = createSelector(
|
||||
selectApp,
|
||||
state => state.selection
|
||||
);
|
||||
|
||||
export const getSharedUrl = createSelector(
|
||||
selectApp,
|
||||
state => state.sharedUrl
|
||||
);
|
||||
|
||||
export const getNavigationState = createSelector(
|
||||
selectApp,
|
||||
state => state.navigation
|
||||
);
|
||||
|
||||
export const isInfoDrawerOpened = createSelector(
|
||||
selectApp,
|
||||
state => state.infoDrawerOpened
|
||||
);
|
||||
|
||||
export const showFacetFilter = createSelector(
|
||||
selectApp,
|
||||
state => state.showFacetFilter
|
||||
);
|
||||
|
||||
export const getDocumentDisplayMode = createSelector(
|
||||
selectApp,
|
||||
state => state.documentDisplayMode
|
||||
);
|
||||
|
||||
export const getRepositoryStatus = createSelector(
|
||||
selectApp,
|
||||
state => state.repository
|
||||
);
|
||||
|
||||
export const isQuickShareEnabled = createSelector(
|
||||
getRepositoryStatus,
|
||||
info => info.status.isQuickShareEnabled
|
||||
);
|
||||
|
||||
export const isAdmin = createSelector(
|
||||
selectApp,
|
||||
state => state.user.isAdmin
|
||||
);
|
||||
|
||||
export const getSideNavState = createSelector(
|
||||
getAppSelection,
|
||||
getNavigationState,
|
||||
(selection, navigation) => {
|
||||
return {
|
||||
selection,
|
||||
navigation
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
export const getRuleContext = createSelector(
|
||||
getAppSelection,
|
||||
getNavigationState,
|
||||
getUserProfile,
|
||||
getRepositoryStatus,
|
||||
(selection, navigation, profile, repository) => {
|
||||
return {
|
||||
selection,
|
||||
navigation,
|
||||
profile,
|
||||
repository
|
||||
};
|
||||
}
|
||||
);
|
50
projects/aca-shared/store/src/states/app.state.ts
Normal file
50
projects/aca-shared/store/src/states/app.state.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
SelectionState,
|
||||
ProfileState,
|
||||
NavigationState
|
||||
} from '@alfresco/adf-extensions';
|
||||
import { RepositoryInfo } from '@alfresco/js-api';
|
||||
|
||||
export interface AppState {
|
||||
appName: string;
|
||||
headerColor: string;
|
||||
logoPath: string;
|
||||
languagePicker: boolean;
|
||||
sharedUrl: string;
|
||||
selection: SelectionState;
|
||||
user: ProfileState;
|
||||
navigation: NavigationState;
|
||||
infoDrawerOpened: boolean;
|
||||
showFacetFilter: boolean;
|
||||
documentDisplayMode: string;
|
||||
repository: RepositoryInfo;
|
||||
}
|
||||
|
||||
export interface AppStore {
|
||||
app: AppState;
|
||||
}
|
37
projects/aca-shared/store/src/store.module.ts
Normal file
37
projects/aca-shared/store/src/store.module.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2019 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import { SnackbarEffects } from './effects/snackbar.effects';
|
||||
import { DialogEffects } from './effects/dialog.effects';
|
||||
import { RouterEffects } from './effects/router.effects';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
EffectsModule.forFeature([SnackbarEffects, DialogEffects, RouterEffects])
|
||||
]
|
||||
})
|
||||
export class SharedStoreModule {}
|
22
projects/aca-shared/test.ts
Normal file
22
projects/aca-shared/test.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
|
||||
import 'core-js/es7/reflect';
|
||||
import 'zone.js/dist/zone';
|
||||
import 'zone.js/dist/zone-testing';
|
||||
import { getTestBed } from '@angular/core/testing';
|
||||
import {
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting
|
||||
} from '@angular/platform-browser-dynamic/testing';
|
||||
|
||||
declare const require: any;
|
||||
|
||||
// First, initialize the Angular testing environment.
|
||||
getTestBed().initTestEnvironment(
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting()
|
||||
);
|
||||
// Then we find all the tests.
|
||||
const context = require.context('./', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
context.keys().map(context);
|
29
projects/aca-shared/tsconfig.lib.json
Normal file
29
projects/aca-shared/tsconfig.lib.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/lib",
|
||||
"target": "es2015",
|
||||
"module": "es2015",
|
||||
"moduleResolution": "node",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"inlineSources": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"types": [],
|
||||
"lib": ["dom", "es2018"],
|
||||
"paths": {
|
||||
"@alfresco/aca-shared/*": ["./*"]
|
||||
}
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"annotateForClosureCompiler": true,
|
||||
"skipTemplateCodegen": true,
|
||||
"strictMetadataEmit": true,
|
||||
"fullTemplateTypeCheck": true,
|
||||
"strictInjectionParameters": true,
|
||||
"enableResourceInlining": true
|
||||
},
|
||||
"exclude": ["test.ts", "**/*.spec.ts"]
|
||||
}
|
9
projects/aca-shared/tsconfig.spec.json
Normal file
9
projects/aca-shared/tsconfig.spec.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../out-tsc/spec",
|
||||
"types": ["jasmine", "node"]
|
||||
},
|
||||
"files": ["test.ts"],
|
||||
"include": ["**/*.spec.ts", "**/*.d.ts"]
|
||||
}
|
7
projects/aca-shared/tslint.json
Normal file
7
projects/aca-shared/tslint.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "../../tslint.json",
|
||||
"rules": {
|
||||
"directive-selector": [true, "attribute", "aca", "camelCase"],
|
||||
"component-selector": [true, "element", "aca", "kebab-case"]
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user