mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-24 17:31:52 +00:00
Prettier upgrade and e2e type checks (#1522)
* upgrade prettier * noImplicitAny rule * fix type * update tsconfig * upgrade to 150 print width
This commit is contained in:
@@ -38,11 +38,7 @@ export interface AcaRuleContext extends RuleContext {
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canCopyNode(context: RuleContext): boolean {
|
||||
return [
|
||||
hasSelection(context),
|
||||
navigation.isNotTrashcan(context),
|
||||
navigation.isNotLibraries(context)
|
||||
].every(Boolean);
|
||||
return [hasSelection(context), navigation.isNotTrashcan(context), navigation.isNotLibraries(context)].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,14 +47,10 @@ export function canCopyNode(context: RuleContext): boolean {
|
||||
*/
|
||||
export function canAddFavorite(context: RuleContext): boolean {
|
||||
if (!context.selection.isEmpty) {
|
||||
if (
|
||||
navigation.isFavorites(context) ||
|
||||
navigation.isLibraries(context) ||
|
||||
navigation.isTrashcan(context)
|
||||
) {
|
||||
if (navigation.isFavorites(context) || navigation.isLibraries(context) || navigation.isTrashcan(context)) {
|
||||
return false;
|
||||
}
|
||||
return context.selection.nodes.some(node => !node.entry.isFavorite);
|
||||
return context.selection.nodes.some((node) => !node.entry.isFavorite);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -72,7 +64,7 @@ export function canRemoveFavorite(context: RuleContext): boolean {
|
||||
if (navigation.isFavorites(context)) {
|
||||
return true;
|
||||
}
|
||||
return context.selection.nodes.every(node => node.entry.isFavorite);
|
||||
return context.selection.nodes.every((node) => node.entry.isFavorite);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -82,12 +74,7 @@ export function canRemoveFavorite(context: RuleContext): boolean {
|
||||
* 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);
|
||||
return [context.selection.file, navigation.isNotTrashcan(context), repository.hasQuickShareEnabled(context), !isShared(context)].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,11 +82,7 @@ export function canShareFile(context: RuleContext): boolean {
|
||||
* JSON ref: `canToggleJoinLibrary`
|
||||
*/
|
||||
export function canToggleJoinLibrary(context: RuleContext): boolean {
|
||||
return [
|
||||
hasLibrarySelected(context),
|
||||
!isPrivateLibrary(context),
|
||||
hasNoLibraryRole(context)
|
||||
].every(Boolean);
|
||||
return [hasLibrarySelected(context), !isPrivateLibrary(context), hasNoLibraryRole(context)].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,10 +91,7 @@ export function canToggleJoinLibrary(context: RuleContext): boolean {
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canEditFolder(context: RuleContext): boolean {
|
||||
return [
|
||||
canUpdateSelectedFolder(context),
|
||||
navigation.isNotTrashcan(context)
|
||||
].every(Boolean);
|
||||
return [canUpdateSelectedFolder(context), navigation.isNotTrashcan(context)].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,15 +103,8 @@ export function isShared(context: RuleContext): boolean {
|
||||
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']
|
||||
);
|
||||
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;
|
||||
@@ -225,10 +198,7 @@ export function canUpload(context: RuleContext): boolean {
|
||||
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 node.entry && (node.entry.isFile || node.entry.isFolder || !!node.entry.nodeId);
|
||||
});
|
||||
}
|
||||
return false;
|
||||
@@ -258,13 +228,7 @@ export function hasLibrarySelected(context: RuleContext): boolean {
|
||||
*/
|
||||
export function isPrivateLibrary(context: RuleContext): boolean {
|
||||
const library = context.selection.library;
|
||||
return library
|
||||
? !!(
|
||||
library.entry &&
|
||||
library.entry.visibility &&
|
||||
library.entry.visibility === 'PRIVATE'
|
||||
)
|
||||
: false;
|
||||
return library ? !!(library.entry && library.entry.visibility && library.entry.visibility === 'PRIVATE') : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -321,8 +285,7 @@ export function canUpdateSelectedFolder(context: RuleContext): boolean {
|
||||
if (folder) {
|
||||
return (
|
||||
// workaround for Favorites Api
|
||||
navigation.isFavorites(context) ||
|
||||
context.permissions.check(folder.entry, ['update'])
|
||||
navigation.isFavorites(context) || context.permissions.check(folder.entry, ['update'])
|
||||
);
|
||||
}
|
||||
return false;
|
||||
@@ -334,16 +297,12 @@ export function canUpdateSelectedFolder(context: RuleContext): boolean {
|
||||
*/
|
||||
export function hasLockedFiles(context: RuleContext): boolean {
|
||||
if (context && context.selection && context.selection.nodes) {
|
||||
return context.selection.nodes.some(node => {
|
||||
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 node.entry.isLocked || (node.entry.properties && node.entry.properties['cm:lockType'] === 'READ_ONLY_LOCK');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -362,8 +321,7 @@ export function isWriteLocked(context: RuleContext): boolean {
|
||||
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')
|
||||
context.selection.file.entry.properties['cm:lockType'] === 'READ_ONLY_LOCK')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -376,8 +334,7 @@ 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
|
||||
context.selection.file.entry.properties['cm:lockOwner'].id === context.profile.id
|
||||
);
|
||||
}
|
||||
|
||||
@@ -395,11 +352,7 @@ export function canLockFile(context: RuleContext): boolean {
|
||||
*/
|
||||
export function canUnlockFile(context: RuleContext): boolean {
|
||||
const { file } = context.selection;
|
||||
return (
|
||||
isWriteLocked(context) &&
|
||||
(context.permissions.check(file.entry, ['delete']) ||
|
||||
isUserWriteLockOwner(context))
|
||||
);
|
||||
return isWriteLocked(context) && (context.permissions.check(file.entry, ['delete']) || isUserWriteLockOwner(context));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -414,9 +367,7 @@ export function canUploadVersion(context: RuleContext): boolean {
|
||||
return [
|
||||
hasFileSelected(context),
|
||||
navigation.isNotTrashcan(context),
|
||||
isWriteLocked(context)
|
||||
? isUserWriteLockOwner(context)
|
||||
: canUpdateSelectedNode(context)
|
||||
isWriteLocked(context) ? isUserWriteLockOwner(context) : canUpdateSelectedNode(context)
|
||||
].every(Boolean);
|
||||
}
|
||||
|
||||
@@ -435,9 +386,7 @@ export function isTrashcanItemSelected(context: RuleContext): boolean {
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canViewFile(context: RuleContext): boolean {
|
||||
return [hasFileSelected(context), navigation.isNotTrashcan(context)].every(
|
||||
Boolean
|
||||
);
|
||||
return [hasFileSelected(context), navigation.isNotTrashcan(context)].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -455,10 +404,7 @@ export function canLeaveLibrary(context: RuleContext): boolean {
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canToggleSharedLink(context: RuleContext): boolean {
|
||||
return [
|
||||
hasFileSelected(context),
|
||||
[canShareFile(context), isShared(context)].some(Boolean)
|
||||
].every(Boolean);
|
||||
return [hasFileSelected(context), [canShareFile(context), isShared(context)].some(Boolean)].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -467,11 +413,7 @@ export function canToggleSharedLink(context: RuleContext): boolean {
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canShowInfoDrawer(context: RuleContext): boolean {
|
||||
return [
|
||||
hasSelection(context),
|
||||
navigation.isNotLibraries(context),
|
||||
navigation.isNotTrashcan(context)
|
||||
].every(Boolean);
|
||||
return [hasSelection(context), navigation.isNotLibraries(context), navigation.isNotTrashcan(context)].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -480,11 +422,7 @@ export function canShowInfoDrawer(context: RuleContext): boolean {
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canManageFileVersions(context: RuleContext): boolean {
|
||||
return [
|
||||
hasFileSelected(context),
|
||||
navigation.isNotTrashcan(context),
|
||||
!hasLockedFiles(context)
|
||||
].every(Boolean);
|
||||
return [hasFileSelected(context), navigation.isNotTrashcan(context), !hasLockedFiles(context)].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -493,10 +431,7 @@ export function canManageFileVersions(context: RuleContext): boolean {
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canManagePermissions(context: RuleContext): boolean {
|
||||
return [
|
||||
canUpdateSelectedNode(context),
|
||||
navigation.isNotTrashcan(context)
|
||||
].every(Boolean);
|
||||
return [canUpdateSelectedNode(context), navigation.isNotTrashcan(context)].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -505,11 +440,7 @@ export function canManagePermissions(context: RuleContext): boolean {
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function canToggleEditOffline(context: RuleContext): boolean {
|
||||
return [
|
||||
hasFileSelected(context),
|
||||
navigation.isNotTrashcan(context),
|
||||
canLockFile(context) || canUnlockFile(context)
|
||||
].every(Boolean);
|
||||
return [hasFileSelected(context), navigation.isNotTrashcan(context), canLockFile(context) || canUnlockFile(context)].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -520,12 +451,9 @@ export function canToggleEditOffline(context: RuleContext): boolean {
|
||||
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)
|
||||
[navigation.isRecentFiles(context), navigation.isSharedFiles(context), navigation.isSearchResults(context), navigation.isFavorites(context)].some(
|
||||
Boolean
|
||||
)
|
||||
].every(Boolean);
|
||||
}
|
||||
|
||||
@@ -553,9 +481,5 @@ export function canShowLogout(context: AcaRuleContext): boolean {
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export function isLibraryManager(context: RuleContext): boolean {
|
||||
return (
|
||||
hasLibrarySelected(context) &&
|
||||
context.selection.library.entry &&
|
||||
context.selection.library.entry.role === 'SiteManager'
|
||||
);
|
||||
return hasLibrarySelected(context) && context.selection.library.entry && context.selection.library.entry.role === 'SiteManager';
|
||||
}
|
||||
|
@@ -31,12 +31,7 @@ import { RuleContext } from '@alfresco/adf-extensions';
|
||||
*/
|
||||
export function isPreview(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return (
|
||||
url &&
|
||||
(url.includes('/preview/') ||
|
||||
url.includes('viewer:view') ||
|
||||
url.includes('/view/'))
|
||||
);
|
||||
return url && (url.includes('/preview/') || url.includes('viewer:view') || url.includes('/view/'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,9 +109,7 @@ export function isLibraryFiles(context: RuleContext): boolean {
|
||||
*/
|
||||
export function isLibraries(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return (
|
||||
url && (url.endsWith('/libraries') || url.startsWith('/search-libraries'))
|
||||
);
|
||||
return url && (url.endsWith('/libraries') || url.startsWith('/search-libraries'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,10 +141,8 @@ export function isNotRecentFiles(context: RuleContext): boolean {
|
||||
* Checks if a **Search Results** route is activated.
|
||||
* JSON ref: `app.navigation.isSearchResults`
|
||||
*/
|
||||
export function isSearchResults(
|
||||
context: RuleContext /*,
|
||||
...args: RuleParameter[]*/
|
||||
): boolean {
|
||||
export function isSearchResults(context: RuleContext /*,
|
||||
...args: RuleParameter[]*/): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url && url.startsWith('/search');
|
||||
}
|
||||
@@ -170,11 +161,7 @@ export function isNotSearchResults(context: RuleContext): boolean {
|
||||
*/
|
||||
export function isSharedPreview(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return (
|
||||
url &&
|
||||
(url.startsWith('/shared/preview/') ||
|
||||
(url.startsWith('/shared') && url.includes('viewer:view')))
|
||||
);
|
||||
return url && (url.startsWith('/shared/preview/') || (url.startsWith('/shared') && url.includes('viewer:view')));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,11 +170,7 @@ export function isSharedPreview(context: RuleContext): boolean {
|
||||
*/
|
||||
export function isFavoritesPreview(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return (
|
||||
url &&
|
||||
(url.startsWith('/favorites/preview/') ||
|
||||
(url.startsWith('/favorites') && url.includes('viewer:view')))
|
||||
);
|
||||
return url && (url.startsWith('/favorites/preview/') || (url.startsWith('/favorites') && url.includes('viewer:view')));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -52,9 +52,7 @@ describe('ExtensionsDataLoaderGuard', () => {
|
||||
|
||||
it('should emit true and complete in case of only one callback is present, completed', () => {
|
||||
const subject = new Subject<true>();
|
||||
const guard = new ExtensionsDataLoaderGuard([
|
||||
() => subject.asObservable()
|
||||
]);
|
||||
const guard = new ExtensionsDataLoaderGuard([() => subject.asObservable()]);
|
||||
|
||||
guard.canActivate(route).subscribe(emittedSpy, erroredSpy, completedSpy);
|
||||
|
||||
@@ -70,9 +68,7 @@ describe('ExtensionsDataLoaderGuard', () => {
|
||||
});
|
||||
|
||||
it('should emit true and complete in case of only one callback is present, errored', () => {
|
||||
const guard = new ExtensionsDataLoaderGuard([
|
||||
() => throwError(new Error())
|
||||
]);
|
||||
const guard = new ExtensionsDataLoaderGuard([() => throwError(new Error())]);
|
||||
|
||||
guard.canActivate(route).subscribe(emittedSpy, erroredSpy, completedSpy);
|
||||
expect(emittedSpy).toHaveBeenCalledWith(true);
|
||||
@@ -83,10 +79,7 @@ describe('ExtensionsDataLoaderGuard', () => {
|
||||
it('should NOT complete in case of multiple callbacks are present and not all of them have been completed', () => {
|
||||
const subject1 = new Subject<true>();
|
||||
const subject2 = new Subject<true>();
|
||||
const guard = new ExtensionsDataLoaderGuard([
|
||||
() => subject1.asObservable(),
|
||||
() => subject2.asObservable()
|
||||
]);
|
||||
const guard = new ExtensionsDataLoaderGuard([() => subject1.asObservable(), () => subject2.asObservable()]);
|
||||
|
||||
guard.canActivate(route).subscribe(emittedSpy, erroredSpy, completedSpy);
|
||||
|
||||
@@ -101,10 +94,7 @@ describe('ExtensionsDataLoaderGuard', () => {
|
||||
it('should emit true and complete in case of multiple callbacks are present and all of them have been completed', () => {
|
||||
const subject1 = new Subject<true>();
|
||||
const subject2 = new Subject<true>();
|
||||
const guard = new ExtensionsDataLoaderGuard([
|
||||
() => subject1.asObservable(),
|
||||
() => subject2.asObservable()
|
||||
]);
|
||||
const guard = new ExtensionsDataLoaderGuard([() => subject1.asObservable(), () => subject2.asObservable()]);
|
||||
|
||||
guard.canActivate(route).subscribe(emittedSpy, erroredSpy, completedSpy);
|
||||
|
||||
@@ -119,10 +109,7 @@ describe('ExtensionsDataLoaderGuard', () => {
|
||||
|
||||
it('should emit true and complete even if one of the observables are errored, to not block the application loading', () => {
|
||||
const subject1 = new Subject<true>();
|
||||
const guard = new ExtensionsDataLoaderGuard([
|
||||
() => subject1.asObservable(),
|
||||
() => throwError(new Error())
|
||||
]);
|
||||
const guard = new ExtensionsDataLoaderGuard([() => subject1.asObservable(), () => throwError(new Error())]);
|
||||
|
||||
guard.canActivate(route).subscribe(emittedSpy, erroredSpy, completedSpy);
|
||||
|
||||
@@ -135,7 +122,7 @@ describe('ExtensionsDataLoaderGuard', () => {
|
||||
it('should call canActivate only once', () => {
|
||||
const subject1 = new Subject<true>();
|
||||
const extensionLoaders = {
|
||||
fct1: function() {
|
||||
fct1: function () {
|
||||
return subject1.asObservable();
|
||||
}
|
||||
};
|
||||
|
@@ -28,17 +28,13 @@ import { CanActivate, ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { Observable, forkJoin, of } from 'rxjs';
|
||||
import { map, catchError } from 'rxjs/operators';
|
||||
|
||||
export type ExtensionLoaderCallback = (
|
||||
route: ActivatedRouteSnapshot
|
||||
) => Observable<boolean>;
|
||||
export type ExtensionLoaderCallback = (route: ActivatedRouteSnapshot) => Observable<boolean>;
|
||||
|
||||
export function DefaultExtensionLoaderFactory() {
|
||||
return [];
|
||||
}
|
||||
|
||||
export const EXTENSION_DATA_LOADERS = new InjectionToken<
|
||||
ExtensionLoaderCallback[]
|
||||
>('EXTENSION_DATA_LOADERS', {
|
||||
export const EXTENSION_DATA_LOADERS = new InjectionToken<ExtensionLoaderCallback[]>('EXTENSION_DATA_LOADERS', {
|
||||
providedIn: 'root',
|
||||
factory: DefaultExtensionLoaderFactory
|
||||
});
|
||||
@@ -60,20 +56,16 @@ export class ExtensionsDataLoaderGuard implements CanActivate {
|
||||
return of(true);
|
||||
}
|
||||
|
||||
const dataLoaderCallbacks = this.extensionDataLoaders.map(callback =>
|
||||
callback(route)
|
||||
);
|
||||
const dataLoaderCallbacks = this.extensionDataLoaders.map((callback) => callback(route));
|
||||
|
||||
// Undocumented forkJoin behaviour/bug:
|
||||
// https://github.com/ReactiveX/rxjs/issues/3246
|
||||
// So all callbacks need to emit before completion, otherwise forkJoin will short circuit
|
||||
return forkJoin(...dataLoaderCallbacks).pipe(
|
||||
map(() => true),
|
||||
catchError(e => {
|
||||
catchError((e) => {
|
||||
// tslint:disable-next-line
|
||||
console.error(
|
||||
'Some of the extension data loader guards has been errored.'
|
||||
);
|
||||
console.error('Some of the extension data loader guards has been errored.');
|
||||
// tslint:disable-next-line
|
||||
console.error(e);
|
||||
return of(true);
|
||||
|
@@ -23,12 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
ViewEncapsulation,
|
||||
ChangeDetectionStrategy,
|
||||
Input
|
||||
} from '@angular/core';
|
||||
import { Component, ViewEncapsulation, ChangeDetectionStrategy, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-generic-error',
|
||||
|
@@ -26,10 +26,7 @@ import { ContentActionRef } from '@alfresco/adf-extensions';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { Store } from '@ngrx/store';
|
||||
import {
|
||||
SetInfoDrawerStateAction,
|
||||
ToggleInfoDrawerAction
|
||||
} from '@alfresco/aca-shared/store';
|
||||
import { SetInfoDrawerStateAction, ToggleInfoDrawerAction } from '@alfresco/aca-shared/store';
|
||||
import { of, Subject } from 'rxjs';
|
||||
import { InfoDrawerComponent } from './info-drawer.component';
|
||||
import { LibTestingModule } from '../../testing/lib-testing-module';
|
||||
@@ -64,11 +61,7 @@ describe('InfoDrawerComponent', () => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [LibTestingModule, SharedToolbarModule],
|
||||
declarations: [InfoDrawerComponent],
|
||||
providers: [
|
||||
ContentApiService,
|
||||
{ provide: AppExtensionService, useValue: extensionServiceMock },
|
||||
{ provide: Store, useValue: storeMock }
|
||||
],
|
||||
providers: [ContentApiService, { provide: AppExtensionService, useValue: extensionServiceMock }, { provide: Store, useValue: storeMock }],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
});
|
||||
|
||||
@@ -95,9 +88,7 @@ describe('InfoDrawerComponent', () => {
|
||||
fixture.detectChanges();
|
||||
component.ngOnDestroy();
|
||||
|
||||
expect(storeMock.dispatch).toHaveBeenCalledWith(
|
||||
new SetInfoDrawerStateAction(false)
|
||||
);
|
||||
expect(storeMock.dispatch).toHaveBeenCalledWith(new SetInfoDrawerStateAction(false));
|
||||
});
|
||||
|
||||
it('should set displayNode when node is library', async(() => {
|
||||
@@ -174,9 +165,7 @@ describe('InfoDrawerComponent', () => {
|
||||
|
||||
fixture.debugElement.nativeElement.dispatchEvent(event);
|
||||
|
||||
expect(storeMock.dispatch).toHaveBeenCalledWith(
|
||||
new ToggleInfoDrawerAction()
|
||||
);
|
||||
expect(storeMock.dispatch).toHaveBeenCalledWith(new ToggleInfoDrawerAction());
|
||||
});
|
||||
|
||||
it('should show the icons from extension', () => {
|
||||
|
@@ -23,26 +23,11 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
HostListener,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit
|
||||
} from '@angular/core';
|
||||
import {
|
||||
MinimalNodeEntity,
|
||||
MinimalNodeEntryEntity,
|
||||
SiteEntry
|
||||
} from '@alfresco/js-api';
|
||||
import { Component, HostListener, Input, OnChanges, OnDestroy, OnInit } from '@angular/core';
|
||||
import { MinimalNodeEntity, MinimalNodeEntryEntity, SiteEntry } from '@alfresco/js-api';
|
||||
import { ContentActionRef, SidebarTabRef } from '@alfresco/adf-extensions';
|
||||
import { Store } from '@ngrx/store';
|
||||
import {
|
||||
getAppSelection,
|
||||
SetInfoDrawerStateAction,
|
||||
ToggleInfoDrawerAction
|
||||
} from '@alfresco/aca-shared/store';
|
||||
import { getAppSelection, SetInfoDrawerStateAction, ToggleInfoDrawerAction } from '@alfresco/aca-shared/store';
|
||||
import { AppExtensionService } from '../../services/app.extension.service';
|
||||
import { ContentApiService } from '../../services/content-api.service';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
@@ -69,11 +54,7 @@ export class InfoDrawerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
this.close();
|
||||
}
|
||||
|
||||
constructor(
|
||||
private store: Store<any>,
|
||||
private contentApi: ContentApiService,
|
||||
private extensions: AppExtensionService
|
||||
) {}
|
||||
constructor(private store: Store<any>, private contentApi: ContentApiService, private extensions: AppExtensionService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.tabs = this.extensions.getSidebarTabs();
|
||||
@@ -117,7 +98,7 @@ export class InfoDrawerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
this.isLoading = true;
|
||||
|
||||
this.contentApi.getNodeInfo(nodeId).subscribe(
|
||||
entity => {
|
||||
(entity) => {
|
||||
this.setDisplayNode(entity);
|
||||
this.isLoading = false;
|
||||
},
|
||||
|
@@ -32,14 +32,7 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { SharedToolbarModule } from '../tool-bar/shared-toolbar.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
InfoDrawerModule,
|
||||
MatProgressBarModule,
|
||||
ExtensionsModule,
|
||||
ToolbarModule,
|
||||
SharedToolbarModule
|
||||
],
|
||||
imports: [CommonModule, InfoDrawerModule, MatProgressBarModule, ExtensionsModule, ToolbarModule, SharedToolbarModule],
|
||||
declarations: [InfoDrawerComponent],
|
||||
exports: [InfoDrawerComponent]
|
||||
})
|
||||
|
@@ -23,13 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
Input,
|
||||
OnInit,
|
||||
ChangeDetectionStrategy,
|
||||
ViewEncapsulation
|
||||
} from '@angular/core';
|
||||
import { Component, Input, OnInit, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core';
|
||||
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
|
||||
@@ -60,10 +54,7 @@ export class LockedByComponent implements OnInit {
|
||||
|
||||
writeLockedBy() {
|
||||
return (
|
||||
this.node &&
|
||||
this.node.entry.properties &&
|
||||
this.node.entry.properties['cm:lockOwner'] &&
|
||||
this.node.entry.properties['cm:lockOwner'].displayName
|
||||
this.node && this.node.entry.properties && this.node.entry.properties['cm:lockOwner'] && this.node.entry.properties['cm:lockOwner'].displayName
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -23,19 +23,11 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
ViewEncapsulation,
|
||||
ChangeDetectionStrategy,
|
||||
Input,
|
||||
HostBinding
|
||||
} from '@angular/core';
|
||||
import { Component, ViewEncapsulation, ChangeDetectionStrategy, Input, HostBinding } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-page-layout-content',
|
||||
template: `
|
||||
<ng-content></ng-content>
|
||||
`,
|
||||
template: `<ng-content></ng-content>`,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { class: 'aca-page-layout-content' }
|
||||
|
@@ -23,17 +23,11 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
ViewEncapsulation,
|
||||
ChangeDetectionStrategy
|
||||
} from '@angular/core';
|
||||
import { Component, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-page-layout-error',
|
||||
template: `
|
||||
<ng-content></ng-content>
|
||||
`,
|
||||
template: `<ng-content></ng-content>`,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { class: 'aca-page-layout-error' }
|
||||
|
@@ -23,11 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
ViewEncapsulation,
|
||||
ChangeDetectionStrategy
|
||||
} from '@angular/core';
|
||||
import { Component, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-page-layout-header',
|
||||
|
@@ -23,12 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
ViewEncapsulation,
|
||||
ChangeDetectionStrategy,
|
||||
Input
|
||||
} from '@angular/core';
|
||||
import { Component, ViewEncapsulation, ChangeDetectionStrategy, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-page-layout',
|
||||
|
@@ -32,17 +32,7 @@ import { CommonModule } from '@angular/common';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
declarations: [
|
||||
PageLayoutContentComponent,
|
||||
PageLayoutErrorComponent,
|
||||
PageLayoutHeaderComponent,
|
||||
PageLayoutComponent
|
||||
],
|
||||
exports: [
|
||||
PageLayoutContentComponent,
|
||||
PageLayoutErrorComponent,
|
||||
PageLayoutHeaderComponent,
|
||||
PageLayoutComponent
|
||||
]
|
||||
declarations: [PageLayoutContentComponent, PageLayoutErrorComponent, PageLayoutHeaderComponent, PageLayoutComponent],
|
||||
exports: [PageLayoutContentComponent, PageLayoutErrorComponent, PageLayoutHeaderComponent, PageLayoutComponent]
|
||||
})
|
||||
export class PageLayoutModule {}
|
||||
|
@@ -34,17 +34,7 @@ import { ExtensionsModule } from '@alfresco/adf-extensions';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, CoreModule, ExtensionsModule],
|
||||
declarations: [
|
||||
ToolbarButtonComponent,
|
||||
ToolbarActionComponent,
|
||||
ToolbarMenuItemComponent,
|
||||
ToolbarMenuComponent
|
||||
],
|
||||
exports: [
|
||||
ToolbarButtonComponent,
|
||||
ToolbarActionComponent,
|
||||
ToolbarMenuItemComponent,
|
||||
ToolbarMenuComponent
|
||||
]
|
||||
declarations: [ToolbarButtonComponent, ToolbarActionComponent, ToolbarMenuItemComponent, ToolbarMenuComponent],
|
||||
exports: [ToolbarButtonComponent, ToolbarActionComponent, ToolbarMenuItemComponent, ToolbarMenuComponent]
|
||||
})
|
||||
export class SharedToolbarModule {}
|
||||
|
@@ -23,14 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Component,
|
||||
ViewEncapsulation,
|
||||
ChangeDetectionStrategy,
|
||||
Input,
|
||||
DoCheck,
|
||||
ChangeDetectorRef
|
||||
} from '@angular/core';
|
||||
import { Component, ViewEncapsulation, ChangeDetectionStrategy, Input, DoCheck, ChangeDetectorRef } from '@angular/core';
|
||||
import { ContentActionRef } from '@alfresco/adf-extensions';
|
||||
|
||||
@Component({
|
||||
|
@@ -40,11 +40,7 @@ export class ToolbarMenuComponent {
|
||||
color = '';
|
||||
|
||||
get hasChildren(): boolean {
|
||||
return (
|
||||
this.actionRef &&
|
||||
this.actionRef.children &&
|
||||
this.actionRef.children.length > 0
|
||||
);
|
||||
return this.actionRef && this.actionRef.children && this.actionRef.children.length > 0;
|
||||
}
|
||||
|
||||
trackById(_: number, obj: { id: string }) {
|
||||
|
@@ -48,8 +48,7 @@ describe('ContextActionsDirective', () => {
|
||||
|
||||
it('should call service to render context menu', fakeAsync(() => {
|
||||
const el = document.createElement('div');
|
||||
el.className =
|
||||
'adf-datatable-cell adf-datatable-cell--text adf-datatable-row';
|
||||
el.className = 'adf-datatable-cell adf-datatable-cell--text adf-datatable-row';
|
||||
|
||||
const fragment = document.createDocumentFragment();
|
||||
fragment.appendChild(el);
|
||||
@@ -62,8 +61,6 @@ describe('ContextActionsDirective', () => {
|
||||
|
||||
tick(500);
|
||||
|
||||
expect(storeMock.dispatch).toHaveBeenCalledWith(
|
||||
new ContextMenu(mouseEventMock)
|
||||
);
|
||||
expect(storeMock.dispatch).toHaveBeenCalledWith(new ContextMenu(mouseEventMock));
|
||||
}));
|
||||
});
|
||||
|
@@ -23,13 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Directive,
|
||||
HostListener,
|
||||
Input,
|
||||
OnInit,
|
||||
OnDestroy
|
||||
} from '@angular/core';
|
||||
import { Directive, HostListener, Input, OnInit, OnDestroy } from '@angular/core';
|
||||
import { debounceTime, takeUntil } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
import { Store } from '@ngrx/store';
|
||||
@@ -64,11 +58,9 @@ export class ContextActionsDirective implements OnInit, OnDestroy {
|
||||
constructor(private store: Store<AppStore>) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.execute$
|
||||
.pipe(debounceTime(300), takeUntil(this.onDestroy$))
|
||||
.subscribe((event: MouseEvent) => {
|
||||
this.store.dispatch(new ContextMenu(event));
|
||||
});
|
||||
this.execute$.pipe(debounceTime(300), takeUntil(this.onDestroy$)).subscribe((event: MouseEvent) => {
|
||||
this.store.dispatch(new ContextMenu(event));
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
@@ -94,9 +86,7 @@ export class ContextActionsDirective implements OnInit, OnDestroy {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.findAncestor(target, 'adf-datatable-row').classList.contains(
|
||||
'adf-is-selected'
|
||||
);
|
||||
return this.findAncestor(target, 'adf-datatable-row').classList.contains('adf-is-selected');
|
||||
}
|
||||
|
||||
private findAncestor(el: Element, className: string): Element {
|
||||
|
@@ -47,15 +47,8 @@ describe('PaginationDirective', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
LibTestingModule,
|
||||
SharedDirectivesModule,
|
||||
CoreTestingModule
|
||||
],
|
||||
providers: [
|
||||
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }
|
||||
]
|
||||
imports: [TranslateModule.forRoot(), LibTestingModule, SharedDirectivesModule, CoreTestingModule],
|
||||
providers: [{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }]
|
||||
});
|
||||
|
||||
preferences = TestBed.inject(UserPreferencesService);
|
||||
|
@@ -24,12 +24,7 @@
|
||||
*/
|
||||
|
||||
import { Directive, OnInit, OnDestroy } from '@angular/core';
|
||||
import {
|
||||
PaginationComponent,
|
||||
UserPreferencesService,
|
||||
PaginationModel,
|
||||
AppConfigService
|
||||
} from '@alfresco/adf-core';
|
||||
import { PaginationComponent, UserPreferencesService, PaginationModel, AppConfigService } from '@alfresco/adf-core';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
@Directive({
|
||||
@@ -38,16 +33,10 @@ import { Subscription } from 'rxjs';
|
||||
export class PaginationDirective implements OnInit, OnDestroy {
|
||||
private subscriptions: Subscription[] = [];
|
||||
|
||||
constructor(
|
||||
private pagination: PaginationComponent,
|
||||
private preferences: UserPreferencesService,
|
||||
private config: AppConfigService
|
||||
) {}
|
||||
constructor(private pagination: PaginationComponent, private preferences: UserPreferencesService, private config: AppConfigService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.pagination.supportedPageSizes = this.config.get(
|
||||
'pagination.supportedPageSizes'
|
||||
);
|
||||
this.pagination.supportedPageSizes = this.config.get('pagination.supportedPageSizes');
|
||||
|
||||
this.subscriptions.push(
|
||||
this.pagination.changePageSize.subscribe((event: PaginationModel) => {
|
||||
@@ -57,7 +46,7 @@ export class PaginationDirective implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.forEach(subscription => subscription.unsubscribe());
|
||||
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
|
||||
this.subscriptions = [];
|
||||
}
|
||||
}
|
||||
|
@@ -23,11 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
RouteReuseStrategy,
|
||||
DetachedRouteHandle,
|
||||
ActivatedRouteSnapshot
|
||||
} from '@angular/router';
|
||||
import { RouteReuseStrategy, DetachedRouteHandle, ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { ComponentRef, Injectable } from '@angular/core';
|
||||
|
||||
interface RouteData {
|
||||
@@ -44,7 +40,7 @@ export class AppRouteReuseStrategy implements RouteReuseStrategy {
|
||||
private routeCache = new Map<string, RouteInfo>();
|
||||
|
||||
resetCache() {
|
||||
this.routeCache.forEach(value => {
|
||||
this.routeCache.forEach((value) => {
|
||||
this.deactivateComponent(value.handle);
|
||||
});
|
||||
this.routeCache.clear();
|
||||
@@ -60,10 +56,7 @@ export class AppRouteReuseStrategy implements RouteReuseStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
shouldReuseRoute(
|
||||
future: ActivatedRouteSnapshot,
|
||||
curr: ActivatedRouteSnapshot
|
||||
): boolean {
|
||||
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
|
||||
const ret = future.routeConfig === curr.routeConfig;
|
||||
if (ret) {
|
||||
this.addRedirectsRecursively(future); // update redirects
|
||||
@@ -91,9 +84,7 @@ export class AppRouteReuseStrategy implements RouteReuseStrategy {
|
||||
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;
|
||||
return data && data.reuse && this.routeCache.has(url) ? this.routeCache.get(url).handle : null;
|
||||
}
|
||||
|
||||
private addRedirectsRecursively(route: ActivatedRouteSnapshot): void {
|
||||
@@ -101,40 +92,30 @@ export class AppRouteReuseStrategy implements RouteReuseStrategy {
|
||||
if (config) {
|
||||
if (!config.loadChildren) {
|
||||
const routeFirstChild = route.firstChild;
|
||||
const routeFirstChildUrl = routeFirstChild
|
||||
? this.getRouteUrlPaths(routeFirstChild).join('/')
|
||||
: '';
|
||||
const routeFirstChildUrl = routeFirstChild ? this.getRouteUrlPaths(routeFirstChild).join('/') : '';
|
||||
const childConfigs = config.children;
|
||||
if (childConfigs) {
|
||||
const childConfigWithRedirect = childConfigs.find(
|
||||
c => c.path === '' && !!c.redirectTo
|
||||
);
|
||||
const childConfigWithRedirect = childConfigs.find((c) => c.path === '' && !!c.redirectTo);
|
||||
if (childConfigWithRedirect) {
|
||||
childConfigWithRedirect.redirectTo = routeFirstChildUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
route.children.forEach(childRoute =>
|
||||
this.addRedirectsRecursively(childRoute)
|
||||
);
|
||||
route.children.forEach((childRoute) => this.addRedirectsRecursively(childRoute));
|
||||
}
|
||||
}
|
||||
|
||||
private getFullRouteUrl(route: ActivatedRouteSnapshot): string {
|
||||
return this.getFullRouteUrlPaths(route)
|
||||
.filter(Boolean)
|
||||
.join('/');
|
||||
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;
|
||||
return route.parent ? [...this.getFullRouteUrlPaths(route.parent), ...paths] : paths;
|
||||
}
|
||||
|
||||
private getRouteUrlPaths(route: ActivatedRouteSnapshot): string[] {
|
||||
return route.url.map(urlSegment => urlSegment.path);
|
||||
return route.url.map((urlSegment) => urlSegment.path);
|
||||
}
|
||||
|
||||
private getRouteData(route: ActivatedRouteSnapshot): RouteData {
|
||||
|
@@ -39,15 +39,11 @@ export class AppSharedRuleGuard implements CanActivate {
|
||||
this.isQuickShareEnabled$ = store.select(isQuickShareEnabled);
|
||||
}
|
||||
|
||||
canActivate(
|
||||
_: ActivatedRouteSnapshot
|
||||
): Observable<boolean> | Promise<boolean> | boolean {
|
||||
canActivate(_: ActivatedRouteSnapshot): Observable<boolean> | Promise<boolean> | boolean {
|
||||
return this.isQuickShareEnabled$;
|
||||
}
|
||||
|
||||
canActivateChild(
|
||||
route: ActivatedRouteSnapshot
|
||||
): Observable<boolean> | Promise<boolean> | boolean {
|
||||
canActivateChild(route: ActivatedRouteSnapshot): Observable<boolean> | Promise<boolean> | boolean {
|
||||
return this.canActivate(route);
|
||||
}
|
||||
}
|
||||
|
@@ -567,9 +567,7 @@ describe('AppExtensionService', () => {
|
||||
});
|
||||
|
||||
it('should use implicit order', () => {
|
||||
const sorted = [{ id: '3' }, { id: '2' }, { id: '1', order: 1 }].sort(
|
||||
sortByOrder
|
||||
);
|
||||
const sorted = [{ id: '3' }, { id: '2' }, { id: '1', order: 1 }].sort(sortByOrder);
|
||||
|
||||
expect(sorted[0].id).toBe('1');
|
||||
expect(sorted[1].id).toBe('3');
|
||||
@@ -579,11 +577,7 @@ describe('AppExtensionService', () => {
|
||||
|
||||
describe('filtering', () => {
|
||||
it('should filter out disabled items', () => {
|
||||
const items = [
|
||||
{ id: 1, disabled: true },
|
||||
{ id: 2 },
|
||||
{ id: 3, disabled: true }
|
||||
].filter(filterEnabled);
|
||||
const items = [{ id: 1, disabled: true }, { id: 2 }, { id: 3, disabled: true }].filter(filterEnabled);
|
||||
|
||||
expect(items.length).toBe(1);
|
||||
expect(items[0].id).toBe(2);
|
||||
@@ -594,11 +588,7 @@ describe('AppExtensionService', () => {
|
||||
{ id: '1', disabled: true },
|
||||
{
|
||||
id: '2',
|
||||
someItems: [
|
||||
{ id: '21', disabled: true },
|
||||
{ id: '22', disabled: false },
|
||||
{ id: '23' }
|
||||
],
|
||||
someItems: [{ id: '21', disabled: true }, { id: '22', disabled: false }, { id: '23' }],
|
||||
someObjectProp: {
|
||||
innerItems: [{ id: '24' }, { id: '25', disabled: true }]
|
||||
}
|
||||
@@ -700,10 +690,7 @@ describe('AppExtensionService', () => {
|
||||
{ items: [{ children: [{ route: 'route3', disabled: true }] }] }
|
||||
]);
|
||||
|
||||
expect(navigation).toEqual([
|
||||
{ items: [{ route: 'route1', url: '/route1' }] },
|
||||
{ items: [{ children: [] }] }
|
||||
] as NavBarGroupRef[]);
|
||||
expect(navigation).toEqual([{ items: [{ route: 'route1', url: '/route1' }] }, { items: [{ children: [] }] }] as NavBarGroupRef[]);
|
||||
});
|
||||
|
||||
it('should filter out items based on rule', () => {
|
||||
|
@@ -27,11 +27,7 @@ import { Injectable, Type } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { MatIconRegistry } from '@angular/material/icon';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import {
|
||||
AppStore,
|
||||
getRuleContext,
|
||||
getLanguagePickerState
|
||||
} from '@alfresco/aca-shared/store';
|
||||
import { AppStore, getRuleContext, getLanguagePickerState } from '@alfresco/aca-shared/store';
|
||||
import {
|
||||
SelectionState,
|
||||
NavigationState,
|
||||
@@ -53,11 +49,7 @@ import {
|
||||
DocumentListPresetRef,
|
||||
IconRef
|
||||
} from '@alfresco/adf-extensions';
|
||||
import {
|
||||
AppConfigService,
|
||||
AuthenticationService,
|
||||
LogService
|
||||
} from '@alfresco/adf-core';
|
||||
import { AppConfigService, AuthenticationService, LogService } from '@alfresco/adf-core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { RepositoryInfo, NodeEntry } from '@alfresco/js-api';
|
||||
import { ViewerRules } from '../models/viewer.rules';
|
||||
@@ -132,14 +124,14 @@ export class AppExtensionService implements RuleContext {
|
||||
) {
|
||||
this.references$ = this._references.asObservable();
|
||||
|
||||
this.store.select(getRuleContext).subscribe(result => {
|
||||
this.store.select(getRuleContext).subscribe((result) => {
|
||||
this.selection = result.selection;
|
||||
this.navigation = result.navigation;
|
||||
this.profile = result.profile;
|
||||
this.repository = result.repository;
|
||||
});
|
||||
|
||||
this.store.select(getLanguagePickerState).subscribe(result => {
|
||||
this.store.select(getLanguagePickerState).subscribe((result) => {
|
||||
this.languagePicker = result;
|
||||
});
|
||||
}
|
||||
@@ -155,62 +147,26 @@ export class AppExtensionService implements RuleContext {
|
||||
return;
|
||||
}
|
||||
|
||||
this.settingGroups = this.loader.getElements<SettingsGroupRef>(
|
||||
config,
|
||||
'settings'
|
||||
);
|
||||
this.settingGroups = this.loader.getElements<SettingsGroupRef>(config, 'settings');
|
||||
|
||||
this.headerActions = this.loader.getContentActions(
|
||||
config,
|
||||
'features.header'
|
||||
);
|
||||
this.sidebarActions = this.loader.getContentActions(
|
||||
config,
|
||||
'features.sidebar.toolbar'
|
||||
);
|
||||
this.toolbarActions = this.loader.getContentActions(
|
||||
config,
|
||||
'features.toolbar'
|
||||
);
|
||||
this.viewerToolbarActions = this.loader.getContentActions(
|
||||
config,
|
||||
'features.viewer.toolbarActions'
|
||||
);
|
||||
this.sharedLinkViewerToolbarActions = this.loader.getContentActions(
|
||||
config,
|
||||
'features.viewer.shared.toolbarActions'
|
||||
);
|
||||
this.headerActions = this.loader.getContentActions(config, 'features.header');
|
||||
this.sidebarActions = this.loader.getContentActions(config, 'features.sidebar.toolbar');
|
||||
this.toolbarActions = this.loader.getContentActions(config, 'features.toolbar');
|
||||
this.viewerToolbarActions = this.loader.getContentActions(config, 'features.viewer.toolbarActions');
|
||||
this.sharedLinkViewerToolbarActions = this.loader.getContentActions(config, 'features.viewer.shared.toolbarActions');
|
||||
|
||||
this.contextMenuActions = this.loader.getContentActions(
|
||||
config,
|
||||
'features.contextMenu'
|
||||
);
|
||||
this.openWithActions = this.loader.getContentActions(
|
||||
config,
|
||||
'features.viewer.openWith'
|
||||
);
|
||||
this.createActions = this.loader.getElements<ContentActionRef>(
|
||||
config,
|
||||
'features.create'
|
||||
);
|
||||
this.contextMenuActions = this.loader.getContentActions(config, 'features.contextMenu');
|
||||
this.openWithActions = this.loader.getContentActions(config, 'features.viewer.openWith');
|
||||
this.createActions = this.loader.getElements<ContentActionRef>(config, 'features.create');
|
||||
this.navbar = this.loadNavBar(config);
|
||||
this.sidebarTabs = this.loader.getElements<SidebarTabRef>(
|
||||
config,
|
||||
'features.sidebar.tabs'
|
||||
);
|
||||
this.userActions = this.loader.getContentActions(
|
||||
config,
|
||||
'features.userActions'
|
||||
);
|
||||
this.sidebarTabs = this.loader.getElements<SidebarTabRef>(config, 'features.sidebar.tabs');
|
||||
this.userActions = this.loader.getContentActions(config, 'features.userActions');
|
||||
this.contentMetadata = this.loadContentMetadata(config);
|
||||
|
||||
this.documentListPresets = {
|
||||
files: this.getDocumentListPreset(config, 'files'),
|
||||
libraries: this.getDocumentListPreset(config, 'libraries'),
|
||||
favoriteLibraries: this.getDocumentListPreset(
|
||||
config,
|
||||
'favoriteLibraries'
|
||||
),
|
||||
favoriteLibraries: this.getDocumentListPreset(config, 'favoriteLibraries'),
|
||||
shared: this.getDocumentListPreset(config, 'shared'),
|
||||
recent: this.getDocumentListPreset(config, 'recent'),
|
||||
favorites: this.getDocumentListPreset(config, 'favorites'),
|
||||
@@ -218,10 +174,7 @@ export class AppExtensionService implements RuleContext {
|
||||
searchLibraries: this.getDocumentListPreset(config, 'search-libraries')
|
||||
};
|
||||
|
||||
this.withCredentials = this.appConfig.get<boolean>(
|
||||
'auth.withCredentials',
|
||||
false
|
||||
);
|
||||
this.withCredentials = this.appConfig.get<boolean>('auth.withCredentials', false);
|
||||
|
||||
if (config.features && config.features.viewer) {
|
||||
this.viewerRules = (config.features.viewer['rules'] as ViewerRules) || {};
|
||||
@@ -229,16 +182,12 @@ export class AppExtensionService implements RuleContext {
|
||||
|
||||
this.registerIcons(config);
|
||||
|
||||
const references = (config.$references || [])
|
||||
.filter(entry => typeof entry === 'object')
|
||||
.map(entry => entry as ExtensionRef);
|
||||
const references = (config.$references || []).filter((entry) => typeof entry === 'object').map((entry) => entry as ExtensionRef);
|
||||
this._references.next(references);
|
||||
}
|
||||
|
||||
protected registerIcons(config: ExtensionConfig) {
|
||||
const icons: Array<IconRef> = this.loader
|
||||
.getElements<IconRef>(config, 'features.icons')
|
||||
.filter(entry => !entry.disabled);
|
||||
const icons: Array<IconRef> = this.loader.getElements<IconRef>(config, 'features.icons').filter((entry) => !entry.disabled);
|
||||
|
||||
for (const icon of icons) {
|
||||
const [ns, id] = icon.id.split(':');
|
||||
@@ -249,11 +198,7 @@ export class AppExtensionService implements RuleContext {
|
||||
} else if (!ns || !id) {
|
||||
console.warn(`Incorrect icon id format: "${icon.id}".`);
|
||||
} else {
|
||||
this.matIconRegistry.addSvgIconInNamespace(
|
||||
ns,
|
||||
id,
|
||||
this.sanitizer.bypassSecurityTrustResourceUrl(value)
|
||||
);
|
||||
this.matIconRegistry.addSvgIconInNamespace(ns, id, this.sanitizer.bypassSecurityTrustResourceUrl(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,31 +208,26 @@ export class AppExtensionService implements RuleContext {
|
||||
}
|
||||
|
||||
protected getDocumentListPreset(config: ExtensionConfig, key: string) {
|
||||
return this.loader
|
||||
.getElements<DocumentListPresetRef>(
|
||||
config,
|
||||
`features.documentList.${key}`
|
||||
)
|
||||
.filter(entry => !entry.disabled);
|
||||
return this.loader.getElements<DocumentListPresetRef>(config, `features.documentList.${key}`).filter((entry) => !entry.disabled);
|
||||
}
|
||||
|
||||
getApplicationNavigation(elements): Array<NavBarGroupRef> {
|
||||
return elements
|
||||
.filter(group => this.filterVisible(group))
|
||||
.map(group => {
|
||||
.filter((group) => this.filterVisible(group))
|
||||
.map((group) => {
|
||||
return {
|
||||
...group,
|
||||
items: (group.items || [])
|
||||
.filter(entry => !entry.disabled)
|
||||
.filter(item => this.filterVisible(item))
|
||||
.filter((entry) => !entry.disabled)
|
||||
.filter((item) => this.filterVisible(item))
|
||||
.sort(sortByOrder)
|
||||
.map(item => {
|
||||
.map((item) => {
|
||||
if (item.children && item.children.length > 0) {
|
||||
item.children = item.children
|
||||
.filter(entry => !entry.disabled)
|
||||
.filter(child => this.filterVisible(child))
|
||||
.filter((entry) => !entry.disabled)
|
||||
.filter((child) => this.filterVisible(child))
|
||||
.sort(sortByOrder)
|
||||
.map(child => {
|
||||
.map((child) => {
|
||||
if (child.component) {
|
||||
return {
|
||||
...child
|
||||
@@ -295,12 +235,8 @@ export class AppExtensionService implements RuleContext {
|
||||
}
|
||||
|
||||
if (!child.click) {
|
||||
const childRouteRef = this.extensions.getRouteById(
|
||||
child.route
|
||||
);
|
||||
const childUrl = `/${
|
||||
childRouteRef ? childRouteRef.path : child.route
|
||||
}`;
|
||||
const childRouteRef = this.extensions.getRouteById(child.route);
|
||||
const childUrl = `/${childRouteRef ? childRouteRef.path : child.route}`;
|
||||
return {
|
||||
...child,
|
||||
url: childUrl
|
||||
@@ -342,10 +278,7 @@ export class AppExtensionService implements RuleContext {
|
||||
}
|
||||
|
||||
loadContentMetadata(config: ExtensionConfig): any {
|
||||
const elements = this.loader.getElements<any>(
|
||||
config,
|
||||
'features.content-metadata-presets'
|
||||
);
|
||||
const elements = this.loader.getElements<any>(config, 'features.content-metadata-presets');
|
||||
if (!elements.length) {
|
||||
return null;
|
||||
}
|
||||
@@ -356,10 +289,7 @@ export class AppExtensionService implements RuleContext {
|
||||
try {
|
||||
this.appConfig.config['content-metadata'] = { presets };
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
error,
|
||||
'- could not change content-metadata from app.config -'
|
||||
);
|
||||
this.logger.error(error, '- could not change content-metadata from app.config -');
|
||||
}
|
||||
|
||||
return { presets };
|
||||
@@ -367,12 +297,10 @@ export class AppExtensionService implements RuleContext {
|
||||
|
||||
filterDisabled(object: Array<{ disabled: boolean }> | { disabled: boolean }) {
|
||||
if (Array.isArray(object)) {
|
||||
return object
|
||||
.filter(item => !item.disabled)
|
||||
.map(item => this.filterDisabled(item));
|
||||
return object.filter((item) => !item.disabled).map((item) => this.filterDisabled(item));
|
||||
} else if (typeof object === 'object') {
|
||||
if (!object.disabled) {
|
||||
Object.keys(object).forEach(prop => {
|
||||
Object.keys(object).forEach((prop) => {
|
||||
object[prop] = this.filterDisabled(object[prop]);
|
||||
});
|
||||
return object;
|
||||
@@ -387,7 +315,7 @@ export class AppExtensionService implements RuleContext {
|
||||
}
|
||||
|
||||
getSidebarTabs(): Array<SidebarTabRef> {
|
||||
return this.sidebarTabs.filter(action => this.filterVisible(action));
|
||||
return this.sidebarTabs.filter((action) => this.filterVisible(action));
|
||||
}
|
||||
|
||||
getComponentById(id: string): Type<{}> {
|
||||
@@ -395,10 +323,8 @@ export class AppExtensionService implements RuleContext {
|
||||
}
|
||||
|
||||
getApplicationRoutes(): Array<ExtensionRoute> {
|
||||
return this.extensions.routes.map(route => {
|
||||
const guards = this.extensions.getAuthGuards(
|
||||
route.auth && route.auth.length > 0 ? route.auth : this.defaults.auth
|
||||
);
|
||||
return this.extensions.routes.map((route) => {
|
||||
const guards = this.extensions.getAuthGuards(route.auth && route.auth.length > 0 ? route.auth : this.defaults.auth);
|
||||
|
||||
return {
|
||||
path: route.path,
|
||||
@@ -419,10 +345,10 @@ export class AppExtensionService implements RuleContext {
|
||||
|
||||
getCreateActions(): Array<ContentActionRef> {
|
||||
return this.createActions
|
||||
.filter(action => this.filterVisible(action))
|
||||
.map(action => this.copyAction(action))
|
||||
.map(action => this.buildMenu(action))
|
||||
.map(action => {
|
||||
.filter((action) => this.filterVisible(action))
|
||||
.map((action) => this.copyAction(action))
|
||||
.map((action) => this.buildMenu(action))
|
||||
.map((action) => {
|
||||
let disabled = false;
|
||||
|
||||
if (action.rules && action.rules.enabled) {
|
||||
@@ -437,24 +363,15 @@ export class AppExtensionService implements RuleContext {
|
||||
}
|
||||
|
||||
private buildMenu(actionRef: ContentActionRef): ContentActionRef {
|
||||
if (
|
||||
actionRef.type === ContentActionType.menu &&
|
||||
actionRef.children &&
|
||||
actionRef.children.length > 0
|
||||
) {
|
||||
const children = actionRef.children
|
||||
.filter(action => this.filterVisible(action))
|
||||
.map(action => this.buildMenu(action));
|
||||
if (actionRef.type === ContentActionType.menu && actionRef.children && actionRef.children.length > 0) {
|
||||
const children = actionRef.children.filter((action) => this.filterVisible(action)).map((action) => this.buildMenu(action));
|
||||
|
||||
actionRef.children = children
|
||||
.map(action => {
|
||||
.map((action) => {
|
||||
let disabled = false;
|
||||
|
||||
if (action.rules && action.rules.enabled) {
|
||||
disabled = !this.extensions.evaluateRule(
|
||||
action.rules.enabled,
|
||||
this
|
||||
);
|
||||
disabled = !this.extensions.evaluateRule(action.rules.enabled, this);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -472,14 +389,14 @@ export class AppExtensionService implements RuleContext {
|
||||
|
||||
private getAllowedActions(actions: ContentActionRef[]): ContentActionRef[] {
|
||||
return (actions || [])
|
||||
.filter(action => this.filterVisible(action))
|
||||
.map(action => {
|
||||
.filter((action) => this.filterVisible(action))
|
||||
.map((action) => {
|
||||
if (action.type === ContentActionType.menu) {
|
||||
const copy = this.copyAction(action);
|
||||
if (copy.children && copy.children.length > 0) {
|
||||
copy.children = copy.children
|
||||
.filter(entry => !entry.disabled)
|
||||
.filter(childAction => this.filterVisible(childAction))
|
||||
.filter((entry) => !entry.disabled)
|
||||
.filter((childAction) => this.filterVisible(childAction))
|
||||
.sort(sortByOrder)
|
||||
.reduce(reduceSeparators, []);
|
||||
}
|
||||
@@ -509,13 +426,13 @@ export class AppExtensionService implements RuleContext {
|
||||
|
||||
getHeaderActions(): Array<ContentActionRef> {
|
||||
return this.headerActions
|
||||
.filter(action => this.filterVisible(action))
|
||||
.map(action => {
|
||||
.filter((action) => this.filterVisible(action))
|
||||
.map((action) => {
|
||||
if (action.type === ContentActionType.menu) {
|
||||
const copy = this.copyAction(action);
|
||||
if (copy.children && copy.children.length > 0) {
|
||||
copy.children = copy.children
|
||||
.filter(childAction => this.filterVisible(childAction))
|
||||
.filter((childAction) => this.filterVisible(childAction))
|
||||
.sort(sortByOrder)
|
||||
.reduce(reduceEmptyMenus, [])
|
||||
.reduce(reduceSeparators, []);
|
||||
@@ -535,25 +452,21 @@ export class AppExtensionService implements RuleContext {
|
||||
}
|
||||
|
||||
getUserActions(): Array<ContentActionRef> {
|
||||
return this.userActions
|
||||
.filter(action => this.filterVisible(action))
|
||||
.sort(sortByOrder);
|
||||
return this.userActions.filter((action) => this.filterVisible(action)).sort(sortByOrder);
|
||||
}
|
||||
|
||||
getSettingsGroups(): Array<SettingsGroupRef> {
|
||||
return this.settingGroups.filter(group => this.filterVisible(group));
|
||||
return this.settingGroups.filter((group) => this.filterVisible(group));
|
||||
}
|
||||
|
||||
copyAction(action: ContentActionRef): ContentActionRef {
|
||||
return {
|
||||
...action,
|
||||
children: (action.children || []).map(child => this.copyAction(child))
|
||||
children: (action.children || []).map((child) => this.copyAction(child))
|
||||
};
|
||||
}
|
||||
|
||||
filterVisible(
|
||||
action: ContentActionRef | SettingsGroupRef | SidebarTabRef
|
||||
): boolean {
|
||||
filterVisible(action: ContentActionRef | SettingsGroupRef | SidebarTabRef): boolean {
|
||||
if (action && action.rules && action.rules.visible) {
|
||||
return this.extensions.evaluateRule(action.rules.visible, this);
|
||||
}
|
||||
|
@@ -61,27 +61,17 @@ describe('AppService', () => {
|
||||
|
||||
spyOn(routeReuse, 'resetCache').and.stub();
|
||||
|
||||
service = new AppService(
|
||||
auth,
|
||||
appConfig,
|
||||
searchQueryBuilderService,
|
||||
routeReuse
|
||||
);
|
||||
service = new AppService(auth, appConfig, searchQueryBuilderService, routeReuse);
|
||||
});
|
||||
|
||||
it('should be ready if [withCredentials] mode is used', done => {
|
||||
it('should be ready if [withCredentials] mode is used', (done) => {
|
||||
appConfig.config = {
|
||||
auth: {
|
||||
withCredentials: true
|
||||
}
|
||||
};
|
||||
|
||||
const instance = new AppService(
|
||||
auth,
|
||||
appConfig,
|
||||
searchQueryBuilderService,
|
||||
routeReuse
|
||||
);
|
||||
const instance = new AppService(auth, appConfig, searchQueryBuilderService, routeReuse);
|
||||
expect(instance.withCredentials).toBeTruthy();
|
||||
|
||||
instance.ready$.subscribe(() => {
|
||||
@@ -101,7 +91,7 @@ describe('AppService', () => {
|
||||
|
||||
it('should be ready after login', async () => {
|
||||
let isReady = false;
|
||||
service.ready$.subscribe(value => {
|
||||
service.ready$.subscribe((value) => {
|
||||
isReady = value;
|
||||
});
|
||||
auth.onLogin.next();
|
||||
|
@@ -49,10 +49,7 @@ import { map } from 'rxjs/operators';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ContentApiService {
|
||||
constructor(
|
||||
private api: AlfrescoApiService,
|
||||
private preferences: UserPreferencesService
|
||||
) {}
|
||||
constructor(private api: AlfrescoApiService, private preferences: UserPreferencesService) {}
|
||||
|
||||
/**
|
||||
* Moves a node to the trashcan.
|
||||
@@ -60,10 +57,7 @@ export class ContentApiService {
|
||||
* @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> {
|
||||
deleteNode(nodeId: string, options: { permanent?: boolean } = {}): Observable<void> {
|
||||
return from(this.api.nodesApi.deleteNode(nodeId, options));
|
||||
}
|
||||
|
||||
@@ -101,13 +95,7 @@ export class ContentApiService {
|
||||
const defaults = {
|
||||
maxItems: this.preferences.paginationSize,
|
||||
skipCount: 0,
|
||||
include: [
|
||||
'isLocked',
|
||||
'path',
|
||||
'properties',
|
||||
'allowableOperations',
|
||||
'permissions'
|
||||
]
|
||||
include: ['isLocked', 'path', 'properties', 'allowableOperations', 'permissions']
|
||||
};
|
||||
const queryOptions = Object.assign(defaults, options);
|
||||
|
||||
@@ -140,10 +128,7 @@ export class ContentApiService {
|
||||
* @param personId ID of the target user
|
||||
* @returns User information
|
||||
*/
|
||||
getPerson(
|
||||
personId: string,
|
||||
options?: { fields?: Array<string> }
|
||||
): Observable<PersonEntry> {
|
||||
getPerson(personId: string, options?: { fields?: Array<string> }): Observable<PersonEntry> {
|
||||
return from(this.api.peopleApi.getPerson(personId, options));
|
||||
}
|
||||
|
||||
@@ -154,15 +139,8 @@ export class ContentApiService {
|
||||
* @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)
|
||||
);
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,9 +148,7 @@ export class ContentApiService {
|
||||
* @returns ProductVersionModel containing product details
|
||||
*/
|
||||
getRepositoryInformation(): Observable<DiscoveryEntry> {
|
||||
return from(
|
||||
this.api.getInstance().discovery.discoveryApi.getRepositoryInformation()
|
||||
);
|
||||
return from(this.api.getInstance().discovery.discoveryApi.getRepositoryInformation());
|
||||
}
|
||||
|
||||
getFavorites(
|
||||
@@ -187,10 +163,7 @@ export class ContentApiService {
|
||||
return from(this.api.favoritesApi.getFavorites(personId, opts));
|
||||
}
|
||||
|
||||
getFavoriteLibraries(
|
||||
personId: string = '-me-',
|
||||
opts?: any
|
||||
): Observable<FavoritePaging> {
|
||||
getFavoriteLibraries(personId: string = '-me-', opts?: any): Observable<FavoritePaging> {
|
||||
return this.getFavorites(personId, {
|
||||
...opts,
|
||||
where: '(EXISTS(target/site))'
|
||||
@@ -246,10 +219,7 @@ export class ContentApiService {
|
||||
return from(this.api.sitesApi.createSite(siteBody, opts));
|
||||
}
|
||||
|
||||
getSite(
|
||||
siteId?: string,
|
||||
opts?: { relations?: Array<string>; fields?: Array<string> }
|
||||
): Observable<SiteEntry> {
|
||||
getSite(siteId?: string, opts?: { relations?: Array<string>; fields?: Array<string> }): Observable<SiteEntry> {
|
||||
return from(this.api.sitesApi.getSite(siteId, opts));
|
||||
}
|
||||
|
||||
@@ -258,7 +228,7 @@ export class ContentApiService {
|
||||
}
|
||||
|
||||
addFavorite(nodes: Array<MinimalNodeEntity>): Observable<FavoriteEntry> {
|
||||
const payload: FavoriteBody[] = nodes.map(node => {
|
||||
const payload: FavoriteBody[] = nodes.map((node) => {
|
||||
const { isFolder, nodeId, id } = node.entry as any;
|
||||
const siteId = node.entry['guid'];
|
||||
const type = siteId ? 'site' : isFolder ? 'folder' : 'file';
|
||||
|
@@ -112,9 +112,7 @@ describe('NodePermissionService', () => {
|
||||
}
|
||||
];
|
||||
|
||||
expect(
|
||||
permission.check(source, ['update', 'other'], { operation: 'AND' })
|
||||
).toBe(true);
|
||||
expect(permission.check(source, ['update', 'other'], { operation: 'AND' })).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when source has no `AND` allowableOperations permission', () => {
|
||||
@@ -128,27 +126,17 @@ describe('NodePermissionService', () => {
|
||||
}
|
||||
];
|
||||
|
||||
expect(
|
||||
permission.check(source, ['update', 'bogus'], { operation: 'AND' })
|
||||
).toBe(false);
|
||||
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'] } }
|
||||
];
|
||||
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'] } }
|
||||
];
|
||||
const source = [{ entry: {} }, { entry: {} }, { entry: { allowableOperations: ['update'] } }];
|
||||
|
||||
expect(permission.check(source, ['update'])).toBe(false);
|
||||
});
|
||||
@@ -196,9 +184,7 @@ describe('NodePermissionService', () => {
|
||||
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);
|
||||
expect(permission.check(source, ['update', 'other'], { operation: 'AND' })).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when source has no `AND` allowableOperations permission', () => {
|
||||
@@ -206,9 +192,7 @@ describe('NodePermissionService', () => {
|
||||
entry: { allowableOperations: ['update', 'updatePermissions', 'other'] }
|
||||
};
|
||||
|
||||
expect(
|
||||
permission.check(source, ['update', 'bogus'], { operation: 'AND' })
|
||||
).toBe(false);
|
||||
expect(permission.check(source, ['update', 'bogus'], { operation: 'AND' })).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when source has no allowableOperations', () => {
|
||||
|
@@ -45,11 +45,7 @@ export class NodePermissionService implements NodePermissions {
|
||||
target: null
|
||||
};
|
||||
|
||||
check(
|
||||
source: PermissionSource | PermissionSource[],
|
||||
permissions: string[],
|
||||
options?: PermissionOptions
|
||||
): boolean {
|
||||
check(source: PermissionSource | PermissionSource[], permissions: string[], options?: PermissionOptions): boolean {
|
||||
const opts = Object.assign({}, this.defaultOptions, options || {});
|
||||
|
||||
if (!source) {
|
||||
@@ -57,12 +53,10 @@ export class NodePermissionService implements NodePermissions {
|
||||
}
|
||||
|
||||
if (Array.isArray(source)) {
|
||||
source = source.filter(item => item);
|
||||
source = source.filter((item) => item);
|
||||
|
||||
if (source.length > 0) {
|
||||
return source.every(node =>
|
||||
this.isOperationAllowed(node, permissions, opts)
|
||||
);
|
||||
return source.every((node) => this.isOperationAllowed(node, permissions, opts));
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
@@ -70,35 +64,21 @@ export class NodePermissionService implements NodePermissions {
|
||||
}
|
||||
}
|
||||
|
||||
private isOperationAllowed(
|
||||
node: PermissionSource,
|
||||
permissions: string[],
|
||||
options: PermissionOptions
|
||||
): boolean {
|
||||
const allowableOperations = this.getAllowableOperations(
|
||||
node,
|
||||
options.target
|
||||
);
|
||||
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)
|
||||
);
|
||||
return permissions.some((permission) => allowableOperations.includes(permission));
|
||||
} else {
|
||||
return permissions.every(permission =>
|
||||
allowableOperations.includes(permission)
|
||||
);
|
||||
return permissions.every((permission) => allowableOperations.includes(permission));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private getAllowableOperations(
|
||||
node: PermissionSource,
|
||||
property?: string
|
||||
): string[] {
|
||||
private getAllowableOperations(node: PermissionSource, property?: string): string[] {
|
||||
let entry: Node | SharedLink;
|
||||
|
||||
if ('entry' in node) {
|
||||
|
@@ -30,21 +30,12 @@ export function isLocked(node: { entry: Node }): boolean {
|
||||
|
||||
return (
|
||||
(entry && entry.isLocked) ||
|
||||
(entry.properties &&
|
||||
(entry.properties['cm:lockType'] === 'READ_ONLY_LOCK' ||
|
||||
entry.properties['cm:lockType'] === 'WRITE_LOCK'))
|
||||
(entry.properties && (entry.properties['cm:lockType'] === 'READ_ONLY_LOCK' || entry.properties['cm:lockType'] === 'WRITE_LOCK'))
|
||||
);
|
||||
}
|
||||
|
||||
export function isLibrary(node: { entry: Node | any }): boolean {
|
||||
const { entry } = node;
|
||||
|
||||
return (
|
||||
(entry.guid &&
|
||||
entry.id &&
|
||||
entry.preset &&
|
||||
entry.title &&
|
||||
entry.visibility) ||
|
||||
entry.nodeType === 'st:site'
|
||||
);
|
||||
return (entry.guid && entry.id && entry.preset && entry.title && entry.visibility) || entry.nodeType === 'st:site';
|
||||
}
|
||||
|
@@ -25,8 +25,7 @@
|
||||
|
||||
import { Action } from '@ngrx/store';
|
||||
|
||||
export const SET_INFO_DRAWER_METADATA_ASPECT =
|
||||
'SET_INFO_DRAWER_METADATA_ASPECT';
|
||||
export const SET_INFO_DRAWER_METADATA_ASPECT = 'SET_INFO_DRAWER_METADATA_ASPECT';
|
||||
|
||||
export class SetInfoDrawerMetadataAspectAction implements Action {
|
||||
readonly type = SET_INFO_DRAWER_METADATA_ASPECT;
|
||||
|
@@ -35,10 +35,7 @@ export enum SearchActionTypes {
|
||||
|
||||
export class SearchByTermAction implements Action {
|
||||
readonly type = SearchActionTypes.SearchByTerm;
|
||||
constructor(
|
||||
public payload: string,
|
||||
public searchOptions?: SearchOptionModel[]
|
||||
) {}
|
||||
constructor(public payload: string, public searchOptions?: SearchOptionModel[]) {}
|
||||
}
|
||||
|
||||
export class ToggleSearchFilterAction implements Action {
|
||||
|
@@ -27,10 +27,7 @@ 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';
|
||||
import { CloseModalDialogsAction, AppActionTypes } from '../actions/app.actions';
|
||||
|
||||
@Injectable()
|
||||
export class DialogEffects {
|
||||
|
@@ -30,27 +30,17 @@ 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 { 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
|
||||
) {}
|
||||
constructor(private store: Store<AppStore>, private actions$: Actions, private router: Router) {}
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
navigateUrl$ = this.actions$.pipe(
|
||||
ofType<NavigateUrlAction>(RouterActionTypes.NavigateUrl),
|
||||
map(action => {
|
||||
map((action) => {
|
||||
if (action.payload) {
|
||||
this.router.navigateByUrl(action.payload);
|
||||
}
|
||||
@@ -60,7 +50,7 @@ export class RouterEffects {
|
||||
@Effect({ dispatch: false })
|
||||
navigateRoute$ = this.actions$.pipe(
|
||||
ofType<NavigateRouteAction>(RouterActionTypes.NavigateRoute),
|
||||
map(action => {
|
||||
map((action) => {
|
||||
this.router.navigate(action.payload);
|
||||
})
|
||||
);
|
||||
@@ -68,7 +58,7 @@ export class RouterEffects {
|
||||
@Effect({ dispatch: false })
|
||||
navigateToFolder$ = this.actions$.pipe(
|
||||
ofType<NavigateToFolder>(RouterActionTypes.NavigateFolder),
|
||||
map(action => {
|
||||
map((action) => {
|
||||
if (action.payload && action.payload.entry) {
|
||||
this.navigateToFolder(action.payload.entry);
|
||||
}
|
||||
@@ -78,7 +68,7 @@ export class RouterEffects {
|
||||
@Effect({ dispatch: false })
|
||||
navigateToParentFolder$ = this.actions$.pipe(
|
||||
ofType<NavigateToParentFolder>(RouterActionTypes.NavigateParentFolder),
|
||||
map(action => {
|
||||
map((action) => {
|
||||
if (action.payload && action.payload.entry) {
|
||||
this.navigateToParentFolder(action.payload.entry);
|
||||
}
|
||||
@@ -131,18 +121,12 @@ export class RouterEffects {
|
||||
this.router.navigate(link);
|
||||
}, 10);
|
||||
} else {
|
||||
this.store.dispatch(
|
||||
new SnackbarErrorAction('APP.MESSAGES.ERRORS.CANNOT_NAVIGATE_LOCATION')
|
||||
);
|
||||
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'
|
||||
) {
|
||||
if (path && path.elements.length >= 2 && path.elements[1].name === 'Sites') {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -30,13 +30,7 @@ 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';
|
||||
import { SnackbarInfoAction, SnackbarActionTypes, SnackbarWarningAction, SnackbarErrorAction, SnackbarAction } from '../actions/snackbar.actions';
|
||||
|
||||
@Injectable()
|
||||
export class SnackbarEffects {
|
||||
|
@@ -28,80 +28,29 @@ import { createSelector } from '@ngrx/store';
|
||||
|
||||
export const selectApp = (state: AppStore) => state.app;
|
||||
|
||||
export const getHeaderColor = createSelector(
|
||||
selectApp,
|
||||
state => state.headerColor
|
||||
);
|
||||
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 getHeaderImagePath = createSelector(selectApp, (state) => state.headerImagePath);
|
||||
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 getAppName = createSelector(selectApp, state => state.appName);
|
||||
export const getLogoPath = createSelector(selectApp, state => state.logoPath);
|
||||
|
||||
export const getHeaderImagePath = createSelector(
|
||||
selectApp,
|
||||
state => state.headerImagePath
|
||||
);
|
||||
|
||||
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 getSideNavState = createSelector(getAppSelection, getNavigationState, (selection, navigation) => {
|
||||
return {
|
||||
selection,
|
||||
navigation
|
||||
};
|
||||
});
|
||||
|
||||
export const getRuleContext = createSelector(
|
||||
getAppSelection,
|
||||
@@ -118,7 +67,4 @@ export const getRuleContext = createSelector(
|
||||
}
|
||||
);
|
||||
|
||||
export const infoDrawerMetadataAspect = createSelector(
|
||||
selectApp,
|
||||
state => state.infoDrawerMetadataAspect
|
||||
);
|
||||
export const infoDrawerMetadataAspect = createSelector(selectApp, (state) => state.infoDrawerMetadataAspect);
|
||||
|
@@ -23,11 +23,7 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
SelectionState,
|
||||
ProfileState,
|
||||
NavigationState
|
||||
} from '@alfresco/adf-extensions';
|
||||
import { SelectionState, ProfileState, NavigationState } from '@alfresco/adf-extensions';
|
||||
import { RepositoryInfo } from '@alfresco/js-api';
|
||||
|
||||
export interface AppState {
|
||||
|
@@ -30,8 +30,6 @@ import { DialogEffects } from './effects/dialog.effects';
|
||||
import { RouterEffects } from './effects/router.effects';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
EffectsModule.forFeature([SnackbarEffects, DialogEffects, RouterEffects])
|
||||
]
|
||||
imports: [EffectsModule.forFeature([SnackbarEffects, DialogEffects, RouterEffects])]
|
||||
})
|
||||
export class SharedStoreModule {}
|
||||
|
@@ -28,18 +28,12 @@
|
||||
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';
|
||||
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
|
||||
|
||||
declare const require: any;
|
||||
|
||||
// First, initialize the Angular testing environment.
|
||||
getTestBed().initTestEnvironment(
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting()
|
||||
);
|
||||
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
|
||||
// Then we find all the tests.
|
||||
const context = require.context('./', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
|
Reference in New Issue
Block a user