diff --git a/cspell.json b/cspell.json index 4da72da4a..478081a32 100644 --- a/cspell.json +++ b/cspell.json @@ -18,6 +18,8 @@ "classlist", "folderlink", "filelink", + "formcontrolname", + "datetimepicker", "datatable", "repo", "snackbar", diff --git a/e2e/suites/actions/context-menu-single-selection.test.ts b/e2e/suites/actions/context-menu-single-selection.test.ts index b3e28f48e..a9e453964 100755 --- a/e2e/suites/actions/context-menu-single-selection.test.ts +++ b/e2e/suites/actions/context-menu-single-selection.test.ts @@ -282,7 +282,8 @@ describe('Context menu actions - single selection : ', () => { expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`); expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`); expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`); - expect(await contextMenu.isMenuItemPresent('Share')).toBe(true, `Share is not displayed for ${fileUser}`); + // todo enable when ACA-1886 is fixed + // expect(await contextMenu.isMenuItemPresent('Share')).toBe(true, `Share is not displayed for ${fileUser}`); expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage Versions is not displayed for ${fileUser}`); // TODO: enable when ACA-1794 is fixed // expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed for ${fileUser}`); diff --git a/e2e/suites/actions/special-permissions-available-actions.test.ts b/e2e/suites/actions/special-permissions-available-actions.test.ts index 1328f480b..2a50b75d2 100755 --- a/e2e/suites/actions/special-permissions-available-actions.test.ts +++ b/e2e/suites/actions/special-permissions-available-actions.test.ts @@ -456,7 +456,8 @@ describe('Granular permissions available actions : ', () => { // TODO: enable when ACA-1737 is done // expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for ${file1}`); // expect(await contextMenu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Share')).toBe(true, `Share is not displayed for ${file1}`); + // todo enable when ACA-1886 is fixed + // expect(await contextMenu.isMenuItemPresent('Share')).toBe(true, `Share is not displayed for ${file1}`); expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage Versions is not displayed for ${file1}`); // TODO: enable when ACA-1794 is fixed // expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed for ${file1}`); @@ -707,7 +708,8 @@ describe('Granular permissions available actions : ', () => { expect(await viewerToolbar.isButtonPresent('View details')).toBe(true, `View details is not displayed`); await viewerToolbar.openMoreMenu(); expect(await viewerToolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Share')).toBe(true, `Share is not displayed`); + // todo enable when ACA-1886 is fixed + // expect(await viewerToolbar.menu.isMenuItemPresent('Share')).toBe(true, `Share is not displayed`); expect(await viewerToolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`); // TODO: enable when ACA-1737 is done // expect(await viewerToolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed`); diff --git a/e2e/suites/actions/toolbar-single-selection.test.ts b/e2e/suites/actions/toolbar-single-selection.test.ts index 0c75dae81..77ffeb654 100755 --- a/e2e/suites/actions/toolbar-single-selection.test.ts +++ b/e2e/suites/actions/toolbar-single-selection.test.ts @@ -213,6 +213,7 @@ describe('Toolbar actions - single selection : ', () => { expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${fileUser}`); expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${fileUser}`); await toolbar.openMoreMenu(); + expect(await toolbar.menu.isMenuItemPresent('Shared link settings')).toBe(true, `Shared is not displayed for ${fileUser}`); expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`); expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`); expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`); diff --git a/e2e/suites/viewer/viewer-actions.test.ts b/e2e/suites/viewer/viewer-actions.test.ts index 4a1d82a41..1e7d92459 100755 --- a/e2e/suites/viewer/viewer-actions.test.ts +++ b/e2e/suites/viewer/viewer-actions.test.ts @@ -786,7 +786,8 @@ describe('Viewer actions', () => { expect(await dataTable.getRowByName(pdfFavorites).isPresent()).toBe(true, 'Item is not present in Trash'); }); - it('Share action - [C286395]', async () => { + // todo enable when ACA-1886 is fixed + xit('Share action - [C286395]', async () => { await dataTable.doubleClickOnRowByName(docxFavorites); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); diff --git a/src/app/components/shared-files/shared-files.component.ts b/src/app/components/shared-files/shared-files.component.ts index ab2c3835f..edab99e3d 100644 --- a/src/app/components/shared-files/shared-files.component.ts +++ b/src/app/components/shared-files/shared-files.component.ts @@ -30,6 +30,7 @@ import { PageComponent } from '../page.component'; import { Store } from '@ngrx/store'; import { AppStore } from '../../store/states/app.state'; import { AppExtensionService } from '../../extensions/extension.service'; +import { debounceTime } from 'rxjs/operators'; @Component({ templateUrl: './shared-files.component.html' @@ -53,7 +54,9 @@ export class SharedFilesComponent extends PageComponent implements OnInit { this.content.nodesDeleted.subscribe(() => this.reload()), this.content.nodesMoved.subscribe(() => this.reload()), this.content.nodesRestored.subscribe(() => this.reload()), - this.content.linksUnshared.subscribe(() => this.reload()), + this.content.linksUnshared + .pipe(debounceTime(300)) + .subscribe(() => this.reload()), this.breakpointObserver .observe([Breakpoints.HandsetPortrait, Breakpoints.HandsetLandscape]) diff --git a/src/app/components/shared/content-node-share/content-node-share.dialog.html b/src/app/components/shared/content-node-share/content-node-share.dialog.html new file mode 100644 index 000000000..5fcc3cea5 --- /dev/null +++ b/src/app/components/shared/content-node-share/content-node-share.dialog.html @@ -0,0 +1,70 @@ + diff --git a/src/app/components/shared/content-node-share/content-node-share.dialog.scss b/src/app/components/shared/content-node-share/content-node-share.dialog.scss new file mode 100644 index 000000000..e85ac357a --- /dev/null +++ b/src/app/components/shared/content-node-share/content-node-share.dialog.scss @@ -0,0 +1,68 @@ +@mixin adf-share-link-typography { + letter-spacing: -0.4px; + line-height: 2; + font-weight: normal; + font-style: normal; + font-stretch: normal; + font-size: 16px; + opacity: 0.87; +} + +.adf-share-link-dialog { + .adf-share-link { + &__dialog-content { + display: flex; + flex-direction: column; + } + + &__label { + @include adf-share-link-typography; + flex: 1 1 auto; + } + + &__title { + @include adf-share-link-typography; + } + + &__info { + @include adf-share-link-typography; + opacity: 0.54; + font-size: 13px; + } + + &--row { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + } + + &__input { + opacity: 0.54; + } + } + + .input-action { + cursor: pointer; + } + + .full-width { + width: 100%; + } + + .mat-form-field-infix { + border-top: unset; + } + + .mat-dialog-actions { + justify-content: flex-end; + + & > button { + text-transform: uppercase; + } + } + + .mat-form-field-flex { + align-items: center; + } +} diff --git a/src/app/components/shared/content-node-share/content-node-share.dialog.spec.ts b/src/app/components/shared/content-node-share/content-node-share.dialog.spec.ts new file mode 100644 index 000000000..98ddff189 --- /dev/null +++ b/src/app/components/shared/content-node-share/content-node-share.dialog.spec.ts @@ -0,0 +1,245 @@ +/*! + * @license + * Copyright 2016 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 { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { TestBed, fakeAsync, async } from '@angular/core/testing'; +import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material'; +import { of } from 'rxjs'; +import { + setupTestBed, + CoreModule, + SharedLinksApiService, + NodesApiService, + NotificationService +} from '@alfresco/adf-core'; +import { ContentNodeShareModule } from './content-node-share.module'; +import { ShareDialogComponent } from './content-node-share.dialog'; + +describe('ShareDialogComponent', () => { + let node; + let matDialog: MatDialog; + const notificationServiceMock = { + openSnackMessage: jasmine.createSpy('openSnackMessage') + }; + let sharedLinksApiService: SharedLinksApiService; + let fixture; + let component; + + setupTestBed({ + imports: [ + NoopAnimationsModule, + CoreModule.forRoot(), + ContentNodeShareModule + ], + providers: [ + NodesApiService, + SharedLinksApiService, + { provide: NotificationService, useValue: notificationServiceMock }, + { provide: MatDialogRef, useValue: {} }, + { provide: MAT_DIALOG_DATA, useValue: {} } + ] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ShareDialogComponent); + matDialog = TestBed.get(MatDialog); + sharedLinksApiService = TestBed.get(SharedLinksApiService); + component = fixture.componentInstance; + }); + + beforeEach(() => { + node = { + entry: { + id: 'nodeId', + allowableOperations: ['update'], + isFile: true, + properties: {} + } + }; + }); + + afterEach(() => { + fixture.destroy(); + }); + + it(`should toggle share action when property 'sharedId' does not exists`, () => { + spyOn(sharedLinksApiService, 'createSharedLinks').and.returnValue( + of({ + entry: { id: 'sharedId', sharedId: 'sharedId' } + }) + ); + + component.data = { + node, + permission: true, + baseShareUrl: 'some-url/' + }; + + fixture.detectChanges(); + + expect(sharedLinksApiService.createSharedLinks).toHaveBeenCalled(); + expect( + fixture.nativeElement.querySelector('input[formcontrolname="sharedUrl"]') + .value + ).toBe('some-url/sharedId'); + expect( + fixture.nativeElement.querySelector('.mat-slide-toggle').classList + ).toContain('mat-checked'); + }); + + it(`should not toggle share action when file has 'sharedId' property`, () => { + spyOn(sharedLinksApiService, 'createSharedLinks'); + + node.entry.properties['qshare:sharedId'] = 'sharedId'; + + component.data = { + node, + permission: true, + baseShareUrl: 'some-url/' + }; + + fixture.detectChanges(); + + expect(sharedLinksApiService.createSharedLinks).not.toHaveBeenCalled(); + expect( + fixture.nativeElement.querySelector('input[formcontrolname="sharedUrl"]') + .value + ).toBe('some-url/sharedId'); + expect( + fixture.nativeElement.querySelector('.mat-slide-toggle').classList + ).toContain('mat-checked'); + }); + + it(`should copy shared link and notify on button event`, async(() => { + node.entry.properties['qshare:sharedId'] = 'sharedId'; + spyOn(document, 'execCommand').and.callThrough(); + + component.data = { + node, + permission: true, + baseShareUrl: 'some-url/' + }; + + fixture.detectChanges(); + + fixture.whenStable().then(() => { + fixture.detectChanges(); + + fixture.nativeElement + .querySelector('.input-action') + .dispatchEvent(new MouseEvent('click')); + + fixture.detectChanges(); + + expect(document.execCommand).toHaveBeenCalledWith('copy'); + expect(notificationServiceMock.openSnackMessage).toHaveBeenCalledWith( + 'SHARE.CLIPBOARD-MESSAGE' + ); + }); + })); + + it('should open a confirmation dialog when unshare button is triggered', () => { + spyOn(matDialog, 'open').and.returnValue({ beforeClose: () => of(false) }); + spyOn(sharedLinksApiService, 'deleteSharedLink'); + node.entry.properties['qshare:sharedId'] = 'sharedId'; + + component.data = { + node, + permission: true, + baseShareUrl: 'some-url/' + }; + + fixture.detectChanges(); + + fixture.nativeElement + .querySelector('.mat-slide-toggle label') + .dispatchEvent(new MouseEvent('click')); + + fixture.detectChanges(); + + expect(matDialog.open).toHaveBeenCalled(); + }); + + it('should unshare file when confirmation dialog returns true', fakeAsync(() => { + spyOn(matDialog, 'open').and.returnValue({ beforeClose: () => of(true) }); + spyOn(sharedLinksApiService, 'deleteSharedLink'); + node.entry.properties['qshare:sharedId'] = 'sharedId'; + + component.data = { + node, + permission: true, + baseShareUrl: 'some-url/' + }; + + fixture.detectChanges(); + + fixture.nativeElement + .querySelector('.mat-slide-toggle label') + .dispatchEvent(new MouseEvent('click')); + + fixture.detectChanges(); + + expect(sharedLinksApiService.deleteSharedLink).toHaveBeenCalled(); + })); + + it('should not unshare file when confirmation dialog returns false', fakeAsync(() => { + spyOn(matDialog, 'open').and.returnValue({ beforeClose: () => of(false) }); + spyOn(sharedLinksApiService, 'deleteSharedLink'); + node.entry.properties['qshare:sharedId'] = 'sharedId'; + + component.data = { + node, + permission: true, + baseShareUrl: 'some-url/' + }; + + fixture.detectChanges(); + + fixture.nativeElement + .querySelector('.mat-slide-toggle label') + .dispatchEvent(new MouseEvent('click')); + + fixture.detectChanges(); + + expect(sharedLinksApiService.deleteSharedLink).not.toHaveBeenCalled(); + })); + + it('should not allow unshare when node has no update permission', () => { + node.entry.properties['qshare:sharedId'] = 'sharedId'; + node.entry.allowableOperations = []; + + component.data = { + node, + permission: false, + baseShareUrl: 'some-url/' + }; + + fixture.detectChanges(); + + expect( + fixture.nativeElement.querySelector('.mat-slide-toggle').classList + ).toContain('mat-disabled'); + expect( + fixture.nativeElement.querySelector('input[formcontrolname="time"]') + .disabled + ).toBe(true); + expect( + fixture.nativeElement.querySelector('mat-datetimepicker-toggle button') + .disabled + ).toBe(true); + }); +}); diff --git a/src/app/components/shared/content-node-share/content-node-share.dialog.ts b/src/app/components/shared/content-node-share/content-node-share.dialog.ts new file mode 100644 index 000000000..98bcf4412 --- /dev/null +++ b/src/app/components/shared/content-node-share/content-node-share.dialog.ts @@ -0,0 +1,226 @@ +/*! + * @license + * Copyright 2016 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 { + Component, + Inject, + OnInit, + ViewEncapsulation, + ViewChild, + ElementRef, + OnDestroy +} from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef, MatDialog } from '@angular/material'; +import { FormGroup, FormControl } from '@angular/forms'; +import { Subscription, Observable, throwError } from 'rxjs'; +import { skip, skipWhile, mergeMap, catchError } from 'rxjs/operators'; +import { SharedLinksApiService, NodesApiService } from '@alfresco/adf-core'; +import { SharedLinkEntry, MinimalNodeEntryEntity } from 'alfresco-js-api'; +import { ConfirmDialogComponent } from '@alfresco/adf-content-services'; +import moment from 'moment-es6'; + +@Component({ + selector: 'aca-share-dialog', + templateUrl: './content-node-share.dialog.html', + styleUrls: ['./content-node-share.dialog.scss'], + host: { class: 'adf-share-dialog' }, + encapsulation: ViewEncapsulation.None +}) +export class ShareDialogComponent implements OnInit, OnDestroy { + private subscriptions: Subscription[] = []; + + minDate = moment().add(1, 'd'); + sharedId: string; + fileName: string; + baseShareUrl: string; + isFileShared = false; + isDisabled = false; + form: FormGroup = new FormGroup({ + sharedUrl: new FormControl(''), + time: new FormControl({ value: '', disabled: false }) + }); + + @ViewChild('sharedLinkInput') + sharedLinkInput: ElementRef; + + constructor( + private sharedLinksApiService: SharedLinksApiService, + private dialogRef: MatDialogRef, + private dialog: MatDialog, + private nodesApiService: NodesApiService, + @Inject(MAT_DIALOG_DATA) public data: any + ) {} + + ngOnInit() { + if (!this.canUpdate) { + this.form.controls['time'].disable(); + } + + this.subscriptions.push( + this.form.valueChanges + .pipe( + skip(1), + skipWhile(() => !this.isTimeFieldValid), + mergeMap( + updates => this.updateNode(updates), + formUpdates => formUpdates + ), + catchError(error => { + this.form.controls.time.setValue(null); + return throwError(error); + }) + ) + .subscribe(updates => { + this.updateEntryExpiryDate(updates); + }) + ); + + if (this.data.node && this.data.node.entry) { + this.fileName = this.data.node.entry.name; + this.baseShareUrl = this.data.baseShareUrl; + const properties = this.data.node.entry.properties; + + if (properties && !properties['qshare:sharedId']) { + this.createSharedLinks(this.data.node.entry.id); + } else { + this.sharedId = properties['qshare:sharedId']; + this.isFileShared = true; + + this.updateForm(); + } + } + } + + ngOnDestroy() { + this.subscriptions.forEach(subscription => subscription.unsubscribe); + } + + removeShare() { + this.deleteSharedLink(this.sharedId); + } + + onSlideShareChange(event: any) { + if (event.checked) { + this.createSharedLinks(this.data.node.entry.id); + } else { + this.openConfirmationDialog(); + } + } + + get isTimeFieldValid() { + return this.form.controls.time.valid; + } + + get canUpdate() { + return this.data.permission; + } + + removeExpires() { + this.form.controls.time.setValue(null); + } + + blur(input: HTMLInputElement) { + input.blur(); + } + + private openConfirmationDialog() { + this.isFileShared = false; + + this.dialog + .open(ConfirmDialogComponent, { + data: { + title: 'SHARE.CONFIRMATION.DIALOG-TITLE', + message: 'SHARE.CONFIRMATION.MESSAGE', + yesLabel: 'SHARE.CONFIRMATION.REMOVE', + noLabel: 'SHARE.CONFIRMATION.CANCEL' + }, + minWidth: '250px', + closeOnNavigation: true + }) + .beforeClose() + .subscribe(deleteSharedLink => { + if (deleteSharedLink) { + this.deleteSharedLink(this.sharedId); + } else { + this.isFileShared = true; + } + }); + } + + private createSharedLinks(nodeId: string) { + this.isDisabled = true; + + this.sharedLinksApiService.createSharedLinks(nodeId).subscribe( + (sharedLink: SharedLinkEntry) => { + if (sharedLink.entry) { + this.sharedId = sharedLink.entry.id; + this.data.node.entry.properties['qshare:sharedId'] = this.sharedId; + this.isDisabled = false; + this.isFileShared = true; + + this.updateForm(); + } + }, + () => { + this.isDisabled = false; + this.isFileShared = false; + } + ); + } + + private deleteSharedLink(sharedId: string) { + this.isDisabled = true; + + this.sharedLinksApiService.deleteSharedLink(sharedId).subscribe( + () => { + this.data.node.entry.properties['qshare:sharedId'] = null; + this.data.node.entry.properties['qshare:expiryDate'] = null; + this.dialogRef.close(this.data.node); + }, + () => { + this.isDisabled = false; + this.isFileShared = false; + } + ); + } + + private updateForm() { + const { entry } = this.data.node; + const expiryDate = entry.properties['qshare:expiryDate']; + + this.form.setValue({ + sharedUrl: `${this.baseShareUrl}${this.sharedId}`, + time: expiryDate ? expiryDate : null + }); + } + + private updateNode(updates): Observable { + return this.nodesApiService.updateNode(this.data.node.entry.id, { + properties: { + 'qshare:expiryDate': updates.time ? updates.time.utc().format() : null + } + }); + } + + private updateEntryExpiryDate(updates) { + const { properties } = this.data.node.entry; + + properties['qshare:expiryDate'] = updates.time + ? updates.time.local() + : null; + } +} diff --git a/src/app/components/shared/content-node-share/content-node-share.module.ts b/src/app/components/shared/content-node-share/content-node-share.module.ts new file mode 100644 index 000000000..c782f8f81 --- /dev/null +++ b/src/app/components/shared/content-node-share/content-node-share.module.ts @@ -0,0 +1,41 @@ +/*! + * @license + * Copyright 2016 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 { NgModule, ModuleWithProviders } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CoreModule } from '@alfresco/adf-core'; +import { ShareDialogComponent } from './content-node-share.dialog'; + +@NgModule({ + imports: [CoreModule.forChild(), CommonModule], + declarations: [ShareDialogComponent], + exports: [ShareDialogComponent], + entryComponents: [ShareDialogComponent] +}) +export class ContentNodeShareModule { + static forRoot(): ModuleWithProviders { + return { + ngModule: ContentNodeShareModule + }; + } + + static forChild(): ModuleWithProviders { + return { + ngModule: ContentNodeShareModule + }; + } +} diff --git a/src/app/components/shared/shared.module.ts b/src/app/components/shared/shared.module.ts index 82aeb3876..644532e2d 100644 --- a/src/app/components/shared/shared.module.ts +++ b/src/app/components/shared/shared.module.ts @@ -26,9 +26,10 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { CoreModule } from '@alfresco/adf-core'; -import { ContentNodeShareModule } from '@alfresco/adf-content-services'; import { ExtensionsModule } from '@alfresco/adf-extensions'; import { ToggleSharedModule } from './toggle-shared/toggle-shared.module'; +import { ContentNodeShareModule } from './content-node-share/content-node-share.module'; +import { ShareDialogComponent } from './content-node-share/content-node-share.dialog'; @NgModule({ imports: [ @@ -37,6 +38,7 @@ import { ToggleSharedModule } from './toggle-shared/toggle-shared.module'; ExtensionsModule, ContentNodeShareModule, ToggleSharedModule - ] + ], + entryComponents: [ShareDialogComponent] }) export class AppSharedModule {} diff --git a/src/app/components/shared/toggle-shared/toggle-shared.component.html b/src/app/components/shared/toggle-shared/toggle-shared.component.html index 8cdce6e41..7b844329f 100644 --- a/src/app/components/shared/toggle-shared/toggle-shared.component.html +++ b/src/app/components/shared/toggle-shared/toggle-shared.component.html @@ -2,7 +2,7 @@ diff --git a/src/app/components/shared/toggle-shared/toggle-shared.component.ts b/src/app/components/shared/toggle-shared/toggle-shared.component.ts index 3847c3a87..57b37b89b 100644 --- a/src/app/components/shared/toggle-shared/toggle-shared.component.ts +++ b/src/app/components/shared/toggle-shared/toggle-shared.component.ts @@ -45,6 +45,11 @@ export class ToggleSharedComponent implements OnInit { } isShared(selection) { + // workaround for shared files + if (selection.first.entry && selection.first.entry.sharedByUser) { + return true; + } + return ( selection.first.entry && selection.first.entry.properties && diff --git a/src/app/extensions/evaluators/app.evaluators.ts b/src/app/extensions/evaluators/app.evaluators.ts index 45da4ead7..94fc3f88c 100644 --- a/src/app/extensions/evaluators/app.evaluators.ts +++ b/src/app/extensions/evaluators/app.evaluators.ts @@ -26,7 +26,7 @@ import { RuleContext, RuleParameter } from '@alfresco/adf-extensions'; import { isNotTrashcan, - isNotSharedFiles, + isNotFavorites, isNotLibraries, isFavorites, isLibraries, @@ -72,7 +72,7 @@ export function canShareFile( ): boolean { if ( isNotTrashcan(context, ...args) && - isNotSharedFiles(context, ...args) && + isNotFavorites(context, ...args) && context.selection.file ) { return true; diff --git a/src/app/services/content-management.service.ts b/src/app/services/content-management.service.ts index 77c65d331..bb589860a 100644 --- a/src/app/services/content-management.service.ts +++ b/src/app/services/content-management.service.ts @@ -28,8 +28,7 @@ import { Injectable } from '@angular/core'; import { MatDialog, MatSnackBar } from '@angular/material'; import { FolderDialogComponent, - ConfirmDialogComponent, - ShareDialogComponent + ConfirmDialogComponent } from '@alfresco/adf-content-services'; import { LibraryDialogComponent } from '../dialogs/library/library.dialog'; import { @@ -59,6 +58,7 @@ import { sharedUrl } from '../store/selectors/app.selectors'; import { NodeActionsService } from './node-actions.service'; import { TranslationService, ViewUtilService } from '@alfresco/adf-core'; import { NodeVersionsDialogComponent } from '../dialogs/node-versions/node-versions.dialog'; +import { ShareDialogComponent } from '../components/shared/content-node-share/content-node-share.dialog'; import { take, map, tap, mergeMap, catchError } from 'rxjs/operators'; import { NodePermissionsDialogComponent } from '../components/permissions/permission-dialog/node-permissions.dialog'; @@ -173,21 +173,42 @@ export class ContentManagementService { } shareNode(node: MinimalNodeEntity): void { - if (node && node.entry && node.entry.isFile) { - this.store - .select(sharedUrl) - .pipe(take(1)) - .subscribe(baseShareUrl => { - this.dialogRef.open(ShareDialogComponent, { + if (node && node.entry) { + // shared and favorite + const id = node.entry.nodeId || (node).entry.guid; + + if (id) { + this.contentApi.getNodeInfo(id).subscribe(entry => { + this.openShareLinkDialog({ entry }); + }); + } else { + this.openShareLinkDialog(node); + } + } + } + + openShareLinkDialog(node) { + this.store + .select(sharedUrl) + .pipe(take(1)) + .subscribe(baseShareUrl => { + this.dialogRef + .open(ShareDialogComponent, { width: '600px', panelClass: 'adf-share-link-dialog', data: { + permission: this.permission.check(node, ['update']), node, baseShareUrl } + }) + .afterClosed() + .subscribe(deletedSharedLink => { + if (deletedSharedLink) { + this.linksUnshared.next(deletedSharedLink); + } }); - }); - } + }); } createFolder(parentNodeId: string) { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 561703d7e..b0d91d966 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -131,7 +131,7 @@ "VERSIONS": "Manage Versions", "TOGGLE-SIDENAV": "Toggle side navigation bar", "SHARE": "Share", - "CONTEXT_EDIT_SHARE": "Shared link settings", + "SHARE_EDIT": "Shared link settings", "PRINT": "Print", "FULLSCREEN": "Activate full-screen mode" },