mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
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:
parent
2284ede0c7
commit
5d64c7f0ed
@ -10,3 +10,4 @@ scripts
|
|||||||
docs/**/*.md
|
docs/**/*.md
|
||||||
lib/js-api/docs/**/*.md
|
lib/js-api/docs/**/*.md
|
||||||
.storybook
|
.storybook
|
||||||
|
webpack.config.js
|
||||||
|
2
.github/workflows/pull-request.yml
vendored
2
.github/workflows/pull-request.yml
vendored
@ -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
4
jest.preset.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
// eslint-disable
|
||||||
|
const nxPreset = require('@nx/jest/preset').default;
|
||||||
|
|
||||||
|
module.exports = {...nxPreset };
|
@ -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"]
|
||||||
}
|
}
|
||||||
|
@ -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"]
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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';
|
||||||
|
@ -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) => {
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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({
|
||||||
|
@ -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] } };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 }))
|
||||||
}));
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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('');
|
||||||
|
@ -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;
|
||||||
|
@ -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))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
|
@ -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]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
@ -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[] {
|
||||||
|
@ -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));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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[] {
|
||||||
|
@ -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) => {
|
||||||
|
@ -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
|
||||||
|
}),
|
||||||
|
{}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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';
|
||||||
}
|
}
|
||||||
|
@ -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'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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'
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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();
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
@ -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: {
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
/**
|
/**
|
||||||
|
@ -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
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
))
|
)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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';
|
||||||
|
@ -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.
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
<div class="adf-empty-search-result">
|
<div class="adf-empty-search-result">
|
||||||
<ng-content></ng-content>
|
<ng-content />
|
||||||
</div>
|
</div>
|
||||||
|
@ -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>
|
||||||
|
@ -15,5 +15,5 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-content></ng-content>
|
<ng-content />
|
||||||
</mat-chip-set>
|
</mat-chip-set>
|
||||||
|
@ -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>
|
||||||
|
@ -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) {
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,5 @@
|
|||||||
<ng-template
|
<ng-template
|
||||||
ngFor
|
ngFor
|
||||||
[ngForOf]="files"
|
[ngForOf]="files"
|
||||||
[ngForTemplate]="template">
|
[ngForTemplate]="template" />
|
||||||
</ng-template>
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -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>
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -14,5 +14,6 @@
|
|||||||
},
|
},
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
"useDefineForClassFields": false
|
"useDefineForClassFields": false
|
||||||
}
|
},
|
||||||
|
"include": ["src/**/*.ts", "index.ts"]
|
||||||
}
|
}
|
||||||
|
@ -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"]
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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)]
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
|
@ -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
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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> {
|
||||||
|
@ -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> {
|
||||||
|
@ -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 {
|
||||||
|
@ -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",
|
||||||
|
@ -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"]
|
||||||
}
|
}
|
||||||
|
@ -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: []
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
};
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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-');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user