[ADF-3530, ADF-3598] Sharing files (#3828)

* share node

* lint fix

* createSharedLinks parameter

* remove es6 async

* use fakeAsync

* removed trailing comma

* e2e update dialog title locator

* Expires label localization

* docs update
This commit is contained in:
Cilibiu Bogdan
2018-10-01 16:10:40 +03:00
committed by Eugenio Romano
parent b34ca87657
commit 42f4bee2b4
39 changed files with 1241 additions and 435 deletions

View File

@@ -24,7 +24,6 @@ import { MaterialModule } from '../material.module';
import { DownloadZipDialogComponent } from './download-zip.dialog';
import { FolderDialogComponent } from './folder.dialog';
import { NodeLockDialogComponent } from './node-lock.dialog';
import { ShareDialogComponent } from './share.dialog';
import { ConfirmDialogComponent } from './confirm.dialog';
import { MatDatetimepickerModule } from '@mat-datetimepicker/core';
import { MatMomentDatetimeModule } from '@mat-datetimepicker/moment';
@@ -43,21 +42,18 @@ import { MatMomentDatetimeModule } from '@mat-datetimepicker/moment';
DownloadZipDialogComponent,
FolderDialogComponent,
NodeLockDialogComponent,
ShareDialogComponent,
ConfirmDialogComponent
],
exports: [
DownloadZipDialogComponent,
FolderDialogComponent,
NodeLockDialogComponent,
ShareDialogComponent,
ConfirmDialogComponent
],
entryComponents: [
DownloadZipDialogComponent,
FolderDialogComponent,
NodeLockDialogComponent,
ShareDialogComponent,
ConfirmDialogComponent
]
})

View File

@@ -18,7 +18,6 @@
export * from './download-zip.dialog';
export * from './folder.dialog';
export * from './node-lock.dialog';
export * from './share.dialog';
export * from './confirm.dialog';
export * from './dialog.module';

View File

@@ -1,32 +0,0 @@
<h1 mat-dialog-title id="adf-share-title">{{ 'SHARE.TITLE' | translate }} {{fileName}}</h1>
<mat-dialog-content>
<span class="spacer"></span>
<mat-slide-toggle id="adf-share-toggle" [checked]="isFileShared" [disabled]="isDisabled"
(change)="onSlideShareChange($event)">
{{ 'SHARE.ACTIONS.SHARE' | translate }}
</mat-slide-toggle>
<span class="spacer"></span>
<h2 *ngIf="isFileShared">{{ 'SHARE.DESCRIPTION' | translate }}</h2>
<div *ngIf="isFileShared">{{ 'SHARE.ALERT' | translate }}</div>
<form *ngIf="isFileShared">
<mat-form-field class="full-width">
<input id="adf-share-link" lass="adf-share-link" matInput placeholder="{{ 'SHARE.PUBLIC-LINK' | translate }}"
[value]="baseShareUrl + sharedId">
<mat-icon matPrefix>link</mat-icon>
</mat-form-field>
</form>
<h2 *ngIf="!isFileShared">{{ 'SHARE.UNSHARED' | translate }}</h2>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button color="primary" (click)="cancelShare()">
{{ 'SHARE.ACTIONS.CLOSE' | translate }}
</button>
</mat-dialog-actions>

View File

@@ -1,14 +0,0 @@
.spacer { flex: 1 1 auto; }
.adf-share-dialog .mat-dialog-actions .mat-button-wrapper {
text-transform: uppercase;
}
.full-width {
width: 100%;
}
.adf-share-link {
margin-left: 10px;
font-size: 18px !important;
}

View File

@@ -1,128 +0,0 @@
/*!
* @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 { async, TestBed } from '@angular/core/testing';
import { ComponentFixture } from '@angular/core/testing';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { of } from 'rxjs';
import { ShareDialogComponent } from './share.dialog';
import { ContentTestingModule } from '../testing/content.testing.module';
import { SharedLinksApiService, setupTestBed } from '@alfresco/adf-core';
describe('ShareDialogComponent', () => {
let fixture: ComponentFixture<ShareDialogComponent>;
let spyCreate: any;
let spyDelete: any;
let component: ShareDialogComponent;
let sharedLinksApiService: SharedLinksApiService;
const dialogRef = {
close: jasmine.createSpy('close')
};
let data: any = {
node: { entry: { properties: { 'qshare:sharedId': 'example-link' }, name: 'example-name' } },
baseShareUrl: 'baseShareUrl-example'
};
setupTestBed({
imports: [ContentTestingModule],
providers: [
{ provide: MatDialogRef, useValue: dialogRef },
{ provide: MAT_DIALOG_DATA, useValue: data }
]
});
beforeEach(() => {
fixture = TestBed.createComponent(ShareDialogComponent);
sharedLinksApiService = TestBed.get(SharedLinksApiService);
component = fixture.componentInstance;
fixture.detectChanges();
spyCreate = spyOn(sharedLinksApiService, 'createSharedLinks').and.returnValue(of({ entry: { id: 'test-sharedId' } }));
spyDelete = spyOn(sharedLinksApiService, 'deleteSharedLink').and.returnValue(of({}));
});
it('should init the dialog with the file name and baseShareUrl', async(() => {
component.data = {
baseShareUrl: 'base-url/',
node: { entry: { properties: { 'qshare:sharedId': 'example-link' }, name: 'example-name' } }
};
component.ngOnInit();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.nativeElement.querySelector('#adf-share-link').value).toBe('base-url/example-link');
});
}));
describe('public link creation', () => {
it('should not create the public link if it already present in the node', () => {
component.data = {
node: { entry: { properties: { 'qshare:sharedId': 'example-link' }, name: 'example-name' } }
};
component.ngOnInit();
expect(spyCreate).not.toHaveBeenCalled();
});
it('should not create the public link if is not present in the node', () => {
component.data = {
node: { entry: { properties: {}, name: 'example-name' } },
baseShareUrl: 'baseShareUrl-example'
};
component.ngOnInit();
expect(spyCreate).not.toHaveBeenCalled();
});
it('should be able to delete the shared link', async(() => {
component.data = {
node: { entry: { name: 'example-name', properties: { 'qshare:sharedId': 'example-link' } } },
baseShareUrl: 'baseShareUrl-example'
};
component.ngOnInit();
fixture.detectChanges();
fixture.nativeElement.querySelector('#adf-share-toggle-input').click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(spyDelete).toHaveBeenCalled();
expect(component.data.node.entry.properties['qshare:sharedId']).toBeNull();
});
}));
it('should show the toggle disabled when the shareid property is null', async(() => {
component.data = {
node: { entry: { name: 'example-name', properties: { 'qshare:sharedId': null } } },
baseShareUrl: 'baseShareUrl-example'
};
component.ngOnInit();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(fixture.nativeElement.querySelector('#adf-share-toggle')).not.toBeNull();
expect(fixture.nativeElement.querySelector('#adf-share-toggle.mat-checked')).toBeNull();
});
}));
});
});

View File

@@ -1,100 +0,0 @@
/*!
* @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 } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { SharedLinksApiService } from '@alfresco/adf-core';
import { SharedLinkEntry } from 'alfresco-js-api';
@Component({
selector: 'adf-share-dialog',
templateUrl: './share.dialog.html',
styleUrls: ['./share.dialog.scss'],
host: { 'class': 'adf-share-dialog' },
encapsulation: ViewEncapsulation.None
})
export class ShareDialogComponent implements OnInit {
sharedId: string;
fileName: string;
baseShareUrl: string;
isFileShared: boolean = false;
isDisabled: boolean = false;
constructor(private sharedLinksApiService: SharedLinksApiService,
private dialogRef: MatDialogRef<ShareDialogComponent>,
@Inject(MAT_DIALOG_DATA)
public data: any) {
}
ngOnInit() {
if (this.data.node && this.data.node.entry) {
this.fileName = this.data.node.entry.name;
this.baseShareUrl = this.data.baseShareUrl;
if (this.data.node.entry.properties && this.data.node.entry.properties['qshare:sharedId']) {
this.sharedId = this.data.node.entry.properties['qshare:sharedId'];
this.isFileShared = true;
} else {
this.isFileShared = false;
this.isDisabled = false;
}
}
}
cancelShare() {
this.dialogRef.close(false);
}
onSlideShareChange(event: any) {
this.isDisabled = true;
if (event.checked) {
this.createSharedLinks(this.data.node.entry.id);
} else {
this.deleteSharedLink(this.sharedId);
}
}
createSharedLinks(nodeId: string) {
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.isFileShared = true;
this.isDisabled = false;
}
},
() => {
this.isFileShared = false;
this.isDisabled = false;
});
}
deleteSharedLink(sharedId: string) {
this.sharedLinksApiService.deleteSharedLink(sharedId).subscribe(() => {
this.data.node.entry.properties['qshare:sharedId'] = null;
this.isFileShared = false;
this.isDisabled = false;
},
() => {
this.isFileShared = true;
this.isDisabled = false;
});
}
}