diff --git a/demo-shell/src/app/components/files/files.component.ts b/demo-shell/src/app/components/files/files.component.ts index 18f39ea8c6..95c8f06843 100644 --- a/demo-shell/src/app/components/files/files.component.ts +++ b/demo-shell/src/app/components/files/files.component.ts @@ -28,7 +28,8 @@ import { AlfrescoApiService, AuthenticationService, AppConfigService, AppConfigValues, ContentService, TranslationService, FileUploadEvent, FolderCreatedEvent, LogService, NotificationService, UploadService, DataColumn, DataRow, UserPreferencesService, - PaginationComponent, FormValues, DisplayMode, InfinitePaginationComponent, HighlightDirective + PaginationComponent, FormValues, DisplayMode, InfinitePaginationComponent, HighlightDirective, + SharedLinksApiService } from '@alfresco/adf-core'; import { @@ -217,7 +218,8 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { @Optional() private route: ActivatedRoute, public authenticationService: AuthenticationService, public alfrescoApiService: AlfrescoApiService, - private contentMetadataService: ContentMetadataService) { + private contentMetadataService: ContentMetadataService, + private sharedLinksApiService: SharedLinksApiService) { } showFile(event) { @@ -275,6 +277,12 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy { .subscribe((err: { message: string }) => { this.notificationService.showError(err.message); }); + + this.sharedLinksApiService.error + .pipe(takeUntil(this.onDestroy$)) + .subscribe((err: { message: string }) => { + this.notificationService.showError(err.message); + }); } ngOnDestroy() { diff --git a/e2e/content-services/share-file/unshare-file.e2e.ts b/e2e/content-services/share-file/unshare-file.e2e.ts index 5d056ab81c..8b85d94921 100644 --- a/e2e/content-services/share-file/unshare-file.e2e.ts +++ b/e2e/content-services/share-file/unshare-file.e2e.ts @@ -16,7 +16,7 @@ */ import CONSTANTS = require('../../util/constants'); -import { StringUtil, BrowserActions } from '@alfresco/adf-testing'; +import { StringUtil, BrowserActions, NotificationHistoryPage } from '@alfresco/adf-testing'; import { NavigationBarPage } from '../../pages/adf/navigationBarPage'; import { LoginPage, ErrorPage } from '@alfresco/adf-testing'; import { ContentServicesPage } from '../../pages/adf/contentServicesPage'; @@ -35,6 +35,7 @@ describe('Unshare file', () => { const contentListPage = contentServicesPage.getDocumentList(); const navBar = new NavigationBarPage(); const errorPage = new ErrorPage(); + const notificationHistoryPage = new NotificationHistoryPage(); const shareDialog = new ShareDialog(); const siteName = `PRIVATE-TEST-SITE-${StringUtil.generateRandomString(5)}`; @@ -171,9 +172,12 @@ describe('Unshare file', () => { contentServicesPage.clickShareButton(); shareDialog.checkDialogIsDisplayed(); shareDialog.shareToggleButtonIsChecked(); - shareDialog.shareToggleButtonIsDisabled(); shareDialog.clickUnShareFile(); - shareDialog.confirmationDialogIsNotDisplayed(); + shareDialog.confirmationDialogIsDisplayed(); + shareDialog.clickConfirmationDialogRemoveButton(); + shareDialog.checkDialogIsDisplayed(); + shareDialog.shareToggleButtonIsChecked(); + notificationHistoryPage.checkNotifyContains(`You don't have permission to unshare this file`); }); }); }); diff --git a/lib/content-services/content-node-share/content-node-share.dialog.html b/lib/content-services/content-node-share/content-node-share.dialog.html index 5aa87dfffc..bc4ca7653f 100644 --- a/lib/content-services/content-node-share/content-node-share.dialog.html +++ b/lib/content-services/content-node-share/content-node-share.dialog.html @@ -52,4 +52,4 @@ {{ 'SHARE.CLOSE' | translate }} - \ No newline at end of file + diff --git a/lib/content-services/content-node-share/content-node-share.dialog.ts b/lib/content-services/content-node-share/content-node-share.dialog.ts index 41f2a21144..a13ab1464d 100644 --- a/lib/content-services/content-node-share/content-node-share.dialog.ts +++ b/lib/content-services/content-node-share/content-node-share.dialog.ts @@ -42,6 +42,7 @@ import { import { SharedLinkEntry, Node } from '@alfresco/js-api'; import { ConfirmDialogComponent } from '../dialogs/confirm.dialog'; import moment from 'moment-es6'; +import { ContentNodeShareSettings } from './content-node-share.settings'; @Component({ selector: 'adf-share-dialog', @@ -82,7 +83,7 @@ export class ShareDialogComponent implements OnInit, OnDestroy { private nodesApiService: NodesApiService, private contentService: ContentService, private renditionService: RenditionsService, - @Inject(MAT_DIALOG_DATA) public data: any + @Inject(MAT_DIALOG_DATA) public data: ContentNodeShareSettings ) {} ngOnInit() { @@ -113,7 +114,7 @@ export class ShareDialogComponent implements OnInit, OnDestroy { this.baseShareUrl = this.data.baseShareUrl; const properties = this.data.node.entry.properties; - if (properties && !properties['qshare:sharedId']) { + if (!properties || !properties['qshare:sharedId']) { this.createSharedLinks(this.data.node.entry.id); } else { this.sharedId = properties['qshare:sharedId']; @@ -141,10 +142,13 @@ export class ShareDialogComponent implements OnInit, OnDestroy { } get canUpdate() { - return this.contentService.hasAllowableOperations( - this.data.node.entry, - 'update' - ); + const { entry } = this.data.node; + + if (entry && entry.allowableOperations) { + return this.contentService.hasAllowableOperations(entry, 'update'); + } + + return true; } onToggleExpirationDate(slideToggle: MatSlideToggleChange) { @@ -195,9 +199,13 @@ export class ShareDialogComponent implements OnInit, OnDestroy { (sharedLink: SharedLinkEntry) => { if (sharedLink.entry) { this.sharedId = sharedLink.entry.id; - this.data.node.entry.properties[ - 'qshare:sharedId' - ] = this.sharedId; + if (this.data.node.entry.properties) { + this.data.node.entry.properties['qshare:sharedId'] = this.sharedId; + } else { + this.data.node.entry.properties = { + 'qshare:sharedId': this.sharedId + }; + } this.isDisabled = false; this.isFileShared = true; this.renditionService @@ -217,21 +225,20 @@ export class ShareDialogComponent implements OnInit, OnDestroy { deleteSharedLink(sharedId: string) { this.isDisabled = true; - this.sharedLinksApiService.deleteSharedLink(sharedId).subscribe( - (response: any) => { + this.sharedLinksApiService + .deleteSharedLink(sharedId) + .subscribe((response: any) => { if (response instanceof Error) { this.isDisabled = false; this.isFileShared = true; this.handleError(response); } else { - this.data.node.entry.properties['qshare:sharedId'] = null; - this.data.node.entry.properties['qshare:expiryDate'] = null; + if (this.data.node.entry.properties) { + this.data.node.entry.properties['qshare:sharedId'] = null; + this.data.node.entry.properties['qshare:expiryDate'] = null; + } this.dialogRef.close(false); } - }, - () => { - this.isDisabled = false; - this.isFileShared = false; } ); } @@ -256,7 +263,11 @@ export class ShareDialogComponent implements OnInit, OnDestroy { private updateForm() { const { entry } = this.data.node; - const expiryDate = entry.properties['qshare:expiryDate']; + let expiryDate = null; + + if (entry && entry.properties) { + expiryDate = entry.properties['qshare:expiryDate']; + } this.form.setValue({ sharedUrl: `${this.baseShareUrl}${this.sharedId}`, @@ -277,8 +288,10 @@ export class ShareDialogComponent implements OnInit, OnDestroy { private updateEntryExpiryDate(date: moment.Moment) { const { properties } = this.data.node.entry; - properties['qshare:expiryDate'] = date - ? date.local() - : null; + if (properties) { + properties['qshare:expiryDate'] = date + ? date.local() + : null; + } } } diff --git a/lib/content-services/content-node-share/content-node-share.directive.ts b/lib/content-services/content-node-share/content-node-share.directive.ts index 0a6b30a282..a6284f325c 100644 --- a/lib/content-services/content-node-share/content-node-share.directive.ts +++ b/lib/content-services/content-node-share/content-node-share.directive.ts @@ -17,9 +17,11 @@ import { Directive, Input, HostListener, OnChanges, NgZone } from '@angular/core'; import { MatDialog } from '@angular/material'; -import { NodeEntry } from '@alfresco/js-api'; +import { NodeEntry, Node } from '@alfresco/js-api'; import { ShareDialogComponent } from './content-node-share.dialog'; +import { Observable, from } from 'rxjs'; +import { AlfrescoApiService } from '@alfresco/adf-core'; @Directive({ selector: '[adf-share]', @@ -46,22 +48,46 @@ export class NodeSharedDirective implements OnChanges { } } - constructor(private dialog: MatDialog, private zone: NgZone) { + constructor( + private dialog: MatDialog, + private zone: NgZone, + private alfrescoApiService: AlfrescoApiService) { } shareNode(nodeEntry: NodeEntry) { if (nodeEntry && nodeEntry.entry && nodeEntry.entry.isFile) { - this.dialog.open(ShareDialogComponent, { - width: '600px', - panelClass: 'adf-share-link-dialog', - data: { - node: nodeEntry, - baseShareUrl: this.baseShareUrl - } - }); + // shared and favorite + const nodeId = nodeEntry.entry['nodeId'] || nodeEntry.entry['guid']; + + if (nodeId) { + this.getNodeInfo(nodeId).subscribe((entry) => { + this.openShareLinkDialog({ entry }); + }); + } else { + this.openShareLinkDialog(nodeEntry); + } } } + private getNodeInfo(nodeId: string): Observable { + const options = { + include: ['allowableOperations'] + }; + + return from(this.alfrescoApiService.nodesApi.getNodeInfo(nodeId, options)); + } + + private openShareLinkDialog(node: NodeEntry) { + this.dialog.open(ShareDialogComponent, { + width: '600px', + panelClass: 'adf-share-link-dialog', + data: { + node, + baseShareUrl: this.baseShareUrl + } + }); + } + ngOnChanges() { this.zone.onStable.subscribe(() => { if (this.node && this.node.entry) { diff --git a/lib/content-services/content-node-share/content-node-share.settings.ts b/lib/content-services/content-node-share/content-node-share.settings.ts new file mode 100644 index 0000000000..9809a9e132 --- /dev/null +++ b/lib/content-services/content-node-share/content-node-share.settings.ts @@ -0,0 +1,23 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NodeEntry } from '@alfresco/js-api'; + +export interface ContentNodeShareSettings { + baseShareUrl: string; + node: NodeEntry; +} diff --git a/lib/content-services/content-node-share/public-api.ts b/lib/content-services/content-node-share/public-api.ts index a7d19f66e5..d5e0110dec 100644 --- a/lib/content-services/content-node-share/public-api.ts +++ b/lib/content-services/content-node-share/public-api.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +export * from './content-node-share.settings'; export * from './content-node-share.dialog'; export * from './content-node-share.directive';