Ng17 migration (#10295)

* Migrate to NG17

* [ci:force] - fixed deps

* [ci:force] - fixed build for testing 1

* Fixed build for all the packages

* [ci:force] - fixing lint

* [ci:force] - Fixed lint

* AAE-26163 Fix infinite loop when authentication error event occured (#10272)

* AAE-26163 Logout user after 3 login attempts failed, avoiding infinite loop when an authentication error occured, like when a user machine clock is significantly out of sync

* AAE-26163 Wait to discovery document to be loaded and user not authenticated to perform a ssoLogin, logout user if login fails after 3 attempts

* AAE-26163 Fix missed id_token_hint invoking logout when a login error occured due to a clock significantly out of sync

* AAE-26163 Add fake observable to unit test

* AAE-26163 Show oauth event logs if showDebugInformation is enabled, remove auth items if access token is not valid

* AAE-26163 Improve tryLogin error message

* AAE-26163 Check if token has expired to fix case when user access the application after the token is expired and with a clock significantly out of sync

* AAE-26163 Test logout when clock is out of sync

* AAE-26163 Create a service to check if local machine time is out of sync

* AAE-26163 Update oauthErrorEvent$ and combinedOAuthErrorsStream$ to return errors

* AAE-26163 Output error within combined oauth error event subscription

* AAE-26163 Fix lint problems

* AAE-26163 Logout user when token refresh error happens for the second time, if the token is not refreshed properly after first refresh error

* AAE-26163 Logout user once an oauth error event occur due to clock out of sync

* AAE-26163 Fix retry login error message if the OAuthErrorEvent doesn t return reason

* AAE-26163 Fix the issue where the logout API call is canceled by the authorize call when login fails due to clock synchronization problems, causing an infinite loop.

* remove console.log

* AAE-26163 Fix retry login error message if the OAuthErrorEvent reason is an empty object

* Cherry picked commit from oidc and run fix lint

* [MIGRATION] - fixed build and lint

* [MIGRATION] - Added injectionContext to avoid error NG0203 for unit tests

* [MIGRATION] - Moving mocha to jest

* [MIGRATION] - Fixing failing migrated tests

* [MIGRATION] - Migrating to Jest - working but some tests fails

* Trying to fix js-api unit tests

* Removing testing lib to sync with develop

* Fixed two excluded unit tests

* Removed unused project parts

* Removed unused project parts

* Reduced tserrors on building storybook

* Fixed sonarqube errors

* Removing temporarily eslint rule from publishing

* [MIGRATION] - Fixed lint

* [MIGRATION] - Fixed type

* [MIGRATION] - Rebased

* [MIGRATION] - Readded removed action

* [MIGRATION] - Checking deps

* [MIGRATION] - updated lock

* [ACS-9052] manage versions close button is too low (#10466)

* [ci:force] - Fixed lint

* [ACS-9052] Fixed close button in version manager position

* [ACS-9052] Reverted unwanted changes

---------

Co-authored-by: VitoAlbano <vito.albano.123@gmail.com>

* [MIGRATION] - fixed storybook builds

* [MIGRATION] - Checking if now eslint is releasable

* [MIGRATION] - Changing the building executor for eslint-rules

* Readded rule for peer deps

* Fixed wrong rule

* [ACS-9075] Fixed incorrect buttons labels color (#10489)

* Update package.json

* Fix ACA pipeline

* [ACS-9084] Fixed incorrect color for notification bell icon (#10513)

* Change dialog label padding

* [AAE-26767] - Fixed lint

* [AAE-26767] - Fixed lint

* updated dependencies

* AAE-30733 Fix incorrect alignment of icons in permission list header

* [MIGRATION] - sync package-lock

* [MIGRATION] - Fixed package on core lib

* [MIGRATION] - Removed unused lock

* Fixed licence

* [MIGRATION] - sync lock file

* [MIGRATION] - fixed lint issues

* [ACS-9271][ACA] Login page input labels are cut if the input is not empty (#10637)

* AAE-31453 Override card-view-textitem readonly color

---------

Co-authored-by: Amedeo Lepore <amedeo.lepore@hyland.com>
Co-authored-by: Ehsan Rezaei <ehsan.rezaei@hyland.com>
Co-authored-by: AleksanderSklorz <115619721+AleksanderSklorz@users.noreply.github.com>
Co-authored-by: DominikIwanek <dominik.iwanek@hyland.com>
Co-authored-by: swapnil-verma-gl <92505353+swapnil-verma-gl@users.noreply.github.com>
Co-authored-by: Wojciech Duda <69160975+wojd0@users.noreply.github.com>
Co-authored-by: dominikiwanekhyland <141320833+dominikiwanekhyland@users.noreply.github.com>
This commit is contained in:
Vito Albano 2025-02-12 11:58:57 +00:00 committed by GitHub
parent 2284ede0c7
commit 5d64c7f0ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
317 changed files with 16460 additions and 15654 deletions

View File

@ -10,3 +10,4 @@ scripts
docs/**/*.md docs/**/*.md
lib/js-api/docs/**/*.md lib/js-api/docs/**/*.md
.storybook .storybook
webpack.config.js

View File

@ -234,7 +234,7 @@ jobs:
- uses: ./.github/actions/setup - uses: ./.github/actions/setup
- uses: ./.github/actions/download-node-modules-and-artifacts - uses: ./.github/actions/download-node-modules-and-artifacts
- run: NX_REJECT_UNKNOWN_LOCAL_CACHE=0 npx nx affected:build $NX_CALCULATION_FLAGS --prod - run: NX_REJECT_UNKNOWN_LOCAL_CACHE=0 npx nx affected:build $NX_CALCULATION_FLAGS --prod
- run: NX_REJECT_UNKNOWN_LOCAL_CACHE=0 npx nx affected --target=build-storybook $NX_CALCULATION_FLAGS --configuration=ci --parallel=1 - run: NX_REJECT_UNKNOWN_LOCAL_CACHE=0 npx nx affected --target=build-storybook $NX_CALCULATION_FLAGS --configuration=ci
- uses: ./.github/actions/upload-node-modules-and-artifacts - uses: ./.github/actions/upload-node-modules-and-artifacts
PR-forbidden-labels: PR-forbidden-labels:

4
jest.preset.js Normal file
View File

@ -0,0 +1,4 @@
// eslint-disable
const nxPreset = require('@nx/jest/preset').default;
module.exports = {...nxPreset };

View File

@ -50,7 +50,7 @@
} }
}, },
"lint": { "lint": {
"executor": "@nrwl/linter:eslint", "executor": "@nx/eslint:lint",
"options": { "options": {
"lintFilePatterns": ["lib/cli/**/*.ts", "lib/cli/**/*.html"] "lintFilePatterns": ["lib/cli/**/*.ts", "lib/cli/**/*.html"]
} }

View File

@ -33,7 +33,7 @@
} }
}, },
"lint": { "lint": {
"executor": "@nrwl/linter:eslint", "executor": "@nx/eslint:lint",
"options": { "options": {
"lintFilePatterns": ["lib/content-services/**/*.ts", "lib/content-services/**/*.html"] "lintFilePatterns": ["lib/content-services/**/*.ts", "lib/content-services/**/*.html"]
} }
@ -45,10 +45,7 @@
"browserTarget": "content-services:storybook", "browserTarget": "content-services:storybook",
"configDir": "lib/content-services/.storybook", "configDir": "lib/content-services/.storybook",
"compodoc": false, "compodoc": false,
"styles": [ "styles": ["node_modules/cropperjs/dist/cropper.min.css", "node_modules/pdfjs-dist/web/pdf_viewer.css"],
"node_modules/cropperjs/dist/cropper.min.css",
"node_modules/pdfjs-dist/web/pdf_viewer.css"
],
"stylePreprocessorOptions": { "stylePreprocessorOptions": {
"includePaths": ["lib", "lib/core/src/lib"] "includePaths": ["lib", "lib/core/src/lib"]
} }
@ -66,10 +63,7 @@
"configDir": "lib/content-services/.storybook", "configDir": "lib/content-services/.storybook",
"outputDir": "dist/storybook/content-services", "outputDir": "dist/storybook/content-services",
"compodoc": false, "compodoc": false,
"styles": [ "styles": ["node_modules/cropperjs/dist/cropper.min.css", "node_modules/pdfjs-dist/web/pdf_viewer.css"],
"node_modules/cropperjs/dist/cropper.min.css",
"node_modules/pdfjs-dist/web/pdf_viewer.css"
],
"stylePreprocessorOptions": { "stylePreprocessorOptions": {
"includePaths": ["lib", "lib/core/src/lib"] "includePaths": ["lib", "lib/core/src/lib"]
} }

View File

@ -23,18 +23,17 @@ import { AlfrescoApiService } from '../services/alfresco-api.service';
@Injectable() @Injectable()
export class AlfrescoApiNoAuthService extends AlfrescoApiService { export class AlfrescoApiNoAuthService extends AlfrescoApiService {
constructor( constructor(storage: StorageService, appConfig: AppConfigService, private readonly adfHttpClient: AdfHttpClient) {
storage: StorageService,
appConfig: AppConfigService,
private readonly adfHttpClient: AdfHttpClient
) {
super(appConfig, storage); super(appConfig, storage);
} }
override createInstance(config: AlfrescoApiConfig) { override createInstance(config: AlfrescoApiConfig) {
return new AlfrescoApi({ return new AlfrescoApi(
...config, {
oauthInit: false ...config,
}, this.adfHttpClient); oauthInit: false
},
this.adfHttpClient
);
} }
} }

View File

@ -18,7 +18,7 @@
import { AlfrescoApiConfig } from '@alfresco/js-api'; import { AlfrescoApiConfig } from '@alfresco/js-api';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { AppConfigService, AppConfigValues, StorageService } from '@alfresco/adf-core'; import { AppConfigService, AppConfigValues, StorageService } from '@alfresco/adf-core';
import { AlfrescoApiService } from '../services/alfresco-api.service'; import { AlfrescoApiService } from '../services/alfresco-api.service';
/** /**
* Create a factory to resolve an api service instance * Create a factory to resolve an api service instance
@ -34,10 +34,11 @@ export function createAlfrescoApiInstance(angularAlfrescoApiService: AlfrescoApi
providedIn: 'root' providedIn: 'root'
}) })
export class AlfrescoApiLoaderService { export class AlfrescoApiLoaderService {
constructor(private readonly appConfig: AppConfigService, constructor(
private readonly apiService: AlfrescoApiService, private readonly appConfig: AppConfigService,
private storageService: StorageService) { private readonly apiService: AlfrescoApiService,
} private storageService: StorageService
) {}
async init(): Promise<any> { async init(): Promise<any> {
await this.appConfig.load(); await this.appConfig.load();

View File

@ -16,7 +16,7 @@
*/ */
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { AlfrescoApiService } from '../../services/alfresco-api.service'; import { AlfrescoApiService } from '../../services/alfresco-api.service';
import { AppConfigService } from '@alfresco/adf-core'; import { AppConfigService } from '@alfresco/adf-core';
import { from, Observable, of, zip } from 'rxjs'; import { from, Observable, of, zip } from 'rxjs';
import { catchError, map } from 'rxjs/operators'; import { catchError, map } from 'rxjs/operators';

View File

@ -25,12 +25,12 @@ import { TagService } from '../../tag/services/tag.service';
providedIn: 'root' providedIn: 'root'
}) })
export class NodeAspectService { export class NodeAspectService {
constructor(
constructor(private nodesApiService: NodesApiService, private nodesApiService: NodesApiService,
private dialogAspectListService: DialogAspectListService, private dialogAspectListService: DialogAspectListService,
private cardViewContentUpdateService: CardViewContentUpdateService, private cardViewContentUpdateService: CardViewContentUpdateService,
private tagService: TagService) { private tagService: TagService
} ) {}
updateNodeAspects(nodeId: string, selectorAutoFocusedOnClose?: string) { updateNodeAspects(nodeId: string, selectorAutoFocusedOnClose?: string) {
this.dialogAspectListService.openAspectListDialog(nodeId, selectorAutoFocusedOnClose).subscribe((aspectList) => { this.dialogAspectListService.openAspectListDialog(nodeId, selectorAutoFocusedOnClose).subscribe((aspectList) => {

View File

@ -54,7 +54,6 @@ describe('ContentAuthLoaderService', () => {
basicAlfrescoAuthService = TestBed.inject(BasicAlfrescoAuthService); basicAlfrescoAuthService = TestBed.inject(BasicAlfrescoAuthService);
}); });
it('should require Alf ticket on login if OAuth and provider is ALL or ECM', fakeAsync(() => { it('should require Alf ticket on login if OAuth and provider is ALL or ECM', fakeAsync(() => {
spyOn(authService, 'isOauth').and.returnValue(true); spyOn(authService, 'isOauth').and.returnValue(true);
spyOn(authService, 'isALLProvider').and.returnValue(true); spyOn(authService, 'isALLProvider').and.returnValue(true);

View File

@ -21,22 +21,15 @@ import { take } from 'rxjs/operators';
@Injectable() @Injectable()
export class ContentAuthLoaderService { export class ContentAuthLoaderService {
constructor(private readonly basicAlfrescoAuthService: BasicAlfrescoAuthService, private readonly authService: AuthenticationService) {}
constructor(
private readonly basicAlfrescoAuthService: BasicAlfrescoAuthService,
private readonly authService: AuthenticationService
) {
}
init(): void { init(): void {
this.authService.onLogin this.authService.onLogin.pipe(take(1)).subscribe({
.pipe(take(1)) next: async () => {
.subscribe({ if (this.authService.isOauth() && (this.authService.isALLProvider() || this.authService.isECMProvider())) {
next: async () => { await this.basicAlfrescoAuthService.requireAlfTicket();
if (this.authService.isOauth() && (this.authService.isALLProvider() || this.authService.isECMProvider())) {
await this.basicAlfrescoAuthService.requireAlfTicket();
}
} }
}); }
});
} }
} }

View File

@ -33,8 +33,7 @@ describe('Breadcrumb', () => {
}); });
let documentListComponent: DocumentListComponent; let documentListComponent: DocumentListComponent;
const getBreadcrumbActionText = (): string => const getBreadcrumbActionText = (): string => fixture.debugElement.nativeElement.querySelector('.adf-breadcrumb-item-current').textContent.trim();
fixture.debugElement.nativeElement.querySelector('.adf-breadcrumb-item-current').textContent.trim();
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({

View File

@ -18,7 +18,10 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { import {
CategoryEntry, CategoryEntry,
CategoryPaging, Pagination, PathInfo, ResultNode, CategoryPaging,
Pagination,
PathInfo,
ResultNode,
ResultSetPaging, ResultSetPaging,
ResultSetPagingList, ResultSetPagingList,
ResultSetRowEntry ResultSetRowEntry
@ -27,7 +30,6 @@ import { Observable, of } from 'rxjs';
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class CategoryServiceMock { export class CategoryServiceMock {
public getSubcategories(parentNodeId: string, skipCount?: number, maxItems?: number): Observable<CategoryPaging> { public getSubcategories(parentNodeId: string, skipCount?: number, maxItems?: number): Observable<CategoryPaging> {
return parentNodeId ? of(this.getChildrenLevelResponse(skipCount, maxItems)) : of(this.getRootLevelResponse(skipCount, maxItems)); return parentNodeId ? of(this.getChildrenLevelResponse(skipCount, maxItems)) : of(this.getRootLevelResponse(skipCount, maxItems));
} }
@ -66,12 +68,12 @@ export class CategoryServiceMock {
} }
private getRootLevelResponse(skipCount?: number, maxItems?: number): CategoryPaging { private getRootLevelResponse(skipCount?: number, maxItems?: number): CategoryPaging {
const rootCategoryEntry: CategoryEntry = {entry: {id: 'testId', name: 'testNode', parentId: '-root-', hasChildren: true}}; const rootCategoryEntry: CategoryEntry = { entry: { id: 'testId', name: 'testNode', parentId: '-root-', hasChildren: true } };
return {list: {pagination: {skipCount, maxItems, hasMoreItems: false}, entries: [rootCategoryEntry]}}; return { list: { pagination: { skipCount, maxItems, hasMoreItems: false }, entries: [rootCategoryEntry] } };
} }
private getChildrenLevelResponse(skipCount?: number, maxItems?: number): CategoryPaging { private getChildrenLevelResponse(skipCount?: number, maxItems?: number): CategoryPaging {
const childCategoryEntry: CategoryEntry = {entry: {id: 'childId', name: 'childNode', parentId: 'testId', hasChildren: false}}; const childCategoryEntry: CategoryEntry = { entry: { id: 'childId', name: 'childNode', parentId: 'testId', hasChildren: false } };
return {list: {pagination: {skipCount, maxItems, hasMoreItems: true}, entries: [childCategoryEntry]}}; return { list: { pagination: { skipCount, maxItems, hasMoreItems: true }, entries: [childCategoryEntry] } };
} }
} }

View File

@ -24,59 +24,65 @@ import { from, Observable } from 'rxjs';
import { map, mergeMap, toArray } from 'rxjs/operators'; import { map, mergeMap, toArray } from 'rxjs/operators';
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class CategoryTreeDatasourceService extends TreeService<CategoryNode> { export class CategoryTreeDatasourceService extends TreeService<CategoryNode> {
constructor(private categoryService: CategoryService) { constructor(private categoryService: CategoryService) {
super(); super();
} }
public getSubNodes(parentNodeId: string, skipCount?: number, maxItems?: number, name?: string): Observable<TreeResponse<CategoryNode>> { public getSubNodes(parentNodeId: string, skipCount?: number, maxItems?: number, name?: string): Observable<TreeResponse<CategoryNode>> {
return !name ? this.categoryService.getSubcategories(parentNodeId, skipCount, maxItems).pipe(map((response: CategoryPaging) => { return !name
const parentNode: CategoryNode = this.getParentNode(parentNodeId); ? this.categoryService.getSubcategories(parentNodeId, skipCount, maxItems).pipe(
const nodesList: CategoryNode[] = response.list.entries.map((entry: CategoryEntry) => ({ map((response: CategoryPaging) => {
id: entry.entry.id, const parentNode: CategoryNode = this.getParentNode(parentNodeId);
nodeName: entry.entry.name, const nodesList: CategoryNode[] = response.list.entries.map((entry: CategoryEntry) => ({
parentId: entry.entry.parentId, id: entry.entry.id,
hasChildren: entry.entry.hasChildren, nodeName: entry.entry.name,
level: parentNode ? parentNode.level + 1 : 0, parentId: entry.entry.parentId,
isLoading: false, hasChildren: entry.entry.hasChildren,
nodeType: TreeNodeType.RegularNode level: parentNode ? parentNode.level + 1 : 0,
})); isLoading: false,
if (response.list.pagination.hasMoreItems && parentNode) { nodeType: TreeNodeType.RegularNode
const loadMoreNode: CategoryNode = { }));
id: 'loadMore', if (response.list.pagination.hasMoreItems && parentNode) {
nodeName: '', const loadMoreNode: CategoryNode = {
parentId: parentNode.id, id: 'loadMore',
hasChildren: false, nodeName: '',
level: parentNode.level + 1, parentId: parentNode.id,
isLoading: false, hasChildren: false,
nodeType: TreeNodeType.LoadMoreNode level: parentNode.level + 1,
}; isLoading: false,
nodesList.push(loadMoreNode); nodeType: TreeNodeType.LoadMoreNode
} };
const treeResponse: TreeResponse<CategoryNode> = {entries: nodesList, pagination: response.list.pagination}; nodesList.push(loadMoreNode);
return treeResponse; }
})) : this.categoryService.searchCategories(name, skipCount, maxItems).pipe(mergeMap((pagingResult) => { const treeResponse: TreeResponse<CategoryNode> = { entries: nodesList, pagination: response.list.pagination };
const nextAfterGeneralPathPartIndex = 3; return treeResponse;
const pathSeparator = '/'; })
return from(pagingResult.list.entries).pipe(mergeMap((category) => { )
const path = category.entry.path.name.split(pathSeparator).slice(nextAfterGeneralPathPartIndex) : this.categoryService.searchCategories(name, skipCount, maxItems).pipe(
.join(pathSeparator); mergeMap((pagingResult) => {
const nextAfterGeneralPathPartIndex = 3;
const pathSeparator = '/';
return from(pagingResult.list.entries).pipe(
mergeMap((category) => {
const path = category.entry.path.name.split(pathSeparator).slice(nextAfterGeneralPathPartIndex).join(pathSeparator);
return this.categoryService.getCategory(category.entry.id).pipe( return this.categoryService.getCategory(category.entry.id).pipe(
map((res) => ({ map((res) => ({
id: category.entry.id, id: category.entry.id,
nodeName: path ? `${path}/${category.entry.name}` : category.entry.name, nodeName: path ? `${path}/${category.entry.name}` : category.entry.name,
parentId: category.entry.parentId, parentId: category.entry.parentId,
level: 0, level: 0,
nodeType: TreeNodeType.RegularNode, nodeType: TreeNodeType.RegularNode,
hasChildren: res.entry.hasChildren, hasChildren: res.entry.hasChildren,
isLoading: false isLoading: false
})) }))
); );
}), }),
toArray(), toArray(),
map(res => ({entries: res, pagination: pagingResult.list.pagination}))); map((res) => ({ entries: res, pagination: pagingResult.list.pagination }))
})); );
})
);
} }
} }

View File

@ -18,35 +18,27 @@
import { FileModel, FileUploadStatus } from '../models/file.model'; import { FileModel, FileUploadStatus } from '../models/file.model';
export class FileUploadEvent { export class FileUploadEvent {
constructor( constructor(
public readonly file: FileModel, public readonly file: FileModel,
public readonly status: FileUploadStatus = FileUploadStatus.Pending, public readonly status: FileUploadStatus = FileUploadStatus.Pending,
public readonly error: any = null) { public readonly error: any = null
} ) {}
} }
export class FileUploadCompleteEvent extends FileUploadEvent { export class FileUploadCompleteEvent extends FileUploadEvent {
constructor(file: FileModel, public totalComplete: number = 0, public data?: any, public totalAborted: number = 0) { constructor(file: FileModel, public totalComplete: number = 0, public data?: any, public totalAborted: number = 0) {
super(file, FileUploadStatus.Complete); super(file, FileUploadStatus.Complete);
} }
} }
export class FileUploadDeleteEvent extends FileUploadEvent { export class FileUploadDeleteEvent extends FileUploadEvent {
constructor(file: FileModel, public totalComplete: number = 0) { constructor(file: FileModel, public totalComplete: number = 0) {
super(file, FileUploadStatus.Deleted); super(file, FileUploadStatus.Deleted);
} }
} }
export class FileUploadErrorEvent extends FileUploadEvent { export class FileUploadErrorEvent extends FileUploadEvent {
constructor(file: FileModel, public error: any, public totalError: number = 0) { constructor(file: FileModel, public error: any, public totalError: number = 0) {
super(file, FileUploadStatus.Error); super(file, FileUploadStatus.Error);
} }
} }

View File

@ -18,9 +18,7 @@
import { FileModel } from './file.model'; import { FileModel } from './file.model';
describe('FileModel', () => { describe('FileModel', () => {
describe('extension', () => { describe('extension', () => {
it('should return the extension if file has it', () => { it('should return the extension if file has it', () => {
const file = new FileModel({ name: 'tyrion-lannister.doc' } as File); const file = new FileModel({ name: 'tyrion-lannister.doc' } as File);
@ -33,7 +31,7 @@ describe('FileModel', () => {
expect(file.extension).toBe(''); expect(file.extension).toBe('');
}); });
it('should return the empty string if file is starting with . and doesn\'t have extension', () => { it("should return the empty string if file is starting with . and doesn't have extension", () => {
const file = new FileModel({ name: '.white-walkers' } as File); const file = new FileModel({ name: '.white-walkers' } as File);
expect(file.extension).toBe(''); expect(file.extension).toBe('');

View File

@ -21,7 +21,7 @@ import { Subject } from 'rxjs';
import { AuthenticationService, ThumbnailService } from '@alfresco/adf-core'; import { AuthenticationService, ThumbnailService } from '@alfresco/adf-core';
import { PermissionsEnum } from '../models/permissions.enum'; import { PermissionsEnum } from '../models/permissions.enum';
import { AllowableOperationsEnum } from '../models/allowable-operations.enum'; import { AllowableOperationsEnum } from '../models/allowable-operations.enum';
import { AlfrescoApiService } from '../../services/alfresco-api.service'; import { AlfrescoApiService } from '../../services/alfresco-api.service';
export interface FolderCreatedEvent { export interface FolderCreatedEvent {
name: string; name: string;

View File

@ -26,7 +26,6 @@ import { catchError } from 'rxjs/operators';
providedIn: 'root' providedIn: 'root'
}) })
export class FavoritesApiService { export class FavoritesApiService {
private _favoritesApi: FavoritesApi; private _favoritesApi: FavoritesApi;
get favoritesApi(): FavoritesApi { get favoritesApi(): FavoritesApi {
this._favoritesApi = this._favoritesApi ?? new FavoritesApi(this.apiService.getInstance()); this._favoritesApi = this._favoritesApi ?? new FavoritesApi(this.apiService.getInstance());
@ -42,16 +41,11 @@ export class FavoritesApiService {
return { entry }; return { entry };
} }
constructor( constructor(private apiService: AlfrescoApiService, private preferences: UserPreferencesService) {}
private apiService: AlfrescoApiService,
private preferences: UserPreferencesService
) {
}
remapFavoritesData(data: FavoritePaging = {}): NodePaging { remapFavoritesData(data: FavoritePaging = {}): NodePaging {
const pagination = (data?.list?.pagination || {}); const pagination = data?.list?.pagination || {};
const entries: any[] = this const entries: any[] = this.remapFavoriteEntries(data?.list?.entries || []);
.remapFavoriteEntries(data?.list?.entries || []);
return { return {
list: { entries, pagination } list: { entries, pagination }
@ -63,7 +57,7 @@ export class FavoritesApiService {
.map(({ entry: { target } }: any) => ({ .map(({ entry: { target } }: any) => ({
entry: target.file || target.folder entry: target.file || target.folder
})) }))
.filter(({ entry }) => (!!entry)) .filter(({ entry }) => !!entry)
.map(FavoritesApiService.remapEntry); .map(FavoritesApiService.remapEntry);
} }
@ -82,12 +76,8 @@ export class FavoritesApiService {
include: ['properties', 'allowableOperations'] include: ['properties', 'allowableOperations']
}; };
const queryOptions = Object.assign(defaultOptions, options); const queryOptions = Object.assign(defaultOptions, options);
const promise = this.favoritesApi const promise = this.favoritesApi.listFavorites(personId, queryOptions).then(this.remapFavoritesData);
.listFavorites(personId, queryOptions)
.then(this.remapFavoritesData);
return from(promise).pipe( return from(promise).pipe(catchError((err) => of(err)));
catchError((err) => of(err))
);
} }
} }

View File

@ -48,7 +48,7 @@ import { TranslateModule } from '@ngx-translate/core';
<ng-container> <ng-container>
<mat-icon>{{ expanded ? 'expand_more' : 'chevron_right' }}</mat-icon> <mat-icon>{{ expanded ? 'expand_more' : 'chevron_right' }}</mat-icon>
<mat-panel-title *ngIf="title" class="adf-metadata-properties-title" [title]="title | translate">{{ title | translate }}</mat-panel-title> <mat-panel-title *ngIf="title" class="adf-metadata-properties-title" [title]="title | translate">{{ title | translate }}</mat-panel-title>
<ng-content></ng-content> <ng-content />
</ng-container> </ng-container>
` `
}) })

View File

@ -19,13 +19,11 @@ import { AspectOrientedConfigService } from './aspect-oriented-config.service';
import { AspectOrientedConfig, Property, OrganisedPropertyGroup, PropertyGroupContainer } from '../../interfaces/content-metadata.interfaces'; import { AspectOrientedConfig, Property, OrganisedPropertyGroup, PropertyGroupContainer } from '../../interfaces/content-metadata.interfaces';
describe('AspectOrientedConfigService', () => { describe('AspectOrientedConfigService', () => {
let configService: AspectOrientedConfigService; let configService: AspectOrientedConfigService;
const createConfigService = (configObj: AspectOrientedConfig) => new AspectOrientedConfigService(configObj); const createConfigService = (configObj: AspectOrientedConfig) => new AspectOrientedConfigService(configObj);
describe('reorganiseByConfig', () => { describe('reorganiseByConfig', () => {
interface TestCase { interface TestCase {
name: string; name: string;
config: AspectOrientedConfig; config: AspectOrientedConfig;
@ -51,54 +49,58 @@ describe('AspectOrientedConfigService', () => {
{ {
name: 'One property from One group', name: 'One property from One group',
config: { config: {
berseria: [ 'property1' ] berseria: ['property1']
},
expectations: [{
title: 'Berseria',
properties: [ property1 ]
}]
},
{
name: 'More properties from One group',
config: {
berseria: [ 'property1', 'property2' ]
},
expectations: [{
title: 'Berseria',
properties: [ property1, property2 ]
}]
},
{
name: 'One-one properties from More group',
config: {
berseria: [ 'property1' ],
zestiria: [ 'property3' ]
}, },
expectations: [ expectations: [
{ {
title: 'Berseria', title: 'Berseria',
properties: [ property1 ] properties: [property1]
}
]
},
{
name: 'More properties from One group',
config: {
berseria: ['property1', 'property2']
},
expectations: [
{
title: 'Berseria',
properties: [property1, property2]
}
]
},
{
name: 'One-one properties from More group',
config: {
berseria: ['property1'],
zestiria: ['property3']
},
expectations: [
{
title: 'Berseria',
properties: [property1]
}, },
{ {
title: 'Zestiria', title: 'Zestiria',
properties: [ property3 ] properties: [property3]
} }
] ]
}, },
{ {
name: 'More properties from More groups', name: 'More properties from More groups',
config: { config: {
zestiria: [ 'property4', 'property3' ], zestiria: ['property4', 'property3'],
berseria: [ 'property2', 'property1' ] berseria: ['property2', 'property1']
}, },
expectations: [ expectations: [
{ {
title: 'Zestiria', title: 'Zestiria',
properties: [ property4, property3 ] properties: [property4, property3]
}, },
{ {
title: 'Berseria', title: 'Berseria',
properties: [ property2, property1 ] properties: [property2, property1]
} }
] ]
}, },
@ -106,16 +108,16 @@ describe('AspectOrientedConfigService', () => {
name: 'Wildcard', name: 'Wildcard',
config: { config: {
berseria: '*', berseria: '*',
zestiria: [ 'property4' ] zestiria: ['property4']
}, },
expectations: [ expectations: [
{ {
title: 'Berseria', title: 'Berseria',
properties: [ property1, property2 ] properties: [property1, property2]
}, },
{ {
title: 'Zestiria', title: 'Zestiria',
properties: [ property4 ] properties: [property4]
} }
] ]
}, },
@ -124,29 +126,29 @@ describe('AspectOrientedConfigService', () => {
config: { config: {
berseria: '*', berseria: '*',
'not-existing-group': '*', 'not-existing-group': '*',
zestiria: [ 'property4' ] zestiria: ['property4']
}, },
expectations: [ expectations: [
{ {
title: 'Berseria', title: 'Berseria',
properties: [ property1, property2 ] properties: [property1, property2]
}, },
{ {
title: 'Zestiria', title: 'Zestiria',
properties: [ property4 ] properties: [property4]
} }
] ]
}, },
{ {
name: 'Not existing property', name: 'Not existing property',
config: { config: {
berseria: [ 'not-existing-property' ], berseria: ['not-existing-property'],
zestiria: [ 'property4' ] zestiria: ['property4']
}, },
expectations: [ expectations: [
{ {
title: 'Zestiria', title: 'Zestiria',
properties: [ property4 ] properties: [property4]
} }
] ]
} }
@ -160,7 +162,7 @@ describe('AspectOrientedConfigService', () => {
expect(organisedPropertyGroups.length).toBe(testCase.expectations.length, 'Group count should match'); expect(organisedPropertyGroups.length).toBe(testCase.expectations.length, 'Group count should match');
testCase.expectations.forEach((expectation, i) => { testCase.expectations.forEach((expectation, i) => {
expect(organisedPropertyGroups[i].title).toBe(expectation.title, 'Group\'s title should match' ); expect(organisedPropertyGroups[i].title).toBe(expectation.title, "Group's title should match");
expect(organisedPropertyGroups[i].properties.length).toBe( expect(organisedPropertyGroups[i].properties.length).toBe(
expectation.properties.length, expectation.properties.length,
`Property count for '${organisedPropertyGroups[i].title}' group should match.` `Property count for '${organisedPropertyGroups[i].title}' group should match.`
@ -194,11 +196,11 @@ describe('AspectOrientedConfigService', () => {
expectations: [ expectations: [
{ {
title: 'Berseria', title: 'Berseria',
properties: [ property1, property2 ] properties: [property1, property2]
}, },
{ {
title: 'Zestiria', title: 'Zestiria',
properties: [ property3, property4 ] properties: [property3, property4]
} }
] ]
}; };
@ -208,7 +210,7 @@ describe('AspectOrientedConfigService', () => {
expect(organisedPropertyGroups.length).toBe(testCase.expectations.length, 'Group count should match'); expect(organisedPropertyGroups.length).toBe(testCase.expectations.length, 'Group count should match');
testCase.expectations.forEach((expectation, i) => { testCase.expectations.forEach((expectation, i) => {
expect(organisedPropertyGroups[i].title).toBe(expectation.title, 'Group\'s title should match' ); expect(organisedPropertyGroups[i].title).toBe(expectation.title, "Group's title should match");
expect(organisedPropertyGroups[i].properties.length).toBe( expect(organisedPropertyGroups[i].properties.length).toBe(
expectation.properties.length, expectation.properties.length,
`Property count for '${organisedPropertyGroups[i].title}' group should match.` `Property count for '${organisedPropertyGroups[i].title}' group should match.`
@ -231,11 +233,11 @@ describe('AspectOrientedConfigService', () => {
expectations: [ expectations: [
{ {
title: 'Berseria', title: 'Berseria',
properties: [ property1, property2 ] properties: [property1, property2]
}, },
{ {
title: 'Zestiria', title: 'Zestiria',
properties: [ property3, property4 ] properties: [property3, property4]
} }
] ]
}; };

View File

@ -19,8 +19,7 @@ import { ContentMetadataConfig, OrganisedPropertyGroup, PropertyGroupContainer,
import { getGroup, getProperty } from './property-group-reader'; import { getGroup, getProperty } from './property-group-reader';
export class AspectOrientedConfigService implements ContentMetadataConfig { export class AspectOrientedConfigService implements ContentMetadataConfig {
constructor(private config: any) {}
constructor(private config: any) { }
public isGroupAllowed(groupName: string): boolean { public isGroupAllowed(groupName: string): boolean {
if (this.isIncludeAllEnabled()) { if (this.isIncludeAllEnabled()) {
@ -43,24 +42,23 @@ export class AspectOrientedConfigService implements ContentMetadataConfig {
} }
public appendAllPreset(propertyGroups: PropertyGroupContainer): OrganisedPropertyGroup[] { public appendAllPreset(propertyGroups: PropertyGroupContainer): OrganisedPropertyGroup[] {
const groups = Object.keys(propertyGroups) const groups = Object.keys(propertyGroups).map((groupName) => {
.map((groupName) => { const propertyGroup = propertyGroups[groupName];
const propertyGroup = propertyGroups[groupName]; const properties = propertyGroup.properties;
const properties = propertyGroup.properties;
if (this.isAspectReadOnly(groupName)) { if (this.isAspectReadOnly(groupName)) {
Object.keys(properties).map((propertyName) => this.setReadOnlyProperty(properties[propertyName])); Object.keys(properties).map((propertyName) => this.setReadOnlyProperty(properties[propertyName]));
} }
return Object.assign({}, propertyGroup, { return Object.assign({}, propertyGroup, {
properties: Object.keys(properties).map((propertyName) => { properties: Object.keys(properties).map((propertyName) => {
if (this.isPropertyReadOnly(propertyName)) { if (this.isPropertyReadOnly(propertyName)) {
this.setReadOnlyProperty(properties[propertyName]); this.setReadOnlyProperty(properties[propertyName]);
} }
return properties[propertyName]; return properties[propertyName];
}) })
});
}); });
});
return groups; return groups;
} }
@ -87,7 +85,6 @@ export class AspectOrientedConfigService implements ContentMetadataConfig {
} else { } else {
return readOnlyAspects === propertyGroupName; return readOnlyAspects === propertyGroupName;
} }
} }
public filterExcludedPreset(propertyGroups: OrganisedPropertyGroup[]): OrganisedPropertyGroup[] { public filterExcludedPreset(propertyGroups: OrganisedPropertyGroup[]): OrganisedPropertyGroup[] {

View File

@ -25,19 +25,17 @@ import { ContentMetadataConfig } from '../../interfaces/content-metadata.interfa
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule } from '@angular/common/http';
describe('ContentMetadataConfigFactory', () => { describe('ContentMetadataConfigFactory', () => {
let factory: ContentMetadataConfigFactory; let factory: ContentMetadataConfigFactory;
let appConfig: AppConfigService; let appConfig: AppConfigService;
let config: ContentMetadataConfig; let config: ContentMetadataConfig;
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [HttpClientModule],
HttpClientModule
],
providers: [ providers: [
{ {
provide: LogService, useValue: { provide: LogService,
useValue: {
error: () => {} error: () => {}
} }
} }
@ -48,7 +46,6 @@ describe('ContentMetadataConfigFactory', () => {
}); });
describe('get', () => { describe('get', () => {
let logService: LogService; let logService: LogService;
beforeEach(() => { beforeEach(() => {
@ -57,7 +54,6 @@ describe('ContentMetadataConfigFactory', () => {
}); });
describe('get', () => { describe('get', () => {
it('should get back to default preset if no preset is provided as parameter', () => { it('should get back to default preset if no preset is provided as parameter', () => {
config = factory.get(); config = factory.get();
@ -85,7 +81,6 @@ describe('ContentMetadataConfigFactory', () => {
}); });
describe('set', () => { describe('set', () => {
const setConfig = (presetName: string, presetConfig: any) => { const setConfig = (presetName: string, presetConfig: any) => {
appConfig.config['content-metadata'] = { appConfig.config['content-metadata'] = {
presets: { presets: {
@ -118,5 +113,5 @@ describe('ContentMetadataConfigFactory', () => {
expect(config).toEqual(jasmine.any(LayoutOrientedConfigService)); expect(config).toEqual(jasmine.any(LayoutOrientedConfigService));
}); });
}); });
}); });
}); });

View File

@ -15,26 +15,22 @@
* limitations under the License. * limitations under the License.
*/ */
import { ContentMetadataConfig, OrganisedPropertyGroup, import { ContentMetadataConfig, OrganisedPropertyGroup, PropertyGroupContainer } from '../../interfaces/content-metadata.interfaces';
PropertyGroupContainer
} from '../../interfaces/content-metadata.interfaces';
export class IndifferentConfigService implements ContentMetadataConfig { export class IndifferentConfigService implements ContentMetadataConfig {
isGroupAllowed(): boolean { isGroupAllowed(): boolean {
return true; return true;
} }
reorganiseByConfig(propertyGroups: PropertyGroupContainer): OrganisedPropertyGroup[] { reorganiseByConfig(propertyGroups: PropertyGroupContainer): OrganisedPropertyGroup[] {
return Object.keys(propertyGroups) return Object.keys(propertyGroups).map((groupName) => {
.map((groupName) => { const propertyGroup = propertyGroups[groupName];
const propertyGroup = propertyGroups[groupName]; const properties = propertyGroup.properties;
const properties = propertyGroup.properties;
return Object.assign({}, propertyGroup, { return Object.assign({}, propertyGroup, {
properties: Object.keys(properties).map((propertyName) => properties[propertyName]) properties: Object.keys(properties).map((propertyName) => properties[propertyName])
});
}); });
});
} }
filterExcludedPreset(propertyGroups: OrganisedPropertyGroup[]): OrganisedPropertyGroup[] { filterExcludedPreset(propertyGroups: OrganisedPropertyGroup[]): OrganisedPropertyGroup[] {
@ -42,7 +38,7 @@ export class IndifferentConfigService implements ContentMetadataConfig {
} }
appendAllPreset(): OrganisedPropertyGroup[] { appendAllPreset(): OrganisedPropertyGroup[] {
return[]; return [];
} }
isIncludeAllEnabled(): boolean { isIncludeAllEnabled(): boolean {

View File

@ -25,8 +25,7 @@ import {
import { getProperty } from './property-group-reader'; import { getProperty } from './property-group-reader';
export class LayoutOrientedConfigService implements ContentMetadataConfig { export class LayoutOrientedConfigService implements ContentMetadataConfig {
constructor(private config: any) {}
constructor(private config: any) { }
public isGroupAllowed(groupName: string): boolean { public isGroupAllowed(groupName: string): boolean {
if (this.isIncludeAllEnabled()) { if (this.isIncludeAllEnabled()) {
@ -41,9 +40,9 @@ export class LayoutOrientedConfigService implements ContentMetadataConfig {
const organisedPropertyGroup = layoutBlocks.map((layoutBlock) => { const organisedPropertyGroup = layoutBlocks.map((layoutBlock) => {
const flattenedItems = this.flattenItems(layoutBlock.items); const flattenedItems = this.flattenItems(layoutBlock.items);
const properties = flattenedItems.reduce((props, explodedItem) => { const properties = flattenedItems.reduce((props, explodedItem) => {
const isProperty = typeof explodedItem.property === 'object'; const isProperty = typeof explodedItem.property === 'object';
const propertyName = isProperty ? explodedItem.property.name : explodedItem.property; const propertyName = isProperty ? explodedItem.property.name : explodedItem.property;
let property = getProperty(propertyGroups, explodedItem.groupName, propertyName) || []; let property = getProperty(propertyGroups, explodedItem.groupName, propertyName) || [];
if (isProperty) { if (isProperty) {
property = this.setPropertyTitle(property, explodedItem.property); property = this.setPropertyTitle(property, explodedItem.property);
} }
@ -61,15 +60,14 @@ export class LayoutOrientedConfigService implements ContentMetadataConfig {
} }
public appendAllPreset(propertyGroups: PropertyGroupContainer): OrganisedPropertyGroup[] { public appendAllPreset(propertyGroups: PropertyGroupContainer): OrganisedPropertyGroup[] {
return Object.keys(propertyGroups) return Object.keys(propertyGroups).map((groupName) => {
.map((groupName) => { const propertyGroup = propertyGroups[groupName];
const propertyGroup = propertyGroups[groupName]; const properties = propertyGroup.properties;
const properties = propertyGroup.properties;
return Object.assign({}, propertyGroup, { return Object.assign({}, propertyGroup, {
properties: Object.keys(properties).map((propertyName) => properties[propertyName]) properties: Object.keys(properties).map((propertyName) => properties[propertyName])
});
}); });
});
} }
public filterExcludedPreset(propertyGroups: OrganisedPropertyGroup[]): OrganisedPropertyGroup[] { public filterExcludedPreset(propertyGroups: OrganisedPropertyGroup[]): OrganisedPropertyGroup[] {
@ -88,16 +86,14 @@ export class LayoutOrientedConfigService implements ContentMetadataConfig {
} }
public isIncludeAllEnabled() { public isIncludeAllEnabled() {
const includeAllProperty = this.config const includeAllProperty = this.config.map((config) => config.includeAll).find((includeAll) => includeAll !== undefined);
.map((config) => config.includeAll)
.find((includeAll) => includeAll !== undefined);
return includeAllProperty !== undefined ? includeAllProperty : false; return includeAllProperty !== undefined ? includeAllProperty : false;
} }
private setEditableProperty(propertyGroup: Property | Property[], itemConfig): Property | Property[] { private setEditableProperty(propertyGroup: Property | Property[], itemConfig): Property | Property[] {
if (Array.isArray(propertyGroup)) { if (Array.isArray(propertyGroup)) {
propertyGroup.map((property) => property.editable = itemConfig.editable !== undefined ? itemConfig.editable : true); propertyGroup.forEach((property) => (property.editable = itemConfig.editable !== undefined ? itemConfig.editable : true));
} else { } else {
propertyGroup.editable = itemConfig.editable !== undefined ? itemConfig.editable : true; propertyGroup.editable = itemConfig.editable !== undefined ? itemConfig.editable : true;
} }
@ -107,7 +103,7 @@ export class LayoutOrientedConfigService implements ContentMetadataConfig {
private setPropertyTitle(item: Property | Property[], property: Property): Property | Property[] { private setPropertyTitle(item: Property | Property[], property: Property): Property | Property[] {
if (!Array.isArray(item)) { if (!Array.isArray(item)) {
return { ...item, ...(item.name === property.name && !!property.title) && { title: property.title } }; return { ...item, ...(item.name === property.name && !!property.title && { title: property.title }) };
} }
return item; return item;
} }

View File

@ -31,24 +31,24 @@ import { VersionCompatibilityService } from '../../version-compatibility/version
providedIn: 'root' providedIn: 'root'
}) })
export class ContentTypePropertiesService { export class ContentTypePropertiesService {
constructor(
constructor(private contentTypeService: ContentTypeService, private contentTypeService: ContentTypeService,
private dialog: MatDialog, private dialog: MatDialog,
private versionCompatibilityService: VersionCompatibilityService, private versionCompatibilityService: VersionCompatibilityService,
private propertyGroupTranslatorService: PropertyGroupTranslatorService) { private propertyGroupTranslatorService: PropertyGroupTranslatorService
} ) {}
getContentTypeCardItem(node: Node): Observable<CardViewItem[]> { getContentTypeCardItem(node: Node): Observable<CardViewItem[]> {
if (this.versionCompatibilityService.isVersionSupported('7')) { if (this.versionCompatibilityService.isVersionSupported('7')) {
return this.contentTypeService.getContentTypeByPrefix(node.nodeType). return this.contentTypeService.getContentTypeByPrefix(node.nodeType).pipe(
pipe( map((contentType) => {
map((contentType) => { const contentTypesOptions$ = this.getContentTypesAsSelectOption(contentType);
const contentTypesOptions$ = this.getContentTypesAsSelectOption(contentType); const contentTypeCard = this.buildContentTypeSelectCardModel(contentType.entry.id, contentTypesOptions$);
const contentTypeCard = this.buildContentTypeSelectCardModel(contentType.entry.id, contentTypesOptions$); const filteredProperties = this.getContentTypeSpecificProperties(contentType);
const filteredProperties = this.getContentTypeSpecificProperties(contentType); const propertiesCard = this.buildCardItemsFromPropertyList(filteredProperties, node.properties);
const propertiesCard = this.buildCardItemsFromPropertyList(filteredProperties, node.properties); return [contentTypeCard, ...propertiesCard];
return [contentTypeCard, ...propertiesCard]; })
})); );
} else { } else {
return of([this.buildContentTypeTextCardModel(node.nodeType)]); return of([this.buildContentTypeTextCardModel(node.nodeType)]);
} }
@ -80,7 +80,10 @@ export class ContentTypePropertiesService {
return contentTypeCard; return contentTypeCard;
} }
private buildContentTypeSelectCardModel(currentValue: string, options$: Observable<CardViewSelectItemOption<string>[]>): CardViewSelectItemModel<string> { private buildContentTypeSelectCardModel(
currentValue: string,
options$: Observable<CardViewSelectItemOption<string>[]>
): CardViewSelectItemModel<string> {
const contentTypeCard = new CardViewSelectItemModel({ const contentTypeCard = new CardViewSelectItemModel({
label: 'CORE.METADATA.BASIC.CONTENT_TYPE', label: 'CORE.METADATA.BASIC.CONTENT_TYPE',
value: currentValue, value: currentValue,
@ -100,7 +103,8 @@ export class ContentTypePropertiesService {
map(([contentTypesEntries, currentContentType]) => { map(([contentTypesEntries, currentContentType]) => {
const updatedTypes = this.appendCurrentType(currentContentType, contentTypesEntries); const updatedTypes = this.appendCurrentType(currentContentType, contentTypesEntries);
return updatedTypes.map((contentType) => ({ key: contentType.entry.id, label: contentType.entry.title ?? contentType.entry.id })); return updatedTypes.map((contentType) => ({ key: contentType.entry.id, label: contentType.entry.title ?? contentType.entry.id }));
})); })
);
} }
private appendCurrentType(currentType: TypeEntry, contentTypesEntries: TypeEntry[]): TypeEntry[] { private appendCurrentType(currentType: TypeEntry, contentTypesEntries: TypeEntry[]): TypeEntry[] {

View File

@ -36,14 +36,13 @@ describe('PropertyDescriptorLoaderService', () => {
it('should load the groups passed by paramter', (done) => { it('should load the groups passed by paramter', (done) => {
spyOn(classesApi, 'getClass').and.returnValue(Promise.resolve({})); spyOn(classesApi, 'getClass').and.returnValue(Promise.resolve({}));
service.load(['exif:exif', 'cm:content', 'custom:custom']) service.load(['exif:exif', 'cm:content', 'custom:custom']).subscribe(() => {
.subscribe(() => { expect(classesApi.getClass).toHaveBeenCalledTimes(3);
expect(classesApi.getClass).toHaveBeenCalledTimes(3); expect(classesApi.getClass).toHaveBeenCalledWith('exif_exif');
expect(classesApi.getClass).toHaveBeenCalledWith('exif_exif'); expect(classesApi.getClass).toHaveBeenCalledWith('cm_content');
expect(classesApi.getClass).toHaveBeenCalledWith('cm_content'); expect(classesApi.getClass).toHaveBeenCalledWith('custom_custom');
expect(classesApi.getClass).toHaveBeenCalledWith('custom_custom'); done();
done(); });
});
}); });
it('should merge the forked values', (done) => { it('should merge the forked values', (done) => {

View File

@ -26,29 +26,29 @@ import { ClassesApi } from '@alfresco/js-api';
providedIn: 'root' providedIn: 'root'
}) })
export class PropertyDescriptorsService { export class PropertyDescriptorsService {
private _classesApi: ClassesApi; private _classesApi: ClassesApi;
get classesApi(): ClassesApi { get classesApi(): ClassesApi {
this._classesApi = this._classesApi ?? new ClassesApi(this.alfrescoApiService.getInstance()); this._classesApi = this._classesApi ?? new ClassesApi(this.alfrescoApiService.getInstance());
return this._classesApi; return this._classesApi;
} }
constructor(private alfrescoApiService: AlfrescoApiService) { constructor(private alfrescoApiService: AlfrescoApiService) {}
}
load(groupNames: string[]): Observable<PropertyGroupContainer> { load(groupNames: string[]): Observable<PropertyGroupContainer> {
const groupFetchStreams = groupNames const groupFetchStreams = groupNames
.map((groupName) => groupName.replace(':', '_')) .map((groupName) => groupName.replace(':', '_'))
.map((groupName) => defer(() => this.classesApi.getClass(groupName))); .map((groupName) => defer(() => this.classesApi.getClass(groupName)));
return forkJoin(groupFetchStreams).pipe( return forkJoin(groupFetchStreams).pipe(map(this.convertToObject));
map(this.convertToObject)
);
} }
private convertToObject(propertyGroupsArray: PropertyGroup[]): PropertyGroupContainer { private convertToObject(propertyGroupsArray: PropertyGroup[]): PropertyGroupContainer {
return propertyGroupsArray.reduce((propertyGroups, propertyGroup) => Object.assign({}, propertyGroups, { return propertyGroupsArray.reduce(
[propertyGroup.name]: propertyGroup (propertyGroups, propertyGroup) =>
}), {}); Object.assign({}, propertyGroups, {
[propertyGroup.name]: propertyGroup
}),
{}
);
} }
} }

View File

@ -26,7 +26,6 @@ import { AlfrescoApiService } from '../../services/alfresco-api.service';
providedIn: 'root' providedIn: 'root'
}) })
export class SharedLinksApiService { export class SharedLinksApiService {
error = new Subject<{ statusCode: number; message: string }>(); error = new Subject<{ statusCode: number; message: string }>();
private _sharedLinksApi: SharedlinksApi; private _sharedLinksApi: SharedlinksApi;
@ -35,9 +34,7 @@ export class SharedLinksApiService {
return this._sharedLinksApi; return this._sharedLinksApi;
} }
constructor(private apiService: AlfrescoApiService, constructor(private apiService: AlfrescoApiService, private preferences: UserPreferencesService) {}
private preferences: UserPreferencesService) {
}
/** /**
* Gets shared links available to the current user. * Gets shared links available to the current user.
@ -54,9 +51,7 @@ export class SharedLinksApiService {
const queryOptions = Object.assign({}, defaultOptions, options); const queryOptions = Object.assign({}, defaultOptions, options);
const promise = this.sharedLinksApi.listSharedLinks(queryOptions); const promise = this.sharedLinksApi.listSharedLinks(queryOptions);
return from(promise).pipe( return from(promise).pipe(catchError((err) => of(err)));
catchError((err) => of(err))
);
} }
/** /**
@ -68,11 +63,9 @@ export class SharedLinksApiService {
* @returns The shared link just created * @returns The shared link just created
*/ */
createSharedLinks(nodeId: string, sharedLinkWithExpirySettings?: SharedLinkBodyCreate, options: any = {}): Observable<SharedLinkEntry> { createSharedLinks(nodeId: string, sharedLinkWithExpirySettings?: SharedLinkBodyCreate, options: any = {}): Observable<SharedLinkEntry> {
const promise = this.sharedLinksApi.createSharedLink(sharedLinkWithExpirySettings? sharedLinkWithExpirySettings : { nodeId }, options); const promise = this.sharedLinksApi.createSharedLink(sharedLinkWithExpirySettings ? sharedLinkWithExpirySettings : { nodeId }, options);
return from(promise).pipe( return from(promise).pipe(catchError((err) => of(err)));
catchError((err) => of(err))
);
} }
/** /**
@ -84,8 +77,6 @@ export class SharedLinksApiService {
deleteSharedLink(sharedId: string): Observable<any | Error> { deleteSharedLink(sharedId: string): Observable<any | Error> {
const promise = this.sharedLinksApi.deleteSharedLink(sharedId); const promise = this.sharedLinksApi.deleteSharedLink(sharedId);
return from(promise).pipe( return from(promise).pipe(catchError((err: Error) => of(err)));
catchError((err: Error) => of(err))
);
} }
} }

View File

@ -25,15 +25,13 @@ import { map } from 'rxjs/operators';
providedIn: 'root' providedIn: 'root'
}) })
export class ContentTypeService { export class ContentTypeService {
private _typesApi: TypesApi; private _typesApi: TypesApi;
get typesApi(): TypesApi { get typesApi(): TypesApi {
this._typesApi = this._typesApi ?? new TypesApi(this.alfrescoApiService.getInstance()); this._typesApi = this._typesApi ?? new TypesApi(this.alfrescoApiService.getInstance());
return this._typesApi; return this._typesApi;
} }
constructor(private alfrescoApiService: AlfrescoApiService) { constructor(private alfrescoApiService: AlfrescoApiService) {}
}
getContentTypeByPrefix(prefixedType: string): Observable<TypeEntry> { getContentTypeByPrefix(prefixedType: string): Observable<TypeEntry> {
return from(this.typesApi.getType(prefixedType)); return from(this.typesApi.getType(prefixedType));
@ -45,8 +43,6 @@ export class ContentTypeService {
where, where,
include: ['properties'] include: ['properties']
}; };
return from(this.typesApi.listTypes(opts)).pipe( return from(this.typesApi.listTypes(opts)).pipe(map((result: TypePaging) => result.list.entries));
map((result: TypePaging) => result.list.entries)
);
} }
} }

View File

@ -24,15 +24,13 @@ import { AlfrescoApiService } from '../../../services/alfresco-api.service';
providedIn: 'root' providedIn: 'root'
}) })
export class DownloadZipService { export class DownloadZipService {
private _downloadsApi: DownloadsApi; private _downloadsApi: DownloadsApi;
get downloadsApi(): DownloadsApi { get downloadsApi(): DownloadsApi {
this._downloadsApi = this._downloadsApi ?? new DownloadsApi(this.apiService.getInstance()); this._downloadsApi = this._downloadsApi ?? new DownloadsApi(this.apiService.getInstance());
return this._downloadsApi; return this._downloadsApi;
} }
constructor(private apiService: AlfrescoApiService) { constructor(private apiService: AlfrescoApiService) {}
}
/** /**
* Creates a new download. * Creates a new download.

View File

@ -11,7 +11,7 @@
#{$mat-form-field-hide-placeholder} { #{$mat-form-field-hide-placeholder} {
#{$mat-floating-label} { #{$mat-floating-label} {
padding-top: 11px; padding-top: 20px;
} }
} }

View File

@ -34,7 +34,7 @@
&#{$mat-form-field-hide-placeholder} { &#{$mat-form-field-hide-placeholder} {
#{$mat-floating-label} { #{$mat-floating-label} {
padding-top: 11px; padding-top: 20px;
} }
} }

View File

@ -48,7 +48,7 @@
<img [alt]="'ADF-DATATABLE.EMPTY.DRAG-AND-DROP.TITLE' | translate" class="adf-empty-folder-image" [src]="emptyFolderImageUrl"> <img [alt]="'ADF-DATATABLE.EMPTY.DRAG-AND-DROP.TITLE' | translate" class="adf-empty-folder-image" [src]="emptyFolderImageUrl">
</div> </div>
</adf-empty-list> </adf-empty-list>
<ng-content select="adf-custom-empty-content-template, empty-folder-content"></ng-content> <ng-content select="adf-custom-empty-content-template, empty-folder-content" />
</ng-template> </ng-template>
</adf-no-content-template> </adf-no-content-template>
@ -58,7 +58,7 @@
<mat-icon>error</mat-icon> <mat-icon>error</mat-icon>
<p class="adf-no-permission__template--text">{{ 'ADF-DOCUMENT-LIST.NO_PERMISSION' | translate }}</p> <p class="adf-no-permission__template--text">{{ 'ADF-DOCUMENT-LIST.NO_PERMISSION' | translate }}</p>
</div> </div>
<ng-content select="adf-custom-no-permission-template, no-permission-content"></ng-content> <ng-content select="adf-custom-no-permission-template, no-permission-content" />
</ng-template> </ng-template>
</adf-no-permission-template> </adf-no-permission-template>
@ -72,7 +72,7 @@
[color]="'primary'" [color]="'primary'"
[mode]="'indeterminate'" /> [mode]="'indeterminate'" />
</div> </div>
<ng-content select="adf-custom-loading-content-template"></ng-content> <ng-content select="adf-custom-loading-content-template" />
</ng-template> </ng-template>
</adf-loading-content-template> </adf-loading-content-template>

View File

@ -735,7 +735,7 @@ export class DocumentListComponent extends DataTableSchema implements OnInit, On
} }
private isLinkFolder(node: Node) { private isLinkFolder(node: Node) {
return node.nodeType === 'app:folderlink' && node.properties && node.properties['cm:destination']; return node.nodeType === 'app:folderlink' && node.properties?.['cm:destination'];
} }
private updateCustomSourceData(nodeId: string): void { private updateCustomSourceData(nodeId: string): void {

View File

@ -15,13 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { import { DataColumn, DataRow, DataSorting, DataTableAdapter, ThumbnailService } from '@alfresco/adf-core';
DataColumn,
DataRow,
DataSorting,
DataTableAdapter,
ThumbnailService
} from '@alfresco/adf-core';
import { NodePaging, NodeEntry } from '@alfresco/js-api'; import { NodePaging, NodeEntry } from '@alfresco/js-api';
import { PermissionStyleModel } from './../models/permissions-style.model'; import { PermissionStyleModel } from './../models/permissions-style.model';
import { ShareDataRow } from './share-data-row.model'; import { ShareDataRow } from './share-data-row.model';
@ -57,12 +51,14 @@ export class ShareDataTableAdapter implements DataTableAdapter {
return this._sortingMode; return this._sortingMode;
} }
constructor(private thumbnailService: ThumbnailService, constructor(
private contentService: ContentService, private thumbnailService: ThumbnailService,
schema: DataColumn[] = [], private contentService: ContentService,
sorting?: DataSorting, schema: DataColumn[] = [],
sortingMode: string = 'client', sorting?: DataSorting,
allowDropFiles: boolean = false) { sortingMode: string = 'client',
allowDropFiles: boolean = false
) {
this.rows = []; this.rows = [];
this.columns = schema || []; this.columns = schema || [];
this.sorting = sorting; this.sorting = sorting;
@ -106,7 +102,6 @@ export class ShareDataTableAdapter implements DataTableAdapter {
} }
if (col.key === '$thumbnail') { if (col.key === '$thumbnail') {
if (this.imageResolver) { if (this.imageResolver) {
const resolved = this.imageResolver(row, col); const resolved = this.imageResolver(row, col);
if (resolved) { if (resolved) {
@ -137,7 +132,6 @@ export class ShareDataTableAdapter implements DataTableAdapter {
} }
if (col.type === 'image') { if (col.type === 'image') {
if (this.imageResolver) { if (this.imageResolver) {
const resolved = this.imageResolver(row, col); const resolved = this.imageResolver(row, col);
if (resolved) { if (resolved) {
@ -149,7 +143,6 @@ export class ShareDataTableAdapter implements DataTableAdapter {
return dataRow.cacheValue(col.key, value); return dataRow.cacheValue(col.key, value);
} }
/** /**
* Gets a thumbnail URL for the given document node. * Gets a thumbnail URL for the given document node.
* *
@ -217,14 +210,12 @@ export class ShareDataTableAdapter implements DataTableAdapter {
isSmartFolder(node: any) { isSmartFolder(node: any) {
const nodeAspects = this.getNodeAspectNames(node); const nodeAspects = this.getNodeAspectNames(node);
return nodeAspects.indexOf('smf:customConfigSmartFolder') > -1 || return nodeAspects.indexOf('smf:customConfigSmartFolder') > -1 || nodeAspects.indexOf('smf:systemConfigSmartFolder') > -1;
(nodeAspects.indexOf('smf:systemConfigSmartFolder') > -1);
} }
isRuleFolder(node: any) { isRuleFolder(node: any) {
const nodeAspects = this.getNodeAspectNames(node); const nodeAspects = this.getNodeAspectNames(node);
return nodeAspects.indexOf('rule:rules') > -1 || return nodeAspects.indexOf('rule:rules') > -1;
(nodeAspects.indexOf('rule:rules') > -1);
} }
isALinkFolder(node: any) { isALinkFolder(node: any) {
@ -233,7 +224,7 @@ export class ShareDataTableAdapter implements DataTableAdapter {
} }
private getNodeAspectNames(node: any): any[] { private getNodeAspectNames(node: any): any[] {
return node.entry?.aspectNames ? node.entry.aspectNames : (node.aspectNames ? node.aspectNames : []); return node.entry?.aspectNames ? node.entry.aspectNames : node.aspectNames ? node.aspectNames : [];
} }
private sortRows(rows: DataRow[], sorting: DataSorting) { private sortRows(rows: DataRow[], sorting: DataSorting) {
@ -244,7 +235,6 @@ export class ShareDataTableAdapter implements DataTableAdapter {
const options: Intl.CollatorOptions = {}; const options: Intl.CollatorOptions = {};
if (sorting?.key && rows?.length) { if (sorting?.key && rows?.length) {
if (sorting.key.includes('sizeInBytes') || sorting.key === 'name') { if (sorting.key.includes('sizeInBytes') || sorting.key === 'name') {
options.numeric = true; options.numeric = true;
} }
@ -256,21 +246,19 @@ export class ShareDataTableAdapter implements DataTableAdapter {
let left = a.getValue(sorting.key); let left = a.getValue(sorting.key);
if (left) { if (left) {
left = (left instanceof Date) ? left.valueOf().toString() : left.toString(); left = left instanceof Date ? left.valueOf().toString() : left.toString();
} else { } else {
left = ''; left = '';
} }
let right = b.getValue(sorting.key); let right = b.getValue(sorting.key);
if (right) { if (right) {
right = (right instanceof Date) ? right.valueOf().toString() : right.toString(); right = right instanceof Date ? right.valueOf().toString() : right.toString();
} else { } else {
right = ''; right = '';
} }
return sorting.direction === 'asc' return sorting.direction === 'asc' ? left.localeCompare(right, undefined, options) : right.localeCompare(left, undefined, options);
? left.localeCompare(right, undefined, options)
: right.localeCompare(left, undefined, options);
}); });
} }
} }
@ -283,7 +271,9 @@ export class ShareDataTableAdapter implements DataTableAdapter {
if (nodePaging?.list) { if (nodePaging?.list) {
const nodeEntries: NodeEntry[] = nodePaging.list.entries; const nodeEntries: NodeEntry[] = nodePaging.list.entries;
if (nodeEntries?.length) { if (nodeEntries?.length) {
shareDataRows = nodeEntries.map((item) => new ShareDataRow(item, this.contentService, this.permissionsStyle, this.thumbnailService, this.allowDropFiles)); shareDataRows = nodeEntries.map(
(item) => new ShareDataRow(item, this.contentService, this.permissionsStyle, this.thumbnailService, this.allowDropFiles)
);
if (this.filter) { if (this.filter) {
shareDataRows = shareDataRows.filter(this.filter); shareDataRows = shareDataRows.filter(this.filter);
@ -326,6 +316,6 @@ export class ShareDataTableAdapter implements DataTableAdapter {
} }
getRowByNodeId(nodeId: string): DataRow { getRowByNodeId(nodeId: string): DataRow {
return this.rows.find((row: DataRow) => row.node.entry.id === nodeId); return this.rows.find((row: DataRow) => row.node.entry.id === nodeId);
} }
} }

View File

@ -59,14 +59,14 @@ export enum ContentActionTarget {
export type ContentActionHandler = (obj: any, target?: any, permission?: string) => any; export type ContentActionHandler = (obj: any, target?: any, permission?: string) => any;
export class DocumentActionModel extends ContentActionModel { export class DocumentActionModel extends ContentActionModel {
constructor(json?: any) { constructor(json?: any) {
super(json); super(json);
this.target = 'document'; this.target = 'document';
} }
} }
export class FolderActionModel extends ContentActionModel { export class FolderActionModel extends ContentActionModel {
constructor(json?: any) { constructor(json?: any) {
super(json); super(json);
this.target = 'folder'; this.target = 'folder';
} }

View File

@ -29,17 +29,18 @@ import { NodeActionsService } from './node-actions.service';
providedIn: 'root' providedIn: 'root'
}) })
export class FolderActionsService { export class FolderActionsService {
permissionEvent = new Subject<PermissionModel>(); permissionEvent = new Subject<PermissionModel>();
error = new Subject<Error>(); error = new Subject<Error>();
success = new Subject<string>(); success = new Subject<string>();
private handlers: { [id: string]: ContentActionHandler } = {}; private handlers: { [id: string]: ContentActionHandler } = {};
constructor(private nodeActionsService: NodeActionsService, constructor(
private documentListService: DocumentListService, private nodeActionsService: NodeActionsService,
private contentService: ContentService, private documentListService: DocumentListService,
private translation: TranslationService) { private contentService: ContentService,
private translation: TranslationService
) {
this.setupActionHandlers(); this.setupActionHandlers();
} }
@ -107,36 +108,36 @@ export class FolderActionsService {
} }
private prepareHandlers(actionObservable: Observable<any>, target?: any): void { private prepareHandlers(actionObservable: Observable<any>, target?: any): void {
actionObservable.subscribe( actionObservable.subscribe((fileOperationMessage) => {
(fileOperationMessage) => { if (target && typeof target.reload === 'function') {
if (target && typeof target.reload === 'function') { target.reload();
target.reload(); }
} this.success.next(fileOperationMessage);
this.success.next(fileOperationMessage); }, this.error.next.bind(this.error));
},
this.error.next.bind(this.error)
);
} }
private deleteNode(node: NodeEntry, target?: any, permission?: string): Observable<any> { private deleteNode(node: NodeEntry, target?: any, permission?: string): Observable<any> {
if (this.canExecuteAction(node)) { if (this.canExecuteAction(node)) {
if (this.contentService.hasAllowableOperations(node.entry, permission)) { if (this.contentService.hasAllowableOperations(node.entry, permission)) {
const handlerObservable = this.documentListService.deleteNode(node.entry.id); const handlerObservable = this.documentListService.deleteNode(node.entry.id);
handlerObservable.subscribe(() => { handlerObservable.subscribe(
if (target && typeof target.reload === 'function') { () => {
target.reload(); if (target && typeof target.reload === 'function') {
} target.reload();
}
const message = this.translation.instant('CORE.DELETE_NODE.SINGULAR', { name: node.entry.name }); const message = this.translation.instant('CORE.DELETE_NODE.SINGULAR', { name: node.entry.name });
this.success.next(message); this.success.next(message);
}, () => { },
const message = this.translation.instant('CORE.DELETE_NODE.ERROR_SINGULAR', { name: node.entry.name }); () => {
this.error.next(message); const message = this.translation.instant('CORE.DELETE_NODE.ERROR_SINGULAR', { name: node.entry.name });
}); this.error.next(message);
}
);
return handlerObservable; return handlerObservable;
} else { } else {
this.permissionEvent.next(new PermissionModel({type: 'folder', action: 'delete', permission})); this.permissionEvent.next(new PermissionModel({ type: 'folder', action: 'delete', permission }));
return throwError(new Error('No permission to delete')); return throwError(new Error('No permission to delete'));
} }
} }

View File

@ -24,9 +24,7 @@ import { isAfter } from 'date-fns';
providedIn: 'root' providedIn: 'root'
}) })
export class LockService { export class LockService {
constructor(private authService: AuthenticationService) {}
constructor(private authService: AuthenticationService) {
}
isLocked(node: Node): boolean { isLocked(node: Node): boolean {
let isLocked = false; let isLocked = false;

View File

@ -25,27 +25,27 @@ import { map } from 'rxjs/operators';
providedIn: 'root' providedIn: 'root'
}) })
export class GroupService { export class GroupService {
private _groupsApi: GroupsApi; private _groupsApi: GroupsApi;
get groupsApi(): GroupsApi { get groupsApi(): GroupsApi {
this._groupsApi = this._groupsApi ?? new GroupsApi(this.alfrescoApiService.getInstance()); this._groupsApi = this._groupsApi ?? new GroupsApi(this.alfrescoApiService.getInstance());
return this._groupsApi; return this._groupsApi;
} }
constructor( constructor(private alfrescoApiService: AlfrescoApiService) {}
private alfrescoApiService: AlfrescoApiService
) {
}
async listAllGroupMembershipsForPerson(personId: string, opts?: any, accumulator = []): Promise<GroupEntry[]> { async listAllGroupMembershipsForPerson(personId: string, opts?: any, accumulator = []): Promise<GroupEntry[]> {
const groupsPaginated = await this.groupsApi.listGroupMembershipsForPerson(personId, opts); const groupsPaginated = await this.groupsApi.listGroupMembershipsForPerson(personId, opts);
accumulator = [...accumulator, ...groupsPaginated.list.entries]; accumulator = [...accumulator, ...groupsPaginated.list.entries];
if (groupsPaginated.list.pagination.hasMoreItems) { if (groupsPaginated.list.pagination.hasMoreItems) {
const skip = groupsPaginated.list.pagination.skipCount + groupsPaginated.list.pagination.count; const skip = groupsPaginated.list.pagination.skipCount + groupsPaginated.list.pagination.count;
return this.listAllGroupMembershipsForPerson(personId, { return this.listAllGroupMembershipsForPerson(
maxItems: opts.maxItems, personId,
skipCount: skip {
}, accumulator); maxItems: opts.maxItems,
skipCount: skip
},
accumulator
);
} else { } else {
return accumulator; return accumulator;
} }
@ -59,10 +59,12 @@ export class GroupService {
* @returns Observable<GroupEntry> group for specified id. * @returns Observable<GroupEntry> group for specified id.
*/ */
getGroup(id: string, opts?: ContentIncludeQuery): Observable<GroupEntry> { getGroup(id: string, opts?: ContentIncludeQuery): Observable<GroupEntry> {
return from(this.groupsApi.getGroup(id, opts)).pipe(map((group) => { return from(this.groupsApi.getGroup(id, opts)).pipe(
group.entry.description ||= ''; map((group) => {
return group; group.entry.description ||= '';
})); return group;
})
);
} }
/** /**
@ -73,12 +75,20 @@ export class GroupService {
* @returns Observable<GroupEntry> updated group. * @returns Observable<GroupEntry> updated group.
*/ */
updateGroup(group: Group, opts?: ContentIncludeQuery): Observable<GroupEntry> { updateGroup(group: Group, opts?: ContentIncludeQuery): Observable<GroupEntry> {
return from(this.groupsApi.updateGroup(group.id, { return from(
displayName: group.displayName, this.groupsApi.updateGroup(
description: group.description group.id,
}, opts)).pipe(map((updatedGroup) => { {
updatedGroup.entry.description ||= ''; displayName: group.displayName,
return updatedGroup; description: group.description
})); },
opts
)
).pipe(
map((updatedGroup) => {
updatedGroup.entry.description ||= '';
return updatedGroup;
})
);
} }
} }

View File

@ -17,128 +17,126 @@
/* spellchecker: disable */ /* spellchecker: disable */
export const fakeAuthorityResults: any[] = [{ export const fakeAuthorityResults: any[] = [
entry: { {
aspectNames: [ entry: {
'cm:personDisabled', aspectNames: ['cm:personDisabled', 'cm:ownable', 'cm:preferences'],
'cm:ownable', isFolder: false,
'cm:preferences' search: {
], score: 4.014668
isFolder: false,
search: {
score: 4.014668
},
isFile: false,
name: 'dc103838-645f-43c1-8a2a-bc187e13c343',
location: 'nodes',
id: 'dc103838-645f-43c1-8a2a-bc187e13c343',
nodeType: 'cm:person',
properties: {
'cm:location': 'Tilbury, UK',
'cm:persondescription': {
contentUrl: 'store://2018/4/18/9/30/514bb261-bc61-4502-ad2f-dfafec9ae4eb.bin',
mimetype: 'application/octet-stream',
size: 55,
encoding: 'UTF-8',
locale: 'en_US',
id: 148,
infoUrl: 'contentUrl=store://2018/4/18/9/30/514bb261-bc61-4502-ad2f-dfafec9ae4eb.bin|mimetype=application/octet-stream|size=55|encoding=UTF-8|locale=en_US_'
}, },
'cm:owner': { isFile: false,
id: 'abeecher', name: 'dc103838-645f-43c1-8a2a-bc187e13c343',
displayName: 'Alice Beecher' location: 'nodes',
id: 'dc103838-645f-43c1-8a2a-bc187e13c343',
nodeType: 'cm:person',
properties: {
'cm:location': 'Tilbury, UK',
'cm:persondescription': {
contentUrl: 'store://2018/4/18/9/30/514bb261-bc61-4502-ad2f-dfafec9ae4eb.bin',
mimetype: 'application/octet-stream',
size: 55,
encoding: 'UTF-8',
locale: 'en_US',
id: 148,
infoUrl:
'contentUrl=store://2018/4/18/9/30/514bb261-bc61-4502-ad2f-dfafec9ae4eb.bin|mimetype=application/octet-stream|size=55|encoding=UTF-8|locale=en_US_'
},
'cm:owner': {
id: 'abeecher',
displayName: 'Alice Beecher'
},
'cm:companyaddress2': 'Tilbury',
'cm:userStatus': 'Helping to design the look and feel of the new web site',
'cm:companyaddress1': '200 Butterwick Street',
'cm:telephone': '0112211001100',
'cm:preferenceValues': {
contentUrl: 'store://2018/4/18/9/30/afc39bc9-6bac-4f24-8730-9d9f617a322e.bin',
mimetype: 'text/plain',
size: 709,
encoding: 'UTF-8',
locale: 'en_US',
id: 147,
infoUrl:
'contentUrl=store://2018/4/18/9/30/afc39bc9-6bac-4f24-8730-9d9f617a322e.bin|mimetype=text/plain|size=709|encoding=UTF-8|locale=en_US_'
},
'cm:userName': 'abeecher',
'cm:companyaddress3': 'UK',
'cm:userStatusTime': '2011-02-15T20:20:13.432+0000',
'cm:email': 'abeecher@example.com',
'cm:skype': 'abeecher',
'cm:jobtitle': 'Graphic Designer',
'cm:homeFolderProvider': 'userHomesHomeFolderProvider',
'cm:homeFolder': '242533d8-68e6-4811-bc3d-61ec63c614aa',
'cm:lastName': 'Beecher',
'cm:sizeCurrent': 8382006,
'cm:sizeQuota': -1,
'cm:firstName': 'Alice',
'cm:emailFeedId': 440,
'cm:authorizationStatus': 'NEVER_AUTHORIZED',
'cm:mobile': '0112211001100',
'cm:organization': 'Moresby, Garland and Wedge',
'cm:companypostcode': 'ALF1 SAM1'
}, },
'cm:companyaddress2': 'Tilbury', parentId: '063f5d48-a0b3-4cbf-826c-88a4fbfa3336'
'cm:userStatus': 'Helping to design the look and feel of the new web site', }
'cm:companyaddress1': '200 Butterwick Street', },
'cm:telephone': '0112211001100', {
'cm:preferenceValues': { entry: {
contentUrl: 'store://2018/4/18/9/30/afc39bc9-6bac-4f24-8730-9d9f617a322e.bin', aspectNames: ['cm:ownable', 'cm:preferences'],
mimetype: 'text/plain', isFolder: false,
size: 709, search: {
encoding: 'UTF-8', score: 4.014668
locale: 'en_US',
id: 147,
infoUrl: 'contentUrl=store://2018/4/18/9/30/afc39bc9-6bac-4f24-8730-9d9f617a322e.bin|mimetype=text/plain|size=709|encoding=UTF-8|locale=en_US_'
}, },
'cm:userName': 'abeecher', isFile: false,
'cm:companyaddress3': 'UK', name: 'e320c16b-a763-4a4e-9f22-286ff5d8dca2',
'cm:userStatusTime': '2011-02-15T20:20:13.432+0000', location: 'nodes',
'cm:email': 'abeecher@example.com', id: 'e320c16b-a763-4a4e-9f22-286ff5d8dca2',
'cm:skype': 'abeecher', nodeType: 'cm:person',
'cm:jobtitle': 'Graphic Designer', properties: {
'cm:homeFolderProvider': 'userHomesHomeFolderProvider', 'cm:homeFolderProvider': 'bootstrapHomeFolderProvider',
'cm:homeFolder': '242533d8-68e6-4811-bc3d-61ec63c614aa', 'cm:preferenceValues': {
'cm:lastName': 'Beecher', contentUrl: 'store://2018/4/23/14/42/92bb4aa9-db27-41a4-9804-ddab3cc83d3e.bin',
'cm:sizeCurrent': 8382006, mimetype: 'text/plain',
'cm:sizeQuota': -1, size: 102,
'cm:firstName': 'Alice', encoding: 'UTF-8',
'cm:emailFeedId': 440, locale: 'en',
'cm:authorizationStatus': 'NEVER_AUTHORIZED', id: 313,
'cm:mobile': '0112211001100', infoUrl:
'cm:organization': 'Moresby, Garland and Wedge', 'contentUrl=store://2018/4/23/14/42/92bb4aa9-db27-41a4-9804-ddab3cc83d3e.bin|mimetype=text/plain|size=102|encoding=UTF-8|locale=en_'
'cm:companypostcode': 'ALF1 SAM1' },
}, 'cm:authorizationStatus': 'AUTHORIZED',
parentId: '063f5d48-a0b3-4cbf-826c-88a4fbfa3336' 'cm:homeFolder': 'a20cd541-4ada-4525-9807-9fa0a047d9f4',
'cm:userName': 'admin',
'cm:sizeCurrent': 0,
'cm:email': 'admin@alfresco.com',
'cm:firstName': 'Administrator',
'cm:owner': {
id: 'admin',
displayName: 'Administrator'
}
},
parentId: '063f5d48-a0b3-4cbf-826c-88a4fbfa3336'
}
},
{
entry: {
isFolder: false,
search: {
score: 0.3541112
},
isFile: false,
name: 'GROUP_ALFRESCO_ADMINISTRATORS',
location: 'nodes',
id: 'GROUP_ALFRESCO_ADMINISTRATORS',
nodeType: 'cm:authorityContainer',
properties: {
'cm:authorityName': 'GROUP_ALFRESCO_ADMINISTRATORS'
},
parentId: '030d833e-da8e-4f5c-8ef9-d809638bd04b'
}
} }
}, ];
{
entry: {
aspectNames: [
'cm:ownable',
'cm:preferences'
],
isFolder: false,
search: {
score: 4.014668
},
isFile: false,
name: 'e320c16b-a763-4a4e-9f22-286ff5d8dca2',
location: 'nodes',
id: 'e320c16b-a763-4a4e-9f22-286ff5d8dca2',
nodeType: 'cm:person',
properties: {
'cm:homeFolderProvider': 'bootstrapHomeFolderProvider',
'cm:preferenceValues': {
contentUrl: 'store://2018/4/23/14/42/92bb4aa9-db27-41a4-9804-ddab3cc83d3e.bin',
mimetype: 'text/plain',
size: 102,
encoding: 'UTF-8',
locale: 'en',
id: 313,
infoUrl: 'contentUrl=store://2018/4/23/14/42/92bb4aa9-db27-41a4-9804-ddab3cc83d3e.bin|mimetype=text/plain|size=102|encoding=UTF-8|locale=en_'
},
'cm:authorizationStatus': 'AUTHORIZED',
'cm:homeFolder': 'a20cd541-4ada-4525-9807-9fa0a047d9f4',
'cm:userName': 'admin',
'cm:sizeCurrent': 0,
'cm:email': 'admin@alfresco.com',
'cm:firstName': 'Administrator',
'cm:owner': {
id: 'admin',
displayName: 'Administrator'
}
},
parentId: '063f5d48-a0b3-4cbf-826c-88a4fbfa3336'
}
},
{
entry: {
isFolder: false,
search: {
score: 0.3541112
},
isFile: false,
name: 'GROUP_ALFRESCO_ADMINISTRATORS',
location: 'nodes',
id: 'GROUP_ALFRESCO_ADMINISTRATORS',
nodeType: 'cm:authorityContainer',
properties: {
'cm:authorityName': 'GROUP_ALFRESCO_ADMINISTRATORS'
},
parentId: '030d833e-da8e-4f5c-8ef9-d809638bd04b'
}
}];
export const fakeAuthorityListResult: any = { export const fakeAuthorityListResult: any = {
list: { list: {
@ -168,64 +166,67 @@ export const fakeNameListResult: any = {
lastTxId: 5496 lastTxId: 5496
} }
}, },
entries: [{ entries: [
entry: { {
aspectNames: ['cm:ownable'], entry: {
isFolder: false, aspectNames: ['cm:ownable'],
search: { isFolder: false,
score: 1.0 search: {
}, score: 1.0
isFile: false, },
name: '730cd9b0-5617-4865-aee8-90de1d596997', isFile: false,
location: 'nodes', name: '730cd9b0-5617-4865-aee8-90de1d596997',
id: '730cd9b0-5617-4865-aee8-90de1d596997', location: 'nodes',
nodeType: 'cm:person', id: '730cd9b0-5617-4865-aee8-90de1d596997',
properties: { nodeType: 'cm:person',
'cm:homeFolderProvider': 'userHomesHomeFolderProvider', properties: {
'cm:authorizationStatus': 'NEVER_AUTHORIZED', 'cm:homeFolderProvider': 'userHomesHomeFolderProvider',
'cm:homeFolder': '277f505d-6526-45b1-a7b3-c9bdd66f17f6', 'cm:authorizationStatus': 'NEVER_AUTHORIZED',
'cm:userName': 'test1', 'cm:homeFolder': '277f505d-6526-45b1-a7b3-c9bdd66f17f6',
'cm:lastName': 'lastName1', 'cm:userName': 'test1',
'cm:sizeCurrent': 0, 'cm:lastName': 'lastName1',
'cm:email': 'test1@gmail.com', 'cm:sizeCurrent': 0,
'cm:sizeQuota': 1073741824, 'cm:email': 'test1@gmail.com',
'cm:firstName': 'firstName', 'cm:sizeQuota': 1073741824,
'cm:owner': { 'cm:firstName': 'firstName',
id: 'test1', 'cm:owner': {
displayName: 'firstName lastName1' id: 'test1',
} displayName: 'firstName lastName1'
}, }
parentId: '3e9ce910-a4a0-4531-8f80-7734bece6342' },
parentId: '3e9ce910-a4a0-4531-8f80-7734bece6342'
}
},
{
entry: {
aspectNames: ['cm:ownable'],
isFolder: false,
search: {
score: 1.0
},
isFile: false,
name: '3d1e9e57-505f-431e-bb2b-38ad8d5d2d15',
location: 'nodes',
id: '3d1e9e57-505f-431e-bb2b-38ad8d5d2d15',
nodeType: 'cm:person',
properties: {
'cm:homeFolderProvider': 'userHomesHomeFolderProvider',
'cm:authorizationStatus': 'NEVER_AUTHORIZED',
'cm:homeFolder': '81a07ff0-82fb-4bbb-b869-d5fd92e71e17',
'cm:userName': 'test11',
'cm:lastName': 'lastName2',
'cm:sizeCurrent': 0,
'cm:email': 'test2@gmail.com',
'cm:sizeQuota': -1,
'cm:firstName': 'firstName',
'cm:owner': {
id: 'test11',
displayName: 'firstName lastName2'
}
},
parentId: '3e9ce910-a4a0-4531-8f80-7734bece6342'
}
} }
}, { ]
entry: {
aspectNames: ['cm:ownable'],
isFolder: false,
search: {
score: 1.0
},
isFile: false,
name: '3d1e9e57-505f-431e-bb2b-38ad8d5d2d15',
location: 'nodes',
id: '3d1e9e57-505f-431e-bb2b-38ad8d5d2d15',
nodeType: 'cm:person',
properties: {
'cm:homeFolderProvider': 'userHomesHomeFolderProvider',
'cm:authorizationStatus': 'NEVER_AUTHORIZED',
'cm:homeFolder': '81a07ff0-82fb-4bbb-b869-d5fd92e71e17',
'cm:userName': 'test11',
'cm:lastName': 'lastName2',
'cm:sizeCurrent': 0,
'cm:email': 'test2@gmail.com',
'cm:sizeQuota': -1,
'cm:firstName': 'firstName',
'cm:owner': {
id: 'test11',
displayName: 'firstName lastName2'
}
},
parentId: '3e9ce910-a4a0-4531-8f80-7734bece6342'
}
}]
} }
}; };

View File

@ -21,9 +21,7 @@ import { AppConfigService, StorageService } from '@alfresco/adf-core';
@Injectable() @Injectable()
export class AlfrescoApiServiceMock extends AlfrescoApiService { export class AlfrescoApiServiceMock extends AlfrescoApiService {
constructor(protected appConfig: AppConfigService, protected storageService: StorageService) {
constructor(protected appConfig: AppConfigService,
protected storageService: StorageService) {
super(appConfig, storageService); super(appConfig, storageService);
if (!this.alfrescoApi) { if (!this.alfrescoApi) {
this.initAlfrescoApi(); this.initAlfrescoApi();

View File

@ -18,7 +18,7 @@
import { SearchCategory } from '../search/models/search-category.interface'; import { SearchCategory } from '../search/models/search-category.interface';
export const mockSearchFilterWithoutDisplayedLabelsByField: SearchCategory = { export const mockSearchFilterWithoutDisplayedLabelsByField: SearchCategory = {
id : 'test', id: 'test',
name: 'test', name: 'test',
expanded: false, expanded: false,
enabled: true, enabled: true,
@ -33,7 +33,7 @@ export const mockSearchFilterWithoutDisplayedLabelsByField: SearchCategory = {
}; };
export const mockSearchFilterWithWrongDisplayedLabelsByField: SearchCategory = { export const mockSearchFilterWithWrongDisplayedLabelsByField: SearchCategory = {
id : 'test', id: 'test',
name: 'test', name: 'test',
expanded: false, expanded: false,
enabled: true, enabled: true,
@ -51,7 +51,7 @@ export const mockSearchFilterWithWrongDisplayedLabelsByField: SearchCategory = {
}; };
export const mockSearchFilterWithDisplayedLabelsByField: SearchCategory = { export const mockSearchFilterWithDisplayedLabelsByField: SearchCategory = {
id : 'test', id: 'test',
name: 'test', name: 'test',
expanded: false, expanded: false,
enabled: true, enabled: true,

View File

@ -27,10 +27,13 @@ export const fakeNodeWithCreatePermission = new Node({
path: { path: {
name: '/Company Home/User Homes', name: '/Company Home/User Homes',
isComplete: true, isComplete: true,
elements: [{ elements: [
id: '94acfc73-7014-4475-9bd9-93a2162f0f8c', {
name: 'Company Home' id: '94acfc73-7014-4475-9bd9-93a2162f0f8c',
}, { id: '55052317-7e59-4058-8e07-769f41e615e1', name: 'User Homes' }] name: 'Company Home'
},
{ id: '55052317-7e59-4058-8e07-769f41e615e1', name: 'User Homes' }
]
}, },
isFolder: true, isFolder: true,
modifiedByUser: { id: 'Test', displayName: 'Test' }, modifiedByUser: { id: 'Test', displayName: 'Test' },
@ -51,10 +54,13 @@ export const fakeNodeWithNoPermission = new Node({
path: { path: {
name: '/Company Home/User Homes', name: '/Company Home/User Homes',
isComplete: true, isComplete: true,
elements: [{ elements: [
id: '94acfc73-7014-4475-9bd9-93a2162f0f8c', {
name: 'Company Home' id: '94acfc73-7014-4475-9bd9-93a2162f0f8c',
}, { id: '55052317-7e59-4058-8e07-769f41e615e1', name: 'User Homes' }] name: 'Company Home'
},
{ id: '55052317-7e59-4058-8e07-769f41e615e1', name: 'User Homes' }
]
}, },
isFolder: true, isFolder: true,
modifiedByUser: { id: 'Test', displayName: 'Test' }, modifiedByUser: { id: 'Test', displayName: 'Test' },
@ -72,36 +78,41 @@ export const fakeNodeAnswerWithEntries = {
skipCount: 10, skipCount: 10,
maxItems: 10 maxItems: 10
}, },
entries: [{ entries: [
entry: { {
isFile: true, entry: {
createdByUser: { id: 'admin', displayName: 'Administrator' }, isFile: true,
modifiedAt: '2017-05-24T15:08:55.640Z', createdByUser: { id: 'admin', displayName: 'Administrator' },
nodeType: 'cm:content', modifiedAt: '2017-05-24T15:08:55.640Z',
content: { nodeType: 'cm:content',
mimeType: 'application/rtf', content: {
mimeTypeName: 'Rich Text Format', mimeType: 'application/rtf',
sizeInBytes: 14530, mimeTypeName: 'Rich Text Format',
encoding: 'UTF-8' sizeInBytes: 14530,
}, encoding: 'UTF-8'
parentId: 'd124de26-6ba0-4f40-8d98-4907da2d337a', },
createdAt: '2017-05-24T15:08:55.640Z', parentId: 'd124de26-6ba0-4f40-8d98-4907da2d337a',
path: { createdAt: '2017-05-24T15:08:55.640Z',
name: '/Company Home/Guest Home', path: {
isComplete: true, name: '/Company Home/Guest Home',
elements: [{ isComplete: true,
id: '94acfc73-7014-4475-9bd9-93a2162f0f8c', elements: [
name: 'Company Home' {
}, { id: 'd124de26-6ba0-4f40-8d98-4907da2d337a', name: 'Guest Home' }] id: '94acfc73-7014-4475-9bd9-93a2162f0f8c',
}, name: 'Company Home'
isFolder: false, },
modifiedByUser: { id: 'admin', displayName: 'Administrator' }, { id: 'd124de26-6ba0-4f40-8d98-4907da2d337a', name: 'Guest Home' }
name: 'b_txt_file.rtf', ]
id: '67b80f77-dbca-4f58-be6c-71b9dd61ea53', },
properties: { 'cm:versionLabel': '1.0', 'cm:versionType': 'MAJOR' }, isFolder: false,
allowableOperations: ['delete', 'update'] modifiedByUser: { id: 'admin', displayName: 'Administrator' },
name: 'b_txt_file.rtf',
id: '67b80f77-dbca-4f58-be6c-71b9dd61ea53',
properties: { 'cm:versionLabel': '1.0', 'cm:versionType': 'MAJOR' },
allowableOperations: ['delete', 'update']
}
} }
}] ]
} }
}; };
@ -127,34 +138,38 @@ export const fakeGetSitesAnswer = {
skipCount: 0, skipCount: 0,
maxItems: 20 maxItems: 20
}, },
entries: [{ entries: [
entry: { {
role: 'SiteManager', entry: {
visibility: 'PRIVATE', role: 'SiteManager',
guid: 'ac65fdbe-0c79-4f67-bd6a-b89a2768561b', visibility: 'PRIVATE',
id: 'admin-site', guid: 'ac65fdbe-0c79-4f67-bd6a-b89a2768561b',
preset: 'site-dashboard', id: 'admin-site',
title: 'Admin Site' preset: 'site-dashboard',
title: 'Admin Site'
}
},
{
entry: {
role: 'SiteManager',
visibility: 'PUBLIC',
guid: 'b4cff62a-664d-4d45-9302-98723eac1319',
description: 'This is a Sample Alfresco Team site.',
id: 'swsdp',
preset: 'site-dashboard',
title: 'Sample: Web Site Design Project'
}
},
{
entry: {
visibility: 'PUBLIC',
guid: 'af36cf8f-d43c-4a4b-84e6-d1b03e3a2ce5',
id: 'test-site',
preset: 'site-dashboard',
title: 'Test Site'
}
} }
}, { ]
entry: {
role: 'SiteManager',
visibility: 'PUBLIC',
guid: 'b4cff62a-664d-4d45-9302-98723eac1319',
description: 'This is a Sample Alfresco Team site.',
id: 'swsdp',
preset: 'site-dashboard',
title: 'Sample: Web Site Design Project'
}
}, {
entry: {
visibility: 'PUBLIC',
guid: 'af36cf8f-d43c-4a4b-84e6-d1b03e3a2ce5',
id: 'test-site',
preset: 'site-dashboard',
title: 'Test Site'
}
}]
} }
}; };
@ -167,30 +182,39 @@ export const fakeGetSiteMembership = {
skipCount: 0, skipCount: 0,
maxItems: 20 maxItems: 20
}, },
entries: [{ entries: [
entry: { {
site: { entry: {
site: {
role: 'SiteManager',
visibility: 'PRIVATE',
guid: 'ac65fdbe-0c79-4f67-bd6a-b89a2768561b',
id: 'admin-site',
preset: 'site-dashboard',
title: 'Admin Site'
},
role: 'SiteManager', role: 'SiteManager',
visibility: 'PRIVATE',
guid: 'ac65fdbe-0c79-4f67-bd6a-b89a2768561b', guid: 'ac65fdbe-0c79-4f67-bd6a-b89a2768561b',
id: 'admin-site', id: 'admin-site'
preset: 'site-dashboard', }
title: 'Admin Site' },
}, role: 'SiteManager', guid: 'ac65fdbe-0c79-4f67-bd6a-b89a2768561b', id: 'admin-site' {
} entry: {
}, { site: {
entry: { role: 'SiteManager',
site: { visibility: 'PUBLIC',
guid: 'b4cff62a-664d-4d45-9302-98723eac1319',
description: 'This is a Sample Alfresco Team site.',
id: 'swsdp',
preset: 'site-dashboard',
title: 'Sample: Web Site Design Project'
},
role: 'SiteManager', role: 'SiteManager',
visibility: 'PUBLIC',
guid: 'b4cff62a-664d-4d45-9302-98723eac1319', guid: 'b4cff62a-664d-4d45-9302-98723eac1319',
description: 'This is a Sample Alfresco Team site.', id: 'swsdp'
id: 'swsdp', }
preset: 'site-dashboard',
title: 'Sample: Web Site Design Project'
}, role: 'SiteManager', guid: 'b4cff62a-664d-4d45-9302-98723eac1319', id: 'swsdp'
} }
}] ]
} }
}; };
@ -202,17 +226,24 @@ export const fakeNodePaging: NodePaging = {
totalItems: 5, totalItems: 5,
skipCount: 0, skipCount: 0,
maxItems: 100 maxItems: 100
}, entries: [{ },
entry: fakeNodeWithNoPermission entries: [
}, { {
entry: fakeNodeWithNoPermission entry: fakeNodeWithNoPermission
}, { },
entry: fakeNodeWithNoPermission {
}, { entry: fakeNodeWithNoPermission
entry: fakeNodeWithNoPermission },
}, { {
entry: fakeNodeWithNoPermission entry: fakeNodeWithNoPermission
}] },
{
entry: fakeNodeWithNoPermission
},
{
entry: fakeNodeWithNoPermission
}
]
} }
}; };
@ -232,10 +263,13 @@ export const mockNode1 = new Node({
path: { path: {
name: '/Company Home/Guest Home', name: '/Company Home/Guest Home',
isComplete: true, isComplete: true,
elements: [{ elements: [
id: '94acfc73-7014-4475-9bd9-93a2162f0f8c', {
name: 'Company Home' id: '94acfc73-7014-4475-9bd9-93a2162f0f8c',
}, { id: 'd124de26-6ba0-4f40-8d98-4907da2d337a', name: 'Guest Home' }] name: 'Company Home'
},
{ id: 'd124de26-6ba0-4f40-8d98-4907da2d337a', name: 'Guest Home' }
]
}, },
isFolder: false, isFolder: false,
modifiedByUser: { id: 'admin', displayName: 'Administrator' }, modifiedByUser: { id: 'admin', displayName: 'Administrator' },
@ -261,10 +295,13 @@ export const mockNode2 = new Node({
path: { path: {
name: '/Company Home/Guest Home', name: '/Company Home/Guest Home',
isComplete: true, isComplete: true,
elements: [{ elements: [
id: '94acfc73-7014-4475-9bd9-93a2162f0f8c', {
name: 'Company Home' id: '94acfc73-7014-4475-9bd9-93a2162f0f8c',
}, { id: 'd124de26-6ba0-4f40-8d98-4907da2d337a', name: 'Guest Home' }] name: 'Company Home'
},
{ id: 'd124de26-6ba0-4f40-8d98-4907da2d337a', name: 'Guest Home' }
]
}, },
isFolder: false, isFolder: false,
modifiedByUser: { id: 'admin', displayName: 'Administrator' }, modifiedByUser: { id: 'admin', displayName: 'Administrator' },
@ -290,10 +327,13 @@ export const mockNode3 = new Node({
path: { path: {
name: '/Company Home/Guest Home', name: '/Company Home/Guest Home',
isComplete: true, isComplete: true,
elements: [{ elements: [
id: '94acfc73-7014-4475-9bd9-93a2162f0f8c', {
name: 'Company Home' id: '94acfc73-7014-4475-9bd9-93a2162f0f8c',
}, { id: 'd124de26-6ba0-4f40-8d98-4907da2d337a', name: 'Guest Home' }] name: 'Company Home'
},
{ id: 'd124de26-6ba0-4f40-8d98-4907da2d337a', name: 'Guest Home' }
]
}, },
isFolder: false, isFolder: false,
modifiedByUser: { id: 'admin', displayName: 'Administrator' }, modifiedByUser: { id: 'admin', displayName: 'Administrator' },
@ -320,12 +360,17 @@ export const mockNodePagingWithPreselectedNodes: NodePaging = {
totalItems: 5, totalItems: 5,
skipCount: 0, skipCount: 0,
maxItems: 100 maxItems: 100
}, entries: [{ },
entry: mockNode1 entries: [
}, { {
entry: mockNode2 entry: mockNode1
}, { },
entry: mockNode3 {
}] entry: mockNode2
},
{
entry: mockNode3
}
]
} }
}; };

View File

@ -24,15 +24,12 @@ import { Component } from '@angular/core';
<span id="update-notification" *ngIf="updatedNode"> NODE UPDATED </span> <span id="update-notification" *ngIf="updatedNode"> NODE UPDATED </span>
` `
}) })
export class SimpleInheritedPermissionTestComponent { export class SimpleInheritedPermissionTestComponent {
message: string = ''; message: string = '';
nodeId: string = 'fake-node-id'; nodeId: string = 'fake-node-id';
updatedNode: boolean = false; updatedNode: boolean = false;
constructor() { constructor() {}
}
onUpdate(node: any) { onUpdate(node: any) {
this.updatedNode = node.permissions?.isInheritanceEnabled ?? false; this.updatedNode = node.permissions?.isInheritanceEnabled ?? false;

View File

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
export const mockNode: any = ({ export const mockNode: any = {
isFile: true, isFile: true,
createdByUser: { id: 'admin', displayName: 'Administrator' }, createdByUser: { id: 'admin', displayName: 'Administrator' },
modifiedAt: '2017-05-24T15:08:55.640Z', modifiedAt: '2017-05-24T15:08:55.640Z',
@ -31,10 +31,13 @@ export const mockNode: any = ({
path: { path: {
name: '/Company Home/Guest Home', name: '/Company Home/Guest Home',
isComplete: true, isComplete: true,
elements: [{ elements: [
id: '94acfc73-7014-4475-9bd9-93a2162f0f8c', {
name: 'Company Home' id: '94acfc73-7014-4475-9bd9-93a2162f0f8c',
}, { id: 'd124de26-6ba0-4f40-8d98-4907da2d337a', name: 'Guest Home' }] name: 'Company Home'
},
{ id: 'd124de26-6ba0-4f40-8d98-4907da2d337a', name: 'Guest Home' }
]
}, },
isFolder: false, isFolder: false,
modifiedByUser: { id: 'admin', displayName: 'Administrator' }, modifiedByUser: { id: 'admin', displayName: 'Administrator' },
@ -42,7 +45,7 @@ export const mockNode: any = ({
id: '70e1cc6a-6918-468a-b84a-1048093b06fd', id: '70e1cc6a-6918-468a-b84a-1048093b06fd',
properties: { 'cm:versionLabel': '1.0', 'cm:versionType': 'MAJOR' }, properties: { 'cm:versionLabel': '1.0', 'cm:versionType': 'MAJOR' },
allowableOperations: ['delete', 'update'] allowableOperations: ['delete', 'update']
}); };
export const mockFile = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); export const mockFile = new File(['fakefake'], 'file-fake.png', { type: 'image/png' });
@ -59,21 +62,13 @@ export const mockNewVersionUploaderData: any = {
modifiedAt: '2022-05-24T10:19:43.544Z', modifiedAt: '2022-05-24T10:19:43.544Z',
nodeType: 'cm:content', nodeType: 'cm:content',
content: { content: {
mimeType: mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
mimeTypeName: 'Microsoft Word 2007', mimeTypeName: 'Microsoft Word 2007',
sizeInBytes: 11887, sizeInBytes: 11887,
encoding: 'UTF-8' encoding: 'UTF-8'
}, },
parentId: '422538ca-ea4b-4086-83f9-b36e4521ec7f', parentId: '422538ca-ea4b-4086-83f9-b36e4521ec7f',
aspectNames: [ aspectNames: ['rn:renditioned', 'cm:versionable', 'cm:titled', 'cm:auditable', 'cm:author', 'cm:thumbnailModification'],
'rn:renditioned',
'cm:versionable',
'cm:titled',
'cm:auditable',
'cm:author',
'cm:thumbnailModification'
],
createdAt: '2022-05-24T07:26:44.429Z', createdAt: '2022-05-24T07:26:44.429Z',
isFolder: false, isFolder: false,
modifiedByUser: { modifiedByUser: {
@ -101,21 +96,13 @@ export const mockNewVersionUploaderData: any = {
modifiedAt: '2022-05-24T07:26:45.337Z', modifiedAt: '2022-05-24T07:26:45.337Z',
nodeType: 'cm:content', nodeType: 'cm:content',
content: { content: {
mimeType: mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
mimeTypeName: 'Microsoft Word 2007', mimeTypeName: 'Microsoft Word 2007',
sizeInBytes: 11949, sizeInBytes: 11949,
encoding: 'UTF-8' encoding: 'UTF-8'
}, },
parentId: '422538ca-ea4b-4086-83f9-b36e4521ec7f', parentId: '422538ca-ea4b-4086-83f9-b36e4521ec7f',
aspectNames: [ aspectNames: ['rn:renditioned', 'cm:versionable', 'cm:titled', 'cm:auditable', 'cm:author', 'cm:thumbnailModification'],
'rn:renditioned',
'cm:versionable',
'cm:titled',
'cm:auditable',
'cm:author',
'cm:thumbnailModification'
],
createdAt: '2022-05-24T07:26:44.429Z', createdAt: '2022-05-24T07:26:44.429Z',
path: { path: {
name: '/Company Home/User Homes/hruser', name: '/Company Home/User Homes/hruser',
@ -155,13 +142,7 @@ export const mockNewVersionUploaderData: any = {
accessStatus: 'ALLOWED' accessStatus: 'ALLOWED'
} }
], ],
settable: [ settable: ['Contributor', 'Collaborator', 'Coordinator', 'Editor', 'Consumer'],
'Contributor',
'Collaborator',
'Coordinator',
'Editor',
'Consumer'
],
isInheritanceEnabled: true isInheritanceEnabled: true
}, },
modifiedByUser: { modifiedByUser: {

View File

@ -100,16 +100,11 @@ export const simpleCategories: SearchCategory[] = [
} }
} }
} }
]; ];
export const searchFilter = { export const searchFilter = {
'app:fields': [ 'app:fields': ['cm:name'],
'cm:name' include: ['allowableOperations'],
],
include: [
'allowableOperations'
],
sorting: { sorting: {
options: [ options: [
{ {
@ -412,8 +407,10 @@ export const mockSearchResult = {
label: 'SEARCH.FACET_QUERIES.MIMETYPE', label: 'SEARCH.FACET_QUERIES.MIMETYPE',
filterQuery: 'content.mimetype:text/html', filterQuery: 'content.mimetype:text/html',
metrics: [{ type: 'count', value: { count: 13 } }] metrics: [{ type: 'count', value: { count: 13 } }]
}] }
}, { ]
},
{
type: 'query', type: 'query',
label: 'Size facet queries', label: 'Size facet queries',
buckets: [ buckets: [
@ -421,60 +418,75 @@ export const mockSearchResult = {
label: 'my1', label: 'my1',
filterQuery: 'content.size:[111111 TO MAX]', filterQuery: 'content.size:[111111 TO MAX]',
metrics: [{ type: 'count', value: { count: 806 } }] metrics: [{ type: 'count', value: { count: 806 } }]
}, { },
{
label: 'my3', label: 'my3',
filterQuery: 'content.size:[333333 TO MAX]', filterQuery: 'content.size:[333333 TO MAX]',
metrics: [{ type: 'count', value: { count: 669 } }] metrics: [{ type: 'count', value: { count: 669 } }]
}, { },
{
label: 'my2', label: 'my2',
filterQuery: 'content.size:[222222 TO MAX]', filterQuery: 'content.size:[222222 TO MAX]',
metrics: [{ type: 'count', value: { count: 691 } }] metrics: [{ type: 'count', value: { count: 691 } }]
}, { },
{
label: 'my5', label: 'my5',
filterQuery: 'content.size:[5555 TO MAX]', filterQuery: 'content.size:[5555 TO MAX]',
metrics: [{ type: 'count', value: { count: 1866 } }] metrics: [{ type: 'count', value: { count: 1866 } }]
}, { },
{
label: 'my4', label: 'my4',
filterQuery: 'content.size:[444444 TO MAX]', filterQuery: 'content.size:[444444 TO MAX]',
metrics: [{ type: 'count', value: { count: 665 } }] metrics: [{ type: 'count', value: { count: 665 } }]
}, { },
{
label: 'my7', label: 'my7',
filterQuery: 'content.size:[777777 TO MAX]', filterQuery: 'content.size:[777777 TO MAX]',
metrics: [{ type: 'count', value: { count: 641 } }] metrics: [{ type: 'count', value: { count: 641 } }]
}, { },
{
label: 'SEARCH.FACET_QUERIES.SMALL', label: 'SEARCH.FACET_QUERIES.SMALL',
filterQuery: 'content.size:[10240 TO 102400]', filterQuery: 'content.size:[10240 TO 102400]',
metrics: [{ type: 'count', value: { count: 526 } }] metrics: [{ type: 'count', value: { count: 526 } }]
}, { },
{
label: 'my6', label: 'my6',
filterQuery: 'content.size:[666666 TO MAX]', filterQuery: 'content.size:[666666 TO MAX]',
metrics: [{ type: 'count', value: { count: 652 } }] metrics: [{ type: 'count', value: { count: 652 } }]
}, { },
{
label: 'SEARCH.FACET_QUERIES.XTRALARGE', label: 'SEARCH.FACET_QUERIES.XTRALARGE',
filterQuery: 'content.size:[16777216 TO 134217728]', filterQuery: 'content.size:[16777216 TO 134217728]',
metrics: [{ type: 'count', value: { count: 617 } }] metrics: [{ type: 'count', value: { count: 617 } }]
}, { },
{
label: 'my8', label: 'my8',
filterQuery: 'content.size:[888888 TO MAX]', filterQuery: 'content.size:[888888 TO MAX]',
metrics: [{ type: 'count', value: { count: 641 } }] metrics: [{ type: 'count', value: { count: 641 } }]
}, { },
{
label: 'SEARCH.FACET_QUERIES.XXTRALARGE', label: 'SEARCH.FACET_QUERIES.XXTRALARGE',
filterQuery: 'content.size:[134217728 TO MAX]', filterQuery: 'content.size:[134217728 TO MAX]',
metrics: [{ type: 'count', value: { count: 0 } }] metrics: [{ type: 'count', value: { count: 0 } }]
}, { },
{
label: 'SEARCH.FACET_QUERIES.MEDIUM', label: 'SEARCH.FACET_QUERIES.MEDIUM',
filterQuery: 'content.size:[102400 TO 1048576]', filterQuery: 'content.size:[102400 TO 1048576]',
metrics: [{ type: 'count', value: { count: 630 } }] metrics: [{ type: 'count', value: { count: 630 } }]
}, { },
{
label: 'SEARCH.FACET_QUERIES.LARGE', label: 'SEARCH.FACET_QUERIES.LARGE',
filterQuery: 'content.size:[1048576 TO 16777216]', filterQuery: 'content.size:[1048576 TO 16777216]',
metrics: [{ type: 'count', value: { count: 23 } }] metrics: [{ type: 'count', value: { count: 23 } }]
}, { },
{
label: 'Extra Small', label: 'Extra Small',
filterQuery: 'content.size:[0 TO 10240]', filterQuery: 'content.size:[0 TO 10240]',
metrics: [{ type: 'count', value: { count: 10239 } }] metrics: [{ type: 'count', value: { count: 10239 } }]
}] }
}, { ]
},
{
type: 'query', type: 'query',
label: 'SEARCH.FACET_QUERIES.MY_FACET_QUERIES', label: 'SEARCH.FACET_QUERIES.MY_FACET_QUERIES',
buckets: [ buckets: [
@ -482,37 +494,45 @@ export const mockSearchResult = {
label: 'SEARCH.FACET_QUERIES.CREATED_THIS_YEAR', label: 'SEARCH.FACET_QUERIES.CREATED_THIS_YEAR',
filterQuery: 'created:2019', filterQuery: 'created:2019',
metrics: [{ type: 'count', value: { count: 0 } }] metrics: [{ type: 'count', value: { count: 0 } }]
}] }
]
}, },
{ {
type: 'field', type: 'field',
label: 'SEARCH.FACET_FIELDS.SIZE', label: 'SEARCH.FACET_FIELDS.SIZE',
buckets: [] buckets: []
}, { },
{
type: 'field', type: 'field',
label: 'SEARCH.FACET_FIELDS.CREATED', label: 'SEARCH.FACET_FIELDS.CREATED',
buckets: [] buckets: []
}, { },
{
type: 'field', type: 'field',
label: 'SEARCH.FACET_FIELDS.TYPE', label: 'SEARCH.FACET_FIELDS.TYPE',
buckets: [] buckets: []
}, { },
{
type: 'field', type: 'field',
label: 'SEARCH.FACET_FIELDS.MODIFIER', label: 'SEARCH.FACET_FIELDS.MODIFIER',
buckets: [] buckets: []
}, { },
{
type: 'field', type: 'field',
label: 'SEARCH.FACET_FIELDS.CREATOR', label: 'SEARCH.FACET_FIELDS.CREATOR',
buckets: [] buckets: []
}, { },
{
type: 'interval', type: 'interval',
label: 'TheModified', label: 'TheModified',
buckets: [] buckets: []
}, { },
{
type: 'interval', type: 'interval',
label: 'The Created', label: 'The Created',
buckets: [] buckets: []
}] }
]
} }
} }
}; };
@ -609,29 +629,23 @@ export const sizeOptions = [
} }
]; ];
export const filteredResult = [ export const filteredResult = ['my1 (806)', 'my2 (691)', 'my3 (669)', 'my4 (665)', 'my5 (1866)'];
'my1 (806)',
'my2 (691)',
'my3 (669)',
'my4 (665)',
'my5 (1866)'
];
export const mockContentSizeResponseBucket = { export const mockContentSizeResponseBucket = {
label: '5875', label: '5875',
filterQuery: 'content.size:5875', filterQuery: 'content.size:5875',
metrics: [ metrics: [
{ {
type: 'count', type: 'count',
value: { value: {
count: 364 count: 364
}
} }
] }
}; ]
};
export const getMockSearchResultWithResponseBucket = () => { export const getMockSearchResultWithResponseBucket = () => {
const cloneResult = JSON.parse(JSON.stringify( mockSearchResult)); const cloneResult = JSON.parse(JSON.stringify(mockSearchResult));
cloneResult.list.context.facets[3].buckets.push(mockContentSizeResponseBucket); cloneResult.list.context.facets[3].buckets.push(mockContentSizeResponseBucket);
return cloneResult; return cloneResult;
}; };

View File

@ -1,4 +1,6 @@
.adf-new-version-uploader-dialog { .adf-new-version-uploader-dialog {
display: block;
&-list { &-list {
height: 400px; height: 400px;
} }
@ -33,6 +35,7 @@
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
color: var(--adf-theme-foreground-text-color-054); color: var(--adf-theme-foreground-text-color-054);
-webkit-font-smoothing: antialiased;
button { button {
text-transform: uppercase; text-transform: uppercase;

View File

@ -40,7 +40,10 @@ import { VersionListComponent } from '../version-manager/version-list.component'
], ],
templateUrl: './new-version-uploader.dialog.html', templateUrl: './new-version-uploader.dialog.html',
styleUrls: ['./new-version-uploader.dialog.scss'], styleUrls: ['./new-version-uploader.dialog.scss'],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None,
host: {
class: 'adf-new-version-uploader-dialog'
}
}) })
export class NewVersionUploaderDialogComponent implements OnInit { export class NewVersionUploaderDialogComponent implements OnInit {
/** /**

View File

@ -46,31 +46,33 @@ export const fakeContentComments = {
skipCount: 0, skipCount: 0,
maxItems: 100 maxItems: 100
}, },
entries: [{ entries: [
entry: { {
createdAt: '2018-03-27T10:55:45.725+0000', entry: {
createdBy: fakeUser1, createdAt: '2018-03-27T10:55:45.725+0000',
edited: false, createdBy: fakeUser1,
modifiedAt: '2018-03-27T10:55:45.725+0000', edited: false,
canEdit: true, modifiedAt: '2018-03-27T10:55:45.725+0000',
modifiedBy: fakeUser1, canEdit: true,
canDelete: true, modifiedBy: fakeUser1,
id: '35a0cea7-b6d0-4abc-9030-f4e461dd1ac7', canDelete: true,
content: 'fake-message-1' id: '35a0cea7-b6d0-4abc-9030-f4e461dd1ac7',
content: 'fake-message-1'
}
},
{
entry: {
createdAt: '2018-03-27T10:55:45.725+0000',
createdBy: fakeUser2,
edited: false,
modifiedAt: '2018-03-27T10:55:45.725+0000',
canEdit: true,
modifiedBy: fakeUser2,
canDelete: true,
id: '35a0cea7-b6d0-4abc-9030-f4e461dd1ac7',
content: 'fake-message-2'
}
} }
}, {
entry: {
createdAt: '2018-03-27T10:55:45.725+0000',
createdBy: fakeUser2,
edited: false,
modifiedAt: '2018-03-27T10:55:45.725+0000',
canEdit: true,
modifiedBy: fakeUser2,
canDelete: true,
id: '35a0cea7-b6d0-4abc-9030-f4e461dd1ac7',
content: 'fake-message-2'
}
}
] ]
} }
}; };
@ -146,62 +148,62 @@ export const getDateXMinutesAgo = (minutes: number) => new Date(new Date().getTi
export const commentsNodeData: CommentModel[] = [ export const commentsNodeData: CommentModel[] = [
new CommentModel({ new CommentModel({
id: 1, id: 1,
message: `I've done this component, is it cool?`, message: `I've done this component, is it cool?`,
created: getDateXMinutesAgo(30), created: getDateXMinutesAgo(30),
createdBy: new User(johnDoe), createdBy: new User(johnDoe),
isSelected: false isSelected: false
}), }),
new CommentModel({ new CommentModel({
id: 2, id: 2,
message: 'Yeah', message: 'Yeah',
created: getDateXMinutesAgo(15), created: getDateXMinutesAgo(15),
createdBy: new User(janeEod), createdBy: new User(janeEod),
isSelected: false isSelected: false
}), }),
new CommentModel({ new CommentModel({
id: 3, id: 3,
message: '+1', message: '+1',
created: getDateXMinutesAgo(12), created: getDateXMinutesAgo(12),
createdBy: new User(robertSmith), createdBy: new User(robertSmith),
isSelected: false isSelected: false
}), }),
new CommentModel({ new CommentModel({
id: 4, id: 4,
message: 'ty', message: 'ty',
created: new Date(), created: new Date(),
createdBy: new User(johnDoe), createdBy: new User(johnDoe),
isSelected: false isSelected: false
}) })
]; ];
export const commentsTaskData: CommentModel[] = [ export const commentsTaskData: CommentModel[] = [
new CommentModel({ new CommentModel({
id: 1, id: 1,
message: `I've done this task, what's next?`, message: `I've done this task, what's next?`,
created: getDateXMinutesAgo(30), created: getDateXMinutesAgo(30),
createdBy: new User(johnDoe), createdBy: new User(johnDoe),
isSelected: false isSelected: false
}), }),
new CommentModel({ new CommentModel({
id: 2, id: 2,
message: `I've assigned you another one 🤠`, message: `I've assigned you another one 🤠`,
created: getDateXMinutesAgo(15), created: getDateXMinutesAgo(15),
createdBy: new User(janeEod), createdBy: new User(janeEod),
isSelected: false isSelected: false
}), }),
new CommentModel({ new CommentModel({
id: 3, id: 3,
message: '+1', message: '+1',
created: getDateXMinutesAgo(12), created: getDateXMinutesAgo(12),
createdBy: new User(robertSmith), createdBy: new User(robertSmith),
isSelected: false isSelected: false
}), }),
new CommentModel({ new CommentModel({
id: 4, id: 4,
message: 'Cheers', message: 'Cheers',
created: new Date(), created: new Date(),
createdBy: new User(johnDoe), createdBy: new User(johnDoe),
isSelected: false isSelected: false
}) })
]; ];

View File

@ -63,6 +63,10 @@
margin-left: 12px; margin-left: 12px;
margin-right: 24px; margin-right: 24px;
} }
.adf-toolbar--spacer {
flex: 1 1 auto;
}
} }
&-permission-role-column-header { &-permission-role-column-header {

View File

@ -33,7 +33,7 @@ import { AllowableOperationsEnum } from '../../../common/models/allowable-operat
const SITE_MANAGER_ROLE = 'SiteManager'; const SITE_MANAGER_ROLE = 'SiteManager';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class PermissionListService { export class PermissionListService {
updated = new EventEmitter<PermissionDisplayModel>(); updated = new EventEmitter<PermissionDisplayModel>();
@ -43,7 +43,7 @@ export class PermissionListService {
error$: Subject<boolean> = new Subject(); error$: Subject<boolean> = new Subject();
nodeWithRoles$: Subject<{ node: Node; roles: RoleModel[] }> = new Subject(); nodeWithRoles$: Subject<{ node: Node; roles: RoleModel[] }> = new Subject();
data$: Observable<NodePermissionsModel> = this.nodeWithRoles$.pipe( data$: Observable<NodePermissionsModel> = this.nodeWithRoles$.pipe(
map(({ node, roles}) => { map(({ node, roles }) => {
const nodeLocalPermissions = this.nodePermissionService.getLocalPermissions(node); const nodeLocalPermissions = this.nodePermissionService.getLocalPermissions(node);
const localPermissions = this.updateReadOnlyPermission(node, nodeLocalPermissions); const localPermissions = this.updateReadOnlyPermission(node, nodeLocalPermissions);
return { return {
@ -68,7 +68,8 @@ export class PermissionListService {
fetchPermission(nodeId: string) { fetchPermission(nodeId: string) {
this.loading$.next(true); this.loading$.next(true);
this.nodePermissionService.getNodeWithRoles(nodeId) this.nodePermissionService
.getNodeWithRoles(nodeId)
.pipe(finalize(() => this.loading$.next(false))) .pipe(finalize(() => this.loading$.next(false)))
.subscribe( .subscribe(
({ node, roles }) => { ({ node, roles }) => {
@ -91,26 +92,24 @@ export class PermissionListService {
const authorityId = this.getManagerAuthority(this.node); const authorityId = this.getManagerAuthority(this.node);
if (authorityId) { if (authorityId) {
const permissions = [ const permissions = [...(this.node.permissions.locallySet || []), { authorityId, name: SITE_MANAGER_ROLE, accessStatus: 'ALLOWED' }];
...(this.node.permissions.locallySet || []),
{ authorityId, name: SITE_MANAGER_ROLE, accessStatus: 'ALLOWED' }
];
updateLocalPermission$ = this.nodePermissionService.updatePermissions(this.node, permissions); updateLocalPermission$ = this.nodePermissionService.updatePermissions(this.node, permissions);
} }
updateLocalPermission$.pipe(switchMap(() => this.nodeService.updateNode(this.node.id, nodeBody, {include: ['permissions']}))) updateLocalPermission$.pipe(switchMap(() => this.nodeService.updateNode(this.node.id, nodeBody, { include: ['permissions'] }))).subscribe(
.subscribe( (nodeUpdated: Node) => {
(nodeUpdated: Node) => { const message = nodeUpdated.permissions.isInheritanceEnabled
const message = nodeUpdated.permissions.isInheritanceEnabled ? 'PERMISSION_MANAGER.MESSAGE.INHERIT-ENABLE-SUCCESS' : 'PERMISSION_MANAGER.MESSAGE.INHERIT-DISABLE-SUCCESS'; ? 'PERMISSION_MANAGER.MESSAGE.INHERIT-ENABLE-SUCCESS'
this.notificationService.showInfo(message); : 'PERMISSION_MANAGER.MESSAGE.INHERIT-DISABLE-SUCCESS';
nodeUpdated.permissions.inherited = nodeUpdated.permissions?.inherited ?? []; this.notificationService.showInfo(message);
this.reloadNode(nodeUpdated); nodeUpdated.permissions.inherited = nodeUpdated.permissions?.inherited ?? [];
}, this.reloadNode(nodeUpdated);
() => { },
change.source.checked = this.node.permissions.isInheritanceEnabled; () => {
this.notificationService.showWarning('PERMISSION_MANAGER.MESSAGE.TOGGLE-PERMISSION-FAILED'); change.source.checked = this.node.permissions.isInheritanceEnabled;
} this.notificationService.showWarning('PERMISSION_MANAGER.MESSAGE.TOGGLE-PERMISSION-FAILED');
); }
);
} else { } else {
change.source.checked = this.node.permissions.isInheritanceEnabled; change.source.checked = this.node.permissions.isInheritanceEnabled;
this.notificationService.showError('PERMISSION_MANAGER.ERROR.NOT-ALLOWED'); this.notificationService.showError('PERMISSION_MANAGER.ERROR.NOT-ALLOWED');
@ -121,9 +120,9 @@ export class PermissionListService {
this.nodePermissionDialogService this.nodePermissionDialogService
.openAddPermissionDialog(this.node, this.roles, 'PERMISSION_MANAGER.ADD-PERMISSION.TITLE') .openAddPermissionDialog(this.node, this.roles, 'PERMISSION_MANAGER.ADD-PERMISSION.TITLE')
.pipe( .pipe(
switchMap(selection => { switchMap((selection) => {
const total = selection.length; const total = selection.length;
const group = selection.filter(({authorityId}) => this.isGroup(authorityId)).length; const group = selection.filter(({ authorityId }) => this.isGroup(authorityId)).length;
return forkJoin({ return forkJoin({
user: of(total - group), user: of(total - group),
group: of(group), group: of(group),
@ -131,86 +130,86 @@ export class PermissionListService {
}); });
}) })
) )
.subscribe(({ user, group, node}) => { .subscribe(
this.notificationService.showInfo( 'PERMISSION_MANAGER.MESSAGE.PERMISSION-ADD-SUCCESS', null, { user, group }); ({ user, group, node }) => {
this.notificationService.showInfo('PERMISSION_MANAGER.MESSAGE.PERMISSION-ADD-SUCCESS', null, { user, group });
this.reloadNode(node); this.reloadNode(node);
}, },
() => { () => {
this.notificationService.showError( 'PERMISSION_MANAGER.MESSAGE.PERMISSION-ADD-FAIL'); this.notificationService.showError('PERMISSION_MANAGER.MESSAGE.PERMISSION-ADD-FAIL');
this.reloadNode(); this.reloadNode();
} }
); );
} }
deletePermissions(permissions: PermissionElement[]) { deletePermissions(permissions: PermissionElement[]) {
this.nodePermissionService.removePermissions(this.node, permissions) this.nodePermissionService.removePermissions(this.node, permissions).subscribe(
.subscribe((node) => { (node) => {
const total = permissions.length; const total = permissions.length;
const group = permissions.filter(({authorityId}) => this.isGroup(authorityId)).length; const group = permissions.filter(({ authorityId }) => this.isGroup(authorityId)).length;
this.notificationService.showInfo('PERMISSION_MANAGER.MESSAGE.PERMISSION-BULK-DELETE-SUCCESS', null, {user: total - group, group}); this.notificationService.showInfo('PERMISSION_MANAGER.MESSAGE.PERMISSION-BULK-DELETE-SUCCESS', null, { user: total - group, group });
this.reloadNode(node); this.reloadNode(node);
}, },
() => { () => {
this.notificationService.showError('PERMISSION_MANAGER.MESSAGE.PERMISSION-DELETE-FAIL'); this.notificationService.showError('PERMISSION_MANAGER.MESSAGE.PERMISSION-DELETE-FAIL');
this.reloadNode(); this.reloadNode();
} }
); );
} }
updateRole(role: string, permission: PermissionDisplayModel) { updateRole(role: string, permission: PermissionDisplayModel) {
const updatedPermissionRole = this.buildUpdatedPermission(role, permission); const updatedPermissionRole = this.buildUpdatedPermission(role, permission);
this.nodePermissionService.updatePermissionRole(this.node, updatedPermissionRole) this.nodePermissionService.updatePermissionRole(this.node, updatedPermissionRole).subscribe(
.subscribe((node) => { (node) => {
this.notificationService.showInfo('PERMISSION_MANAGER.MESSAGE.PERMISSION-UPDATE-SUCCESS'); this.notificationService.showInfo('PERMISSION_MANAGER.MESSAGE.PERMISSION-UPDATE-SUCCESS');
this.reloadNode(node); this.reloadNode(node);
this.updated.emit(permission); this.updated.emit(permission);
}, },
() => { () => {
this.notificationService.showError('PERMISSION_MANAGER.MESSAGE.PERMISSION-UPDATE-FAIL'); this.notificationService.showError('PERMISSION_MANAGER.MESSAGE.PERMISSION-UPDATE-FAIL');
this.reloadNode(); this.reloadNode();
this.errored.emit(permission); this.errored.emit(permission);
} }
); );
} }
bulkRoleUpdate(role: string) { bulkRoleUpdate(role: string) {
const permissions = [...this.node.permissions.locallySet].map((permission) => this.buildUpdatedPermission(role, permission)); const permissions = [...this.node.permissions.locallySet].map((permission) => this.buildUpdatedPermission(role, permission));
this.nodePermissionService.updatePermissions(this.node, permissions) this.nodePermissionService.updatePermissions(this.node, permissions).subscribe(
.subscribe((node) => { (node) => {
const total = permissions.length; const total = permissions.length;
const group = permissions.filter(({authorityId}) => this.isGroup(authorityId)).length; const group = permissions.filter(({ authorityId }) => this.isGroup(authorityId)).length;
this.notificationService.showInfo('PERMISSION_MANAGER.MESSAGE.PERMISSION-BULK-UPDATE-SUCCESS', null, {user: total - group, group}); this.notificationService.showInfo('PERMISSION_MANAGER.MESSAGE.PERMISSION-BULK-UPDATE-SUCCESS', null, { user: total - group, group });
this.reloadNode(node); this.reloadNode(node);
}, },
() => { () => {
this.notificationService.showError('PERMISSION_MANAGER.MESSAGE.PERMISSION-UPDATE-FAIL'); this.notificationService.showError('PERMISSION_MANAGER.MESSAGE.PERMISSION-UPDATE-FAIL');
this.reloadNode(); this.reloadNode();
} }
); );
} }
deletePermission(permission: PermissionDisplayModel) { deletePermission(permission: PermissionDisplayModel) {
const cloneNode = { ...this.node, permissions: { ...this.node.permissions, locallySet: [ ...this.node.permissions.locallySet ] } }; const cloneNode = { ...this.node, permissions: { ...this.node.permissions, locallySet: [...this.node.permissions.locallySet] } };
this.nodePermissionService this.nodePermissionService.removePermission(cloneNode, permission).subscribe(
.removePermission(cloneNode, permission) (node) => {
.subscribe((node) => { this.notificationService.showInfo('PERMISSION_MANAGER.MESSAGE.PERMISSION-DELETE-SUCCESS');
this.notificationService.showInfo('PERMISSION_MANAGER.MESSAGE.PERMISSION-DELETE-SUCCESS'); if (!node.permissions.locallySet) {
if (!node.permissions.locallySet) { node.permissions.locallySet = [];
node.permissions.locallySet = [];
}
this.reloadNode(node);
},
() => {
this.notificationService.showError('PERMISSION_MANAGER.MESSAGE.PERMISSION-DELETE-FAIL');
this.reloadNode();
} }
); this.reloadNode(node);
},
() => {
this.notificationService.showError('PERMISSION_MANAGER.MESSAGE.PERMISSION-DELETE-FAIL');
this.reloadNode();
}
);
} }
private buildUpdatedPermission(role: string, permission: PermissionElement): PermissionElement { private buildUpdatedPermission(role: string, permission: PermissionElement): PermissionElement {
return { return {
accessStatus: permission.accessStatus, accessStatus: permission.accessStatus,
name: this.canUpdateThePermission(this.node, permission) ? role : permission.name, name: this.canUpdateThePermission(this.node, permission) ? role : permission.name,
authorityId: permission.authorityId authorityId: permission.authorityId
}; };
} }
@ -228,7 +227,9 @@ export class PermissionListService {
let authorityId: string; let authorityId: string;
if (sitePath) { if (sitePath) {
authorityId = `GROUP_site_${sitePath.name}_${SITE_MANAGER_ROLE}`; authorityId = `GROUP_site_${sitePath.name}_${SITE_MANAGER_ROLE}`;
hasLocalManagerPermission = !!node.permissions.locallySet?.find((permission) => permission.authorityId === authorityId && permission.name === SITE_MANAGER_ROLE); hasLocalManagerPermission = !!node.permissions.locallySet?.find(
(permission) => permission.authorityId === authorityId && permission.name === SITE_MANAGER_ROLE
);
} }
if (!hasLocalManagerPermission && authorityId) { if (!hasLocalManagerPermission && authorityId) {
@ -249,8 +250,8 @@ export class PermissionListService {
canUpdateThePermission(node: Node, permission: PermissionElement): boolean { canUpdateThePermission(node: Node, permission: PermissionElement): boolean {
const sitePath = node.path.elements.find((path) => path.nodeType === 'st:site'); const sitePath = node.path.elements.find((path) => path.nodeType === 'st:site');
if (!node.permissions.isInheritanceEnabled && sitePath) { if (!node.permissions.isInheritanceEnabled && sitePath) {
const authorityId = `GROUP_site_${sitePath.name}_${SITE_MANAGER_ROLE}`; const authorityId = `GROUP_site_${sitePath.name}_${SITE_MANAGER_ROLE}`;
return !(permission.authorityId === authorityId && permission.name === SITE_MANAGER_ROLE); return !(permission.authorityId === authorityId && permission.name === SITE_MANAGER_ROLE);
} }
return true; return true;
} }

View File

@ -31,11 +31,7 @@ import { AllowableOperationsEnum } from '../../common/models/allowable-operation
providedIn: 'root' providedIn: 'root'
}) })
export class NodePermissionDialogService { export class NodePermissionDialogService {
constructor(private dialog: MatDialog, private nodePermissionService: NodePermissionService, private contentService: ContentService) {}
constructor(private dialog: MatDialog,
private nodePermissionService: NodePermissionService,
private contentService: ContentService) {
}
/** /**
* Opens a dialog to add permissions to a node. * Opens a dialog to add permissions to a node.
@ -88,12 +84,14 @@ export class NodePermissionDialogService {
* @returns Node with updated permissions * @returns Node with updated permissions
*/ */
updateNodePermissionByDialog(nodeId?: string, title?: string): Observable<Node> { updateNodePermissionByDialog(nodeId?: string, title?: string): Observable<Node> {
return this.nodePermissionService.getNodeWithRoles(nodeId) return this.nodePermissionService
.getNodeWithRoles(nodeId)
.pipe( .pipe(
switchMap(({node, roles}) => this.openAddPermissionDialog(node, roles, title) switchMap(({ node, roles }) =>
.pipe( this.openAddPermissionDialog(node, roles, title).pipe(
switchMap((selection) => this.nodePermissionService.updateNodePermissions(nodeId, selection)) switchMap((selection) => this.nodePermissionService.updateNodePermissions(nodeId, selection))
)) )
)
); );
} }
} }

View File

@ -19,7 +19,6 @@ import { NodeEntry } from '@alfresco/js-api';
import { NodeNameTooltipPipe } from './node-name-tooltip.pipe'; import { NodeNameTooltipPipe } from './node-name-tooltip.pipe';
describe('NodeNameTooltipPipe', () => { describe('NodeNameTooltipPipe', () => {
const nodeName = 'node-name'; const nodeName = 'node-name';
const nodeTitle = 'node-title'; const nodeTitle = 'node-title';
const nodeDescription = 'node-description'; const nodeDescription = 'node-description';

View File

@ -39,10 +39,7 @@ export class SearchAiService {
toggleSearchAiInput$ = this.toggleSearchAiInput.asObservable(); toggleSearchAiInput$ = this.toggleSearchAiInput.asObservable();
constructor( constructor(private apiService: AlfrescoApiService, private translateService: TranslateService) {}
private apiService: AlfrescoApiService,
private translateService: TranslateService
) {}
/** /**
* Update the state of the search AI input. * Update the state of the search AI input.

View File

@ -1,3 +1,3 @@
<div class="adf-empty-search-result"> <div class="adf-empty-search-result">
<ng-content></ng-content> <ng-content />
</div> </div>

View File

@ -50,8 +50,7 @@
*ngIf="data?.list?.entries.length === 0"> *ngIf="data?.list?.entries.length === 0">
<ng-content <ng-content
selector="adf-empty-search-result" selector="adf-empty-search-result"
*ngIf="isNoSearchTemplatePresent() else defaultNoResult"> *ngIf="isNoSearchTemplatePresent() else defaultNoResult" />
</ng-content>
<ng-template #defaultNoResult> <ng-template #defaultNoResult>
<p matListItemLine class="adf-search-fixed-text">{{ 'SEARCH.RESULTS.NONE' | translate:{searchTerm: <p matListItemLine class="adf-search-fixed-text">{{ 'SEARCH.RESULTS.NONE' | translate:{searchTerm:
searchTerm} }}</p> searchTerm} }}</p>

View File

@ -15,5 +15,5 @@
</ng-container> </ng-container>
</ng-container> </ng-container>
<ng-content></ng-content> <ng-content />
</mat-chip-set> </mat-chip-set>

View File

@ -1,6 +1,6 @@
<div class="adf-search-filter-menu-card"> <div class="adf-search-filter-menu-card">
<div class="adf-search-filter-title"> <div class="adf-search-filter-title">
<ng-content select="filter-title"></ng-content> <ng-content select="filter-title" />
<button mat-icon-button <button mat-icon-button
class="adf-search-filter-title-action" class="adf-search-filter-title-action"
aria-hidden="false" aria-hidden="false"
@ -13,12 +13,12 @@
<mat-divider /> <mat-divider />
<div class="adf-search-filter-content"> <div class="adf-search-filter-content">
<ng-content select="filter-content"></ng-content> <ng-content select="filter-content" />
</div> </div>
<mat-divider /> <mat-divider />
<div class="adf-search-filter-actions"> <div class="adf-search-filter-actions">
<ng-content select="filter-actions"></ng-content> <ng-content select="filter-actions" />
</div> </div>
</div> </div>

View File

@ -55,7 +55,7 @@ export class SearchTextComponent implements SearchWidget, OnInit {
private readonly destroyRef = inject(DestroyRef); private readonly destroyRef = inject(DestroyRef);
ngOnInit() { ngOnInit() {
if (this.context && this.settings && this.settings.pattern) { if (this.context && this.settings?.pattern) {
const pattern = new RegExp(this.settings.pattern, 'g'); const pattern = new RegExp(this.settings.pattern, 'g');
const match = pattern.exec(this.context.queryFragments[this.id] || ''); const match = pattern.exec(this.context.queryFragments[this.id] || '');
if (this.settings.allowUpdateOnChange !== undefined && this.settings.allowUpdateOnChange !== null) { if (this.settings.allowUpdateOnChange !== undefined && this.settings.allowUpdateOnChange !== null) {

View File

@ -2,6 +2,5 @@
[ngClass]="_classList" #panel> [ngClass]="_classList" #panel>
<ng-template <ng-template
[ngTemplateOutlet]="template" [ngTemplateOutlet]="template"
[ngTemplateOutletContext]="{ $implicit: results }"> [ngTemplateOutletContext]="{ $implicit: results }" />
</ng-template>
</div> </div>

View File

@ -18,11 +18,12 @@
import { UntypedFormControl } from '@angular/forms'; import { UntypedFormControl } from '@angular/forms';
export class SearchTermValidator { export class SearchTermValidator {
static minAlphanumericChars(minChars: number) { static minAlphanumericChars(minChars: number) {
return (control: UntypedFormControl) => ('' + control.value).replace(/[^0-9a-zA-Z]+/g, '').length >= minChars ? null : { return (control: UntypedFormControl) =>
hasMinAlphanumericChars: false ('' + control.value).replace(/[^0-9a-zA-Z]+/g, '').length >= minChars
}; ? null
: {
hasMinAlphanumericChars: false
};
} }
} }

View File

@ -26,14 +26,13 @@ export class Payload {
} }
describe('SearchFilterList', () => { describe('SearchFilterList', () => {
const generateItems = (count: number): Payload[] =>
const generateItems = (count: number): Payload[] => Array(count).fill(null).map((_, id) => new Payload(id)); Array(count)
.fill(null)
.map((_, id) => new Payload(id));
it('should init with external items', () => { it('should init with external items', () => {
const items = [ const items = [new Payload(1), new Payload(2)];
new Payload(1),
new Payload(2)
];
const list = new SearchFilterList<Payload>(items); const list = new SearchFilterList<Payload>(items);
expect(list.length).toBe(2); expect(list.length).toBe(2);

View File

@ -18,7 +18,6 @@
const DEFAULT_PAGE_SIZE = 5; const DEFAULT_PAGE_SIZE = 5;
export class SearchFilterList<T> implements Iterable<T> { export class SearchFilterList<T> implements Iterable<T> {
private filteredItems: T[] = []; private filteredItems: T[] = [];
private _filterText: string = ''; private _filterText: string = '';
@ -41,7 +40,7 @@ export class SearchFilterList<T> implements Iterable<T> {
return this._filter; return this._filter;
} }
set filter(value: (item: T) => boolean ) { set filter(value: (item: T) => boolean) {
this._filter = value; this._filter = value;
this.applyFilter(); this.applyFilter();
} }

View File

@ -31,7 +31,6 @@ import { SearchDateRangeTabbedComponent } from '../components/search-date-range-
providedIn: 'root' providedIn: 'root'
}) })
export class SearchFilterService { export class SearchFilterService {
/** /**
* Contains string-to-type mappings for registered widgets. * Contains string-to-type mappings for registered widgets.
*/ */
@ -47,5 +46,4 @@ export class SearchFilterService {
'autocomplete-chips': SearchFilterAutocompleteChipsComponent, 'autocomplete-chips': SearchFilterAutocompleteChipsComponent,
'date-range': SearchDateRangeTabbedComponent 'date-range': SearchDateRangeTabbedComponent
}; };
} }

View File

@ -35,101 +35,111 @@ describe('SearchHeaderQueryBuilderService', () => {
return config; return config;
}; };
const createQueryBuilder = (searchSettings): SearchHeaderQueryBuilderService => {
let builder: SearchHeaderQueryBuilderService;
TestBed.runInInjectionContext(() => {
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
builder = new SearchHeaderQueryBuilderService(buildConfig(searchSettings), alfrescoApiService, null);
});
return builder;
};
it('should load the configuration from app config', () => { it('should load the configuration from app config', () => {
const config: SearchConfiguration = { TestBed.runInInjectionContext(() => {
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any], const config: SearchConfiguration = {
filterQueries: [{ query: 'query1' }, { query: 'query2' }] categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any],
}; filterQueries: [{ query: 'query1' }, { query: 'query2' }]
};
const builder = createQueryBuilder(config); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const builder = new SearchHeaderQueryBuilderService(buildConfig(config), alfrescoApiService, null);
builder.categories = []; builder.categories = [];
builder.filterQueries = []; builder.filterQueries = [];
expect(builder.categories.length).toBe(0); expect(builder.categories.length).toBe(0);
expect(builder.filterQueries.length).toBe(0); expect(builder.filterQueries.length).toBe(0);
builder.resetToDefaults(); builder.resetToDefaults();
expect(builder.categories.length).toBe(2); expect(builder.categories.length).toBe(2);
expect(builder.filterQueries.length).toBe(2); expect(builder.filterQueries.length).toBe(2);
});
}); });
it('should return the category assigned to a column key', () => { it('should return the category assigned to a column key', () => {
const config: SearchConfiguration = { TestBed.runInInjectionContext(() => {
categories: [ const config: SearchConfiguration = {
{ id: 'cat1', columnKey: 'fake-key-1', enabled: true } as any, categories: [
{ id: 'cat2', columnKey: 'fake-key-2', enabled: true } as any { id: 'cat1', columnKey: 'fake-key-1', enabled: true } as any,
], { id: 'cat2', columnKey: 'fake-key-2', enabled: true } as any
filterQueries: [{ query: 'query1' }, { query: 'query2' }] ],
}; filterQueries: [{ query: 'query1' }, { query: 'query2' }]
};
const service = createQueryBuilder(config); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const service = new SearchHeaderQueryBuilderService(buildConfig(config), alfrescoApiService, null);
const category = service.getCategoryForColumn('fake-key-1'); const category = service.getCategoryForColumn('fake-key-1');
expect(category).not.toBeNull(); expect(category).not.toBeNull();
expect(category).not.toBeUndefined(); expect(category).not.toBeUndefined();
expect(category.columnKey).toBe('fake-key-1'); expect(category.columnKey).toBe('fake-key-1');
});
}); });
it('should have empty user query by default', () => { it('should have empty user query by default', () => {
const builder = createQueryBuilder({}); TestBed.runInInjectionContext(() => {
expect(builder.userQuery).toBe(''); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const builder = new SearchHeaderQueryBuilderService(buildConfig({}), alfrescoApiService, null);
expect(builder.userQuery).toBe('');
});
}); });
it('should add the extra filter for the parent node', () => { it('should add the extra filter for the parent node', () => {
const config: SearchConfiguration = { TestBed.runInInjectionContext(() => {
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any], const config: SearchConfiguration = {
filterQueries: [{ query: 'query1' }, { query: 'query2' }] categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any],
}; filterQueries: [{ query: 'query1' }, { query: 'query2' }]
};
const expectedResult = [{ query: 'PARENT:"workspace://SpacesStore/fake-node-id"' }]; const expectedResult = [{ query: 'PARENT:"workspace://SpacesStore/fake-node-id"' }];
const searchHeaderService = createQueryBuilder(config); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const searchHeaderService = new SearchHeaderQueryBuilderService(buildConfig(config), alfrescoApiService, null);
searchHeaderService.setCurrentRootFolderId('fake-node-id'); searchHeaderService.setCurrentRootFolderId('fake-node-id');
expect(searchHeaderService.filterQueries).toEqual(expectedResult, 'Filters are not as expected'); expect(searchHeaderService.filterQueries).toEqual(expectedResult, 'Filters are not as expected');
});
}); });
it('should not add again the parent filter if that node is already added', () => { it('should not add again the parent filter if that node is already added', () => {
const expectedResult = [{ query: 'PARENT:"workspace://SpacesStore/fake-node-id"' }]; TestBed.runInInjectionContext(() => {
const expectedResult = [{ query: 'PARENT:"workspace://SpacesStore/fake-node-id"' }];
const config: SearchConfiguration = { const config: SearchConfiguration = {
categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any], categories: [{ id: 'cat1', enabled: true } as any, { id: 'cat2', enabled: true } as any],
filterQueries: expectedResult filterQueries: expectedResult
}; };
const searchHeaderService = createQueryBuilder(config); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
searchHeaderService.setCurrentRootFolderId('fake-node-id'); const searchHeaderService = new SearchHeaderQueryBuilderService(buildConfig(config), alfrescoApiService, null);
expect(searchHeaderService.filterQueries).toEqual(expectedResult, 'Filters are not as expected'); searchHeaderService.setCurrentRootFolderId('fake-node-id');
expect(searchHeaderService.filterQueries).toEqual(expectedResult, 'Filters are not as expected');
});
}); });
it('should not add duplicate column names in activeFilters', () => { it('should not add duplicate column names in activeFilters', () => {
const activeFilter = 'FakeColumn'; TestBed.runInInjectionContext(() => {
const activeFilter = 'FakeColumn';
const config: SearchConfiguration = { const config: SearchConfiguration = {
categories: [{ id: 'cat1', enabled: true } as any], categories: [{ id: 'cat1', enabled: true } as any],
filterQueries: [{ query: 'PARENT:"workspace://SpacesStore/fake-node-id' }] filterQueries: [{ query: 'PARENT:"workspace://SpacesStore/fake-node-id' }]
}; };
const searchHeaderService = createQueryBuilder(config); const alfrescoApiService = TestBed.inject(AlfrescoApiService);
const searchHeaderService = new SearchHeaderQueryBuilderService(buildConfig(config), alfrescoApiService, null);
expect(searchHeaderService.activeFilters.length).toBe(0); expect(searchHeaderService.activeFilters.length).toBe(0);
searchHeaderService.setActiveFilter(activeFilter, 'fake-value'); searchHeaderService.setActiveFilter(activeFilter, 'fake-value');
searchHeaderService.setActiveFilter(activeFilter, 'fake-value'); searchHeaderService.setActiveFilter(activeFilter, 'fake-value');
expect(searchHeaderService.activeFilters.length).toBe(1); expect(searchHeaderService.activeFilters.length).toBe(1);
});
}); });
}); });

View File

@ -18,7 +18,6 @@
import { NodeEntry } from '@alfresco/js-api'; import { NodeEntry } from '@alfresco/js-api';
export class TreeBaseNode { export class TreeBaseNode {
name: string; name: string;
nodeId: string; nodeId: string;
level: number; level: number;
@ -31,6 +30,5 @@ export class TreeBaseNode {
this.level = level ? level : 0; this.level = level ? level : 0;
this.expandable = expandable ? expandable : true; this.expandable = expandable ? expandable : true;
this.node = nodeEntry ? new NodeEntry(nodeEntry) : undefined; this.node = nodeEntry ? new NodeEntry(nodeEntry) : undefined;
} }
} }

View File

@ -99,8 +99,7 @@
<mat-menu #menu="matMenu"> <mat-menu #menu="matMenu">
<ng-template <ng-template
[ngTemplateOutlet]="nodeActionsMenuTemplate" [ngTemplateOutlet]="nodeActionsMenuTemplate"
[ngTemplateOutletContext]="{ node: node }"> [ngTemplateOutletContext]="{ node: node }" />
</ng-template>
</mat-menu> </mat-menu>
</div> </div>
</mat-tree-node> </mat-tree-node>
@ -109,8 +108,7 @@
</ng-container> </ng-container>
<ng-template #emptyContent> <ng-template #emptyContent>
<ng-template [ngTemplateOutlet]="emptyContentTemplate"> <ng-template [ngTemplateOutlet]="emptyContentTemplate" />
</ng-template>
</ng-template> </ng-template>
<ng-template #loadingSpinner> <ng-template #loadingSpinner>

View File

@ -23,10 +23,10 @@ import { TreeService } from '../services/tree.service';
import { treeNodesMockExpanded } from './tree-node.mock'; import { treeNodesMockExpanded } from './tree-node.mock';
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class TreeServiceMock extends TreeService<TreeNode> { export class TreeServiceMock extends TreeService<TreeNode> {
public getSubNodes(parentNodeId: string, skipCount?: number, maxItems?: number): Observable<TreeResponse<TreeNode>> { public getSubNodes(parentNodeId: string, skipCount?: number, maxItems?: number): Observable<TreeResponse<TreeNode>> {
if (parentNodeId) { if (parentNodeId) {
return of({pagination: {skipCount, maxItems}, entries: Array.from(treeNodesMockExpanded)}); return of({ pagination: { skipCount, maxItems }, entries: Array.from(treeNodesMockExpanded) });
} }
return of(); return of();
} }

View File

@ -27,7 +27,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
// eslint-disable-next-line @angular-eslint/directive-class-suffix // eslint-disable-next-line @angular-eslint/directive-class-suffix
export abstract class UploadBase implements OnInit { export abstract class UploadBase implements OnInit {
protected uploadService = inject(UploadService); protected uploadService = inject(UploadService);
protected translationService = inject(TranslationService); protected translationService: TranslationService = inject(TranslationService);
protected ngZone = inject(NgZone); protected ngZone = inject(NgZone);
/** /**
@ -98,31 +98,26 @@ export abstract class UploadBase implements OnInit {
* @param files files to upload * @param files files to upload
*/ */
uploadFiles(files: File[]): void { uploadFiles(files: File[]): void {
const filteredFiles: FileModel[] = files const filteredFiles: FileModel[] = files.map<FileModel>((file: File) =>
.map<FileModel>((file: File) => this.createFileModel(file, this.rootFolderId, ((file as any).webkitRelativePath || '').replace(/\/[^/]*$/, ''))); this.createFileModel(file, this.rootFolderId, ((file).webkitRelativePath || '').replace(/\/[^/]*$/, ''))
);
this.uploadQueue(filteredFiles); this.uploadQueue(filteredFiles);
} }
uploadFilesInfo(files: FileInfo[]): void { uploadFilesInfo(files: FileInfo[]): void {
const filteredFiles: FileModel[] = files const filteredFiles: FileModel[] = files.map<FileModel>((fileInfo: FileInfo) =>
.map<FileModel>((fileInfo: FileInfo) => this.createFileModel(fileInfo.file, this.rootFolderId, fileInfo.relativeFolder)); this.createFileModel(fileInfo.file, this.rootFolderId, fileInfo.relativeFolder)
);
this.uploadQueue(filteredFiles); this.uploadQueue(filteredFiles);
} }
private uploadQueue(files: FileModel[]) { private uploadQueue(files: FileModel[]) {
const filteredFiles = files const filteredFiles = files.filter(this.isFileAcceptable.bind(this)).filter(this.isFileSizeAcceptable.bind(this));
.filter(this.isFileAcceptable.bind(this))
.filter(this.isFileSizeAcceptable.bind(this));
this.ngZone.run(() => { this.ngZone.run(() => {
const event = new UploadFilesEvent( const event = new UploadFilesEvent([...filteredFiles], this.uploadService, this.success, this.error);
[...filteredFiles],
this.uploadService,
this.success,
this.error
);
this.beginUpload.emit(event); this.beginUpload.emit(event);
if (!event.defaultPrevented) { if (!event.defaultPrevented) {
@ -145,9 +140,7 @@ export abstract class UploadBase implements OnInit {
return true; return true;
} }
const allowedExtensions = this.acceptedFilesType const allowedExtensions = this.acceptedFilesType.split(',').map((ext) => ext.trim().replace(/^\./, ''));
.split(',')
.map((ext) => ext.trim().replace(/^\./, ''));
return allowedExtensions.indexOf(file.extension) !== -1; return allowedExtensions.indexOf(file.extension) !== -1;
} }
@ -162,14 +155,18 @@ export abstract class UploadBase implements OnInit {
* @returns file model * @returns file model
*/ */
protected createFileModel(file: File, parentId: string, path: string, id?: string): FileModel { protected createFileModel(file: File, parentId: string, path: string, id?: string): FileModel {
return new FileModel(file, { return new FileModel(
comment: this.comment, file,
majorVersion: this.majorVersion, {
newVersion: this.versioning, comment: this.comment,
parentId, majorVersion: this.majorVersion,
path, newVersion: this.versioning,
nodeType: this.nodeType parentId,
}, id); path,
nodeType: this.nodeType
},
id
);
} }
protected isFileSizeAllowed(file: FileModel) { protected isFileSizeAllowed(file: FileModel) {
@ -201,15 +198,11 @@ export abstract class UploadBase implements OnInit {
if (!this.isFileSizeAllowed(file)) { if (!this.isFileSizeAllowed(file)) {
acceptableSize = false; acceptableSize = false;
const message = this.translationService.instant( const message = this.translationService.instant('FILE_UPLOAD.MESSAGES.EXCEED_MAX_FILE_SIZE', { fileName: file.name });
'FILE_UPLOAD.MESSAGES.EXCEED_MAX_FILE_SIZE',
{ fileName: file.name }
);
this.error.emit(message); this.error.emit(message);
} }
return acceptableSize; return acceptableSize;
} }
} }

View File

@ -2,6 +2,5 @@
<ng-template <ng-template
ngFor ngFor
[ngForOf]="files" [ngForOf]="files"
[ngForTemplate]="template"> [ngForTemplate]="template" />
</ng-template>
</div> </div>

View File

@ -3,5 +3,5 @@
(folderEntityDropped)="onFolderEntityDropped($event)" (folderEntityDropped)="onFolderEntityDropped($event)"
(upload-files)="onUploadFiles($any($event))" (upload-files)="onUploadFiles($any($event))"
dropzone="" webkitdropzone="*" #droparea> dropzone="" webkitdropzone="*" #droparea>
<ng-content></ng-content> <ng-content />
</div> </div>

View File

@ -31,7 +31,7 @@ export class VersionCompatibilityService {
constructor(private discoveryApiService: DiscoveryApiService) { constructor(private discoveryApiService: DiscoveryApiService) {
this.discoveryApiService.ecmProductInfo$ this.discoveryApiService.ecmProductInfo$
.pipe(filter(acsInfo => !!acsInfo)) .pipe(filter((acsInfo) => !!acsInfo))
.subscribe((acsInfo: RepositoryInfo) => this.initializeAcsVersion(acsInfo.version)); .subscribe((acsInfo: RepositoryInfo) => this.initializeAcsVersion(acsInfo.version));
} }
@ -53,12 +53,13 @@ export class VersionCompatibilityService {
if (currentVersion) { if (currentVersion) {
if (+currentVersion.major > +parsedRequiredVersion.major) { if (+currentVersion.major > +parsedRequiredVersion.major) {
versionSupported = true; versionSupported = true;
} else if (currentVersion.major === parsedRequiredVersion.major && } else if (currentVersion.major === parsedRequiredVersion.major && +currentVersion.minor > +parsedRequiredVersion.minor) {
+currentVersion.minor > +parsedRequiredVersion.minor) {
versionSupported = true; versionSupported = true;
} else if (currentVersion.major === parsedRequiredVersion.major && } else if (
currentVersion.major === parsedRequiredVersion.major &&
currentVersion.minor === parsedRequiredVersion.minor && currentVersion.minor === parsedRequiredVersion.minor &&
+currentVersion.patch >= +parsedRequiredVersion.patch) { +currentVersion.patch >= +parsedRequiredVersion.patch
) {
versionSupported = true; versionSupported = true;
} }
} }

View File

@ -34,23 +34,23 @@
(submitFile)="onSubmitFile($event)"> (submitFile)="onSubmitFile($event)">
<adf-viewer-toolbar *ngIf="toolbar"> <adf-viewer-toolbar *ngIf="toolbar">
<ng-content select="adf-viewer-toolbar"></ng-content> <ng-content select="adf-viewer-toolbar" />
</adf-viewer-toolbar> </adf-viewer-toolbar>
<adf-viewer-toolbar-actions *ngIf="toolbarActions"> <adf-viewer-toolbar-actions *ngIf="toolbarActions">
<ng-content select="adf-viewer-toolbar-actions"></ng-content> <ng-content select="adf-viewer-toolbar-actions" />
</adf-viewer-toolbar-actions> </adf-viewer-toolbar-actions>
<adf-viewer-more-actions *ngIf="moreActions"> <adf-viewer-more-actions *ngIf="moreActions">
<ng-content select="adf-viewer-more-actions"></ng-content> <ng-content select="adf-viewer-more-actions" />
</adf-viewer-more-actions> </adf-viewer-more-actions>
<adf-viewer-open-with *ngIf="openWith"> <adf-viewer-open-with *ngIf="openWith">
<ng-content select="adf-viewer-open-with"></ng-content> <ng-content select="adf-viewer-open-with" />
</adf-viewer-open-with> </adf-viewer-open-with>
<adf-viewer-sidebar *ngIf="sidebar"> <adf-viewer-sidebar *ngIf="sidebar">
<ng-content select="adf-viewer-sidebar"></ng-content> <ng-content select="adf-viewer-sidebar" />
</adf-viewer-sidebar> </adf-viewer-sidebar>
<adf-viewer-toolbar-custom-actions> <adf-viewer-toolbar-custom-actions>

View File

@ -69,6 +69,7 @@ class ViewerWithCustomToolbarComponent {}
selector: 'adf-viewer-container-toolbar-actions', selector: 'adf-viewer-container-toolbar-actions',
standalone: true, standalone: true,
imports: [MatIconModule, MatButtonModule, ViewerToolbarActionsComponent, AlfrescoViewerComponent], imports: [MatIconModule, MatButtonModule, ViewerToolbarActionsComponent, AlfrescoViewerComponent],
// eslint-disable-next-line @alfresco/eslint-angular/no-angular-material-selectors
template: `<adf-alfresco-viewer> template: `<adf-alfresco-viewer>
<adf-viewer-toolbar-actions> <adf-viewer-toolbar-actions>
<button mat-icon-button id="custom-button"> <button mat-icon-button id="custom-button">
@ -103,6 +104,7 @@ class DummyDialogComponent {}
selector: 'adf-viewer-container-open-with', selector: 'adf-viewer-container-open-with',
standalone: true, standalone: true,
imports: [MatIconModule, MatMenuModule, ViewerOpenWithComponent, AlfrescoViewerComponent], imports: [MatIconModule, MatMenuModule, ViewerOpenWithComponent, AlfrescoViewerComponent],
// eslint-disable-next-line @alfresco/eslint-angular/no-angular-material-selectors
template: ` template: `
<adf-alfresco-viewer> <adf-alfresco-viewer>
<adf-viewer-open-with> <adf-viewer-open-with>
@ -128,6 +130,7 @@ class ViewerWithCustomOpenWithComponent {}
selector: 'adf-viewer-container-more-actions', selector: 'adf-viewer-container-more-actions',
standalone: true, standalone: true,
imports: [MatIconModule, MatMenuModule, ViewerMoreActionsComponent, AlfrescoViewerComponent], imports: [MatIconModule, MatMenuModule, ViewerMoreActionsComponent, AlfrescoViewerComponent],
// eslint-disable-next-line @alfresco/eslint-angular/no-angular-material-selectors
template: ` <adf-alfresco-viewer> template: ` <adf-alfresco-viewer>
<adf-viewer-more-actions> <adf-viewer-more-actions>
<button mat-menu-item> <button mat-menu-item>

View File

@ -14,5 +14,6 @@
}, },
"target": "ES2022", "target": "ES2022",
"useDefineForClassFields": false "useDefineForClassFields": false
} },
"include": ["src/**/*.ts", "index.ts"]
} }

View File

@ -6,5 +6,5 @@
"useDefineForClassFields": false "useDefineForClassFields": false
}, },
"files": ["src/test.ts"], "files": ["src/test.ts"],
"include": ["**/*.spec.ts", "**/*.test.ts", "**/*.d.ts"] "include": ["**/*.spec.ts", "**/*.test.ts", "**/*.d.ts", "index.ts"]
} }

View File

@ -21,7 +21,6 @@ import { HttpParameterCodec } from '@angular/common/http';
// does not encode some special characters like + with is causing issues with the alfresco js API and returns 500 error // does not encode some special characters like + with is causing issues with the alfresco js API and returns 500 error
export class AlfrescoApiParamEncoder implements HttpParameterCodec { export class AlfrescoApiParamEncoder implements HttpParameterCodec {
encodeKey(key: string): string { encodeKey(key: string): string {
return encodeURIComponent(key); return encodeURIComponent(key);
} }

View File

@ -16,10 +16,9 @@
*/ */
export class AlfrescoApiResponseError extends Error { export class AlfrescoApiResponseError extends Error {
public name = 'AlfrescoApiResponseError'; public name = 'AlfrescoApiResponseError';
constructor(msg: string, public status: number, public response: Record<string, any> ) { constructor(msg: string, public status: number, public response: Record<string, any>) {
super(msg); super(msg);
} }
} }

View File

@ -18,7 +18,6 @@
import { isConstructor, getQueryParamsWithCustomEncoder, removeNilValues } from './alfresco-api.utils'; import { isConstructor, getQueryParamsWithCustomEncoder, removeNilValues } from './alfresco-api.utils';
describe('AlfrescoApiUtils', () => { describe('AlfrescoApiUtils', () => {
describe('isConstructor', () => { describe('isConstructor', () => {
class MockClass {} class MockClass {}
/** /**
@ -50,9 +49,7 @@ describe('AlfrescoApiUtils', () => {
}); });
}); });
describe('getQueryParamsWithCustomEncoder', () => { describe('getQueryParamsWithCustomEncoder', () => {
it('should return queryParams with removed undefined values', () => { it('should return queryParams with removed undefined values', () => {
const actual = getQueryParamsWithCustomEncoder({ const actual = getQueryParamsWithCustomEncoder({
key1: 'value1', key1: 'value1',
@ -73,9 +70,7 @@ describe('AlfrescoApiUtils', () => {
}); });
}); });
describe('removeUndefinedValues', () => { describe('removeUndefinedValues', () => {
it('should return queryParams with removed undefined values', () => { it('should return queryParams with removed undefined values', () => {
const actual = removeNilValues({ const actual = removeNilValues({
key1: 'value1', key1: 'value1',
@ -98,5 +93,4 @@ describe('AlfrescoApiUtils', () => {
expect(actual?.getAll('key2')).toEqual(['value2', 'value3']); expect(actual?.getAll('key2')).toEqual(['value2', 'value3']);
}); });
}); });
}); });

View File

@ -15,18 +15,31 @@
* limitations under the License. * limitations under the License.
*/ */
import { HttpEvent, HttpUploadProgressEvent, HttpEventType, HttpResponse, HttpParams, HttpParameterCodec, HttpUrlEncodingCodec } from '@angular/common/http'; import {
HttpEvent,
HttpUploadProgressEvent,
HttpEventType,
HttpResponse,
HttpParams,
HttpParameterCodec,
HttpUrlEncodingCodec
} from '@angular/common/http';
import { Constructor } from '../types'; import { Constructor } from '../types';
export const isHttpUploadProgressEvent = <T>(val: HttpEvent<T>): val is HttpUploadProgressEvent => val.type === HttpEventType.UploadProgress; export const isHttpUploadProgressEvent = <T>(val: HttpEvent<T>): val is HttpUploadProgressEvent => val.type === HttpEventType.UploadProgress;
export const isHttpResponseEvent = <T>(val: HttpEvent<T>): val is HttpResponse<T> => val.type === HttpEventType.Response; export const isHttpResponseEvent = <T>(val: HttpEvent<T>): val is HttpResponse<T> => val.type === HttpEventType.Response;
export const isDate = (value: unknown): value is Date => value instanceof Date; export const isDate = (value: unknown): value is Date => value instanceof Date;
export const isXML = (value: unknown): boolean => typeof value === 'string' && value.startsWith('<?xml'); export const isXML = (value: unknown): boolean => typeof value === 'string' && value.startsWith('<?xml');
export const isBlobResponse = (response: HttpResponse<any>, returnType: Constructor<unknown> | 'blob'): response is HttpResponse<Blob> => returnType === 'blob' || response.body instanceof Blob; export const isBlobResponse = (response: HttpResponse<any>, returnType: Constructor<unknown> | 'blob'): response is HttpResponse<Blob> =>
export const isConstructor = <T = unknown>(value: any): value is Constructor<T> => typeof value === 'function' && !!value?.prototype?.constructor.name; returnType === 'blob' || response.body instanceof Blob;
export const isConstructor = <T = unknown>(value: any): value is Constructor<T> =>
typeof value === 'function' && !!value?.prototype?.constructor.name;
const convertParamsToString = (value: any): any => isDate(value) ? value.toISOString() : value; const convertParamsToString = (value: any): any => (isDate(value) ? value.toISOString() : value);
export const getQueryParamsWithCustomEncoder = (obj: Record<string | number, unknown>, encoder: HttpParameterCodec = new HttpUrlEncodingCodec()): HttpParams | undefined => { export const getQueryParamsWithCustomEncoder = (
obj: Record<string | number, unknown>,
encoder: HttpParameterCodec = new HttpUrlEncodingCodec()
): HttpParams | undefined => {
if (!obj) { if (!obj) {
return undefined; return undefined;
} }
@ -38,7 +51,6 @@ export const getQueryParamsWithCustomEncoder = (obj: Record<string | number, unk
const params = removeNilValues(obj); const params = removeNilValues(obj);
for (const key in params) { for (const key in params) {
if (Object.prototype.hasOwnProperty.call(params, key)) { if (Object.prototype.hasOwnProperty.call(params, key)) {
const value = params[key]; const value = params[key];
if (value instanceof Array) { if (value instanceof Array) {
@ -62,7 +74,6 @@ export const getQueryParamsWithCustomEncoder = (obj: Record<string | number, unk
* @returns object with updated values * @returns object with updated values
*/ */
export const removeNilValues = (obj: Record<string | number, unknown>) => { export const removeNilValues = (obj: Record<string | number, unknown>) => {
if (!obj) { if (!obj) {
return {}; return {};
} }
@ -74,9 +85,7 @@ export const removeNilValues = (obj: Record<string | number, unknown>) => {
}, {}); }, {});
}; };
export const convertObjectToFormData = (formParams: Record<string | number, string | Blob>): FormData => { export const convertObjectToFormData = (formParams: Record<string | number, string | Blob>): FormData => {
const formData = new FormData(); const formData = new FormData();
for (const key in formParams) { for (const key in formParams) {

View File

@ -17,6 +17,6 @@
export interface Dictionary<T> { export interface Dictionary<T> {
[key: string]: T; [key: string]: T;
}; }
export type Constructor<T> = new (...args: any[]) => T; export type Constructor<T> = new (...args: any[]) => T;

View File

@ -22,46 +22,47 @@ import { Authentication } from '../authentication';
import { AuthenticationInterceptor, SHOULD_ADD_AUTH_TOKEN } from './authentication.interceptor'; import { AuthenticationInterceptor, SHOULD_ADD_AUTH_TOKEN } from './authentication.interceptor';
class MockAuthentication extends Authentication { class MockAuthentication extends Authentication {
addTokenToHeader(_: string, httpHeaders: HttpHeaders): Observable<HttpHeaders> { addTokenToHeader(_: string, httpHeaders: HttpHeaders): Observable<HttpHeaders> {
return of(httpHeaders); return of(httpHeaders);
} }
} }
const mockNext: HttpHandler = { const mockNext: HttpHandler = {
handle: () => new Observable(subscriber => { handle: () =>
subscriber.complete(); new Observable((subscriber) => {
}) subscriber.complete();
})
}; };
const request = new HttpRequest('GET', 'http://localhost:4200'); const request = new HttpRequest('GET', 'http://localhost:4200');
describe('AuthenticationInterceptor', () => { describe('AuthenticationInterceptor', () => {
let interceptor: AuthenticationInterceptor; let interceptor: AuthenticationInterceptor;
let addTokenToHeaderSpy: jasmine.Spy<any>; let addTokenToHeaderSpy: jasmine.Spy<any>;
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
providers: [AuthenticationInterceptor, {provide: Authentication, useClass: MockAuthentication}] providers: [AuthenticationInterceptor, { provide: Authentication, useClass: MockAuthentication }]
});
interceptor = TestBed.inject(AuthenticationInterceptor);
addTokenToHeaderSpy = spyOn(interceptor['authService'], 'addTokenToHeader');
}); });
interceptor = TestBed.inject(AuthenticationInterceptor);
addTokenToHeaderSpy = spyOn(interceptor['authService'], 'addTokenToHeader');
});
it('should call add auth token method when SHOULD_ADD_AUTH_TOKEN context is set to true', () => { it('should call add auth token method when SHOULD_ADD_AUTH_TOKEN context is set to true', () => {
addTokenToHeaderSpy.and.callThrough(); addTokenToHeaderSpy.and.callThrough();
request.context.set(SHOULD_ADD_AUTH_TOKEN, true); request.context.set(SHOULD_ADD_AUTH_TOKEN, true);
interceptor.intercept(request, mockNext); interceptor.intercept(request, mockNext);
expect(addTokenToHeaderSpy).toHaveBeenCalled(); expect(addTokenToHeaderSpy).toHaveBeenCalled();
}); });
it('should not call add auth token method when SHOULD_ADD_AUTH_TOKEN context is set to false', () => { it('should not call add auth token method when SHOULD_ADD_AUTH_TOKEN context is set to false', () => {
request.context.set(SHOULD_ADD_AUTH_TOKEN, false); request.context.set(SHOULD_ADD_AUTH_TOKEN, false);
interceptor.intercept(request, mockNext); interceptor.intercept(request, mockNext);
expect(addTokenToHeaderSpy).not.toHaveBeenCalled(); expect(addTokenToHeaderSpy).not.toHaveBeenCalled();
}); });
it('should not call add auth token method when SHOULD_ADD_AUTH_TOKEN context is not provided', () => { it('should not call add auth token method when SHOULD_ADD_AUTH_TOKEN context is not provided', () => {
interceptor.intercept(request, mockNext); interceptor.intercept(request, mockNext);
expect(addTokenToHeaderSpy).not.toHaveBeenCalled(); expect(addTokenToHeaderSpy).not.toHaveBeenCalled();
}); });
}); });

View File

@ -36,42 +36,37 @@ export const SHOULD_ADD_AUTH_TOKEN = new HttpContextToken<boolean>(() => false);
@Injectable() @Injectable()
export class AuthenticationInterceptor implements HttpInterceptor { export class AuthenticationInterceptor implements HttpInterceptor {
constructor(private authService: Authentication) {}
constructor( private authService: Authentication) { } intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
if (req.context.get(SHOULD_ADD_AUTH_TOKEN)) {
return this.authService.addTokenToHeader(req.url, req.headers).pipe(
mergeMap((headersWithBearer) => {
const headerWithContentType = this.appendJsonContentType(headersWithBearer);
const kcReq = req.clone({ headers: headerWithContentType });
return next.handle(kcReq).pipe(catchError((error) => observableThrowError(error)));
})
);
}
intercept(req: HttpRequest<any>, next: HttpHandler): return next.handle(req).pipe(catchError((error) => observableThrowError(error)));
Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
if (req.context.get(SHOULD_ADD_AUTH_TOKEN)) {
return this.authService.addTokenToHeader(req.url, req.headers).pipe(
mergeMap((headersWithBearer) => {
const headerWithContentType = this.appendJsonContentType(headersWithBearer);
const kcReq = req.clone({ headers: headerWithContentType});
return next.handle(kcReq)
.pipe(
catchError((error) => observableThrowError(error))
);
})
);
}
return next.handle(req).pipe(catchError((error) => observableThrowError(error)));
} }
private appendJsonContentType(headers: HttpHeaders): HttpHeaders { private appendJsonContentType(headers: HttpHeaders): HttpHeaders {
// prevent adding any content type, to properly handle formData with boundary browser generated value,
// as adding any Content-Type its going to break the upload functionality
// prevent adding any content type, to properly handle formData with boundary browser generated value, if (headers.get('Content-Type') === 'multipart/form-data') {
// as adding any Content-Type its going to break the upload functionality return headers.delete('Content-Type');
}
if (headers.get('Content-Type') === 'multipart/form-data') { if (!headers.get('Content-Type')) {
return headers.delete('Content-Type'); return headers.set('Content-Type', 'application/json;charset=UTF-8');
} }
if (!headers.get('Content-Type')) { return headers;
return headers.set('Content-Type', 'application/json;charset=UTF-8');
}
return headers;
} }
} }

View File

@ -47,13 +47,7 @@ const meta: Meta = {
component: DemoBreadcrumbComponent, component: DemoBreadcrumbComponent,
decorators: [ decorators: [
moduleMetadata({ moduleMetadata({
imports: [ imports: [BreadcrumbComponent, BreadcrumbItemComponent, MatButtonModule, MatMenuModule, MatIconModule]
BreadcrumbComponent,
BreadcrumbItemComponent,
MatButtonModule,
MatMenuModule,
MatIconModule
]
}), }),
applicationConfig({ applicationConfig({
providers: [importProvidersFrom(CoreStoryModule)] providers: [importProvidersFrom(CoreStoryModule)]

View File

@ -15,11 +15,11 @@
* limitations under the License. * limitations under the License.
*/ */
import {Component} from '@angular/core'; import { Component } from '@angular/core';
@Component({ @Component({
selector: 'adf-demo-breadcrumb', selector: 'adf-demo-breadcrumb',
template: ` template: `
<adf-breadcrumb [compact]="compact"> <adf-breadcrumb [compact]="compact">
<adf-breadcrumb-item> <adf-breadcrumb-item>
<a href="/">Home</a> <a href="/">Home</a>
@ -58,6 +58,6 @@ import {Component} from '@angular/core';
` `
}) })
export class DemoBreadcrumbComponent { export class DemoBreadcrumbComponent {
compact = false; compact = false;
showBreadcrumbItemWithMenu = false; showBreadcrumbItemWithMenu = false;
} }

View File

@ -22,7 +22,7 @@ import { Component, TemplateRef, ViewChild } from '@angular/core';
selector: 'adf-breadcrumb-item', selector: 'adf-breadcrumb-item',
template: ` template: `
<ng-template #breadcrumbItemTemplate> <ng-template #breadcrumbItemTemplate>
<ng-content></ng-content> <ng-content />
</ng-template> </ng-template>
` `
}) })

View File

@ -34,13 +34,8 @@ export class BreadcrumbFocusDirective {
private getFocusableElements(root: HTMLElement): HTMLElement[] { private getFocusableElements(root: HTMLElement): HTMLElement[] {
const allFocusableElements = `button, a, input, select, textarea, [tabindex]:not([tabindex="-1"])`; const allFocusableElements = `button, a, input, select, textarea, [tabindex]:not([tabindex="-1"])`;
return Array.from( return Array.from(root.querySelectorAll(allFocusableElements) as NodeListOf<HTMLElement>).filter(
root.querySelectorAll( (element) => !element.hasAttribute('disabled') && element.tabIndex >= 0
allFocusableElements
) as NodeListOf<HTMLElement>
).filter(
(element) =>
!element.hasAttribute('disabled') && element.tabIndex >= 0
); );
} }
} }

View File

@ -23,7 +23,7 @@ import { Observable } from 'rxjs';
export const isFeatureOff = (flag: string) => () => inject(FeaturesServiceToken).isOff$(flag); export const isFeatureOff = (flag: string) => () => inject(FeaturesServiceToken).isOff$(flag);
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class IsFeatureOff { export class IsFeatureOff {
constructor(@Inject(FeaturesServiceToken) private featuresServiceToken: IFeaturesService) {} constructor(@Inject(FeaturesServiceToken) private featuresServiceToken: IFeaturesService) {}
canMatch(route: Route): Observable<boolean> { canMatch(route: Route): Observable<boolean> {

View File

@ -23,7 +23,7 @@ import { Observable } from 'rxjs';
export const isFeatureOn = (flag: string) => () => inject(FeaturesServiceToken).isOn$(flag); export const isFeatureOn = (flag: string) => () => inject(FeaturesServiceToken).isOn$(flag);
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class IsFeatureOn { export class IsFeatureOn {
constructor(@Inject(FeaturesServiceToken) private featuresServiceToken: IFeaturesService) {} constructor(@Inject(FeaturesServiceToken) private featuresServiceToken: IFeaturesService) {}
canMatch(route: Route): Observable<boolean> { canMatch(route: Route): Observable<boolean> {

View File

@ -18,11 +18,10 @@
import { Inject, Injectable, Optional, inject } from '@angular/core'; import { Inject, Injectable, Optional, inject } from '@angular/core';
import { FlagsOverrideToken } from '../interfaces/features.interface'; import { FlagsOverrideToken } from '../interfaces/features.interface';
export const isFlagsOverrideOn = () => () => inject(FlagsOverrideToken) ?? false; export const isFlagsOverrideOn = () => () => inject(FlagsOverrideToken) ?? false;
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class IsFlagsOverrideOn { export class IsFlagsOverrideOn {
constructor(@Optional() @Inject(FlagsOverrideToken) private devToolsToken: boolean) {} constructor(@Optional() @Inject(FlagsOverrideToken) private devToolsToken: boolean) {}
canMatch(): boolean { canMatch(): boolean {

View File

@ -27,22 +27,22 @@
"rxjs": "7.8.1" "rxjs": "7.8.1"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/animations": "16.2.9", "@angular/animations": ">=16.0.0",
"@angular/cdk": "16.2.9", "@angular/cdk": ">=16.0.0",
"@angular/common": "16.2.9", "@angular/common": ">=16.0.0",
"@angular/core": "16.2.9", "@angular/core": ">=16.0.0",
"@angular/forms": "16.2.9", "@angular/forms": ">=16.0.0",
"@angular/material": "16.2.9", "@angular/material": ">=16.0.0",
"@angular/material-date-fns-adapter": "16.2.9", "@angular/material-date-fns-adapter": ">=16.0.0",
"@angular/platform-browser": "16.2.9", "@angular/platform-browser": ">=16.0.0",
"@angular/router": "16.2.9", "@angular/router": ">=16.0.0",
"@mat-datetimepicker/core": "12.0.1", "@mat-datetimepicker/core": ">=12.0.1",
"@ngx-translate/core": "^14.0.0", "@ngx-translate/core": ">=14.0.0",
"@alfresco/js-api": ">=8.0.0-alpha.8-0", "@alfresco/js-api": ">=8.0.0-alpha.8-0",
"@alfresco/adf-extensions": ">=7.0.0-alpha.8-0", "@alfresco/adf-extensions": ">=7.0.0-alpha.8-0",
"minimatch": "^10.0.1", "minimatch": ">=10.0.0",
"pdfjs-dist": "3.3.122", "pdfjs-dist": ">=3.3.122",
"ts-morph": "^20.0.0" "ts-morph": ">=20.0.0"
}, },
"keywords": [ "keywords": [
"core", "core",

View File

@ -24,7 +24,7 @@
"defaultConfiguration": "production" "defaultConfiguration": "production"
}, },
"build-schematics": { "build-schematics": {
"executor": "@nrwl/js:tsc", "executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"], "outputs": ["{options.outputPath}"],
"options": { "options": {
"outputPath": "dist/libs/core/schematics/migrations", "outputPath": "dist/libs/core/schematics/migrations",
@ -48,7 +48,7 @@
} }
}, },
"lint": { "lint": {
"executor": "@nrwl/linter:eslint", "executor": "@nx/eslint:lint",
"options": { "options": {
"lintFilePatterns": [ "lintFilePatterns": [
"lib/core/**/*.ts", "lib/core/**/*.ts",
@ -71,10 +71,7 @@
"browserTarget": "core:build", "browserTarget": "core:build",
"configDir": "lib/core/.storybook", "configDir": "lib/core/.storybook",
"compodoc": false, "compodoc": false,
"styles": [ "styles": ["node_modules/cropperjs/dist/cropper.min.css", "node_modules/pdfjs-dist/web/pdf_viewer.css"],
"node_modules/cropperjs/dist/cropper.min.css",
"node_modules/pdfjs-dist/web/pdf_viewer.css"
],
"stylePreprocessorOptions": { "stylePreprocessorOptions": {
"includePaths": ["lib", "lib/core/src/lib"] "includePaths": ["lib", "lib/core/src/lib"]
} }

View File

@ -20,8 +20,8 @@ import { ShellLayoutComponent } from './components/shell/shell.component';
import { SHELL_AUTH_TOKEN } from './services/shell-app.service'; import { SHELL_AUTH_TOKEN } from './services/shell-app.service';
export const SHELL_LAYOUT_ROUTE: Route = { export const SHELL_LAYOUT_ROUTE: Route = {
path: '', path: '',
component: ShellLayoutComponent, component: ShellLayoutComponent,
canActivate: [SHELL_AUTH_TOKEN], canActivate: [SHELL_AUTH_TOKEN],
children: [] children: []
}; };

View File

@ -69,10 +69,7 @@ describe('StoragePrefixFactory', () => {
} }
}; };
const prefixFactory = new StoragePrefixFactory( const prefixFactory = new StoragePrefixFactory(appConfigService as AppConfigService, externalPrefixFactory);
appConfigService as AppConfigService,
externalPrefixFactory
);
prefixFactory.getPrefix().subscribe((prefix) => { prefixFactory.getPrefix().subscribe((prefix) => {
expect(prefix).toBe('prefix-from-factory'); expect(prefix).toBe('prefix-from-factory');
@ -95,10 +92,7 @@ describe('StoragePrefixFactory', () => {
} }
}; };
const prefixFactory = new StoragePrefixFactory( const prefixFactory = new StoragePrefixFactory(appConfigService as AppConfigService, externalPrefixFactory);
appConfigService as AppConfigService,
externalPrefixFactory
);
prefixFactory.getPrefix().subscribe((prefix) => { prefixFactory.getPrefix().subscribe((prefix) => {
expect(prefix).toBe(appConfigPrefix); expect(prefix).toBe(appConfigPrefix);

View File

@ -33,7 +33,8 @@ export class StoragePrefixFactory {
constructor( constructor(
private appConfigService: AppConfigService, private appConfigService: AppConfigService,
@Optional() @Optional()
@Inject(STORAGE_PREFIX_FACTORY_SERVICE) private storagePrefixFactory?: StoragePrefixFactoryService @Inject(STORAGE_PREFIX_FACTORY_SERVICE)
private storagePrefixFactory?: StoragePrefixFactoryService
) {} ) {}
getPrefix(): Observable<string | undefined> { getPrefix(): Observable<string | undefined> {
@ -43,9 +44,7 @@ export class StoragePrefixFactory {
return of(prefix); return of(prefix);
} }
return this.storagePrefixFactory ? return this.storagePrefixFactory ? this.storagePrefixFactory.getPrefix() : of(prefix);
this.storagePrefixFactory.getPrefix() :
of(prefix);
}) })
); );
} }

View File

@ -34,8 +34,7 @@ export function loadAppConfig(
storageService: StorageService, storageService: StorageService,
adfHttpClient: AdfHttpClient, adfHttpClient: AdfHttpClient,
storagePrefixFactory: StoragePrefixFactory storagePrefixFactory: StoragePrefixFactory
) { ) {
const init = () => { const init = () => {
adfHttpClient.disableCsrf = appConfigService.get<boolean>(AppConfigValues.DISABLECSRF, true); adfHttpClient.disableCsrf = appConfigService.get<boolean>(AppConfigValues.DISABLECSRF, true);
storageService.prefix = appConfigService.get<string>(AppConfigValues.STORAGE_PREFIX, ''); storageService.prefix = appConfigService.get<string>(AppConfigValues.STORAGE_PREFIX, '');
@ -45,4 +44,4 @@ export function loadAppConfig(
}); });
}; };
return () => appConfigService.load(init); return () => appConfigService.load(init);
}; }

View File

@ -23,9 +23,10 @@ import { AuthenticationService } from '../services/authentication.service';
import { RedirectAuthService } from '../oidc/redirect-auth.service'; import { RedirectAuthService } from '../oidc/redirect-auth.service';
const mockNext: HttpHandler = { const mockNext: HttpHandler = {
handle: () => new Observable(subscriber => { handle: () =>
subscriber.complete(); new Observable((subscriber) => {
}) subscriber.complete();
})
}; };
const mockRequest = (url) => new HttpRequest('GET', url); const mockRequest = (url) => new HttpRequest('GET', url);

View File

@ -18,8 +18,15 @@
import { throwError as observableThrowError, Observable } from 'rxjs'; import { throwError as observableThrowError, Observable } from 'rxjs';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { import {
HttpHandler, HttpInterceptor, HttpRequest, HttpHandler,
HttpSentEvent, HttpHeaderResponse, HttpProgressEvent, HttpResponse, HttpUserEvent, HttpHeaders HttpInterceptor,
HttpRequest,
HttpSentEvent,
HttpHeaderResponse,
HttpProgressEvent,
HttpResponse,
HttpUserEvent,
HttpHeaders
} from '@angular/common/http'; } from '@angular/common/http';
import { catchError, mergeMap } from 'rxjs/operators'; import { catchError, mergeMap } from 'rxjs/operators';
import { AuthenticationService } from '../services/authentication.service'; import { AuthenticationService } from '../services/authentication.service';
@ -30,61 +37,52 @@ export class AuthBearerInterceptor implements HttpInterceptor {
private excludedUrlsRegex: RegExp[]; private excludedUrlsRegex: RegExp[];
constructor(private authenticationService: AuthenticationService) { } constructor(private authenticationService: AuthenticationService) {}
private loadExcludedUrlsRegex() { private loadExcludedUrlsRegex() {
const excludedUrls = this.bearerExcludedUrls; const excludedUrls = this.bearerExcludedUrls;
this.excludedUrlsRegex = excludedUrls.map((urlPattern) => new RegExp(`^https?://[^/]+/${urlPattern}`, 'i')) || []; this.excludedUrlsRegex = excludedUrls.map((urlPattern) => new RegExp(`^https?://[^/]+/${urlPattern}`, 'i')) || [];
}
intercept(req: HttpRequest<any>, next: HttpHandler):
Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
if (!this.excludedUrlsRegex) {
this.loadExcludedUrlsRegex();
} }
const requestUrl = req.url; intercept(
const shallPass: boolean = this.excludedUrlsRegex.some((regex) => regex.test(requestUrl)); req: HttpRequest<any>,
if (shallPass) { next: HttpHandler
return next.handle(req) ): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
.pipe( if (!this.excludedUrlsRegex) {
catchError((error) => observableThrowError(error)) this.loadExcludedUrlsRegex();
}
const requestUrl = req.url;
const shallPass: boolean = this.excludedUrlsRegex.some((regex) => regex.test(requestUrl));
if (shallPass) {
return next.handle(req).pipe(catchError((error) => observableThrowError(error)));
}
return this.authenticationService.addTokenToHeader(requestUrl, req.headers).pipe(
mergeMap((headersWithBearer) => {
const headerWithContentType = this.appendJsonContentType(headersWithBearer, req.body);
const kcReq = req.clone({ headers: headerWithContentType });
return next.handle(kcReq).pipe(catchError((error) => observableThrowError(error)));
})
); );
} }
return this.authenticationService.addTokenToHeader(requestUrl, req.headers) private appendJsonContentType(headers: HttpHeaders, reqBody: any): HttpHeaders {
.pipe( // prevent adding any content type, to properly handle formData with boundary browser generated value,
mergeMap((headersWithBearer) => { // as adding any Content-Type its going to break the upload functionality
const headerWithContentType = this.appendJsonContentType(headersWithBearer, req.body);
const kcReq = req.clone({ headers: headerWithContentType});
return next.handle(kcReq)
.pipe(
catchError((error) => observableThrowError(error))
);
})
);
}
private appendJsonContentType(headers: HttpHeaders, reqBody: any): HttpHeaders { if (headers.get('Content-Type') === 'multipart/form-data' && !(reqBody instanceof FormData)) {
return headers.delete('Content-Type');
}
// prevent adding any content type, to properly handle formData with boundary browser generated value, if (!headers.get('Content-Type') && !(reqBody instanceof FormData)) {
// as adding any Content-Type its going to break the upload functionality return headers.set('Content-Type', 'application/json;charset=UTF-8');
}
if (headers.get('Content-Type') === 'multipart/form-data' && !(reqBody instanceof FormData)) { return headers;
return headers.delete('Content-Type');
} }
if (!headers.get('Content-Type') && !(reqBody instanceof FormData)) {
return headers.set('Content-Type', 'application/json;charset=UTF-8');
}
return headers;
}
protected get bearerExcludedUrls(): readonly string[] { protected get bearerExcludedUrls(): readonly string[] {
return this._bearerExcludedUrls; return this._bearerExcludedUrls;
} }
} }

View File

@ -38,7 +38,6 @@ export interface TicketEntry {
providedIn: 'root' providedIn: 'root'
}) })
export class ContentAuth { export class ContentAuth {
onLogin = new ReplaySubject<any>(1); onLogin = new ReplaySubject<any>(1);
onLogout = new ReplaySubject<any>(1); onLogout = new ReplaySubject<any>(1);
onError = new Subject<any>(); onError = new Subject<any>();
@ -60,9 +59,7 @@ export class ContentAuth {
return this.appConfigService.get<string>(AppConfigValues.ECMHOST) + '/' + contextRootEcm + '/api/-default-/public/authentication/versions/1'; return this.appConfigService.get<string>(AppConfigValues.ECMHOST) + '/' + contextRootEcm + '/api/-default-/public/authentication/versions/1';
} }
constructor(private appConfigService: AppConfigService, constructor(private appConfigService: AppConfigService, private adfHttpClient: AdfHttpClient, private storageService: StorageService) {
private adfHttpClient: AdfHttpClient,
private storageService: StorageService) {
this.appConfigService.onLoad.subscribe(() => { this.appConfigService.onLoad.subscribe(() => {
this.setConfig(); this.setConfig();
}); });
@ -72,7 +69,6 @@ export class ContentAuth {
if (this.storageService.getItem(AppConfigValues.CONTENT_TICKET_STORAGE_LABEL)) { if (this.storageService.getItem(AppConfigValues.CONTENT_TICKET_STORAGE_LABEL)) {
this.setTicket(this.storageService.getItem(AppConfigValues.CONTENT_TICKET_STORAGE_LABEL)); this.setTicket(this.storageService.getItem(AppConfigValues.CONTENT_TICKET_STORAGE_LABEL));
} }
} }
saveUsername(username: string) { saveUsername(username: string) {
@ -148,7 +144,8 @@ export class ContentAuth {
this.adfHttpClient.emit('error'); this.adfHttpClient.emit('error');
this.onError.next('error'); this.onError.next('error');
reject(error); reject(error);
}); }
);
}); });
} }
@ -200,12 +197,12 @@ export class ContentAuth {
createTicket(ticketBodyCreate: TicketBody): Promise<TicketEntry> { createTicket(ticketBodyCreate: TicketBody): Promise<TicketEntry> {
if (ticketBodyCreate === null || ticketBodyCreate === undefined) { if (ticketBodyCreate === null || ticketBodyCreate === undefined) {
this.onError.next((`Missing param ticketBodyCreate`)); this.onError.next(`Missing param ticketBodyCreate`);
throw new Error(`Missing param ticketBodyCreate`); throw new Error(`Missing param ticketBodyCreate`);
} }
return this.adfHttpClient.post(this.basePath + '/tickets', {bodyParam: ticketBodyCreate}); return this.adfHttpClient.post(this.basePath + '/tickets', { bodyParam: ticketBodyCreate });
} }
async requireAlfTicket(): Promise<void> { async requireAlfTicket(): Promise<void> {
@ -216,5 +213,4 @@ export class ContentAuth {
deleteTicket(): Promise<any> { deleteTicket(): Promise<any> {
return this.adfHttpClient.delete(this.basePath + '/tickets/-me-'); return this.adfHttpClient.delete(this.basePath + '/tickets/-me-');
} }
} }

View File

@ -22,12 +22,10 @@ import { AppConfigService, AppConfigValues } from '../../app-config/app-config.s
import { StorageService } from '../../common/services/storage.service'; import { StorageService } from '../../common/services/storage.service';
import { ReplaySubject, Subject } from 'rxjs'; import { ReplaySubject, Subject } from 'rxjs';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class ProcessAuth { export class ProcessAuth {
onLogin = new ReplaySubject<any>(1); onLogin = new ReplaySubject<any>(1);
onLogout = new ReplaySubject<any>(1); onLogout = new ReplaySubject<any>(1);
onError = new Subject<any>(); onError = new Subject<any>();
@ -38,7 +36,8 @@ export class ProcessAuth {
}; };
authentications: Authentication = { authentications: Authentication = {
basicAuth: {ticket: ''}, type: 'activiti' basicAuth: { ticket: '' },
type: 'activiti'
}; };
get basePath(): string { get basePath(): string {
@ -46,9 +45,7 @@ export class ProcessAuth {
return this.appConfigService.get<string>(AppConfigValues.BPMHOST) + '/' + contextRootBpm; return this.appConfigService.get<string>(AppConfigValues.BPMHOST) + '/' + contextRootBpm;
} }
constructor(private appConfigService: AppConfigService, constructor(private appConfigService: AppConfigService, private adfHttpClient: AdfHttpClient, private storageService: StorageService) {
private adfHttpClient: AdfHttpClient,
private storageService: StorageService) {
this.appConfigService.onLoad.subscribe(() => { this.appConfigService.onLoad.subscribe(() => {
this.setConfig(); this.setConfig();
}); });
@ -118,7 +115,8 @@ export class ProcessAuth {
this.onError.next('error'); this.onError.next('error');
} }
reject(error); reject(error);
}); }
);
}); });
return promise; return promise;
@ -147,7 +145,8 @@ export class ProcessAuth {
this.adfHttpClient.emit('error'); this.adfHttpClient.emit('error');
this.onError.next('error'); this.onError.next('error');
reject(error); reject(error);
}); }
);
}); });
} }

Some files were not shown because too many files have changed in this diff Show More