[PRODENG-211] integrate JS-API with monorepo (part 1) (#9081)

* integrate JS-API with monorepo

* [ci:force] fix token issue

[ci:force] migrate docs folder

[ci:force] clean personal tokens

* [ci:force] gha workflow support

* [ci:force] npm publish target

* fix js-api test linting

* [ci:force] fix test linting, mocks, https scheme

* [ci:force] fix https scheme

* [ci:force] typescript mappings

* [ci:force] update scripts

* lint fixes

* linting fixes

* fix linting

* [ci:force] linting fixes

* linting fixes

* [ci:force] remove js-api upstream and corresponding scripts

* [ci:force] jsdoc fixes

* fix jsdoc linting

* [ci:force] jsdoc fixes

* [ci:force] jsdoc fixes

* jsdoc fixes

* jsdoc fixes

* jsdoc fixes

* [ci:force] fix jsdoc

* [ci:force] reduce code duplication

* replace 'chai' expect with node.js assert

* replace 'chai' expect with node.js assert

* [ci:force] remove chai and chai-spies for js-api testing

* [ci:force] cleanup and fix imports

* [ci:force] fix linting

* [ci:force] fix unit test

* [ci:force] fix sonar linting findings

* [ci:force] switch activiti api models to interfaces (-2.5% reduction of bundle)

* [ci:force] switch activiti api models to interfaces

* [ci:force] switch AGS api models to interfaces

* [ci:force] switch AGS api models to interfaces

* [ci:force] switch search api models to interfaces

* [ci:force] switch content api models to interfaces where applicable
This commit is contained in:
Denys Vuika
2023-11-21 10:27:51 +00:00
committed by GitHub
parent 804fa2ffd4
commit ea2c0ce229
1334 changed files with 82605 additions and 1068 deletions

View File

@@ -18,7 +18,7 @@
import { Injectable } from '@angular/core';
import { Observable, from } from 'rxjs';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { AuditApi, AuditAppPaging, AuditApp, AuditBodyUpdate, AuditEntryPaging, AuditEntryEntry } from '@alfresco/js-api';
import { AuditApi, AuditAppPaging, AuditApp, AuditEntryPaging, AuditEntryEntry } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
@@ -72,7 +72,7 @@ export class AuditService {
updateAuditApp(auditApplicationId: string, auditAppBodyUpdate: boolean, opts?: any): Observable<AuditApp | any> {
const defaultOptions = {};
const queryOptions = Object.assign({}, defaultOptions, opts);
return from(this.auditApi.updateAuditApp(auditApplicationId, new AuditBodyUpdate({ isEnabled: auditAppBodyUpdate }), queryOptions));
return from(this.auditApi.updateAuditApp(auditApplicationId, { isEnabled: auditAppBodyUpdate }, queryOptions));
}
/**

View File

@@ -20,10 +20,12 @@ import {
CategoryBody,
CategoryEntry,
CategoryLinkBody,
CategoryPaging, PathInfo,
RequestQuery, ResultNode,
CategoryPaging,
PathInfo,
ResultNode,
ResultSetPaging,
ResultSetPagingList, ResultSetRowEntry
ResultSetPagingList,
ResultSetRowEntry
} from '@alfresco/js-api';
import { fakeAsync, TestBed } from '@angular/core/testing';
import { CategoryService } from './category.service';
@@ -35,16 +37,14 @@ describe('CategoryService', () => {
const fakeParentCategoryId = 'testParentId';
const fakeCategoryId = 'fakeId';
const fakeNodeId = 'fakeNodeId';
const fakeCategoriesResponse: CategoryPaging = { list: { pagination: {}, entries: [] }};
const fakeCategoryEntry: CategoryEntry = { entry: { id: 'testId', name: 'testName' }};
const fakeCategoriesResponse: CategoryPaging = { list: { pagination: {}, entries: [] } };
const fakeCategoryEntry: CategoryEntry = { entry: { id: 'testId', name: 'testName' } };
const fakeCategoryBody: CategoryBody = { name: 'updatedName' };
const fakeCategoriesLinkBodies: CategoryLinkBody[] = [{ categoryId: fakeCategoryId }];
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
CoreTestingModule
]
imports: [CoreTestingModule]
});
categoryService = TestBed.inject(CategoryService);
@@ -54,21 +54,21 @@ describe('CategoryService', () => {
it('should fetch categories with provided parentId', fakeAsync(() => {
const getSpy = spyOn(categoryService.categoriesApi, 'getSubcategories').and.returnValue(Promise.resolve(fakeCategoriesResponse));
categoryService.getSubcategories(fakeParentCategoryId, 0, 100).subscribe(() => {
expect(getSpy).toHaveBeenCalledOnceWith(fakeParentCategoryId, {skipCount: 0, maxItems: 100});
expect(getSpy).toHaveBeenCalledOnceWith(fakeParentCategoryId, { skipCount: 0, maxItems: 100 });
});
}));
it('should fetch root level categories when parentId not provided', fakeAsync(() => {
const getSpy = spyOn(categoryService.categoriesApi, 'getSubcategories').and.returnValue(Promise.resolve(fakeCategoriesResponse));
categoryService.getSubcategories(null, 0, 100).subscribe(() => {
expect(getSpy).toHaveBeenCalledOnceWith('-root-', {skipCount: 0, maxItems: 100});
expect(getSpy).toHaveBeenCalledOnceWith('-root-', { skipCount: 0, maxItems: 100 });
});
}));
it('should fetch the category with the provided categoryId', fakeAsync(() => {
const getSpy = spyOn(categoryService.categoriesApi, 'getCategory').and.returnValue(Promise.resolve(fakeCategoryEntry));
categoryService.getCategory(fakeParentCategoryId, {include: ['path']}).subscribe(() => {
expect(getSpy).toHaveBeenCalledOnceWith(fakeParentCategoryId, {include: ['path']});
categoryService.getCategory(fakeParentCategoryId, { include: ['path'] }).subscribe(() => {
expect(getSpy).toHaveBeenCalledOnceWith(fakeParentCategoryId, { include: ['path'] });
});
}));
@@ -119,7 +119,7 @@ describe('CategoryService', () => {
categoryService.searchCategories(name, skipCount, maxItems);
expect(categoryService.searchApi.search).toHaveBeenCalledWith({
query: {
language: RequestQuery.LanguageEnum.Afts,
language: 'afts',
query: `cm:name:"*${name}*" AND TYPE:'cm:category' AND PATH:"/cm:categoryRoot/cm:generalclassifiable//*"`
},
paging: {
@@ -136,7 +136,7 @@ describe('CategoryService', () => {
categoryService.searchCategories(name);
expect(categoryService.searchApi.search).toHaveBeenCalledWith({
query: {
language: RequestQuery.LanguageEnum.Afts,
language: 'afts',
query: `cm:name:"*${name}*" AND TYPE:'cm:category' AND PATH:"/cm:categoryRoot/cm:generalclassifiable//*"`
},
paging: {
@@ -156,9 +156,11 @@ describe('CategoryService', () => {
});
it('should fetch categories linked to node with nodeId with path included', fakeAsync(() => {
const getLinkedCategoriesSpy = spyOn(categoryService.categoriesApi, 'getCategoryLinksForNode').and.returnValue(Promise.resolve(fakeCategoriesResponse));
const getLinkedCategoriesSpy = spyOn(categoryService.categoriesApi, 'getCategoryLinksForNode').and.returnValue(
Promise.resolve(fakeCategoriesResponse)
);
categoryService.getCategoryLinksForNode(fakeNodeId).subscribe(() => {
expect(getLinkedCategoriesSpy).toHaveBeenCalledOnceWith(fakeNodeId, {include: ['path']});
expect(getLinkedCategoriesSpy).toHaveBeenCalledOnceWith(fakeNodeId, { include: ['path'] });
});
}));

View File

@@ -17,16 +17,7 @@
import { Injectable } from '@angular/core';
import { AlfrescoApiService, UserPreferencesService } from '@alfresco/adf-core';
import {
CategoriesApi,
CategoryBody,
CategoryEntry,
CategoryLinkBody,
CategoryPaging,
RequestQuery,
ResultSetPaging,
SearchApi
} from '@alfresco/js-api';
import { CategoriesApi, CategoryBody, CategoryEntry, CategoryLinkBody, CategoryPaging, ResultSetPaging, SearchApi } from '@alfresco/js-api';
import { from, Observable } from 'rxjs';
@Injectable({ providedIn: 'root' })
@@ -55,7 +46,7 @@ export class CategoryService {
* @returns Observable<CategoryPaging>
*/
getSubcategories(parentCategoryId: string, skipCount?: number, maxItems?: number): Observable<CategoryPaging> {
return from(this.categoriesApi.getSubcategories(parentCategoryId ?? '-root-', {skipCount, maxItems}));
return from(this.categoriesApi.getSubcategories(parentCategoryId ?? '-root-', { skipCount, maxItems }));
}
/**
@@ -115,17 +106,19 @@ export class CategoryService {
*/
searchCategories(name: string, skipCount = 0, maxItems?: number): Observable<ResultSetPaging> {
maxItems = maxItems || this.userPreferencesService.paginationSize;
return from(this.searchApi.search({
query: {
language: RequestQuery.LanguageEnum.Afts,
query: `cm:name:"*${name}*" AND TYPE:'cm:category' AND PATH:"/cm:categoryRoot/cm:generalclassifiable//*"`
},
paging: {
skipCount,
maxItems
},
include: ['path']
}));
return from(
this.searchApi.search({
query: {
language: 'afts',
query: `cm:name:"*${name}*" AND TYPE:'cm:category' AND PATH:"/cm:categoryRoot/cm:generalclassifiable//*"`
},
paging: {
skipCount,
maxItems
},
include: ['path']
})
);
}
/**
@@ -135,7 +128,7 @@ export class CategoryService {
* @returns Observable<CategoryPaging> Categories that node is assigned to
*/
getCategoryLinksForNode(nodeId: string): Observable<CategoryPaging> {
return from(this.categoriesApi.getCategoryLinksForNode(nodeId, {include: ['path']}));
return from(this.categoriesApi.getCategoryLinksForNode(nodeId, { include: ['path'] }));
}
/**
@@ -145,7 +138,7 @@ export class CategoryService {
* @param categoryId The identifier of a category.
* @returns Observable<void>
*/
unlinkNodeFromCategory(nodeId: string, categoryId: string): Observable<void> {
unlinkNodeFromCategory(nodeId: string, categoryId: string): Observable<void> {
return from(this.categoriesApi.unlinkNodeFromCategory(nodeId, categoryId));
}
@@ -156,7 +149,7 @@ export class CategoryService {
* @param categoryLinkBodyCreate Array of a categories that node will be linked to.
* @returns Observable<CategoryEntry>
*/
linkNodeToCategory(nodeId: string, categoryLinkBodyCreate: CategoryLinkBody[]): Observable<CategoryPaging | CategoryEntry> {
linkNodeToCategory(nodeId: string, categoryLinkBodyCreate: CategoryLinkBody[]): Observable<CategoryPaging | CategoryEntry> {
return from(this.categoriesApi.linkNodeToCategory(nodeId, categoryLinkBodyCreate));
}
}

View File

@@ -18,14 +18,13 @@
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Node, NodeEntry, NodePaging, PathElement, ResultSetPaging, Site, SiteEntry, SitePaging, SitePagingList, UserInfo } from '@alfresco/js-api';
import { Node, NodeEntry, NodePaging, ResultSetPaging, Site, SiteEntry, SitePaging, SitePagingList, UserInfo } from '@alfresco/js-api';
import { AppConfigService, DataRow, ThumbnailService, DataColumn } from '@alfresco/adf-core';
import { ContentService } from '../common/services/content.service';
import { UploadService } from '../common/services/upload.service';
import { NodesApiService } from '../common/services/nodes-api.service';
import { FileModel, FileUploadStatus } from '../common/models/file.model';
import { FileUploadCompleteEvent } from '../common/events/file.event';
import { of, throwError } from 'rxjs';
import { DropdownBreadcrumbComponent } from '../breadcrumb';
import { ContentNodeSelectorPanelComponent } from './content-node-selector-panel.component';
@@ -129,7 +128,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
it('should trigger siteChange event on init with parent site Title of start folder', () => {
let lastValue: string;
component.siteChange.subscribe((siteTitle: string) => lastValue = siteTitle);
component.siteChange.subscribe((siteTitle: string) => (lastValue = siteTitle));
component.ngOnInit();
fixture.detectChanges();
@@ -143,7 +142,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
await fixture.whenStable();
let lastValue: string;
component.siteChange.subscribe((siteTitle: string) => lastValue = siteTitle);
component.siteChange.subscribe((siteTitle: string) => (lastValue = siteTitle));
const sitesDropdown = fixture.debugElement.query(By.directive(DropdownSitesComponent));
sitesDropdown.componentInstance.selectedSite({ value: fakeSiteEntry });
@@ -180,7 +179,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
it('should trigger the select event when selection has been made', () => {
const expectedNode = { id: 'fakeid' } as Node;
let lastValue: Node[];
component.select.subscribe((nodes) => lastValue = nodes);
component.select.subscribe((nodes) => (lastValue = nodes));
component.chosenNode = [expectedNode];
expect(lastValue.length).toBe(1);
@@ -303,7 +302,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
searchQueryBuilderService.update();
triggerSearchResults(fakeResultSetPaging);
const chosenNode = new Node({ path: { elements: [new PathElement({ name: 'one' })] } });
const chosenNode = new Node({ path: { elements: [{ name: 'one' }] } });
component.onCurrentSelection([{ entry: chosenNode }]);
fixture.detectChanges();
@@ -318,7 +317,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
searchQueryBuilderService.update();
triggerSearchResults(fakeResultSetPaging);
const chosenNode = new Node({ path: { elements: [new PathElement({ name: 'fake-path' })] }, isFile: false, isFolder: true });
const chosenNode = new Node({ path: { elements: [{ name: 'fake-path' }] }, isFile: false, isFolder: true });
component.onCurrentSelection([{ entry: chosenNode }]);
fixture.detectChanges();

View File

@@ -17,8 +17,6 @@
import { Component, Inject, OnInit, ViewEncapsulation } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DownloadEntry } from '@alfresco/js-api';
import { LogService } from '@alfresco/adf-core';
import { NodesApiService } from '../../common/services/nodes-api.service';
import { DownloadZipService } from './services/download-zip.service';
import { ContentService } from '../../common/services/content.service';
@@ -39,7 +37,6 @@ export class DownloadZipDialogComponent implements OnInit {
private dialogRef: MatDialogRef<DownloadZipDialogComponent>,
@Inject(MAT_DIALOG_DATA)
public data: any,
private logService: LogService,
private downloadZipService: DownloadZipService,
private nodeService: NodesApiService,
private contentService: ContentService
@@ -49,8 +46,6 @@ export class DownloadZipDialogComponent implements OnInit {
if (this.data?.nodeIds?.length > 0) {
if (!this.cancelled) {
this.downloadZip(this.data.nodeIds);
} else {
this.logService.log('Cancelled');
}
}
}
@@ -63,12 +58,11 @@ export class DownloadZipDialogComponent implements OnInit {
downloadZip(nodeIds: string[]) {
if (nodeIds && nodeIds.length > 0) {
this.downloadZipService.createDownload({ nodeIds }).subscribe((data: DownloadEntry) => {
this.downloadZipService.createDownload({ nodeIds }).subscribe((data) => {
if (data?.entry?.id) {
const url = this.contentService.getContentUrl(data.entry.id, true);
this.nodeService.getNode(data.entry.id).subscribe((downloadNode) => {
this.logService.log(downloadNode);
const fileName = downloadNode.name;
this.downloadId = data.entry.id;
this.waitAndDownload(data.entry.id, url, fileName);
@@ -83,7 +77,7 @@ export class DownloadZipDialogComponent implements OnInit {
return;
}
this.downloadZipService.getDownload(downloadId).subscribe((downloadEntry: DownloadEntry) => {
this.downloadZipService.getDownload(downloadId).subscribe((downloadEntry) => {
if (downloadEntry.entry) {
if (downloadEntry.entry.status === 'DONE') {
this.download(url, fileName);

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { DownloadBodyCreate, DownloadEntry } from '@alfresco/js-api';
import { DownloadBodyCreate, DownloadEntry, Node } from '@alfresco/js-api';
import { from, Observable, of, ReplaySubject, Subject } from 'rxjs';
import { catchError } from 'rxjs/internal/operators/catchError';
import { zipNode, downloadEntry } from './download-zip-data.mock';
@@ -40,8 +40,7 @@ class AlfrescoApiMock {
}
export class ContentApiMock {
getContentUrl = (_: string, _1?: boolean, _2?: string): string =>
zipNode.entry.contentUrl;
getContentUrl = (_: string, _1?: boolean, _2?: string): string => zipNode.entry.contentUrl;
}
class CoreMock {
@@ -54,13 +53,9 @@ export class NodesApiMock {
}
class DownloadsApiMock {
createDownload = (
_: DownloadBodyCreate,
_2?: any
): Promise<DownloadEntry> => Promise.resolve(downloadEntry);
createDownload = (_: DownloadBodyCreate, _2?: any): Promise<DownloadEntry> => Promise.resolve(downloadEntry);
getDownload = (_: string, _2?: any): Promise<DownloadEntry> =>
Promise.resolve(downloadEntry);
getDownload = (_: string, _2?: any): Promise<DownloadEntry> => Promise.resolve(downloadEntry);
cancelDownload(_: string) {}
}
@@ -72,9 +67,7 @@ export class DownloadZipMockService {
}
createDownload(payload: DownloadBodyCreate): Observable<DownloadEntry> {
return from(this.downloadsApi.createDownload(payload)).pipe(
catchError((err) => of(err))
);
return from(this.downloadsApi.createDownload(payload)).pipe(catchError((err) => of(err)));
}
getDownload(downloadId: string): Observable<DownloadEntry> {

View File

@@ -28,7 +28,6 @@ import { AlfrescoApiService } from '@alfresco/adf-core';
encapsulation: ViewEncapsulation.None
})
export class NodeLockDialogComponent implements OnInit {
form: UntypedFormGroup;
node: Node = null;
nodeName: string;
@@ -46,8 +45,7 @@ export class NodeLockDialogComponent implements OnInit {
@Optional()
@Inject(MAT_DIALOG_DATA)
public data: any
) {
}
) {}
ngOnInit() {
const { node } = this.data;
@@ -73,15 +71,17 @@ export class NodeLockDialogComponent implements OnInit {
}
private get nodeBodyLock(): NodeBodyLock {
return new NodeBodyLock({
return {
timeToExpire: this.lockTimeInSeconds,
type: this.form.value.allowOwner ? 'ALLOW_OWNER_CHANGES' : 'FULL',
lifetime: 'PERSISTENT'
});
};
}
private toggleLock(): Promise<NodeEntry> {
const { data: { node } } = this;
const {
data: { node }
} = this;
if (this.form.value.isLocked) {
return this.nodesApi.lockNode(node.id, this.nodeBodyLock);

View File

@@ -41,7 +41,6 @@ const CREATE_PERMISSION: string = 'create';
@Injectable({ providedIn: 'root' })
export class CustomResourcesService {
private _peopleApi: PeopleApi;
get peopleApi(): PeopleApi {
this._peopleApi = this._peopleApi ?? new PeopleApi(this.apiService.getInstance());
@@ -84,8 +83,7 @@ export class CustomResourcesService {
return this._nodesApi;
}
constructor(private apiService: AlfrescoApiService) {
}
constructor(private apiService: AlfrescoApiService) {}
/**
* Gets files recently accessed by a user.
@@ -120,52 +118,57 @@ export class CustomResourcesService {
];
return new Observable((observer) => {
this.peopleApi.getPerson(personId)
.then((person) => {
const username = person.entry.id;
const filterQueries = [
{ query: `cm:modified:[NOW/DAY-30DAYS TO NOW/DAY+1DAY]` },
{ query: `cm:modifier:'${username}' OR cm:creator:'${username}'` },
{ query: defaultFilter.join(' AND ') }
];
this.peopleApi.getPerson(personId).then(
(person) => {
const username = person.entry.id;
const filterQueries = [
{ query: `cm:modified:[NOW/DAY-30DAYS TO NOW/DAY+1DAY]` },
{ query: `cm:modifier:'${username}' OR cm:creator:'${username}'` },
{ query: defaultFilter.join(' AND ') }
];
if (filters && filters.length > 0) {
filterQueries.push({
query: filters.join()
});
}
if (filters && filters.length > 0) {
filterQueries.push({
query: filters.join()
});
}
const query = new SearchRequest({
query: {
query: '*',
language: 'afts'
},
filterQueries,
include: ['path', 'properties', 'allowableOperations'],
sort: [{
const query: SearchRequest = {
query: {
query: '*',
language: 'afts'
},
filterQueries,
include: ['path', 'properties', 'allowableOperations'],
sort: [
{
type: 'FIELD',
field: 'cm:modified',
ascending: false
}],
paging: {
maxItems: pagination.maxItems,
skipCount: pagination.skipCount
}
});
return this.searchApi.search(query)
.then((searchResult) => {
observer.next(searchResult);
observer.complete();
},
(err) => {
observer.error(err);
observer.complete();
});
},
(err) => {
observer.error(err);
observer.complete();
});
],
paging: {
maxItems: pagination.maxItems,
skipCount: pagination.skipCount
}
};
return this.searchApi.search(query).then(
(searchResult) => {
observer.next(searchResult);
observer.complete();
},
(err) => {
observer.error(err);
observer.complete();
}
);
},
(err) => {
observer.error(err);
observer.complete();
}
);
});
}
@@ -189,36 +192,36 @@ export class CustomResourcesService {
};
return new Observable((observer) => {
this.favoritesApi.listFavorites('-me-', options)
.then((result) => {
const page: FavoritePaging = {
list: {
entries: result.list.entries
.map(({ entry }: any) => {
const target = entry.target.file || entry.target.folder;
target.properties = {
...(target.properties || {
'cm:title': entry.title || target.title,
'cm:description': entry.description || target.description
}),
...(entry.properties || {})
};
return {
entry: target
};
this.favoritesApi.listFavorites('-me-', options).then(
(result) => {
const page: FavoritePaging = {
list: {
entries: result.list.entries.map(({ entry }: any) => {
const target = entry.target.file || entry.target.folder;
target.properties = {
...(target.properties || {
'cm:title': entry.title || target.title,
'cm:description': entry.description || target.description
}),
pagination: result.list.pagination
}
};
...(entry.properties || {})
};
observer.next(page);
observer.complete();
},
(err) => {
observer.error(err);
observer.complete();
});
return {
entry: target
};
}),
pagination: result.list.pagination
}
};
observer.next(page);
observer.complete();
},
(err) => {
observer.error(err);
observer.complete();
}
);
});
}
@@ -238,29 +241,29 @@ export class CustomResourcesService {
};
return new Observable((observer) => {
this.sitesApi.listSiteMembershipsForPerson('-me-', options)
.then((result: SiteRolePaging) => {
const page: SiteMemberPaging = new SiteMemberPaging({
list: {
entries: result.list.entries
.map(({ entry: { site } }: any) => {
site.allowableOperations = site.allowableOperations ? site.allowableOperations : [CREATE_PERMISSION];
site.name = site.name || site.title;
return {
entry: site
};
}),
pagination: result.list.pagination
}
});
observer.next(page);
observer.complete();
},
(err) => {
observer.error(err);
observer.complete();
this.sitesApi.listSiteMembershipsForPerson('-me-', options).then(
(result: SiteRolePaging) => {
const page: SiteMemberPaging = new SiteMemberPaging({
list: {
entries: result.list.entries.map(({ entry: { site } }: any) => {
site.allowableOperations = site.allowableOperations ? site.allowableOperations : [CREATE_PERMISSION];
site.name = site.name || site.title;
return {
entry: site
};
}),
pagination: result.list.pagination
}
});
observer.next(page);
observer.complete();
},
(err) => {
observer.error(err);
observer.complete();
}
);
});
}
@@ -280,23 +283,20 @@ export class CustomResourcesService {
};
return new Observable((observer) => {
this.sitesApi
.listSites(options)
.then(
(page) => {
page.list.entries.map(
({ entry }: any) => {
entry.name = entry.name || entry.title;
return { entry };
}
);
observer.next(page);
observer.complete();
},
(err) => {
observer.error(err);
observer.complete();
this.sitesApi.listSites(options).then(
(page) => {
page.list.entries.map(({ entry }: any) => {
entry.name = entry.name || entry.title;
return { entry };
});
observer.next(page);
observer.complete();
},
(err) => {
observer.error(err);
observer.complete();
}
);
});
}
@@ -410,14 +410,12 @@ export class CustomResourcesService {
*/
getCorrespondingNodeIds(nodeId: string, pagination: PaginationModel = {}): Observable<string[]> {
if (this.isCustomSource(nodeId)) {
return this.loadFolderByNodeId(nodeId, pagination)
.pipe(map((result: any): string[] => result.list.entries.map((node: any): string => this.getIdFromEntry(node, nodeId))));
return this.loadFolderByNodeId(nodeId, pagination).pipe(
map((result: any): string[] => result.list.entries.map((node: any): string => this.getIdFromEntry(node, nodeId)))
);
} else if (nodeId) {
// cases when nodeId is '-my-', '-root-' or '-shared-'
return from(this.nodesApi.getNode(nodeId)
.then((node) => [node.entry.id]));
return from(this.nodesApi.getNode(nodeId).then((node) => [node.entry.id]));
}
return of([]);
@@ -453,7 +451,8 @@ export class CustomResourcesService {
}
private getIncludesFields(includeFields: string[]): string[] {
return ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames', ...includeFields]
.filter((element, index, array) => index === array.indexOf(element));
return ['path', 'properties', 'allowableOperations', 'permissions', 'aspectNames', ...includeFields].filter(
(element, index, array) => index === array.indexOf(element)
);
}
}

View File

@@ -33,7 +33,7 @@ export class SearchPermissionConfigurationService implements SearchConfiguration
) {}
public generateQueryBody(searchTerm: string, maxResults: number, skipCount: number): SearchRequest {
return new SearchRequest({
return {
query: {
query: this.getQuery(searchTerm)
},
@@ -46,7 +46,7 @@ export class SearchPermissionConfigurationService implements SearchConfiguration
/* eslint-disable-next-line */
{ query: "TYPE:'cm:authority'" }
]
});
};
}
private getQuery(searchTerm: string) {

View File

@@ -26,7 +26,7 @@ import { EcmUserModel } from '../../../common/models/ecm-user.model';
template: `
<div class="adf-ellipsis-cell" [attr.data-automation-id]="displayText$ | async">
<span class="adf-user-name-column" title="{{ displayText$ | async }}"> {{ displayText$ | async }}</span>
<br/>
<br />
<span class="adf-user-email-column" title="{{ subTitleText$ | async }}" *ngIf="subTitleText$ | async">
{{ subTitleText$ | async }}
</span>
@@ -51,7 +51,7 @@ export class UserNameColumnComponent implements OnInit {
ngOnInit() {
if (this.context != null) {
const { person, group, authorityId } = this.context.row.obj?.entry ?? this.context.row.obj;
const permissionGroup = authorityId ? { displayName: authorityId } as Group : null;
const permissionGroup = authorityId ? ({ displayName: authorityId } as Group) : null;
this.updatePerson(person);
this.updateGroup(group || permissionGroup);
}
@@ -68,7 +68,7 @@ export class UserNameColumnComponent implements OnInit {
this.displayText$.next(`${person.firstName ?? ''} ${person.lastName ?? ''}`);
this.subTitleText$.next(person.email ?? '');
}
}
}
private updateGroup(group: Group) {
if (group) {

View File

@@ -30,7 +30,7 @@ export interface NodePermissionsModel {
export class MemberModel {
id: string;
role: string;
accessStatus: PermissionElement.AccessStatusEnum | string;
accessStatus: 'ALLOWED' | 'DENIED' | string;
entry: {
person?: EcmUserModel;
group?: Group;
@@ -62,10 +62,10 @@ export class MemberModel {
}
if (entry.nodeType === 'cm:authorityContainer') {
const group = new Group({
const group: Group = {
id: entry.properties['cm:authorityName'],
displayName: entry.properties['cm:authorityDisplayName'] || entry.properties['cm:authorityName']
});
};
result.id = group.id;
result.entry = { group };

View File

@@ -18,10 +18,9 @@
import { PermissionElement } from '@alfresco/js-api';
export class PermissionDisplayModel implements PermissionElement {
authorityId?: string;
name?: string;
accessStatus?: PermissionElement.AccessStatusEnum;
accessStatus?: 'ALLOWED' | 'DENIED' | string;
isInherited: boolean = false;
icon: string;
readonly?: boolean;

View File

@@ -18,17 +18,7 @@
import { AlfrescoApiService, TranslationService } from '@alfresco/adf-core';
import { NodesApiService } from '../../common/services/nodes-api.service';
import { EcmUserModel } from '../../common/models/ecm-user.model';
import {
Group,
GroupMemberEntry,
GroupMemberPaging,
GroupsApi,
Node,
PathElement,
PermissionElement,
ResultSetPaging,
SearchRequest
} from '@alfresco/js-api';
import { Group, GroupMemberPaging, GroupsApi, Node, PathElement, PermissionElement, SearchRequest } from '@alfresco/js-api';
import { SearchService } from '../../search/services/search.service';
import { Injectable } from '@angular/core';
import { forkJoin, from, Observable, of, throwError } from 'rxjs';
@@ -60,13 +50,14 @@ export class NodePermissionService {
* @returns Array of strings representing the roles
*/
getNodeRoles(node: Node): Observable<string[]> {
if (node.path.elements.some(el => (el.nodeType === 'st:site' || el.nodeType === 'st:sites'))) {
if (node.path.elements.some((el) => el.nodeType === 'st:site' || el.nodeType === 'st:sites')) {
const searchRequest = this.buildRetrieveSiteQueryBody(node.path.elements);
return this.searchApiService.searchByQueryBody(searchRequest).pipe(
switchMap((siteNodeList: ResultSetPaging) => {
switchMap((siteNodeList) => {
const siteName = siteNodeList.list.entries[0].entry.name;
return this.getGroupMembersBySiteName(siteName);
}));
})
);
} else {
return of(node.permissions?.settable);
}
@@ -152,7 +143,7 @@ export class NodePermissionService {
private getDuplicatedPermissions(nodeLocallySet: PermissionElement[], permissionListAdded: PermissionElement[]): PermissionElement[] {
const duplicatePermissions: PermissionElement[] = [];
if (nodeLocallySet) {
permissionListAdded.forEach((permission: PermissionElement) => {
permissionListAdded.forEach((permission) => {
const duplicate = nodeLocallySet.find((localPermission) => this.isEqualPermission(localPermission, permission));
if (duplicate) {
duplicatePermissions.push(duplicate);
@@ -193,9 +184,9 @@ export class NodePermissionService {
private getGroupMembersBySiteName(siteName: string): Observable<string[]> {
const groupName = 'GROUP_site_' + siteName;
return this.getGroupMemberByGroupName(groupName).pipe(
map((groupMemberPaging: GroupMemberPaging) => {
map((groupMemberPaging) => {
const displayResult: string[] = [];
groupMemberPaging.list.entries.forEach((member: GroupMemberEntry) => {
groupMemberPaging.list.entries.forEach((member) => {
displayResult.push(this.formattedRoleName(member.entry.displayName, 'site_' + siteName));
});
return displayResult;
@@ -219,7 +210,7 @@ export class NodePermissionService {
}
private buildRetrieveSiteQueryBody(nodePath: PathElement[]): SearchRequest {
const pathNames = nodePath.map((node: PathElement) => 'name: "' + node.name + '"');
const pathNames = nodePath.map((node) => 'name: "' + node.name + '"');
const builtPathNames = pathNames.join(' OR ');
return {
@@ -319,7 +310,7 @@ export class NodePermissionService {
transformNodeToUserPerson(node: Node): { person: EcmUserModel; group: Group } {
let person = null;
let group = null;
let group: Group = null;
if (node.nodeType === 'cm:person') {
const firstName = node.properties['cm:firstName'];
const lastName = node.properties['cm:lastName'];
@@ -331,7 +322,7 @@ export class NodePermissionService {
if (node.nodeType === 'cm:authorityContainer') {
const displayName = node.properties['cm:authorityDisplayName'] || node.properties['cm:authorityName'];
const id = node.properties['cm:authorityName'];
group = new Group({ displayName, id });
group = { displayName, id };
}
return { person, group };
}

View File

@@ -424,14 +424,11 @@ export abstract class BaseQueryBuilderService {
}
protected get sort(): RequestSortDefinitionInner[] {
return this.sorting.map(
(def) =>
new RequestSortDefinitionInner({
type: def.type,
field: def.field,
ascending: def.ascending
})
);
return this.sorting.map((def) => ({
type: def.type,
field: def.field,
ascending: def.ascending
}));
}
protected get facetQueries(): FacetQuery[] {

View File

@@ -32,7 +32,7 @@ export class SearchConfigurationService implements SearchConfigurationInterface
* @returns Query body defined by the parameters
*/
generateQueryBody(searchTerm: string, maxResults: number, skipCount: number): SearchRequest {
return new SearchRequest({
return {
query: {
query: searchTerm ? `'${searchTerm}*' OR name:'${searchTerm}*'` : searchTerm
},
@@ -42,6 +42,6 @@ export class SearchConfigurationService implements SearchConfigurationInterface
skipCount
},
filterQueries: [{ query: `TYPE:'cm:folder' OR TYPE:'cm:content'` }, { query: 'NOT cm:creator:System' }]
});
};
}
}

View File

@@ -21,7 +21,7 @@ import { SecurityControlsService } from './security-controls-groups-marks-securi
import { fakeAuthorityClearanceApiResponse } from './mock/security-authorities.mock';
import { fakeGroupsApiResponse, createNewSecurityGroupMock } from './mock/security-groups.mock';
import { fakeMarksApiResponse, createNewSecurityMarkMock } from './mock/security-marks.mock';
import { SecurityGroup, SecurityGroupBody, SecurityGroupEntry, SecurityMarkBody, SecurityMarkEntry } from '@alfresco/js-api';
import { SecurityGroupBody, SecurityMarkBody, SecurityMarkEntry } from '@alfresco/js-api';
describe('SecurityControlsService', () => {
let service: SecurityControlsService;
@@ -74,15 +74,13 @@ describe('SecurityControlsService', () => {
it('should create new security group', async () => {
spyOn(service.groupsApi, 'createSecurityGroup').and.returnValue(
Promise.resolve(
new SecurityGroupEntry({
entry: new SecurityGroup({
groupName: 'TestGroup',
groupType: 'HIERARCHICAL',
id: 'eddf6269-ceba-42c6-b979-9ac445d29a94'
})
})
)
Promise.resolve({
entry: {
groupName: 'TestGroup',
groupType: 'HIERARCHICAL',
id: 'eddf6269-ceba-42c6-b979-9ac445d29a94'
}
})
);
const response = await service.createSecurityGroup(createNewSecurityGroupMock).toPromise();
@@ -110,37 +108,31 @@ describe('SecurityControlsService', () => {
it('should create new security mark', async () => {
spyOn(service.marksApi, 'createSecurityMarks').and.returnValue(
Promise.resolve(
new SecurityMarkEntry({
entry: {
groupId: 'eddf6269-ceba-42c6-b979-9ac445d29a94',
name: 'securityMark1',
id: 'ffBOeOJJ'
}
})
)
Promise.resolve({
entry: {
groupId: 'eddf6269-ceba-42c6-b979-9ac445d29a94',
name: 'securityMark1',
id: 'ffBOeOJJ'
}
})
);
const response = await service.createSecurityMarks(securityGroupId, createNewSecurityMarkMock);
if (response instanceof SecurityMarkEntry) {
securityMarkId = response.entry.id;
expect(response.entry.groupId).toEqual('eddf6269-ceba-42c6-b979-9ac445d29a94');
expect(response.entry.name).toEqual('securityMark1');
expect(response.entry.id).toEqual('ffBOeOJJ');
}
const response = (await service.createSecurityMarks(securityGroupId, createNewSecurityMarkMock)) as SecurityMarkEntry;
securityMarkId = response.entry.id;
expect(response.entry.groupId).toEqual('eddf6269-ceba-42c6-b979-9ac445d29a94');
expect(response.entry.name).toEqual('securityMark1');
expect(response.entry.id).toEqual('ffBOeOJJ');
});
it('should edit a security mark', async () => {
spyOn(service.marksApi, 'updateSecurityMark').and.returnValue(
Promise.resolve(
new SecurityMarkEntry({
entry: {
groupId: 'eddf6269-ceba-42c6-b979-9ac445d29a94',
name: 'securityMark1',
id: 'ffBOeOJJ'
}
})
)
Promise.resolve({
entry: {
groupId: 'eddf6269-ceba-42c6-b979-9ac445d29a94',
name: 'securityMark1',
id: 'ffBOeOJJ'
}
})
);
const response = await service.updateSecurityMark(securityGroupId, securityMarkId, securityMarkBody);
@@ -153,15 +145,13 @@ describe('SecurityControlsService', () => {
it('should update a security group', async () => {
spyOn(service.groupsApi, 'updateSecurityGroup').and.returnValue(
Promise.resolve(
new SecurityGroupEntry({
entry: new SecurityGroup({
groupName: 'TestGroup',
groupType: 'HIERARCHICAL',
id: 'eddf6269-ceba-42c6-b979-9ac445d29a94'
})
})
)
Promise.resolve({
entry: {
groupName: 'TestGroup',
groupType: 'HIERARCHICAL',
id: 'eddf6269-ceba-42c6-b979-9ac445d29a94'
}
})
);
const opts = {};
const response = await service.updateSecurityGroup(securityGroupId, securityGroupBody, opts);
@@ -172,15 +162,13 @@ describe('SecurityControlsService', () => {
it('should delete a security mark', async () => {
spyOn(service.marksApi, 'deleteSecurityMark').and.returnValue(
Promise.resolve(
new SecurityMarkEntry({
entry: {
groupId: 'eddf6269-ceba-42c6-b979-9ac445d29a94',
name: 'securityMark1',
id: 'ffBOeOJJ'
}
})
)
Promise.resolve({
entry: {
groupId: 'eddf6269-ceba-42c6-b979-9ac445d29a94',
name: 'securityMark1',
id: 'ffBOeOJJ'
}
})
);
const response = await service.deleteSecurityMark(securityGroupId, securityMarkId);
securityMarkId = response.entry.id;
@@ -218,17 +206,15 @@ describe('SecurityControlsService', () => {
it('should update a clearances for authority', async () => {
spyOn(service.authorityClearanceApi, 'updateAuthorityClearance').and.returnValue(
Promise.resolve(
new SecurityMarkEntry({
entry: {
id: 'test-id',
name: 'test-name',
groupId: 'test-groupId'
}
})
)
Promise.resolve({
entry: {
id: 'test-id',
name: 'test-name',
groupId: 'test-groupId'
}
})
);
const response = await service
const response = (await service
.updateClearancesForAuthority('test-id', [
{
groupId: 'test-group-id',
@@ -236,13 +222,11 @@ describe('SecurityControlsService', () => {
id: 'test-id'
}
])
.toPromise();
.toPromise()) as SecurityMarkEntry;
if (response instanceof SecurityMarkEntry) {
expect(response.entry.id).toEqual('test-id');
expect(response.entry.groupId).toEqual('test-groupId');
expect(response.entry.name).toEqual('test-name');
}
expect(response.entry.id).toEqual('test-id');
expect(response.entry.groupId).toEqual('test-groupId');
expect(response.entry.name).toEqual('test-name');
});
it('should reload security groups', (doneCallback) => {

View File

@@ -27,7 +27,6 @@ import {
SecurityGroupBody,
SecurityMarkPaging,
SecurityMarkBody,
SecurityGroupPaging,
AuthorityClearanceApi,
AuthorityClearanceGroupPaging,
NodeSecurityMarkBody,
@@ -98,13 +97,11 @@ export class SecurityControlsService {
skipCount,
maxItems
})
.then((response: SecurityGroupPaging) => {
.then((response) => {
this.groupsPaginatedSource.next(
(securityControlsGroupResponse = {
pagination: response.list.pagination,
entries: response.list.entries.map(
(group: SecurityGroupEntry) => group.entry
)
entries: response.list.entries.map((group) => group.entry)
})
);
resolve(securityControlsGroupResponse);
@@ -119,9 +116,7 @@ export class SecurityControlsService {
* @param input securityGroupBody.
* @returns Observable<SecurityGroupEntry>
*/
createSecurityGroup(
input: SecurityGroupBody
): Observable<SecurityGroupEntry> {
createSecurityGroup(input: SecurityGroupBody): Observable<SecurityGroupEntry> {
this.loadingSource.next(true);
const payload: SecurityGroupBody = {
...input
@@ -131,9 +126,7 @@ export class SecurityControlsService {
};
const promise = this.groupsApi.createSecurityGroup(payload, opts);
return from(promise).pipe(
finalize(() => this.loadingSource.next(false))
);
return from(promise).pipe(finalize(() => this.loadingSource.next(false)));
}
/**
@@ -143,15 +136,10 @@ export class SecurityControlsService {
* @param input securityMarkBody[].
* @returns Promise<SecurityMarkPaging | SecurityMarkEntry>
*/
createSecurityMarks(
securityGroupId: string,
input: SecurityMarkBody[]
): Promise<SecurityMarkPaging | SecurityMarkEntry> {
createSecurityMarks(securityGroupId: string, input: SecurityMarkBody[]): Promise<SecurityMarkPaging | SecurityMarkEntry> {
this.loadingSource.next(true);
const promise = this.marksApi.createSecurityMarks(
securityGroupId,
input
)
const promise = this.marksApi
.createSecurityMarks(securityGroupId, input)
.then((result) => {
this.loadingSource.next(false);
return result;
@@ -172,23 +160,18 @@ export class SecurityControlsService {
* @param skipCount The number of entities that exist in the collection before those included in this list.
* @returns Promise<SecurityControlsMarkResponse>
*/
getSecurityMark(
securityGroupId: string,
skipCount = DEFAULT_SKIP_COUNT
): Promise<SecurityControlsMarkResponse> {
getSecurityMark(securityGroupId: string, skipCount = DEFAULT_SKIP_COUNT): Promise<SecurityControlsMarkResponse> {
let securityControlsMarkResponse: SecurityControlsMarkResponse;
return new Promise((resolve, reject) => {
this.marksApi
.getSecurityMarks(securityGroupId, {
skipCount
})
.then((response: SecurityMarkPaging) => {
.then((response) => {
this.marksPaginatedSource.next(
(securityControlsMarkResponse = {
pagination: response.list.pagination,
entries: response.list.entries.map(
(mark: SecurityMarkEntry) => mark.entry
)
entries: response.list.entries.map((mark) => mark.entry)
})
);
resolve(securityControlsMarkResponse);
@@ -205,11 +188,7 @@ export class SecurityControlsService {
* @param opts additional information about the security group
* @returns Promise<SecurityGroupEntry>
*/
updateSecurityGroup(
securityGroupId: string,
input: SecurityGroupBody,
opts?: any
): Promise<SecurityGroupEntry> {
updateSecurityGroup(securityGroupId: string, input: SecurityGroupBody, opts?: any): Promise<SecurityGroupEntry> {
this.loadingSource.next(true);
const payload: SecurityGroupBody = {
...input
@@ -219,11 +198,8 @@ export class SecurityControlsService {
DEFAULT_INCLUDE
};
}
const promise = this.groupsApi.updateSecurityGroup(
securityGroupId,
payload,
opts
)
const promise = this.groupsApi
.updateSecurityGroup(securityGroupId, payload, opts)
.then((result) => {
this.loadingSource.next(false);
return result;
@@ -244,20 +220,13 @@ export class SecurityControlsService {
* @param input securityMarkBody.
* @returns Promise<SecurityMarkEntry>
*/
updateSecurityMark(
securityGroupId: string,
securityMarkId: string,
input: SecurityMarkBody
): Promise<SecurityMarkEntry> {
updateSecurityMark(securityGroupId: string, securityMarkId: string, input: SecurityMarkBody): Promise<SecurityMarkEntry> {
this.loadingSource.next(true);
const payload: SecurityMarkBody = {
...input
};
const promise = this.marksApi.updateSecurityMark(
securityGroupId,
securityMarkId,
payload
)
const promise = this.marksApi
.updateSecurityMark(securityGroupId, securityMarkId, payload)
.then((result) => {
this.loadingSource.next(false);
return result;
@@ -276,15 +245,11 @@ export class SecurityControlsService {
* @param securityGroupId The key for the security group id.
* @returns Observable<void>
*/
deleteSecurityGroup(
securityGroupId: string
): Observable<void> {
deleteSecurityGroup(securityGroupId: string): Observable<void> {
this.loadingSource.next(true);
const promise = this.groupsApi.deleteSecurityGroup(securityGroupId);
return from(promise).pipe(
finalize(() => this.loadingSource.next(false))
);
return from(promise).pipe(finalize(() => this.loadingSource.next(false)));
}
/**
@@ -294,15 +259,10 @@ export class SecurityControlsService {
* @param securityMarkId The key for the security mark id.
* @returns Promise<SecurityMarkEntry>
*/
deleteSecurityMark(
securityGroupId: string,
securityMarkId: string
): Promise<SecurityMarkEntry> {
deleteSecurityMark(securityGroupId: string, securityMarkId: string): Promise<SecurityMarkEntry> {
this.loadingSource.next(true);
const promise = this.marksApi.deleteSecurityMark(
securityGroupId,
securityMarkId
)
const promise = this.marksApi
.deleteSecurityMark(securityGroupId, securityMarkId)
.then((result) => {
this.loadingSource.next(false);
return result;
@@ -330,14 +290,12 @@ export class SecurityControlsService {
): Observable<AuthorityClearanceGroupPaging> {
this.loadingSource.next(true);
const opts = {
skipCount, maxItems
skipCount,
maxItems
};
const promise =
this.authorityClearanceApi.getAuthorityClearanceForAuthority(authorityName, opts);
const promise = this.authorityClearanceApi.getAuthorityClearanceForAuthority(authorityName, opts);
return from(promise).pipe(
finalize(() => this.loadingSource.next(false))
);
return from(promise).pipe(finalize(() => this.loadingSource.next(false)));
}
/**
@@ -347,7 +305,10 @@ export class SecurityControlsService {
* @param securityMarksList NodeSecurityMarkBody[]
* @returns Observable<SecurityMarkEntry | SecurityMarkPaging>
*/
updateClearancesForAuthority(authorityName: string, securityMarksList: NodeSecurityMarkBody[]): Observable<SecurityMarkEntry | SecurityMarkPaging> {
updateClearancesForAuthority(
authorityName: string,
securityMarksList: NodeSecurityMarkBody[]
): Observable<SecurityMarkEntry | SecurityMarkPaging> {
this.loadingSource.next(true);
const promise = this.authorityClearanceApi.updateAuthorityClearance(authorityName, securityMarksList);

View File

@@ -25,15 +25,13 @@ import { RatingServiceInterface } from './rating.service.interface';
providedIn: 'root'
})
export class RatingService implements RatingServiceInterface {
private _ratingsApi: RatingsApi;
get ratingsApi(): RatingsApi {
this._ratingsApi = this._ratingsApi ?? new RatingsApi(this.apiService.getInstance());
return this._ratingsApi;
}
constructor(private apiService: AlfrescoApiService) {
}
constructor(private apiService: AlfrescoApiService) {}
/**
* Gets the current user's rating for a node.
@@ -55,10 +53,10 @@ export class RatingService implements RatingServiceInterface {
* @returns Details about the rating, including the new value
*/
postRating(nodeId: string, ratingType: string, vote: any): Observable<RatingEntry | any> {
const ratingBody: RatingBody = new RatingBody({
const ratingBody: RatingBody = {
id: ratingType,
myRating: vote
});
};
return from(this.ratingsApi.createRating(nodeId, ratingBody));
}

View File

@@ -8,7 +8,9 @@
"@alfresco/adf-extensions": ["../../../dist/libs/extensions"],
"@alfresco/adf-extensions/*": ["../../../dist/libs/extensions/*"],
"@alfresco/adf-core": ["../../../dist/libs/core"],
"@alfresco/adf-core/*": ["../../../dist/libs/core/*"]
"@alfresco/adf-core/*": ["../../../dist/libs/core/*"],
"@alfresco/js-api": ["../../../dist/libs/js-api"],
"@alfresco/js-api/*": ["../../../dist/libs/js-api/*"]
}
}
}