mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-24 17:31:52 +00:00
[ACS-5281] Changed editable state of metadata content based on change o… (#3400)
* ACS-5281 Changed editable state of metadata content based on change of file lock state * ACS-5281 Updated versions * ACS-5281 Reverted change * ACS-5281 Upgrade version * ACS-5281 Small correction * ACS-5281 Fixed e2e
This commit is contained in:
@@ -23,11 +23,11 @@
|
||||
*/
|
||||
|
||||
import { Action } from '@ngrx/store';
|
||||
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
|
||||
export const AOS_ACTION = 'AOS_ACTION';
|
||||
|
||||
export class AosAction implements Action {
|
||||
readonly type = AOS_ACTION;
|
||||
constructor(public payload: MinimalNodeEntryEntity) {}
|
||||
constructor(public payload: Node) {}
|
||||
}
|
||||
|
@@ -25,11 +25,11 @@
|
||||
/* cspell:disable */
|
||||
import { AppConfigService, AuthenticationService, LogService, NotificationService } from '@alfresco/adf-core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
import { getFileExtension, supportedExtensions } from '@alfresco/aca-shared/rules';
|
||||
|
||||
export interface IAosEditOnlineService {
|
||||
onActionEditOnlineAos(node: MinimalNodeEntryEntity): void;
|
||||
onActionEditOnlineAos(node: Node): void;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
@@ -43,7 +43,7 @@ export class AosEditOnlineService implements IAosEditOnlineService {
|
||||
private logService: LogService
|
||||
) {}
|
||||
|
||||
onActionEditOnlineAos(node: MinimalNodeEntryEntity): void {
|
||||
onActionEditOnlineAos(node: Node): void {
|
||||
if (node && this.isFile(node) && node.properties) {
|
||||
if (node.isLocked) {
|
||||
// const checkedOut = node.aspectNames.find(
|
||||
@@ -88,7 +88,7 @@ export class AosEditOnlineService implements IAosEditOnlineService {
|
||||
return fileExtension && supportedExtensions[fileExtension];
|
||||
}
|
||||
|
||||
private triggerEditOnlineAos(node: MinimalNodeEntryEntity): void {
|
||||
private triggerEditOnlineAos(node: Node): void {
|
||||
const aosHost = this.appConfigService.get('aosHost');
|
||||
let url: string;
|
||||
const pathElements = (node.path?.elements || []).map((segment) => segment.name);
|
||||
@@ -139,13 +139,13 @@ export class AosEditOnlineService implements IAosEditOnlineService {
|
||||
}, 500);
|
||||
}
|
||||
|
||||
private isFile(node: MinimalNodeEntryEntity): boolean {
|
||||
private isFile(node: Node): boolean {
|
||||
const implicitFile = (node as any).nodeId || (node as any).guid;
|
||||
|
||||
return !!implicitFile || node.isFile;
|
||||
}
|
||||
|
||||
private getNodeId(node: MinimalNodeEntryEntity): string {
|
||||
private getNodeId(node: Node): string {
|
||||
return (node as any).nodeId || (node as any).guid || node.id;
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@
|
||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { provideMockActions } from '@ngrx/effects/testing';
|
||||
import { Observable, of } from 'rxjs';
|
||||
@@ -60,7 +60,7 @@ describe('AosEffects', () => {
|
||||
it('should call onActionEditOnlineAos on AOS_ACTION', () => {
|
||||
const onActionEditOnlineAosSpy = spyOn(aosEditOnlineService, 'onActionEditOnlineAos');
|
||||
|
||||
const payload = new MinimalNodeEntryEntity();
|
||||
const payload = new Node();
|
||||
const action = new AosAction(payload);
|
||||
aosActions$ = of(action);
|
||||
|
||||
|
@@ -5,10 +5,10 @@
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^14.1.0",
|
||||
"@angular/core": "^14.1.0",
|
||||
"@alfresco/adf-core": "^6.3.0-5833590093",
|
||||
"@alfresco/adf-content-services": "^6.3.0-5833590093",
|
||||
"@alfresco/adf-extensions": "^6.3.0-5833590093",
|
||||
"@alfresco/js-api": ">=6.3.0-1104",
|
||||
"@alfresco/adf-core": "^6.3.0-5977252204",
|
||||
"@alfresco/adf-content-services": "^6.3.0-5977252204",
|
||||
"@alfresco/adf-extensions": "^6.3.0-5977252204",
|
||||
"@alfresco/js-api": ">=6.3.0-1172",
|
||||
"@angular/animations": "^14.1.3",
|
||||
"@angular/cdk": "^14.1.3",
|
||||
"@angular/forms": "^14.1.3",
|
||||
|
@@ -39,7 +39,7 @@ import { PreviewComponent } from './preview.component';
|
||||
import { BehaviorSubject, Observable, of, throwError } from 'rxjs';
|
||||
import { ContentApiService, AppHookService, DocumentBasePageService } from '@alfresco/aca-shared';
|
||||
import { Store, StoreModule } from '@ngrx/store';
|
||||
import { Node, NodePaging, FavoritePaging, SharedLinkPaging, PersonEntry, ResultSetPaging, RepositoryInfo } from '@alfresco/js-api';
|
||||
import { Node, NodePaging, FavoritePaging, SharedLinkPaging, PersonEntry, ResultSetPaging, RepositoryInfo, VersionInfo } from '@alfresco/js-api';
|
||||
import { PreviewModule } from '../preview.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
@@ -134,7 +134,14 @@ describe('PreviewComponent', () => {
|
||||
provide: DiscoveryApiService,
|
||||
useValue: {
|
||||
ecmProductInfo$: new BehaviorSubject<RepositoryInfo | null>(null),
|
||||
getEcmProductInfo: (): Observable<RepositoryInfo> => of(new RepositoryInfo({ version: '10.0.0' }))
|
||||
getEcmProductInfo: (): Observable<RepositoryInfo> =>
|
||||
of(
|
||||
new RepositoryInfo({
|
||||
version: {
|
||||
major: '10.0.0'
|
||||
} as VersionInfo
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
import { Component, Input, ChangeDetectionStrategy, OnInit, ViewEncapsulation, HostListener, inject } from '@angular/core';
|
||||
import { PathInfo, MinimalNodeEntity } from '@alfresco/js-api';
|
||||
import { PathInfo, NodeEntry } from '@alfresco/js-api';
|
||||
import { Observable, BehaviorSubject, of } from 'rxjs';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { NavigateToParentFolder } from '@alfresco/aca-shared/store';
|
||||
@@ -75,14 +75,14 @@ export class LocationLinkComponent implements OnInit {
|
||||
|
||||
goToLocation() {
|
||||
if (this.context) {
|
||||
const node: MinimalNodeEntity = this.context.row.node;
|
||||
const node: NodeEntry = this.context.row.node;
|
||||
this.store.dispatch(new NavigateToParentFolder(node));
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.context) {
|
||||
const node: MinimalNodeEntity = this.context.row.node;
|
||||
const node: NodeEntry = this.context.row.node;
|
||||
if (node && node.entry && node.entry.path) {
|
||||
const path = node.entry.path;
|
||||
|
||||
|
@@ -31,7 +31,7 @@ import {
|
||||
PaginationDirective,
|
||||
ToolbarComponent
|
||||
} from '@alfresco/aca-shared';
|
||||
import { MinimalNodeEntity, MinimalNodeEntryEntity, PathElementEntity, PathInfo } from '@alfresco/js-api';
|
||||
import { NodeEntry, Node, PathElement, PathInfo } from '@alfresco/js-api';
|
||||
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { debounceTime, map } from 'rxjs/operators';
|
||||
import { DocumentListPresetRef, ExtensionsModule } from '@alfresco/adf-extensions';
|
||||
@@ -79,24 +79,24 @@ export class FavoritesComponent extends PageComponent implements OnInit {
|
||||
this.columns = this.extensions.documentListPresets.favorites;
|
||||
}
|
||||
|
||||
navigate(favorite: MinimalNodeEntryEntity) {
|
||||
navigate(favorite: Node) {
|
||||
const { isFolder, id } = favorite;
|
||||
|
||||
// TODO: rework as it will fail on non-English setups
|
||||
const isSitePath = (path: PathInfo): boolean => path && path.elements && path.elements.some(({ name }: PathElementEntity) => name === 'Sites');
|
||||
const isSitePath = (path: PathInfo): boolean => path && path.elements && path.elements.some(({ name }: PathElement) => name === 'Sites');
|
||||
|
||||
if (isFolder) {
|
||||
this.contentApi
|
||||
.getNode(id)
|
||||
.pipe(map((node) => node.entry))
|
||||
.subscribe(({ path }: MinimalNodeEntryEntity) => {
|
||||
.subscribe(({ path }: Node) => {
|
||||
const routeUrl = isSitePath(path) ? '/libraries' : '/personal-files';
|
||||
this.router.navigate([routeUrl, id]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onNodeDoubleClick(node: MinimalNodeEntity) {
|
||||
onNodeDoubleClick(node: NodeEntry) {
|
||||
if (node && node.entry) {
|
||||
if (node.entry.isFolder) {
|
||||
this.navigate(node.entry);
|
||||
|
@@ -32,7 +32,7 @@ import { AppTestingModule } from '../../testing/app-testing.module';
|
||||
import { ContentApiService } from '@alfresco/aca-shared';
|
||||
import { of, Subject, throwError } from 'rxjs';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { NodeEntry, NodePaging } from '@alfresco/js-api';
|
||||
import { NodeEntry, NodePaging, Node } from '@alfresco/js-api';
|
||||
|
||||
describe('FilesComponent', () => {
|
||||
let node;
|
||||
@@ -424,7 +424,7 @@ describe('FilesComponent', () => {
|
||||
|
||||
it('should reset the pagination when navigating to a folder', () => {
|
||||
const resetNewFolderPaginationSpy = spyOn(component.documentList, 'resetNewFolderPagination');
|
||||
const fakeFolderNode = new NodeEntry({ entry: { id: 'fakeFolderNode', isFolder: true, isFile: false } });
|
||||
const fakeFolderNode = new NodeEntry({ entry: { id: 'fakeFolderNode', isFolder: true, isFile: false } as Node });
|
||||
component.navigateTo(fakeFolderNode);
|
||||
|
||||
expect(resetNewFolderPaginationSpy).toHaveBeenCalled();
|
||||
@@ -432,7 +432,7 @@ describe('FilesComponent', () => {
|
||||
|
||||
it('should not reset the pagination when the node to navigate is not a folder', () => {
|
||||
const resetNewFolderPaginationSpy = spyOn(component.documentList, 'resetNewFolderPagination');
|
||||
const fakeFileNode = new NodeEntry({ entry: { id: 'fakeFileNode', isFolder: false, isFile: true } });
|
||||
const fakeFileNode = new NodeEntry({ entry: { id: 'fakeFileNode', isFolder: false, isFile: true } as Node });
|
||||
component.navigateTo(fakeFileNode);
|
||||
|
||||
expect(resetNewFolderPaginationSpy).not.toHaveBeenCalled();
|
||||
|
@@ -25,7 +25,7 @@
|
||||
import { DataTableModule, PaginationModule, ShowHeaderMode } from '@alfresco/adf-core';
|
||||
import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { ActivatedRoute, Params } from '@angular/router';
|
||||
import { MinimalNodeEntity, MinimalNodeEntryEntity, PathElement, PathElementEntity } from '@alfresco/js-api';
|
||||
import { NodeEntry, Node, PathElement } from '@alfresco/js-api';
|
||||
import { NodeActionsService } from '../../services/node-actions.service';
|
||||
import {
|
||||
ContentApiService,
|
||||
@@ -72,7 +72,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
|
||||
isValidPath = true;
|
||||
isAdmin = false;
|
||||
selectedNode: MinimalNodeEntity;
|
||||
selectedNode: NodeEntry;
|
||||
queryParams = null;
|
||||
|
||||
showLoader$ = this.store.select(showLoaderSelector);
|
||||
@@ -186,7 +186,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
|
||||
this.store.dispatch(new UploadFileVersionAction(ev));
|
||||
}
|
||||
|
||||
navigateTo(node: MinimalNodeEntity) {
|
||||
navigateTo(node: NodeEntry) {
|
||||
if (node && node.entry) {
|
||||
this.selectedNode = node;
|
||||
const { isFolder } = node.entry;
|
||||
@@ -213,7 +213,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
|
||||
this.navigateTo((event as CustomEvent).detail?.node);
|
||||
}
|
||||
|
||||
onBreadcrumbNavigate(route: PathElementEntity) {
|
||||
onBreadcrumbNavigate(route: PathElement) {
|
||||
this.documentList.resetNewFolderPagination();
|
||||
|
||||
// todo: review this approach once 5.2.3 is out
|
||||
@@ -226,7 +226,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
onFileUploadedEvent(event: FileUploadEvent) {
|
||||
const node: MinimalNodeEntity = event.file.data;
|
||||
const node: NodeEntry = event.file.data;
|
||||
|
||||
// check root and child nodes
|
||||
if (node && node.entry && node.entry.parentId === this.getParentNodeId()) {
|
||||
@@ -265,7 +265,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
|
||||
this.reload(this.selectedNode);
|
||||
}
|
||||
|
||||
onContentCopied(nodes: MinimalNodeEntity[]) {
|
||||
onContentCopied(nodes: NodeEntry[]) {
|
||||
const newNode = nodes.find((node) => node && node.entry && node.entry.parentId === this.getParentNodeId());
|
||||
if (newNode) {
|
||||
this.reload(this.selectedNode);
|
||||
@@ -273,7 +273,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
// todo: review this approach once 5.2.3 is out
|
||||
private async updateCurrentNode(node: MinimalNodeEntryEntity) {
|
||||
private async updateCurrentNode(node: Node) {
|
||||
this.nodePath = null;
|
||||
|
||||
if (node && node.path && node.path.elements) {
|
||||
@@ -297,7 +297,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
// todo: review this approach once 5.2.3 is out
|
||||
private async normalizeSitePath(node: MinimalNodeEntryEntity) {
|
||||
private async normalizeSitePath(node: Node) {
|
||||
const elements = node.path.elements;
|
||||
|
||||
// remove 'Sites'
|
||||
@@ -325,7 +325,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
isSiteContainer(node: MinimalNodeEntryEntity): boolean {
|
||||
isSiteContainer(node: Node): boolean {
|
||||
if (node && node.aspectNames && node.aspectNames.length > 0) {
|
||||
return node.aspectNames.indexOf('st:siteContainer') >= 0;
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
import { NodePermissionService, isLocked } from '@alfresco/aca-shared';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { NodeCommentsModule } from '@alfresco/adf-content-services';
|
||||
@@ -37,7 +37,7 @@ import { NodeCommentsModule } from '@alfresco/adf-content-services';
|
||||
})
|
||||
export class CommentsTabComponent implements OnInit {
|
||||
@Input()
|
||||
node: MinimalNodeEntryEntity;
|
||||
node: Node;
|
||||
|
||||
canUpdateNode = false;
|
||||
|
||||
|
@@ -23,14 +23,16 @@
|
||||
*/
|
||||
|
||||
import { MetadataTabComponent } from './metadata-tab.component';
|
||||
import { MinimalNodeEntryEntity, Node } from '@alfresco/js-api';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AppTestingModule } from '../../../testing/app-testing.module';
|
||||
import { AppConfigService } from '@alfresco/adf-core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppState, SetInfoDrawerMetadataAspectAction } from '@alfresco/aca-shared/store';
|
||||
import { AppState, EditOfflineAction, SetInfoDrawerMetadataAspectAction } from '@alfresco/aca-shared/store';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { AppExtensionService, NodePermissionService } from '@alfresco/aca-shared';
|
||||
import { Actions } from '@ngrx/effects';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
describe('MetadataTabComponent', () => {
|
||||
let fixture: ComponentFixture<MetadataTabComponent>;
|
||||
@@ -39,6 +41,7 @@ describe('MetadataTabComponent', () => {
|
||||
let appConfig: AppConfigService;
|
||||
let extensions: AppExtensionService;
|
||||
let nodePermissionService: NodePermissionService;
|
||||
let actions$: Subject<EditOfflineAction>;
|
||||
|
||||
const presets = {
|
||||
default: {
|
||||
@@ -47,11 +50,18 @@ describe('MetadataTabComponent', () => {
|
||||
custom: []
|
||||
};
|
||||
beforeEach(() => {
|
||||
actions$ = new Subject<EditOfflineAction>();
|
||||
TestBed.configureTestingModule({
|
||||
imports: [AppTestingModule, MetadataTabComponent]
|
||||
imports: [AppTestingModule, MetadataTabComponent],
|
||||
providers: [
|
||||
{
|
||||
provide: Actions,
|
||||
useValue: actions$
|
||||
}
|
||||
]
|
||||
});
|
||||
nodePermissionService = TestBed.inject(NodePermissionService);
|
||||
spyOn(nodePermissionService, 'check').and.callFake((source: MinimalNodeEntryEntity, permissions: string[]) => {
|
||||
spyOn(nodePermissionService, 'check').and.callFake((source: Node, permissions: string[]) => {
|
||||
return permissions.some((permission) => source.allowableOperations.includes(permission));
|
||||
});
|
||||
});
|
||||
@@ -85,7 +95,7 @@ describe('MetadataTabComponent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('canUpdateNode()', () => {
|
||||
describe('canUpdateNode', () => {
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MetadataTabComponent);
|
||||
component = fixture.componentInstance;
|
||||
@@ -129,6 +139,113 @@ describe('MetadataTabComponent', () => {
|
||||
component.ngOnInit();
|
||||
expect(component.canUpdateNode).toBe(false);
|
||||
});
|
||||
|
||||
describe('set by triggering EditOfflineAction', () => {
|
||||
let editOfflineAction: EditOfflineAction;
|
||||
|
||||
beforeEach(() => {
|
||||
component.node = {
|
||||
id: 'some id',
|
||||
allowableOperations: []
|
||||
} as Node;
|
||||
component.ngOnInit();
|
||||
editOfflineAction = new EditOfflineAction({
|
||||
entry: {
|
||||
isLocked: false,
|
||||
allowableOperations: ['update'],
|
||||
id: component.node.id
|
||||
} as Node
|
||||
});
|
||||
component.canUpdateNode = true;
|
||||
});
|
||||
|
||||
it('should have set true if node is not locked and has update permission', () => {
|
||||
component.canUpdateNode = false;
|
||||
actions$.next(editOfflineAction);
|
||||
expect(component.canUpdateNode).toBeTrue();
|
||||
});
|
||||
|
||||
it('should not have set false if changed node has different id than original', () => {
|
||||
editOfflineAction.payload.entry.id = 'some other id';
|
||||
editOfflineAction.payload.entry.isLocked = true;
|
||||
actions$.next(editOfflineAction);
|
||||
expect(component.canUpdateNode).toBeTrue();
|
||||
});
|
||||
|
||||
it('should have set false if node is locked', () => {
|
||||
editOfflineAction.payload.entry.isLocked = true;
|
||||
actions$.next(editOfflineAction);
|
||||
expect(component.canUpdateNode).toBeFalse();
|
||||
});
|
||||
|
||||
it('should have set false if node has no update permission', () => {
|
||||
editOfflineAction.payload.entry.allowableOperations = ['other'];
|
||||
actions$.next(editOfflineAction);
|
||||
expect(component.canUpdateNode).toBeFalse();
|
||||
});
|
||||
|
||||
it('should have set false if node has read only property', () => {
|
||||
editOfflineAction.payload.entry.properties = {
|
||||
'cm:lockType': 'WRITE_LOCK'
|
||||
};
|
||||
actions$.next(editOfflineAction);
|
||||
expect(component.canUpdateNode).toBeFalse();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('editable', () => {
|
||||
let editOfflineAction: EditOfflineAction;
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MetadataTabComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.node = {
|
||||
id: 'some id',
|
||||
allowableOperations: []
|
||||
} as Node;
|
||||
component.ngOnInit();
|
||||
editOfflineAction = new EditOfflineAction({
|
||||
entry: {
|
||||
isLocked: false,
|
||||
allowableOperations: ['update'],
|
||||
id: component.node.id
|
||||
} as Node
|
||||
});
|
||||
component.editable = true;
|
||||
});
|
||||
|
||||
it('should not have set false if node is not locked and has update permission', () => {
|
||||
actions$.next(editOfflineAction);
|
||||
expect(component.editable).toBeTrue();
|
||||
});
|
||||
|
||||
it('should not have set false if changed node has different id than original', () => {
|
||||
editOfflineAction.payload.entry.id = 'some other id';
|
||||
editOfflineAction.payload.entry.isLocked = true;
|
||||
actions$.next(editOfflineAction);
|
||||
expect(component.editable).toBeTrue();
|
||||
});
|
||||
|
||||
it('should have set false if node is locked', () => {
|
||||
editOfflineAction.payload.entry.isLocked = true;
|
||||
actions$.next(editOfflineAction);
|
||||
expect(component.editable).toBeFalse();
|
||||
});
|
||||
|
||||
it('should have set false if node has no update permission', () => {
|
||||
editOfflineAction.payload.entry.allowableOperations = ['other'];
|
||||
actions$.next(editOfflineAction);
|
||||
expect(component.editable).toBeFalse();
|
||||
});
|
||||
|
||||
it('should have set false if node has read only property', () => {
|
||||
editOfflineAction.payload.entry.properties = {
|
||||
'cm:lockType': 'WRITE_LOCK'
|
||||
};
|
||||
actions$.next(editOfflineAction);
|
||||
expect(component.editable).toBeFalse();
|
||||
});
|
||||
});
|
||||
|
||||
describe('displayAspect', () => {
|
||||
|
@@ -23,22 +23,29 @@
|
||||
*/
|
||||
|
||||
import { Component, Input, ViewEncapsulation, OnInit, OnDestroy } from '@angular/core';
|
||||
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
import { NodePermissionService, isLocked, AppExtensionService } from '@alfresco/aca-shared';
|
||||
import { AppStore, infoDrawerMetadataAspect } from '@alfresco/aca-shared/store';
|
||||
import { AppStore, EditOfflineAction, infoDrawerMetadataAspect, NodeActionTypes } from '@alfresco/aca-shared/store';
|
||||
import { AppConfigService, NotificationService } from '@alfresco/adf-core';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { ContentMetadataModule, ContentMetadataService } from '@alfresco/adf-content-services';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { filter, takeUntil } from 'rxjs/operators';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Actions, ofType } from '@ngrx/effects';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [CommonModule, ContentMetadataModule],
|
||||
selector: 'app-metadata-tab',
|
||||
template: `
|
||||
<adf-content-metadata-card [readOnly]="!canUpdateNode" [preset]="'custom'" [node]="node" [displayAspect]="displayAspect$ | async">
|
||||
<adf-content-metadata-card
|
||||
[readOnly]="!canUpdateNode"
|
||||
[preset]="'custom'"
|
||||
[node]="node"
|
||||
[displayAspect]="displayAspect$ | async"
|
||||
[(editable)]="editable"
|
||||
>
|
||||
</adf-content-metadata-card>
|
||||
`,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
@@ -48,11 +55,11 @@ export class MetadataTabComponent implements OnInit, OnDestroy {
|
||||
protected onDestroy$ = new Subject<boolean>();
|
||||
|
||||
@Input()
|
||||
node: MinimalNodeEntryEntity;
|
||||
node: Node;
|
||||
|
||||
displayAspect$: Observable<string>;
|
||||
|
||||
canUpdateNode = false;
|
||||
editable = false;
|
||||
|
||||
constructor(
|
||||
private permission: NodePermissionService,
|
||||
@@ -60,7 +67,8 @@ export class MetadataTabComponent implements OnInit, OnDestroy {
|
||||
private appConfig: AppConfigService,
|
||||
private store: Store<AppStore>,
|
||||
private notificationService: NotificationService,
|
||||
private contentMetadataService: ContentMetadataService
|
||||
private contentMetadataService: ContentMetadataService,
|
||||
private actions$: Actions
|
||||
) {
|
||||
if (this.extensions.contentMetadata) {
|
||||
this.appConfig.config['content-metadata'].presets = this.extensions.contentMetadata.presets;
|
||||
@@ -72,13 +80,27 @@ export class MetadataTabComponent implements OnInit, OnDestroy {
|
||||
this.contentMetadataService.error.pipe(takeUntil(this.onDestroy$)).subscribe((err: { message: string }) => {
|
||||
this.notificationService.showError(err.message);
|
||||
});
|
||||
if (this.node && !isLocked({ entry: this.node })) {
|
||||
this.canUpdateNode = this.permission.check(this.node, ['update']);
|
||||
}
|
||||
this.checkIfNodeIsUpdatable(this.node);
|
||||
this.actions$
|
||||
.pipe(
|
||||
ofType<EditOfflineAction>(NodeActionTypes.EditOffline),
|
||||
filter((updatedNode) => this.node.id === updatedNode.payload.entry.id),
|
||||
takeUntil(this.onDestroy$)
|
||||
)
|
||||
.subscribe((updatedNode) => {
|
||||
this.checkIfNodeIsUpdatable(updatedNode?.payload.entry);
|
||||
if (!this.canUpdateNode) {
|
||||
this.editable = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
private checkIfNodeIsUpdatable(node: Node) {
|
||||
this.canUpdateNode = node && !isLocked({ entry: node }) ? this.permission.check(node, ['update']) : false;
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
import { Component, Input, OnChanges, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { VersionManagerModule } from '@alfresco/adf-content-services';
|
||||
import { AppConfigModule } from '@alfresco/adf-core';
|
||||
@@ -55,7 +55,7 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||
})
|
||||
export class VersionsTabComponent implements OnInit, OnChanges {
|
||||
@Input()
|
||||
node: MinimalNodeEntryEntity;
|
||||
node: Node;
|
||||
|
||||
isFileSelected = false;
|
||||
|
||||
|
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { MinimalNodeEntity } from '@alfresco/js-api';
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
import {
|
||||
ContextActionsDirective,
|
||||
@@ -78,7 +78,7 @@ export class RecentFilesComponent extends PageComponent implements OnInit {
|
||||
this.columns = this.extensions.documentListPresets.recent || [];
|
||||
}
|
||||
|
||||
onNodeDoubleClick(node: MinimalNodeEntity) {
|
||||
onNodeDoubleClick(node: NodeEntry) {
|
||||
if (node && node.entry) {
|
||||
this.showPreview(node, { location: this.router.url });
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
import { Component, Input, OnInit, ViewEncapsulation, ChangeDetectionStrategy, OnDestroy } from '@angular/core';
|
||||
import { MinimalNodeEntity } from '@alfresco/js-api';
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
import { ViewNodeAction, NavigateToFolder } from '@alfresco/aca-shared/store';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { BehaviorSubject, Subject } from 'rxjs';
|
||||
@@ -46,7 +46,7 @@ import { MatDialogModule } from '@angular/material/dialog';
|
||||
host: { class: 'aca-search-results-row' }
|
||||
})
|
||||
export class SearchResultsRowComponent implements OnInit, OnDestroy {
|
||||
private node: MinimalNodeEntity;
|
||||
private node: NodeEntry;
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
@Input()
|
||||
|
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { MinimalNodeEntity, Pagination, ResultSetPaging } from '@alfresco/js-api';
|
||||
import { NodeEntry, Pagination, ResultSetPaging } from '@alfresco/js-api';
|
||||
import { ActivatedRoute, Params } from '@angular/router';
|
||||
import { AlfrescoViewerModule, DocumentListModule, SearchModule, SearchQueryBuilderService } from '@alfresco/adf-content-services';
|
||||
import {
|
||||
@@ -265,7 +265,7 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
||||
return ['name', 'asc'];
|
||||
}
|
||||
|
||||
onNodeDoubleClick(node: MinimalNodeEntity) {
|
||||
onNodeDoubleClick(node: NodeEntry) {
|
||||
if (node && node.entry) {
|
||||
if (node.entry.isFolder) {
|
||||
this.store.dispatch(new NavigateToFolder(node));
|
||||
|
@@ -24,7 +24,7 @@
|
||||
|
||||
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
import { MinimalNodeEntity } from '@alfresco/js-api';
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
import {
|
||||
AppHookService,
|
||||
ContextActionsDirective,
|
||||
@@ -80,7 +80,7 @@ export class SharedFilesComponent extends PageComponent implements OnInit {
|
||||
this.columns = this.extensions.documentListPresets.shared || [];
|
||||
}
|
||||
|
||||
preview(node: MinimalNodeEntity) {
|
||||
preview(node: NodeEntry) {
|
||||
this.showPreview(node, { location: this.router.url });
|
||||
}
|
||||
|
||||
|
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
import { AppStore, DownloadNodesAction, EditOfflineAction, SnackbarErrorAction, getAppSelection } from '@alfresco/aca-shared/store';
|
||||
import { MinimalNodeEntity, NodeEntry, SharedLinkEntry, Node, NodesApi } from '@alfresco/js-api';
|
||||
import { NodeEntry, SharedLinkEntry, Node, NodesApi } from '@alfresco/js-api';
|
||||
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { isLocked } from '@alfresco/aca-shared';
|
||||
@@ -55,7 +55,7 @@ import { MatIconModule } from '@angular/material/icon';
|
||||
})
|
||||
export class ToggleEditOfflineComponent implements OnInit {
|
||||
private nodesApi: NodesApi;
|
||||
selection: MinimalNodeEntity;
|
||||
selection: NodeEntry;
|
||||
nodeTitle = '';
|
||||
isNodeLocked = false;
|
||||
|
||||
|
@@ -31,7 +31,7 @@ import { Store } from '@ngrx/store';
|
||||
import { AppHookService } from '@alfresco/aca-shared';
|
||||
import { SetSelectedNodesAction } from '@alfresco/aca-shared/store';
|
||||
import { takeUntil, filter } from 'rxjs/operators';
|
||||
import { MinimalNodeEntity } from '@alfresco/js-api';
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
|
||||
@Directive({
|
||||
standalone: true,
|
||||
@@ -39,7 +39,7 @@ import { MinimalNodeEntity } from '@alfresco/js-api';
|
||||
})
|
||||
export class DocumentListDirective implements OnInit, OnDestroy {
|
||||
private isLibrary = false;
|
||||
selectedNode: MinimalNodeEntity;
|
||||
selectedNode: NodeEntry;
|
||||
|
||||
onDestroy$ = new Subject<boolean>();
|
||||
|
||||
@@ -132,7 +132,7 @@ export class DocumentListDirective implements OnInit, OnDestroy {
|
||||
this.store.dispatch(new SetSelectedNodesAction(selection));
|
||||
}
|
||||
|
||||
private reload(selectedNode?: MinimalNodeEntity) {
|
||||
private reload(selectedNode?: NodeEntry) {
|
||||
this.documentList.resetSelection();
|
||||
if (selectedNode) {
|
||||
this.store.dispatch(new SetSelectedNodesAction([selectedNode]));
|
||||
|
@@ -55,7 +55,7 @@ import { NodeActionsService } from './node-actions.service';
|
||||
import { TranslationService, NotificationService } from '@alfresco/adf-core';
|
||||
import { MatDialog, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
||||
import { MatSnackBarModule, MatSnackBarRef, SimpleSnackBar } from '@angular/material/snack-bar';
|
||||
import { NodeEntry, Node, VersionPaging, MinimalNodeEntity } from '@alfresco/js-api';
|
||||
import { NodeEntry, Node, VersionPaging } from '@alfresco/js-api';
|
||||
import {
|
||||
NewVersionUploaderDataAction,
|
||||
NewVersionUploaderService,
|
||||
@@ -1685,7 +1685,7 @@ describe('ContentManagementService', () => {
|
||||
const elementToFocus = document.createElement(elementToFocusSelector);
|
||||
spyOn(elementToFocus, 'focus');
|
||||
spyOn(document, 'querySelector').withArgs(elementToFocusSelector).and.returnValue(elementToFocus);
|
||||
contentManagementService.editFolder({} as MinimalNodeEntity, elementToFocusSelector);
|
||||
contentManagementService.editFolder({} as NodeEntry, elementToFocusSelector);
|
||||
afterClosed$.next();
|
||||
expect(elementToFocus.focus).toHaveBeenCalled();
|
||||
});
|
||||
@@ -1699,7 +1699,7 @@ describe('ContentManagementService', () => {
|
||||
}
|
||||
} as MatDialogRef<any>);
|
||||
spyOn(document, 'querySelector');
|
||||
contentManagementService.editFolder({} as MinimalNodeEntity, '');
|
||||
contentManagementService.editFolder({} as NodeEntry, '');
|
||||
afterClosed$.next();
|
||||
expect(document.querySelector).not.toHaveBeenCalled();
|
||||
});
|
||||
|
@@ -57,16 +57,7 @@ import {
|
||||
NodesApiService
|
||||
} from '@alfresco/adf-content-services';
|
||||
import { TranslationService, NotificationService } from '@alfresco/adf-core';
|
||||
import {
|
||||
DeletedNodesPaging,
|
||||
MinimalNodeEntity,
|
||||
MinimalNodeEntryEntity,
|
||||
Node,
|
||||
NodeEntry,
|
||||
PathInfoEntity,
|
||||
SiteBody,
|
||||
SiteEntry
|
||||
} from '@alfresco/js-api';
|
||||
import { DeletedNodesPaging, Node, NodeEntry, PathInfo, SiteBodyCreate, SiteEntry } from '@alfresco/js-api';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
|
||||
import { Store } from '@ngrx/store';
|
||||
@@ -77,7 +68,7 @@ import { Router } from '@angular/router';
|
||||
|
||||
interface RestoredNode {
|
||||
status: number;
|
||||
entry: MinimalNodeEntryEntity;
|
||||
entry: Node;
|
||||
statusCode?: number;
|
||||
}
|
||||
|
||||
@@ -102,7 +93,7 @@ export class ContentManagementService {
|
||||
private router: Router
|
||||
) {}
|
||||
|
||||
addFavorite(nodes: Array<MinimalNodeEntity>) {
|
||||
addFavorite(nodes: Array<NodeEntry>) {
|
||||
if (nodes && nodes.length > 0) {
|
||||
this.contentApi.addFavorite(nodes).subscribe(() => {
|
||||
const favoriteNodes = nodes.map((node) => {
|
||||
@@ -116,7 +107,7 @@ export class ContentManagementService {
|
||||
}
|
||||
}
|
||||
|
||||
removeFavorite(nodes: Array<MinimalNodeEntity>) {
|
||||
removeFavorite(nodes: Array<NodeEntry>) {
|
||||
if (nodes && nodes.length > 0) {
|
||||
this.contentApi.removeFavorite(nodes).subscribe(() => {
|
||||
const favoriteNodes = nodes.map((node) => {
|
||||
@@ -244,7 +235,7 @@ export class ContentManagementService {
|
||||
});
|
||||
}
|
||||
|
||||
editFolder(folder: MinimalNodeEntity, focusedElementOnCloseSelector?: string) {
|
||||
editFolder(folder: NodeEntry, focusedElementOnCloseSelector?: string) {
|
||||
if (!folder) {
|
||||
return;
|
||||
}
|
||||
@@ -332,7 +323,7 @@ export class ContentManagementService {
|
||||
});
|
||||
}
|
||||
|
||||
updateLibrary(siteId: string, siteBody: SiteBody) {
|
||||
updateLibrary(siteId: string, siteBody: SiteBodyCreate) {
|
||||
this.contentApi.updateLibrary(siteId, siteBody).subscribe(
|
||||
(siteEntry: SiteEntry) => {
|
||||
this.appHookService.libraryUpdated.next(siteEntry);
|
||||
@@ -344,21 +335,21 @@ export class ContentManagementService {
|
||||
);
|
||||
}
|
||||
|
||||
async unshareNodes(links: Array<MinimalNodeEntity>) {
|
||||
async unshareNodes(links: Array<NodeEntry>) {
|
||||
const promises = links.map((link) => this.contentApi.deleteSharedLink(link.entry.id).toPromise());
|
||||
await Promise.all(promises);
|
||||
this.appHookService.linksUnshared.next();
|
||||
}
|
||||
|
||||
canUpdateNode(node: MinimalNodeEntity | Node): boolean {
|
||||
canUpdateNode(node: NodeEntry | Node): boolean {
|
||||
return this.permission.check(node, ['update']);
|
||||
}
|
||||
|
||||
canUploadContent(folderNode: MinimalNodeEntity | Node): boolean {
|
||||
canUploadContent(folderNode: NodeEntry | Node): boolean {
|
||||
return this.permission.check(folderNode, ['create']);
|
||||
}
|
||||
|
||||
purgeDeletedNodes(nodes: MinimalNodeEntity[]) {
|
||||
purgeDeletedNodes(nodes: NodeEntry[]) {
|
||||
if (!nodes || nodes.length === 0) {
|
||||
return;
|
||||
}
|
||||
@@ -389,7 +380,7 @@ export class ContentManagementService {
|
||||
});
|
||||
}
|
||||
|
||||
restoreDeletedNodes(selection: MinimalNodeEntity[] = []) {
|
||||
restoreDeletedNodes(selection: NodeEntry[] = []) {
|
||||
if (!selection.length) {
|
||||
return;
|
||||
}
|
||||
@@ -426,7 +417,7 @@ export class ContentManagementService {
|
||||
});
|
||||
}
|
||||
|
||||
copyNodes(nodes: Array<MinimalNodeEntity>, focusedElementOnCloseSelector?: string) {
|
||||
copyNodes(nodes: Array<NodeEntry>, focusedElementOnCloseSelector?: string) {
|
||||
zip(this.nodeActionsService.copyNodes(nodes, undefined, focusedElementOnCloseSelector), this.nodeActionsService.contentCopied).subscribe(
|
||||
(result) => {
|
||||
const [operationResult, newItems] = result;
|
||||
@@ -438,7 +429,7 @@ export class ContentManagementService {
|
||||
);
|
||||
}
|
||||
|
||||
moveNodes(nodes: Array<MinimalNodeEntity>, focusedElementOnCloseSelector?: string) {
|
||||
moveNodes(nodes: Array<NodeEntry>, focusedElementOnCloseSelector?: string) {
|
||||
const permissionForMove = '!';
|
||||
|
||||
zip(this.nodeActionsService.moveNodes(nodes, permissionForMove, focusedElementOnCloseSelector), this.nodeActionsService.contentMoved).subscribe(
|
||||
@@ -474,7 +465,7 @@ export class ContentManagementService {
|
||||
return i18nMessageString;
|
||||
}
|
||||
|
||||
getNodeInfo(): Observable<MinimalNodeEntryEntity> {
|
||||
getNodeInfo(): Observable<Node> {
|
||||
return this.store.select(getAppSelection).pipe(
|
||||
take(1),
|
||||
mergeMap(({ file }) => {
|
||||
@@ -498,7 +489,7 @@ export class ContentManagementService {
|
||||
});
|
||||
}
|
||||
|
||||
private showCopyMessage(info: any, nodes: Array<MinimalNodeEntity>, newItems?: Array<MinimalNodeEntity>) {
|
||||
private showCopyMessage(info: any, nodes: Array<NodeEntry>, newItems?: Array<NodeEntry>) {
|
||||
const numberOfCopiedItems = newItems ? newItems.length : 0;
|
||||
const failedItems = nodes.length - numberOfCopiedItems;
|
||||
|
||||
@@ -547,7 +538,7 @@ export class ContentManagementService {
|
||||
.subscribe(() => this.undoCopyNodes(newItems));
|
||||
}
|
||||
|
||||
private undoCopyNodes(nodes: MinimalNodeEntity[]) {
|
||||
private undoCopyNodes(nodes: NodeEntry[]) {
|
||||
const batch = this.nodeActionsService
|
||||
.flatten(nodes)
|
||||
.filter((item) => item.entry)
|
||||
@@ -665,7 +656,7 @@ export class ContentManagementService {
|
||||
);
|
||||
}
|
||||
|
||||
deleteNodes(items: MinimalNodeEntity[]): void {
|
||||
deleteNodes(items: NodeEntry[]): void {
|
||||
const batch: Observable<DeletedNodeInfo>[] = [];
|
||||
|
||||
items.forEach((node) => {
|
||||
@@ -744,7 +735,7 @@ export class ContentManagementService {
|
||||
return null;
|
||||
}
|
||||
|
||||
private restoreNode(node: MinimalNodeEntity): Observable<RestoredNode> {
|
||||
private restoreNode(node: NodeEntry): Observable<RestoredNode> {
|
||||
const { entry } = node;
|
||||
|
||||
return this.contentApi.restoreNode(entry.id).pipe(
|
||||
@@ -882,7 +873,7 @@ export class ContentManagementService {
|
||||
if (message) {
|
||||
if (status.oneSucceeded && !status.someFailed) {
|
||||
const isSite = this.isSite(status.success[0].entry);
|
||||
const path: PathInfoEntity = status.success[0].entry.path;
|
||||
const path: PathInfo = status.success[0].entry.path;
|
||||
const parent = path.elements[path.elements.length - 1];
|
||||
const route = isSite ? ['/libraries', parent.id] : ['/personal-files', parent.id];
|
||||
|
||||
@@ -901,11 +892,11 @@ export class ContentManagementService {
|
||||
}
|
||||
}
|
||||
|
||||
private isSite(entry: MinimalNodeEntryEntity): boolean {
|
||||
private isSite(entry: Node): boolean {
|
||||
return entry.nodeType === 'st:site';
|
||||
}
|
||||
|
||||
private isLibraryContent(path: PathInfoEntity): boolean {
|
||||
private isLibraryContent(path: PathInfo): boolean {
|
||||
return path && path.elements.length >= 2 && path.elements[1].name === 'Sites';
|
||||
}
|
||||
|
||||
@@ -1017,7 +1008,7 @@ export class ContentManagementService {
|
||||
return null;
|
||||
}
|
||||
|
||||
private showMoveMessage(nodes: Array<MinimalNodeEntity>, info: any, moveResponse?: any) {
|
||||
private showMoveMessage(nodes: Array<NodeEntry>, info: any, moveResponse?: any) {
|
||||
const succeeded = moveResponse && moveResponse['succeeded'] ? moveResponse['succeeded'].length : 0;
|
||||
const partiallySucceeded = moveResponse && moveResponse['partiallySucceeded'] ? moveResponse['partiallySucceeded'].length : 0;
|
||||
const failures = moveResponse && moveResponse['failed'] ? moveResponse['failed'].length : 0;
|
||||
|
@@ -28,12 +28,12 @@ import { of, throwError, Subject, Observable } from 'rxjs';
|
||||
import { AlfrescoApiService, TranslationService } from '@alfresco/adf-core';
|
||||
import { DocumentListService, NodeAction } from '@alfresco/adf-content-services';
|
||||
import { NodeActionsService } from './node-actions.service';
|
||||
import { MinimalNodeEntryEntity, NodeChildAssociationEntry, NodeEntry } from '@alfresco/js-api';
|
||||
import { Node, NodeChildAssociationEntry, NodeEntry } from '@alfresco/js-api';
|
||||
import { AppTestingModule } from '../testing/app-testing.module';
|
||||
import { ContentApiService } from '@alfresco/aca-shared';
|
||||
|
||||
class TestNode {
|
||||
entry: MinimalNodeEntryEntity;
|
||||
entry: Node;
|
||||
|
||||
constructor(id?: string, isFile?: boolean, name?: string, permission?: string[], nodeType?: string, properties?: any) {
|
||||
this.entry = {} as any;
|
||||
@@ -242,7 +242,7 @@ describe('NodeActionsService', () => {
|
||||
|
||||
it('should not throw error if entry in "contentEntities" does not have id, but has nodeId property', () => {
|
||||
const contentEntities = [new TestNode(), { entry: { nodeId: '1234' } }];
|
||||
const subject = new Subject<MinimalNodeEntryEntity[]>();
|
||||
const subject = new Subject<Node[]>();
|
||||
|
||||
spyOn(service, 'getContentNodeSelection').and.returnValue(subject);
|
||||
spyOn(service, 'copyNodeAction').and.returnValue(of({}));
|
||||
@@ -333,7 +333,7 @@ describe('NodeActionsService', () => {
|
||||
});
|
||||
|
||||
it('should be called', () => {
|
||||
const subject = new Subject<MinimalNodeEntryEntity[]>();
|
||||
const subject = new Subject<Node[]>();
|
||||
const spyOnBatchOperation = spyOn(service, 'doBatchOperation').and.callThrough();
|
||||
spyOn(service, 'getContentNodeSelection').and.returnValue(subject);
|
||||
spyOn(service, 'copyNodeAction').and.returnValue(of({}));
|
||||
@@ -720,10 +720,10 @@ describe('NodeActionsService', () => {
|
||||
let destinationFolder: TestNode;
|
||||
let spyOnBatchOperation: jasmine.Spy;
|
||||
let documentListService: DocumentListService;
|
||||
let subject: Subject<MinimalNodeEntryEntity[]>;
|
||||
let subject: Subject<Node[]>;
|
||||
|
||||
beforeEach(() => {
|
||||
subject = new Subject<MinimalNodeEntryEntity[]>();
|
||||
subject = new Subject<Node[]>();
|
||||
fileToMove = new TestNode('file-to-be-moved', isFile, 'file-name');
|
||||
folderToMove = new TestNode('fid', !isFile, 'folder-name');
|
||||
destinationFolder = new TestNode(folderDestinationId);
|
||||
|
@@ -35,14 +35,7 @@ import {
|
||||
NodeAction,
|
||||
ContentService
|
||||
} from '@alfresco/adf-content-services';
|
||||
import {
|
||||
MinimalNodeEntity,
|
||||
MinimalNodeEntryEntity,
|
||||
SitePaging,
|
||||
NodeChildAssociationPaging,
|
||||
NodeChildAssociationEntry,
|
||||
NodesApi
|
||||
} from '@alfresco/js-api';
|
||||
import { NodeEntry, Node, SitePaging, NodeChildAssociationPaging, NodeChildAssociationEntry, NodesApi, Site, SitePagingList } from '@alfresco/js-api';
|
||||
import { ContentApiService } from '@alfresco/aca-shared';
|
||||
import { catchError, map, mergeMap } from 'rxjs/operators';
|
||||
|
||||
@@ -52,7 +45,7 @@ type BatchOperationType = Extract<NodeAction, NodeAction.COPY | NodeAction.MOVE>
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class NodeActionsService {
|
||||
contentCopied: Subject<MinimalNodeEntity[]> = new Subject<MinimalNodeEntity[]>();
|
||||
contentCopied: Subject<NodeEntry[]> = new Subject<NodeEntry[]>();
|
||||
contentMoved: Subject<any> = new Subject<any>();
|
||||
moveDeletedEntries: any[] = [];
|
||||
isSitesDestinationAvailable = false;
|
||||
@@ -110,7 +103,7 @@ export class NodeActionsService {
|
||||
observable.error(new Error(JSON.stringify({ error: { statusCode: 400 } })));
|
||||
} else if (this.checkPermission(action, contentEntities, permission)) {
|
||||
const destinationSelection = this.getContentNodeSelection(action, contentEntities, focusedElementOnCloseSelector);
|
||||
destinationSelection.subscribe((selections: MinimalNodeEntryEntity[]) => {
|
||||
destinationSelection.subscribe((selections: Node[]) => {
|
||||
const contentEntry = contentEntities[0].entry;
|
||||
// Check if there's nodeId for Shared Files
|
||||
const contentEntryId = contentEntry.nodeId || contentEntry.id;
|
||||
@@ -162,7 +155,7 @@ export class NodeActionsService {
|
||||
return !notAllowedNode;
|
||||
}
|
||||
|
||||
getEntryParentId(nodeEntry: MinimalNodeEntryEntity) {
|
||||
getEntryParentId(nodeEntry: Node) {
|
||||
let entryParentId = '';
|
||||
|
||||
if (nodeEntry.parentId) {
|
||||
@@ -174,11 +167,7 @@ export class NodeActionsService {
|
||||
return entryParentId;
|
||||
}
|
||||
|
||||
getContentNodeSelection(
|
||||
action: NodeAction,
|
||||
contentEntities: MinimalNodeEntity[],
|
||||
focusedElementOnCloseSelector?: string
|
||||
): Subject<MinimalNodeEntryEntity[]> {
|
||||
getContentNodeSelection(action: NodeAction, contentEntities: NodeEntry[], focusedElementOnCloseSelector?: string): Subject<Node[]> {
|
||||
const currentParentFolderId = this.getEntryParentId(contentEntities[0].entry);
|
||||
|
||||
const customDropdown = new SitePaging({
|
||||
@@ -188,16 +177,16 @@ export class NodeActionsService {
|
||||
entry: {
|
||||
guid: '-my-',
|
||||
title: this.translation.instant('APP.BROWSE.PERSONAL.SIDENAV_LINK.LABEL')
|
||||
}
|
||||
} as Site
|
||||
},
|
||||
{
|
||||
entry: {
|
||||
guid: '-mysites-',
|
||||
title: this.translation.instant('APP.BROWSE.LIBRARIES.MENU.MY_LIBRARIES.SIDENAV_LINK.LABEL')
|
||||
}
|
||||
} as Site
|
||||
}
|
||||
]
|
||||
}
|
||||
} as SitePagingList
|
||||
});
|
||||
|
||||
const title = this.getTitleTranslation(action, contentEntities);
|
||||
@@ -214,7 +203,7 @@ export class NodeActionsService {
|
||||
imageResolver: this.imageResolver.bind(this),
|
||||
isSelectionValid: this.canCopyMoveInsideIt.bind(this),
|
||||
breadcrumbTransform: this.customizeBreadcrumb.bind(this),
|
||||
select: new Subject<MinimalNodeEntryEntity[]>(),
|
||||
select: new Subject<Node[]>(),
|
||||
excludeSiteContent: ContentNodeDialogService.nonDocumentSiteContent
|
||||
};
|
||||
|
||||
@@ -235,7 +224,7 @@ export class NodeActionsService {
|
||||
return data.select;
|
||||
}
|
||||
|
||||
getTitleTranslation(action: string, nodes: MinimalNodeEntity[] = []): string {
|
||||
getTitleTranslation(action: string, nodes: NodeEntry[] = []): string {
|
||||
let keyPrefix = 'ITEMS';
|
||||
let name = '';
|
||||
|
||||
@@ -248,11 +237,11 @@ export class NodeActionsService {
|
||||
return this.translation.instant(`NODE_SELECTOR.${action.toUpperCase()}_${keyPrefix}`, { name, number });
|
||||
}
|
||||
|
||||
private canCopyMoveInsideIt(entry: MinimalNodeEntryEntity): boolean {
|
||||
private canCopyMoveInsideIt(entry: Node): boolean {
|
||||
return this.hasEntityCreatePermission(entry) && !this.isSite(entry);
|
||||
}
|
||||
|
||||
private hasEntityCreatePermission(entry: MinimalNodeEntryEntity): boolean {
|
||||
private hasEntityCreatePermission(entry: Node): boolean {
|
||||
return this.contentService.hasAllowableOperations(entry, 'create');
|
||||
}
|
||||
|
||||
@@ -265,7 +254,7 @@ export class NodeActionsService {
|
||||
}
|
||||
|
||||
// todo: review this approach once 5.2.3 is out
|
||||
private customizeBreadcrumb(node: MinimalNodeEntryEntity) {
|
||||
private customizeBreadcrumb(node: Node) {
|
||||
if (node && node.path && node.path.elements) {
|
||||
const elements = node.path.elements;
|
||||
|
||||
@@ -300,7 +289,7 @@ export class NodeActionsService {
|
||||
}
|
||||
|
||||
// todo: review this approach once 5.2.3 is out
|
||||
private normalizeSitePath(node: MinimalNodeEntryEntity) {
|
||||
private normalizeSitePath(node: Node) {
|
||||
const elements = node.path.elements;
|
||||
|
||||
// remove 'Company Home'
|
||||
@@ -326,7 +315,7 @@ export class NodeActionsService {
|
||||
}
|
||||
}
|
||||
|
||||
isSiteContainer(node: MinimalNodeEntryEntity): boolean {
|
||||
isSiteContainer(node: Node): boolean {
|
||||
if (node && node.aspectNames && node.aspectNames.length > 0) {
|
||||
return node.aspectNames.indexOf('st:siteContainer') >= 0;
|
||||
}
|
||||
@@ -551,7 +540,7 @@ export class NodeActionsService {
|
||||
return matchedNodes;
|
||||
}
|
||||
|
||||
private isActionAllowed(action: BatchOperationType, node: MinimalNodeEntryEntity, permission?: string): boolean {
|
||||
private isActionAllowed(action: BatchOperationType, node: Node, permission?: string): boolean {
|
||||
if (action === NodeAction.COPY) {
|
||||
return true;
|
||||
}
|
||||
@@ -559,14 +548,14 @@ export class NodeActionsService {
|
||||
}
|
||||
|
||||
private rowFilter(row: ShareDataRow): boolean {
|
||||
const node: MinimalNodeEntryEntity = row.node.entry;
|
||||
const node: Node = row.node.entry;
|
||||
|
||||
this.isSitesDestinationAvailable = !!node['guid'];
|
||||
return !node.isFile && node.nodeType !== 'app:folderlink';
|
||||
}
|
||||
|
||||
private imageResolver(row: ShareDataRow): string | null {
|
||||
const entry: MinimalNodeEntryEntity = row.node.entry;
|
||||
const entry: Node = row.node.entry;
|
||||
if (!this.contentService.hasAllowableOperations(entry, 'update')) {
|
||||
return this.thumbnailService.getMimeTypeIcon('disable/folder');
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ import { Injectable } from '@angular/core';
|
||||
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||
import { CreateFromTemplateDialogComponent } from '../dialogs/node-template/create-from-template.dialog';
|
||||
import { Subject, from, of } from 'rxjs';
|
||||
import { Node, MinimalNode, MinimalNodeEntryEntity, ResultNode, PathElement, SearchApi } from '@alfresco/js-api';
|
||||
import { Node, ResultNode, PathElement, SearchApi } from '@alfresco/js-api';
|
||||
import { AlfrescoApiService, TranslationService } from '@alfresco/adf-core';
|
||||
import { switchMap, catchError } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
@@ -124,7 +124,7 @@ export class NodeTemplateService {
|
||||
return dialog;
|
||||
}
|
||||
|
||||
private transformNode(node: MinimalNode): MinimalNode {
|
||||
private transformNode(node: Node): Node {
|
||||
if (node && node.path && node.path && node.path.elements instanceof Array) {
|
||||
node.path.elements = this.getPathElements(node);
|
||||
}
|
||||
@@ -157,7 +157,7 @@ export class NodeTemplateService {
|
||||
}
|
||||
|
||||
private rowFilter(row: ShareDataRow): boolean {
|
||||
const node: MinimalNodeEntryEntity = row.node.entry;
|
||||
const node: Node = row.node.entry;
|
||||
return node.nodeType !== 'app:filelink' && node.nodeType !== 'app:folderlink';
|
||||
}
|
||||
|
||||
|
@@ -24,7 +24,7 @@
|
||||
|
||||
import { AppStore, DownloadNodesAction, NodeActionTypes, NodeInfo, getAppSelection, getCurrentVersion } from '@alfresco/aca-shared/store';
|
||||
import { DownloadZipDialogComponent } from '@alfresco/adf-content-services';
|
||||
import { MinimalNodeEntity, Version } from '@alfresco/js-api';
|
||||
import { NodeEntry, Version } from '@alfresco/js-api';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Actions, ofType, createEffect } from '@ngrx/effects';
|
||||
@@ -74,7 +74,7 @@ export class DownloadEffects {
|
||||
{ dispatch: false }
|
||||
);
|
||||
|
||||
private downloadNodes(toDownload: Array<MinimalNodeEntity>, focusedElementSelector?: string) {
|
||||
private downloadNodes(toDownload: Array<NodeEntry>, focusedElementSelector?: string) {
|
||||
const nodes = toDownload.map((node) => {
|
||||
const { id, nodeId, name, isFile, isFolder } = node.entry as any;
|
||||
|
||||
|
@@ -39,7 +39,7 @@ import { Store } from '@ngrx/store';
|
||||
import { of } from 'rxjs';
|
||||
import { catchError, map, take } from 'rxjs/operators';
|
||||
import { ContentManagementService } from '../../services/content-management.service';
|
||||
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
import { UploadService, FileModel } from '@alfresco/adf-content-services';
|
||||
|
||||
@Injectable()
|
||||
@@ -137,7 +137,7 @@ export class UploadEffects {
|
||||
return of(null);
|
||||
})
|
||||
)
|
||||
.subscribe((node: MinimalNodeEntryEntity) => {
|
||||
.subscribe((node: Node) => {
|
||||
if (node) {
|
||||
this.contentService.versionUpdateDialog(node, this.fileVersionInput.files[0]);
|
||||
this.fileVersionInput.value = '';
|
||||
|
@@ -35,7 +35,7 @@ import {
|
||||
PageTitleService
|
||||
} from '@alfresco/adf-core';
|
||||
import { DiscoveryApiService, SearchQueryBuilderService } from '@alfresco/adf-content-services';
|
||||
import { RepositoryInfo } from '@alfresco/js-api';
|
||||
import { RepositoryInfo, VersionInfo } from '@alfresco/js-api';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { StoreModule } from '@ngrx/store';
|
||||
import { appReducer } from '../store/reducers/app.reducer';
|
||||
@@ -76,7 +76,14 @@ import { STORE_INITIAL_APP_DATA } from '@alfresco/aca-shared/store';
|
||||
provide: DiscoveryApiService,
|
||||
useValue: {
|
||||
ecmProductInfo$: new BehaviorSubject<RepositoryInfo | null>(null),
|
||||
getEcmProductInfo: (): Observable<RepositoryInfo> => of(new RepositoryInfo({ version: '10.0.0' }))
|
||||
getEcmProductInfo: (): Observable<RepositoryInfo> =>
|
||||
of(
|
||||
new RepositoryInfo({
|
||||
version: {
|
||||
major: '10.0.0'
|
||||
} as VersionInfo
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@@ -43,7 +43,7 @@ import {
|
||||
ViewNodeAction
|
||||
} from '@alfresco/aca-shared/store';
|
||||
import { ContentActionRef, SelectionState } from '@alfresco/adf-extensions';
|
||||
import { MinimalNodeEntryEntity, SearchRequest, VersionEntry, VersionsApi } from '@alfresco/js-api';
|
||||
import { Node, SearchRequest, VersionEntry, VersionsApi } from '@alfresco/js-api';
|
||||
import { Component, HostListener, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { ActivatedRoute, PRIMARY_OUTLET, Router } from '@angular/router';
|
||||
import { AlfrescoApiService, AppConfigModule, ObjectUtils, UserPreferencesService, ViewerModule } from '@alfresco/adf-core';
|
||||
@@ -76,7 +76,7 @@ export class AcaViewerComponent implements OnInit, OnDestroy {
|
||||
folderId: string = null;
|
||||
nodeId: string = null;
|
||||
versionId: string = null;
|
||||
node: MinimalNodeEntryEntity;
|
||||
node: Node;
|
||||
selection: SelectionState;
|
||||
infoDrawerOpened$: Observable<boolean>;
|
||||
|
||||
|
Reference in New Issue
Block a user