[ACA] Shared link expiration date update (#719)

* delete input field animation

* refactor show hide date input

* update date time input functonality on toggle

* refactor tests

* remove unsunsed method

* update tests
This commit is contained in:
Cilibiu Bogdan
2018-10-15 22:56:44 +03:00
committed by Denys Vuika
parent c3ed743cd0
commit 84f8931eb4
4 changed files with 101 additions and 91 deletions

View File

@@ -1,53 +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 {
state,
style,
transition,
animate,
sequence,
AnimationStateMetadata,
AnimationTransitionMetadata
} from '@angular/animations';
export const formFieldAnimation: (
| AnimationStateMetadata
| AnimationTransitionMetadata)[] = [
state(
'false',
style({
opacity: 0,
height: 0,
visibility: 'hidden'
})
),
transition(
'true => false',
sequence([
animate('200ms linear', style({ opacity: 0, height: 0 })),
animate('2ms', style({ visibility: 'hidden' }))
])
),
transition(
'false => true',
sequence([
animate('200ms linear', style({ opacity: 1, height: '*' })),
animate('200ms', style({ visibility: 'visible' }))
])
)
];

View File

@@ -40,17 +40,25 @@
<h1 class="adf-share-link__label">{{ 'SHARE.EXPIRES' | translate }}</h1> <h1 class="adf-share-link__label">{{ 'SHARE.EXPIRES' | translate }}</h1>
<mat-slide-toggle <mat-slide-toggle
[disabled]="!canUpdate" [disabled]="!canUpdate"
#slideToggle #slideToggleExpirationDate
color="primary" color="primary"
data-automation-id="adf-expire-toggle" data-automation-id="adf-expire-toggle"
[checked]="form.controls['time'].value" [checked]="form.controls['time'].value"
(change)="removeExpirationDate()"> (change)="onToggleExpirationDate($event)">
</mat-slide-toggle> </mat-slide-toggle>
</div> </div>
<mat-form-field class="full-width" [@visibilityChanged]="slideToggle.checked"> <mat-form-field class="full-width">
<mat-datetimepicker-toggle [for]="datetimePicker" matSuffix></mat-datetimepicker-toggle> <mat-datetimepicker-toggle
<mat-datetimepicker #datetimePicker (closed)="blur(dateTimePickerInput)" type="datetime" openOnFocus="true" timeInterval="1"></mat-datetimepicker> #matDatetimepickerToggle="matDatetimepickerToggle"
[for]="datetimePicker"
matSuffix>
</mat-datetimepicker-toggle>
<mat-datetimepicker #datetimePicker
(closed)="onDatetimepickerClosed()"
type="datetime" openOnFocus="true"
timeInterval="1">
</mat-datetimepicker>
<input class="adf-share-link__input" <input class="adf-share-link__input"
#dateTimePickerInput #dateTimePickerInput
matInput matInput

View File

@@ -16,7 +16,7 @@
*/ */
import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { TestBed, fakeAsync, async } from '@angular/core/testing'; import { TestBed, fakeAsync, async, tick } from '@angular/core/testing';
import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material'; import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { import {
@@ -79,7 +79,7 @@ describe('ShareDialogComponent', () => {
fixture.destroy(); fixture.destroy();
}); });
it(`should toggle share action when property 'sharedId' does not exists`, () => { it(`should toggle share action when property 'sharedId' does not exists`, fakeAsync(() => {
spyOn(sharedLinksApiService, 'createSharedLinks').and.returnValue( spyOn(sharedLinksApiService, 'createSharedLinks').and.returnValue(
of({ of({
entry: { id: 'sharedId', sharedId: 'sharedId' } entry: { id: 'sharedId', sharedId: 'sharedId' }
@@ -93,6 +93,7 @@ describe('ShareDialogComponent', () => {
}; };
fixture.detectChanges(); fixture.detectChanges();
tick(500);
expect(sharedLinksApiService.createSharedLinks).toHaveBeenCalled(); expect(sharedLinksApiService.createSharedLinks).toHaveBeenCalled();
expect( expect(
@@ -100,13 +101,14 @@ describe('ShareDialogComponent', () => {
.value .value
).toBe('some-url/sharedId'); ).toBe('some-url/sharedId');
expect( expect(
fixture.nativeElement.querySelector('.mat-slide-toggle').classList fixture.nativeElement.querySelector(
'.mat-slide-toggle[data-automation-id="adf-share-toggle"'
).classList
).toContain('mat-checked'); ).toContain('mat-checked');
}); }));
it(`should not toggle share action when file has 'sharedId' property`, () => { it(`should not toggle share action when file has 'sharedId' property`, fakeAsync(() => {
spyOn(sharedLinksApiService, 'createSharedLinks'); spyOn(sharedLinksApiService, 'createSharedLinks');
node.entry.properties['qshare:sharedId'] = 'sharedId'; node.entry.properties['qshare:sharedId'] = 'sharedId';
component.data = { component.data = {
@@ -116,6 +118,7 @@ describe('ShareDialogComponent', () => {
}; };
fixture.detectChanges(); fixture.detectChanges();
tick(500);
expect(sharedLinksApiService.createSharedLinks).not.toHaveBeenCalled(); expect(sharedLinksApiService.createSharedLinks).not.toHaveBeenCalled();
expect( expect(
@@ -123,9 +126,11 @@ describe('ShareDialogComponent', () => {
.value .value
).toBe('some-url/sharedId'); ).toBe('some-url/sharedId');
expect( expect(
fixture.nativeElement.querySelector('.mat-slide-toggle').classList fixture.nativeElement.querySelector(
'.mat-slide-toggle[data-automation-id="adf-share-toggle"'
).classList
).toContain('mat-checked'); ).toContain('mat-checked');
}); }));
it(`should copy shared link and notify on button event`, async(() => { it(`should copy shared link and notify on button event`, async(() => {
node.entry.properties['qshare:sharedId'] = 'sharedId'; node.entry.properties['qshare:sharedId'] = 'sharedId';
@@ -169,7 +174,9 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
fixture.nativeElement fixture.nativeElement
.querySelector('.mat-slide-toggle label') .querySelector(
'.mat-slide-toggle[data-automation-id="adf-share-toggle"] label'
)
.dispatchEvent(new MouseEvent('click')); .dispatchEvent(new MouseEvent('click'));
fixture.detectChanges(); fixture.detectChanges();
@@ -191,7 +198,9 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
fixture.nativeElement fixture.nativeElement
.querySelector('.mat-slide-toggle label') .querySelector(
'.mat-slide-toggle[data-automation-id="adf-share-toggle"] label'
)
.dispatchEvent(new MouseEvent('click')); .dispatchEvent(new MouseEvent('click'));
fixture.detectChanges(); fixture.detectChanges();
@@ -213,7 +222,9 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
fixture.nativeElement fixture.nativeElement
.querySelector('.mat-slide-toggle label') .querySelector(
'.mat-slide-toggle[data-automation-id="adf-share-toggle"] label'
)
.dispatchEvent(new MouseEvent('click')); .dispatchEvent(new MouseEvent('click'));
fixture.detectChanges(); fixture.detectChanges();
@@ -221,9 +232,42 @@ describe('ShareDialogComponent', () => {
expect(sharedLinksApiService.deleteSharedLink).not.toHaveBeenCalled(); expect(sharedLinksApiService.deleteSharedLink).not.toHaveBeenCalled();
})); }));
it('should reset expiration date when toggle is unchecked', () => {
spyOn(nodesApiService, 'updateNode').and.returnValue(of({}));
node.entry.properties['qshare:sharedId'] = 'sharedId';
node.entry.properties['qshare:sharedId'] = '2017-04-15T18:31:37+00:00';
component.data = {
node,
permission: true,
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 unshare when node has no update permission', () => { it('should not allow unshare when node has no update permission', () => {
node.entry.properties['qshare:sharedId'] = 'sharedId'; node.entry.properties['qshare:sharedId'] = 'sharedId';
node.entry.allowableOperations = [];
component.data = { component.data = {
node, node,
@@ -234,22 +278,24 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
expect( expect(
fixture.nativeElement.querySelector('.mat-slide-toggle').classList fixture.nativeElement.querySelector(
'.mat-slide-toggle[data-automation-id="adf-share-toggle"'
).classList
).toContain('mat-disabled'); ).toContain('mat-disabled');
expect( expect(
fixture.nativeElement.querySelector('input[formcontrolname="time"]') fixture.nativeElement.querySelector('input[formcontrolname="time"]')
.disabled .disabled
).toBe(true); ).toBe(true);
expect( expect(
fixture.nativeElement.querySelector('mat-datetimepicker-toggle button') fixture.nativeElement.querySelector(
.disabled '.mat-slide-toggle[data-automation-id="adf-expire-toggle"]'
).toBe(true); ).classList
).toContain('mat-disabled');
}); });
it('should update node expiration date with selected date and time', () => { it('should update node expiration date with selected date and time', () => {
const date = moment(); const date = moment();
node.entry.properties['qshare:sharedId'] = 'sharedId'; node.entry.properties['qshare:sharedId'] = 'sharedId';
node.entry.allowableOperations = [];
spyOn(nodesApiService, 'updateNode').and.returnValue(of({})); spyOn(nodesApiService, 'updateNode').and.returnValue(of({}));
fixture.componentInstance.form.controls['time'].setValue(null); fixture.componentInstance.form.controls['time'].setValue(null);
@@ -262,7 +308,9 @@ describe('ShareDialogComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
fixture.nativeElement fixture.nativeElement
.querySelector('mat-slide-toggle[data-automation-id="adf-expire-toggle"]') .querySelector(
'mat-slide-toggle[data-automation-id="adf-expire-toggle"] label'
)
.dispatchEvent(new MouseEvent('click')); .dispatchEvent(new MouseEvent('click'));
fixture.componentInstance.form.controls['time'].setValue(date); fixture.componentInstance.form.controls['time'].setValue(date);

View File

@@ -21,7 +21,6 @@ import {
OnInit, OnInit,
ViewEncapsulation, ViewEncapsulation,
ViewChild, ViewChild,
ElementRef,
OnDestroy OnDestroy
} from '@angular/core'; } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef, MatDialog } from '@angular/material'; import { MAT_DIALOG_DATA, MatDialogRef, MatDialog } from '@angular/material';
@@ -33,8 +32,6 @@ import {
catchError, catchError,
distinctUntilChanged distinctUntilChanged
} from 'rxjs/operators'; } from 'rxjs/operators';
import { trigger } from '@angular/animations';
import { formFieldAnimation } from './animation';
import { SharedLinksApiService, NodesApiService } from '@alfresco/adf-core'; import { SharedLinksApiService, NodesApiService } from '@alfresco/adf-core';
import { SharedLinkEntry, MinimalNodeEntryEntity } from 'alfresco-js-api'; import { SharedLinkEntry, MinimalNodeEntryEntity } from 'alfresco-js-api';
import { ConfirmDialogComponent } from '@alfresco/adf-content-services'; import { ConfirmDialogComponent } from '@alfresco/adf-content-services';
@@ -45,8 +42,7 @@ import moment from 'moment-es6';
templateUrl: './content-node-share.dialog.html', templateUrl: './content-node-share.dialog.html',
styleUrls: ['./content-node-share.dialog.scss'], styleUrls: ['./content-node-share.dialog.scss'],
host: { class: 'adf-share-dialog' }, host: { class: 'adf-share-dialog' },
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None
animations: [trigger('visibilityChanged', formFieldAnimation)]
}) })
export class ShareDialogComponent implements OnInit, OnDestroy { export class ShareDialogComponent implements OnInit, OnDestroy {
private subscriptions: Subscription[] = []; private subscriptions: Subscription[] = [];
@@ -62,8 +58,14 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
time: new FormControl({ value: '', disabled: false }) time: new FormControl({ value: '', disabled: false })
}); });
@ViewChild('sharedLinkInput') @ViewChild('matDatetimepickerToggle')
sharedLinkInput: ElementRef; matDatetimepickerToggle;
@ViewChild('slideToggleExpirationDate')
slideToggleExpirationDate;
@ViewChild('dateTimePickerInput')
dateTimePickerInput;
constructor( constructor(
private sharedLinksApiService: SharedLinksApiService, private sharedLinksApiService: SharedLinksApiService,
@@ -116,10 +118,6 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
this.subscriptions.forEach(subscription => subscription.unsubscribe); this.subscriptions.forEach(subscription => subscription.unsubscribe);
} }
removeShare() {
this.deleteSharedLink(this.sharedId);
}
onSlideShareChange() { onSlideShareChange() {
this.openConfirmationDialog(); this.openConfirmationDialog();
} }
@@ -128,12 +126,21 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
return this.data.permission; return this.data.permission;
} }
removeExpirationDate() { onToggleExpirationDate(slideToggle) {
this.form.controls.time.setValue(null); if (slideToggle.checked) {
this.matDatetimepickerToggle.datetimepicker.open();
} else {
this.matDatetimepickerToggle.datetimepicker.close();
this.form.controls.time.setValue(null);
}
} }
blur(input: HTMLInputElement) { onDatetimepickerClosed() {
input.blur(); this.dateTimePickerInput.nativeElement.blur();
if (!this.form.controls.time.value) {
this.slideToggleExpirationDate.checked = false;
}
} }
private openConfirmationDialog() { private openConfirmationDialog() {