[ADF-4496] Share dialog enhancements (#4705)

* raise snackbars on unshare errors

* remove time from datepicker

* update tests

* Update en.json

* code updates as per review

* update docs

* bind datetimepicker type attribute

* set datetimepicker type by configuration or default

* tests

* e2e test

* update docs

* e2e set sharedLinkDateTimePickerType config
This commit is contained in:
Denys Vuika 2019-06-06 16:32:37 +01:00 committed by Eugenio Romano
parent c3b1300d86
commit 99f4b07878
24 changed files with 381 additions and 121 deletions

View File

@ -67,3 +67,17 @@ and passes it to a [Viewer component](../../core/components/viewer.component.md)
[allowGoBack]="false">
</adf-viewer>
```
## Date and time widget
Date and time widget for setting the expiration date can be configured to show only the date picker or both date and time piker.
By default, the widget will show both date and time picker if `sharedLinkDateTimePickerType` is not present in the app.config.json.
Possible values are `'date'` or `'datetime'`
```json
{
...
"sharedLinkDateTimePickerType": 'date'
...
}
```

View File

@ -27,6 +27,12 @@ Finds shared links to Content Services items.
- _options:_ `any` - Options supported by JS-API
- **Returns** [`Observable`](http://reactivex.io/documentation/observable.html)`<`[`NodePaging`](https://github.com/Alfresco/alfresco-js-api/blob/development/src/api/content-rest-api/docs/NodePaging.md)`>` - List of shared links
### Events
| Name | Type | Description |
| --- | --- | --- |
| error | `Subject<{ statusCode: number, message: string }>` | Gets emitted upon errors. |
## Details
Content Services allows users to generate URLs that can be shared with

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { LoginPage, BrowserActions } from '@alfresco/adf-testing';
import { LoginPage, BrowserActions, LocalStorageUtil } from '@alfresco/adf-testing';
import { ContentServicesPage } from '../../pages/adf/contentServicesPage';
import { NavigationBarPage } from '../../pages/adf/navigationBarPage';
import { ViewerPage } from '../../pages/adf/viewerPage';
@ -140,6 +140,22 @@ describe('Share file', () => {
shareDialog.clickDateTimePickerButton();
shareDialog.calendarTodayDayIsDisabled();
});
it('[C310329] Should be possible to set expiry date only for link', async () => {
await LocalStorageUtil.setConfigField('sharedLinkDateTimePickerType', JSON.stringify('date'));
contentServicesPage.clickShareButton();
shareDialog.checkDialogIsDisplayed();
shareDialog.clickDateTimePickerButton();
shareDialog.setDefaultDay();
shareDialog.dateTimePickerDialogIsClosed();
const value = await shareDialog.getExpirationDate();
shareDialog.clickCloseButton();
shareDialog.dialogIsClosed();
contentServicesPage.clickShareButton();
shareDialog.checkDialogIsDisplayed();
shareDialog.expirationDateInputHasValue(value);
BrowserActions.closeMenuAndDialogs();
});
});
describe('Shared link preview', () => {

View File

@ -1,6 +1,5 @@
<div class="adf-share-link__dialog-content">
<h1 data-automation-id="adf-share-dialog-title"
class="adf-share-link__title">
<h1 data-automation-id="adf-share-dialog-title" class="adf-share-link__title">
{{ 'SHARE.DIALOG-TITLE' | translate }} {{ fileName }}
</h1>
@ -10,50 +9,47 @@
<div class="adf-share-link--row">
<h1 class="adf-share-link__label">{{ 'SHARE.TITLE' | translate }}</h1>
<mat-slide-toggle
color="primary"
data-automation-id="adf-share-toggle"
[checked]="isFileShared"
[disabled]="!canUpdate || isDisabled"
(change)="onSlideShareChange($event)">
<mat-slide-toggle color="primary" data-automation-id="adf-share-toggle" [checked]="isFileShared"
[disabled]="!canUpdate || isDisabled" (change)="onSlideShareChange($event)">
</mat-slide-toggle>
</div>
<form [formGroup]="form">
<mat-form-field class="adf-full-width">
<input #sharedLinkInput
data-automation-id="adf-share-link"
class="adf-share-link__input"
matInput
cdkFocusInitial
placeholder="{{ 'SHARE.PUBLIC-LINK' | translate }}"
formControlName="sharedUrl"
<input #sharedLinkInput data-automation-id="adf-share-link" class="adf-share-link__input" matInput
cdkFocusInitial placeholder="{{ 'SHARE.PUBLIC-LINK' | translate }}" formControlName="sharedUrl"
readonly="readonly">
<mat-icon class="adf-input-action" matSuffix
[clipboard-notification]="'SHARE.CLIPBOARD-MESSAGE' | translate"
[adf-clipboard] [target]="sharedLinkInput">
link
</mat-icon>
<mat-icon class="adf-input-action" matSuffix
[clipboard-notification]="'SHARE.CLIPBOARD-MESSAGE' | translate" [adf-clipboard]
[target]="sharedLinkInput">
link
</mat-icon>
</mat-form-field>
<div class="adf-share-link--row">
<h1 class="adf-share-link__label">{{ 'SHARE.EXPIRES' | translate }}</h1>
<mat-slide-toggle [disabled]="!canUpdate" #slideToggleExpirationDate color="primary"
data-automation-id="adf-expire-toggle" [checked]="form.controls['time'].value"
(change)="onToggleExpirationDate($event)">
</mat-slide-toggle>
</div>
<mat-form-field class="adf-full-width">
<mat-datetimepicker-toggle [for]="datetimePicker" matSuffix></mat-datetimepicker-toggle>
<mat-datetimepicker #datetimePicker type="datetime" openOnFocus="true" timeInterval="1"></mat-datetimepicker>
<mat-datetimepicker-toggle #matDatetimepickerToggle="matDatetimepickerToggle" [for]="datetimePicker" matSuffix></mat-datetimepicker-toggle>
<mat-datetimepicker #datetimePicker (closed)="onDatetimepickerClosed()" [type]="type" openOnFocus="true" timeInterval="1"></mat-datetimepicker>
<input class="adf-share-link__input"
#dateTimePickerInput
matInput
[min]="minDate"
formControlName="time"
[matDatetimepicker]="datetimePicker">
[matDatetimepicker]="datetimePicker" />
</mat-form-field>
</form>
</mat-dialog-content>
<div mat-dialog-actions>
<button
data-automation-id="adf-share-dialog-close"
mat-button color="primary" mat-dialog-close>
<button data-automation-id="adf-share-dialog-close" mat-button color="primary" mat-dialog-close>
{{ 'SHARE.CLOSE' | translate }}
</button>
</div>
</div>
</div>

View File

@ -16,17 +16,19 @@
*/
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { TestBed, fakeAsync, async } from '@angular/core/testing';
import { TestBed, fakeAsync, async, ComponentFixture } from '@angular/core/testing';
import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material';
import { of, empty } from 'rxjs';
import {
setupTestBed,
CoreModule,
SharedLinksApiService,
NodesApiService,
NotificationService,
RenditionsService
RenditionsService,
AppConfigService
} from '@alfresco/adf-core';
import { CoreTestingModule } from '../../core/testing/core.testing.module';
import { AppConfigServiceMock } from '../../core/mock/app-config.service.mock';
import { ContentNodeShareModule } from './content-node-share.module';
import { ShareDialogComponent } from './content-node-share.dialog';
import moment from 'moment-es6';
@ -40,18 +42,20 @@ describe('ShareDialogComponent', () => {
let sharedLinksApiService: SharedLinksApiService;
let renditionService: RenditionsService;
let nodesApiService: NodesApiService;
let fixture;
let component;
let fixture: ComponentFixture<ShareDialogComponent>;
let component: ShareDialogComponent;
let appConfigService: AppConfigService;
setupTestBed({
imports: [
NoopAnimationsModule,
CoreModule.forRoot(),
CoreTestingModule,
ContentNodeShareModule
],
providers: [
NodesApiService,
SharedLinksApiService,
{ provide: AppConfigService, useClass: AppConfigServiceMock },
{ provide: NotificationService, useValue: notificationServiceMock },
{ provide: MatDialogRef, useValue: { close: () => {}} },
{ provide: MAT_DIALOG_DATA, useValue: {} }
@ -64,10 +68,9 @@ describe('ShareDialogComponent', () => {
sharedLinksApiService = TestBed.get(SharedLinksApiService);
renditionService = TestBed.get(RenditionsService);
nodesApiService = TestBed.get(NodesApiService);
appConfigService = TestBed.get(AppConfigService);
component = fixture.componentInstance;
});
beforeEach(() => {
node = {
entry: {
id: 'nodeId',
@ -78,6 +81,38 @@ describe('ShareDialogComponent', () => {
};
});
describe('Error Handling', () => {
it('should emit a generic error when unshare fails', (done) => {
spyOn(sharedLinksApiService, 'deleteSharedLink').and.returnValue(
of(new Error(`{ "error": { "statusCode": 999 } }`))
);
const sub = sharedLinksApiService.error.subscribe((err) => {
expect(err.statusCode).toBe(999);
expect(err.message).toBe('SHARE.UNSHARE_ERROR');
sub.unsubscribe();
done();
});
component.deleteSharedLink('guid');
});
it('should emit permission error when unshare fails', (done) => {
spyOn(sharedLinksApiService, 'deleteSharedLink').and.returnValue(
of(new Error(`{ "error": { "statusCode": 403 } }`))
);
const sub = sharedLinksApiService.error.subscribe((err) => {
expect(err.statusCode).toBe(403);
expect(err.message).toBe('SHARE.UNSHARE_PERMISSION_ERROR');
sub.unsubscribe();
done();
});
component.deleteSharedLink('guid');
});
});
it(`should toggle share action when property 'sharedId' does not exists`, () => {
spyOn(sharedLinksApiService, 'createSharedLinks').and.returnValue(of({
entry: { id: 'sharedId', sharedId: 'sharedId' }
@ -196,21 +231,126 @@ describe('ShareDialogComponent', () => {
expect(fixture.nativeElement.querySelector('mat-datetimepicker-toggle button').disabled).toBe(true);
});
it('should not update shared node expiryDate property when value changes', () => {
const date = moment();
it('should reset expiration date when toggle is unchecked', () => {
spyOn(nodesApiService, 'updateNode').and.returnValue(of({}));
node.entry.properties['qshare:sharedId'] = 'sharedId';
spyOn(nodesApiService, 'updateNode');
fixture.componentInstance.form.controls['time'].setValue(null);
node.entry.properties['qshare:sharedId'] = '2017-04-15T18:31:37+00:00';
node.entry.allowableOperations = ['update'];
component.data = {
node,
baseShareUrl: 'some-url/'
};
fixture.detectChanges();
component.form.controls['time'].setValue(moment());
fixture.detectChanges();
fixture.nativeElement
.querySelector(
'.mat-slide-toggle[data-automation-id="adf-expire-toggle"] label'
)
.dispatchEvent(new MouseEvent('click'));
fixture.detectChanges();
expect(nodesApiService.updateNode).toHaveBeenCalledWith('nodeId', {
properties: { 'qshare:expiryDate': null }
});
expect(
fixture.nativeElement.querySelector('input[formcontrolname="time"]').value
).toBe('');
});
it('should not allow expiration date action when node has no update permission', () => {
node.entry.properties['qshare:sharedId'] = 'sharedId';
node.entry.allowableOperations = [];
component.data = {
node,
baseShareUrl: 'some-url/'
};
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('input[formcontrolname="time"]').disabled).toBe(true);
expect(fixture.nativeElement.querySelector('.mat-slide-toggle[data-automation-id="adf-expire-toggle"]')
.classList).toContain('mat-disabled');
});
it('should update node expiration date with selected date', () => {
const date = moment();
node.entry.allowableOperations = ['update'];
node.entry.properties['qshare:sharedId'] = 'sharedId';
spyOn(nodesApiService, 'updateNode').and.returnValue(of({}));
fixture.componentInstance.form.controls['time'].setValue(null);
component.data = {
node,
baseShareUrl: 'some-url/'
};
fixture.detectChanges();
fixture.nativeElement
.querySelector(
'mat-slide-toggle[data-automation-id="adf-expire-toggle"] label'
)
.dispatchEvent(new MouseEvent('click'));
fixture.componentInstance.form.controls['time'].setValue(date);
fixture.detectChanges();
expect(nodesApiService.updateNode).toHaveBeenCalled();
expect(nodesApiService.updateNode).toHaveBeenCalledWith('nodeId', {
properties: { 'qshare:expiryDate': date.utc().format() }
});
});
describe('datetimepicker type', () => {
beforeEach(() => {
spyOn(nodesApiService, 'updateNode').and.returnValue(of({}));
spyOn(sharedLinksApiService, 'createSharedLinks').and.returnValue(of({}));
node.entry.allowableOperations = ['update'];
component.data = {
node,
baseShareUrl: 'some-url/'
};
});
it('it should update node with input date and end of day time when type is `date`', () => {
const dateTimePickerType = 'date';
const date = moment('2525-01-01 13:00:00');
spyOn(appConfigService, 'get').and.callFake(() => dateTimePickerType);
fixture.detectChanges();
fixture.nativeElement.querySelector('mat-slide-toggle[data-automation-id="adf-expire-toggle"] label')
.dispatchEvent(new MouseEvent('click'));
fixture.componentInstance.form.controls['time'].setValue(date);
fixture.detectChanges();
expect(nodesApiService.updateNode).toHaveBeenCalledWith('nodeId', {
properties: { 'qshare:expiryDate': date.endOf('day').utc().format() }
});
});
it('it should update node with input date and time when type is `datetime`', () => {
const dateTimePickerType = 'datetime';
const date = moment('2525-01-01 13:00:00');
spyOn(appConfigService, 'get').and.callFake(() => dateTimePickerType);
fixture.detectChanges();
fixture.nativeElement.querySelector('mat-slide-toggle[data-automation-id="adf-expire-toggle"] label')
.dispatchEvent(new MouseEvent('click'));
fixture.componentInstance.form.controls['time'].setValue(date);
fixture.detectChanges();
expect(nodesApiService.updateNode).toHaveBeenCalledWith('nodeId', {
properties: { 'qshare:expiryDate': date.utc().format() }
});
});
});
});

View File

@ -21,18 +21,23 @@ import {
OnInit,
ViewEncapsulation,
ViewChild,
ElementRef,
OnDestroy
} from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef, MatDialog } from '@angular/material';
import { MAT_DIALOG_DATA, MatDialogRef, MatDialog, MatSlideToggleChange } from '@angular/material';
import { FormGroup, FormControl } from '@angular/forms';
import { Subscription, Observable } from 'rxjs';
import { tap, skip } from 'rxjs/operators';
import { Subscription, Observable, throwError } from 'rxjs';
import {
skip,
distinctUntilChanged,
mergeMap,
catchError
} from 'rxjs/operators';
import {
SharedLinksApiService,
NodesApiService,
ContentService,
RenditionsService
RenditionsService,
AppConfigService
} from '@alfresco/adf-core';
import { SharedLinkEntry, Node } from '@alfresco/js-api';
import { ConfirmDialogComponent } from '../dialogs/confirm.dialog';
@ -42,7 +47,7 @@ import moment from 'moment-es6';
selector: 'adf-share-dialog',
templateUrl: './content-node-share.dialog.html',
styleUrls: ['./content-node-share.dialog.scss'],
host: { 'class': 'adf-share-dialog' },
host: { class: 'adf-share-dialog' },
encapsulation: ViewEncapsulation.None
})
export class ShareDialogComponent implements OnInit, OnDestroy {
@ -55,34 +60,49 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
isFileShared: boolean = false;
isDisabled: boolean = false;
form: FormGroup = new FormGroup({
'sharedUrl': new FormControl(''),
'time': new FormControl({value: '', disabled: false})
sharedUrl: new FormControl(''),
time: new FormControl({ value: '', disabled: false })
});
type = 'datetime';
@ViewChild('sharedLinkInput') sharedLinkInput: ElementRef;
@ViewChild('matDatetimepickerToggle')
matDatetimepickerToggle;
@ViewChild('slideToggleExpirationDate')
slideToggleExpirationDate;
@ViewChild('dateTimePickerInput')
dateTimePickerInput;
constructor(
private appConfigService: AppConfigService,
private sharedLinksApiService: SharedLinksApiService,
private dialogRef: MatDialogRef<ShareDialogComponent>,
private dialog: MatDialog,
private nodesApiService: NodesApiService,
private contentService: ContentService,
private renditionService: RenditionsService,
@Inject(MAT_DIALOG_DATA) public data: any) {
}
@Inject(MAT_DIALOG_DATA) public data: any
) {}
ngOnInit() {
this.type = this.appConfigService.get<string>('sharedLinkDateTimePickerType', 'datetime');
if (!this.canUpdate) {
this.form.controls['time'].disable();
}
this.subscriptions.push(
this.form.valueChanges
this.form.controls.time.valueChanges
.pipe(
skip(1),
tap((updates) => {
this.updateNode(updates);
distinctUntilChanged(),
mergeMap(
(updates) => this.updateNode(updates),
(formUpdates) => formUpdates
),
catchError((error) => {
return throwError(error);
})
)
.subscribe((updates) => this.updateEntryExpiryDate(updates))
@ -94,9 +114,7 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
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;
@ -123,7 +141,27 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
}
get canUpdate() {
return this.contentService.hasAllowableOperations(this.data.node.entry, 'update');
return this.contentService.hasAllowableOperations(
this.data.node.entry,
'update'
);
}
onToggleExpirationDate(slideToggle: MatSlideToggleChange) {
if (slideToggle.checked) {
this.matDatetimepickerToggle.datetimepicker.open();
} else {
this.matDatetimepickerToggle.datetimepicker.close();
this.form.controls.time.setValue(null);
}
}
onDatetimepickerClosed() {
this.dateTimePickerInput.nativeElement.blur();
if (!this.form.controls.time.value) {
this.slideToggleExpirationDate.checked = false;
}
}
private openConfirmationDialog() {
@ -140,7 +178,8 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
minWidth: '250px',
closeOnNavigation: true
})
.beforeClose().subscribe((deleteSharedLink) => {
.beforeClose()
.subscribe((deleteSharedLink) => {
if (deleteSharedLink) {
this.deleteSharedLink(this.sharedId);
} else {
@ -152,15 +191,18 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
private createSharedLinks(nodeId: string) {
this.isDisabled = true;
this.sharedLinksApiService.createSharedLinks(nodeId)
.subscribe((sharedLink: SharedLinkEntry) => {
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.data.node.entry.properties[
'qshare:sharedId'
] = this.sharedId;
this.isDisabled = false;
this.isFileShared = true;
this.renditionService.generateRenditionForNode(this.data.node.entry.id).subscribe(() => {});
this.renditionService
.generateRenditionForNode(this.data.node.entry.id)
.subscribe(() => {});
this.updateForm();
}
@ -168,21 +210,48 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
() => {
this.isDisabled = false;
this.isFileShared = false;
});
}
);
}
private deleteSharedLink(sharedId: string) {
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(false);
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;
this.dialogRef.close(false);
}
},
() => {
this.isDisabled = false;
this.isFileShared = false;
});
}
);
}
private handleError(error: Error) {
let message = 'SHARE.UNSHARE_ERROR';
let statusCode = 0;
try {
statusCode = JSON.parse(error.message).error.statusCode;
} catch {}
if (statusCode === 403) {
message = 'SHARE.UNSHARE_PERMISSION_ERROR';
}
this.sharedLinksApiService.error.next({
statusCode,
message
});
}
private updateForm() {
@ -190,27 +259,26 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
const expiryDate = entry.properties['qshare:expiryDate'];
this.form.setValue({
'sharedUrl': `${this.baseShareUrl}${this.sharedId}`,
'time': expiryDate ? expiryDate : null
sharedUrl: `${this.baseShareUrl}${this.sharedId}`,
time: expiryDate ? moment(expiryDate).local() : null
});
}
private updateNode(updates): Observable<Node> {
return this.nodesApiService.updateNode(
this.data.node.entry.id,
{
properties: {
'qshare:expiryDate': updates.time ? updates.time.utc().format() : null
}
private updateNode(date: moment.Moment): Observable<Node> {
return this.nodesApiService.updateNode(this.data.node.entry.id, {
properties: {
'qshare:expiryDate': date ?
(this.type === 'date' ? date.endOf('day').utc().format() : date.utc().format()) :
null
}
);
});
}
private updateEntryExpiryDate(updates) {
private updateEntryExpiryDate(date: moment.Moment) {
const { properties } = this.data.node.entry;
properties['qshare:expiryDate'] = updates.time
? updates.time.local()
properties['qshare:expiryDate'] = date
? date.local()
: null;
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "سيتم حذف هذا الرابط وسيتم إنشاء رابط جديد في المرة التالية التي يتم فيها مشاركة هذا الملف",
"CANCEL": "إلغاء",
"REMOVE": "إزالة"
}
},
"UNSHARE_PERMISSION_ERROR": "ليس لديك إذن لإلغاء مشاركة هذا الملف"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "تم تحديث خصائص المكتبة"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "Tento odkaz se odstraní a při dalším sdílení tohoto souboru se vytvoří odkaz nový",
"CANCEL": "Zrušit",
"REMOVE": "Odstranit"
}
},
"UNSHARE_PERMISSION_ERROR": "Nemáte potřebná oprávnění pro zrušení sdílení tohoto souboru"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "Vlastnosti knihovny byly upraveny"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "Dette link bliver slettet, og der oprettes et nyt link, når filen deles næste gang",
"CANCEL": "Annuller",
"REMOVE": "Fjern"
}
},
"UNSHARE_PERMISSION_ERROR": "Du har ikke tilladelse til at ophæve delingen af denne fil"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "Egenskaberne for biblioteket er blevet opdateret"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "Dieser Link wird gelöscht und ein neuer Link wird erstellt wenn diese Datei das nächste Mal geteilt wird.",
"CANCEL": "Abbrechen",
"REMOVE": "Entfernen"
}
},
"UNSHARE_PERMISSION_ERROR": "Sie verfügen nicht über die Berechtigung die Freigabe für diese Datei aufzuheben"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "Bibliothekseigenschaften aktualisiert"
}
}
}
}

View File

@ -297,7 +297,9 @@
"MESSAGE": "This link will be deleted and a new link will be created next time this file is shared",
"CANCEL": "Cancel",
"REMOVE": "Remove"
}
},
"UNSHARE_ERROR": "Error unsharing this file",
"UNSHARE_PERMISSION_ERROR": "You don't have permission to unshare this file"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {

View File

@ -292,7 +292,8 @@
"MESSAGE": "Este enlace será eliminado. Se creará un enlace nuevo la próxima vez que comparta este fichero.",
"CANCEL": "Cancelar",
"REMOVE": "Eliminar"
}
},
"UNSHARE_PERMISSION_ERROR": "No tiene acceso para dejar de compartir este fichero"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "Propiedades de la biblioteca actualizadas"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "Tämä linkki poistetaan ja uusi linkki luodaan, kun tiedosto jaetaan seuraavan kerran",
"CANCEL": "Peruuta",
"REMOVE": "Poista"
}
},
"UNSHARE_PERMISSION_ERROR": "Sinulla ei ole oikeuksia peruuttaa tämän tiedoston jakamista"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "Kirjaston ominaisuudet päivitettiin"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "Ce lien sera supprimé et un nouveau lien sera créé lors du prochain partage de ce fichier",
"CANCEL": "Annuler",
"REMOVE": "Supprimer"
}
},
"UNSHARE_PERMISSION_ERROR": "Vous n'avez pas les droits d'accès pour ne pas partager ce fichier"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "Les propriétés de la bibliothèque ont été mises à jour"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "Il link verrà eliminato e verrà creato un nuovo link per il prossimo file condiviso",
"CANCEL": "Annulla",
"REMOVE": "Rimuovi"
}
},
"UNSHARE_PERMISSION_ERROR": "Non hai il permesso per rimuovere la condivisione di questo file"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "Proprietà della raccolta aggiornate"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "このリンクは削除され、次回このファイルを共有するときに新しいリンクが作成されます。",
"CANCEL": "キャンセル",
"REMOVE": "削除"
}
},
"UNSHARE_PERMISSION_ERROR": "このファイルの共有を解除する権限がありません。"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "ライブラリのプロパティが更新されました"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "Denne koblingen vil bli slettet, og en ny kobling vil bli opprettet neste gang denne filen deles",
"CANCEL": "Avbryt",
"REMOVE": "Fjern"
}
},
"UNSHARE_PERMISSION_ERROR": "Du har ikke tillatelse til å oppheve deling av denne filen"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "Bibliotekegenskaper oppdatert"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "Deze koppeling wordt verwijderd en er wordt een nieuwe koppeling gemaakt de volgende keer dat dit bestand wordt gedeeld",
"CANCEL": "Annuleren",
"REMOVE": "Verwijderen"
}
},
"UNSHARE_PERMISSION_ERROR": "U hebt geen rechten om het delen van dit bestand ongedaan te maken"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "Bibliotheekeigenschappen bijgewerkt"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "Ten link zostanie usunięty, a przy następnym udostępnieniu tego pliku zostanie utworzony nowy link.",
"CANCEL": "Anuluj",
"REMOVE": "Usuń"
}
},
"UNSHARE_PERMISSION_ERROR": "Nie masz uprawnień, aby cofnąć udostępnianie tego pliku"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "Zaktualizowano właściwości biblioteki"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "Este link será excluído. Um novo link será criado na próxima vez que esse arquivo for compartilhado.",
"CANCEL": "Cancelar",
"REMOVE": "Remover"
}
},
"UNSHARE_PERMISSION_ERROR": "Você não tem permissão para descompartilhar deste arquivo"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "Propriedades da biblioteca atualizadas"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "Эта ссылка будет удалена, и новая ссылка будет создана при следующем совместном использовании этого файла",
"CANCEL": "Отмена",
"REMOVE": "Удалить"
}
},
"UNSHARE_PERMISSION_ERROR": "У вас нет разрешения на снятие этого файла с публикации"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "Свойства библиотеки обновлены"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "Den här länken kommer att raderas och en ny länk kommer att skapas nästa gång den här filen delas",
"CANCEL": "Avbryt",
"REMOVE": "Ta bort"
}
},
"UNSHARE_PERMISSION_ERROR": "Du har inte behörighet att sluta dela den här filen"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "Biblioteksegenskaper uppdaterade"
}
}
}
}

View File

@ -292,7 +292,8 @@
"MESSAGE": "此链接将被删除,下次共享此文件时将会创建新链接",
"CANCEL": "取消",
"REMOVE": "删除"
}
},
"UNSHARE_PERMISSION_ERROR": "你没有权限取消这个文件的共享"
},
"PERMISSION_MANAGER": {
"PERMISSION_DISPLAY": {
@ -363,4 +364,4 @@
"LIBRARY_UPDATED": "已更新库属性"
}
}
}
}

View File

@ -17,7 +17,7 @@
import { Injectable } from '@angular/core';
import { NodePaging, SharedLinkEntry } from '@alfresco/js-api';
import { Observable, from, of } from 'rxjs';
import { Observable, from, of, Subject } from 'rxjs';
import { AlfrescoApiService } from './alfresco-api.service';
import { UserPreferencesService } from './user-preferences.service';
import { catchError } from 'rxjs/operators';
@ -27,6 +27,8 @@ import { catchError } from 'rxjs/operators';
})
export class SharedLinksApiService {
error = new Subject<{ statusCode: number, message: string }>();
constructor(private apiService: AlfrescoApiService,
private preferences: UserPreferencesService) {
}
@ -73,11 +75,11 @@ export class SharedLinksApiService {
* @param sharedId ID of the link to delete
* @returns Null response notifying when the operation is complete
*/
deleteSharedLink(sharedId: string): Observable<SharedLinkEntry> {
deleteSharedLink(sharedId: string): Observable<any | Error> {
const promise = this.sharedLinksApi.deleteSharedLink(sharedId);
return from(promise).pipe(
catchError((err) => of(err))
catchError((err: Error) => of(err))
);
}
}