diff --git a/cspell.json b/cspell.json index 3442ccab09..0d062bca4a 100644 --- a/cspell.json +++ b/cspell.json @@ -128,7 +128,8 @@ "ECMBPM", "processwithvariables", "dropdownrestprocess", - "devops" + "devops", + "mouseenter" ], "dictionaries": [ "html", diff --git a/docs/README.md b/docs/README.md index 3b02999305..0a5e30f6bd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -292,6 +292,7 @@ for more information about installing and using the source code. | [Folder Edit directive](content-services/directives/folder-edit.directive.md) | Allows folders to be edited. | [Source](../lib/content-services/folder-directive/folder-edit.directive.ts) | | [Inherit Permission directive](content-services/directives/inherited-button.directive.md) | Update the current node by adding/removing the inherited permissions. | [Source](../lib/content-services/permission-manager/components/inherited-button.directive.ts) | | [Node Lock directive](content-services/directives/node-lock.directive.md) | Locks or unlocks a node. | [Source](../lib/content-services/directives/node-lock.directive.ts) | +| [Toggle Icon directive](content-services/directives/toggle-icon.directive.md) | Toggle icon on mouse and keyboard event. | [Source](../lib/content-services/upload/directives/toggle-icon.directive.ts) | ### Dialogs diff --git a/docs/content-services/directives/toggle-icon.directive.md b/docs/content-services/directives/toggle-icon.directive.md new file mode 100644 index 0000000000..847d8f5737 --- /dev/null +++ b/docs/content-services/directives/toggle-icon.directive.md @@ -0,0 +1,34 @@ +--- +Title: Toggle Icon directive +Added: v2.0.0 +Status: Active +Last reviewed: 2019-04-09 +--- + +# [Toggle Icon directive](../../../lib/content-services/upload/directives/toggle-icon.directive.ts 'Defined in toggle-icon.directive.ts') + +Toggle icon on mouse or keyboard event for a selectable element. + +## Example Usage + +```html + + +``` + +## Class members + +### Properties + +| Name | Type | Default value | Description | +| --------- | --------- | ------------- | ----------------------------------------------- | +| isToggled | `boolean` | false | Is element active by mouseenter or focus event? | +| isFocused | `boolean` | false | Is element focused by keyboard navigation? | diff --git a/docs/versionIndex.md b/docs/versionIndex.md index 01fc9a418c..e8ff615fc1 100644 --- a/docs/versionIndex.md +++ b/docs/versionIndex.md @@ -36,6 +36,7 @@ backend services have been tested with each released version of ADF. - [Identity group service](core/services/identity-group.service.md) - [Local preference cloud service](process-services-cloud/services/local-preference-cloud.service.md) - [User preference cloud service](process-services-cloud/services/user-preference-cloud.service.md) +- [Toggle icon directive](content-services/directives/toggle-icon.directive.md) diff --git a/e2e/content-services/upload/cancel-upload.e2e.ts b/e2e/content-services/upload/cancel-upload.e2e.ts index ad0494e7e3..e2b1723579 100644 --- a/e2e/content-services/upload/cancel-upload.e2e.ts +++ b/e2e/content-services/upload/cancel-upload.e2e.ts @@ -79,7 +79,7 @@ describe('Upload component', async () => { }); it('[C272792] Should be possible to cancel upload of a big file using row cancel icon', async () => { - await browser.executeScript(' setTimeout(() => {document.querySelector(\'mat-icon[class*="adf-file-uploading-row__action"]\').click();}, 3000)'); + await browser.executeScript('setTimeout(() => {document.querySelector("div[data-automation-id=\'cancel-upload-progress\']").click();}, 3000)'); await contentServicesPage.uploadFile(largeFile.location); diff --git a/e2e/content-services/version/version-actions.e2e.ts b/e2e/content-services/version/version-actions.e2e.ts index 2a77989bb9..e2fe26eac6 100644 --- a/e2e/content-services/version/version-actions.e2e.ts +++ b/e2e/content-services/version/version-actions.e2e.ts @@ -157,7 +157,7 @@ describe('Version component actions', () => { it('[C307033] Should be possible to cancel the upload of a new version', async () => { await browser.refresh(); await contentServicesPage.versionManagerContent(txtFileModel.name); - await browser.executeScript(' setTimeout(() => {document.querySelector(\'mat-icon[class*="adf-file-uploading-row__action"]\').click();}, 1000)'); + await browser.executeScript(' setTimeout(() => {document.querySelector("div[data-automation-id=\'cancel-upload-progress\']").click();}, 1000)'); await BrowserActions.click(versionManagePage.showNewVersionButton); diff --git a/lib/content-services/i18n/en.json b/lib/content-services/i18n/en.json index 425721b080..b9986fdf9e 100644 --- a/lib/content-services/i18n/en.json +++ b/lib/content-services/i18n/en.json @@ -117,7 +117,8 @@ "REMOVE_FILE": "Remove uploaded file" }, "STATUS": { - "FILE_CANCELED_STATUS": "Canceled" + "FILE_CANCELED_STATUS": "Canceled", + "FILE_DONE_STATUS": "Uploaded" }, "CONFIRMATION": { "BUTTON": { @@ -130,12 +131,16 @@ } }, "ARIA-LABEL": { - "VERSION": "File version", + "VERSION": "File version {{ version }}", "DIALOG": "Upload list", "DIALOG_MAXIMIZE": "Maximize upload dialog", "DIALOG_MINIMIZE": "Minimize upload dialog", "DIALOG_CLOSE": "Close upload dialog", "CANCEL_ALL": "Cancel all uploading files", + "REMOVE_FILE": "Remove uploaded file {{ file }}", + "CANCEL_FILE": "Cancel scheduled file {{ file }}", + "CANCEL_FILE_UPLOAD": "Cancel file upload {{ file }}", + "UPLOAD_FILE_ERROR": "Upload error {{ error }}", "CONFIRMATION": { "CANCEL": "Confirm cancel", "CONTINUE": "Continue uploading" diff --git a/lib/content-services/upload/components/file-uploading-dialog.component.html b/lib/content-services/upload/components/file-uploading-dialog.component.html index 002c2a4ff1..cd0b6d9f8d 100644 --- a/lib/content-services/upload/components/file-uploading-dialog.component.html +++ b/lib/content-services/upload/components/file-uploading-dialog.component.html @@ -23,6 +23,7 @@ {{ 'FILE_UPLOAD.MESSAGES.UPLOAD_PROGRESS' @@ -34,6 +35,7 @@ {{ 'FILE_UPLOAD.MESSAGES.UPLOAD_CANCELED' | translate }} @@ -41,6 +43,7 @@
{{ (totalErrors > 1 diff --git a/lib/content-services/upload/components/file-uploading-list-row.component.html b/lib/content-services/upload/components/file-uploading-list-row.component.html index 729b18c1ee..f07ebe25d2 100644 --- a/lib/content-services/upload/components/file-uploading-list-row.component.html +++ b/lib/content-services/upload/components/file-uploading-list-row.component.html @@ -6,54 +6,69 @@ {{ file.name }} - - {{ - versionNumber + + {{ + versionNumber }}
- + + {{ file.progress.loaded | adfFileSize }} / {{ file.progress.total | adfFileSize }} - clear
-
- check_circle - remove_circle -
+
+ class="adf-file-uploading-row__file-version" + [attr.aria-label]="'ADF_FILE_UPLOAD.STATUS.FILE_DONE_STATUS' | translate" + role="status" + > @@ -61,34 +76,44 @@
-
+ class="adf-file-uploading-row__group" + title="{{ 'ADF_FILE_UPLOAD.BUTTON.CANCEL_FILE' | translate }}" + [attr.aria-label]="'ADF_FILE_UPLOAD.ARIA-LABEL.CANCEL_FILE' | translate: { file: file.name }"> schedule remove_circle -
+
report_problem
{{ 'ADF_FILE_UPLOAD.STATUS.FILE_CANCELED_STATUS' | translate }} diff --git a/lib/content-services/upload/components/file-uploading-list-row.component.scss b/lib/content-services/upload/components/file-uploading-list-row.component.scss index a3eb07584b..ff8ddd8c12 100644 --- a/lib/content-services/upload/components/file-uploading-list-row.component.scss +++ b/lib/content-services/upload/components/file-uploading-list-row.component.scss @@ -15,7 +15,7 @@ .adf-file-uploading-row { display: flex; align-items: center; - padding: 0.5em 1em; + padding: 0.3em 1em; cursor: default; &:hover { @@ -34,28 +34,15 @@ min-width: 100px; display: flex; justify-content: flex-end; + line-height: 40px; } &__group--toggle { cursor: pointer; - - .adf-file-uploading-row__status { - display: flex; - } - - .adf-file-uploading-row__action { - display: none; - } - - &:hover { - .adf-file-uploading-row__status { - display: none; - } - - .adf-file-uploading-row__action { - display: flex; - } - } + display:flex; + align-items: center; + height: 40px; + line-height: 40px; } &__status--done { diff --git a/lib/content-services/upload/directives/toggle-icon.directive.spec.ts b/lib/content-services/upload/directives/toggle-icon.directive.spec.ts new file mode 100644 index 0000000000..bb6b8ccd71 --- /dev/null +++ b/lib/content-services/upload/directives/toggle-icon.directive.spec.ts @@ -0,0 +1,91 @@ +/*! + * @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 { Component, ViewChild } from '@angular/core'; +import { ToggleIconDirective } from './toggle-icon.directive'; +import { setupTestBed } from '@alfresco/adf-core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +@Component({ + selector: 'adf-test-component', + template: ` + + ` +}) +class TestComponent { + @ViewChild(ToggleIconDirective) directive: ToggleIconDirective; +} + +describe('ToggleIconDirective', () => { + let fixture: ComponentFixture; + let component: TestComponent; + + setupTestBed({ + declarations: [ + TestComponent, + ToggleIconDirective + ] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should set toggle to true on mouseenter', () => { + const button: HTMLElement = fixture.nativeElement.querySelector('#testButton'); + button.dispatchEvent(new MouseEvent('mouseenter')); + + expect(component.directive.isToggled).toBe(true); + }); + + it('should set toggle to false on mouseleave if element is not focused', () => { + const button: HTMLElement = fixture.nativeElement.querySelector('#testButton'); + button.dispatchEvent(new MouseEvent('mouseleave')); + + expect(component.directive.isToggled).toBe(false); + }); + + it('should set toggle and focus to false on mouseleave when element is focused', () => { + const button: HTMLElement = fixture.nativeElement.querySelector('#testButton'); + button.dispatchEvent(new Event('focus')); + expect(component.directive.isToggled).toBe(true); + + button.dispatchEvent(new MouseEvent('mouseleave')); + + expect(component.directive.isToggled).toBe(false); + expect(component.directive.isFocused).toBe(false); + }); + + it('should set toggle and focus to true when element is focused', () => { + const button: HTMLElement = fixture.nativeElement.querySelector('#testButton'); + button.dispatchEvent(new Event('focus')); + + expect(component.directive.isToggled).toBe(true); + expect(component.directive.isFocused).toBe(true); + }); + + it('should set toggle and focus to true when element blur event', () => { + const button: HTMLElement = fixture.nativeElement.querySelector('#testButton'); + button.dispatchEvent(new Event('focus')); + button.dispatchEvent(new Event('blur')); + + expect(component.directive.isToggled).toBe(false); + expect(component.directive.isFocused).toBe(false); + }); +}); diff --git a/lib/content-services/upload/directives/toggle-icon.directive.ts b/lib/content-services/upload/directives/toggle-icon.directive.ts new file mode 100644 index 0000000000..c9a32891fc --- /dev/null +++ b/lib/content-services/upload/directives/toggle-icon.directive.ts @@ -0,0 +1,62 @@ +/*! + * @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 { Directive, HostListener } from '@angular/core'; + +@Directive({ + selector: '[adf-toggle-icon]', + exportAs: 'toggleIcon' +}) +export class ToggleIconDirective { + private isFocus: boolean = false; + private toggle: boolean = false; + + @HostListener('mouseenter') onMouseEnter() { + if (!this.isFocus) { + this.toggle = true; + } + } + + @HostListener('mouseleave') onMouseLeave() { + if (!this.isFocus) { + this.toggle = false; + } + + if (this.isFocus && this.toggle) { + this.isFocus = false; + this.toggle = false; + } + } + + @HostListener('focus') onFocus() { + this.isFocus = true; + this.toggle = true; + } + + @HostListener('blur') onBlur() { + this.isFocus = false; + this.toggle = false; + } + + get isToggled(): boolean { + return this.toggle; + } + + get isFocused(): boolean { + return this.isFocus; + } +} diff --git a/lib/content-services/upload/public-api.ts b/lib/content-services/upload/public-api.ts index b90cfce57a..e7010786f9 100644 --- a/lib/content-services/upload/public-api.ts +++ b/lib/content-services/upload/public-api.ts @@ -24,6 +24,7 @@ export * from './components/file-uploading-list-row.component'; export * from './components/upload-files.event'; export * from './directives/file-draggable.directive'; +export * from './directives/toggle-icon.directive'; export * from './pipes/file-upload-error.pipe'; diff --git a/lib/content-services/upload/upload.module.ts b/lib/content-services/upload/upload.module.ts index bed4e4ca30..75e446a5e0 100644 --- a/lib/content-services/upload/upload.module.ts +++ b/lib/content-services/upload/upload.module.ts @@ -27,6 +27,7 @@ import { UploadDragAreaComponent } from './components/upload-drag-area.component import { FileUploadErrorPipe } from './pipes/file-upload-error.pipe'; import { CoreModule } from '@alfresco/adf-core'; import { FileDraggableDirective } from './directives/file-draggable.directive'; +import { ToggleIconDirective } from './directives/toggle-icon.directive'; @NgModule({ imports: [ @@ -42,7 +43,8 @@ import { FileDraggableDirective } from './directives/file-draggable.directive'; FileUploadingDialogComponent, FileUploadingListComponent, FileUploadingListRowComponent, - FileUploadErrorPipe + FileUploadErrorPipe, + ToggleIconDirective ], exports: [ FileDraggableDirective, @@ -52,7 +54,8 @@ import { FileDraggableDirective } from './directives/file-draggable.directive'; FileUploadingDialogComponent, FileUploadingListComponent, FileUploadingListRowComponent, - FileUploadErrorPipe + FileUploadErrorPipe, + ToggleIconDirective ] }) export class UploadModule {}