diff --git a/demo-shell/resources/i18n/en.json b/demo-shell/resources/i18n/en.json index 17e745dcd7..5eb8d9adf4 100644 --- a/demo-shell/resources/i18n/en.json +++ b/demo-shell/resources/i18n/en.json @@ -179,7 +179,9 @@ "REPLACE_COLUMNS": "Replace columns", "LOAD_NODE": "Load Node", "MULTISELECT": "Multiselect", - "MULTISELECT_DESCRIPTION": "Use Cmd (Mac) or Ctrl (Windows) to toggle selection of multiple items" + "MULTISELECT_DESCRIPTION": "Use Cmd (Mac) or Ctrl (Windows) to toggle selection of multiple items", + "CLICK_TO_COPY": "Click to copy", + "SUCCESS_COPY": "Text copied to clipboard" }, "ANALYTICS_REPORT": { "NO_REPORT_MESSAGE": "No report selected. Choose a report from the list" diff --git a/demo-shell/src/app/components/datatable/datatable.component.html b/demo-shell/src/app/components/datatable/datatable.component.html index 32fca95c03..4b95fd54ba 100644 --- a/demo-shell/src/app/components/datatable/datatable.component.html +++ b/demo-shell/src/app/components/datatable/datatable.component.html @@ -11,8 +11,8 @@
- ``` @@ -117,7 +117,7 @@ export class DataTableDemo { ``` ```html - ``` @@ -178,16 +178,16 @@ export class DataTableDemo { // columns this.schema = [ - { - type: 'text', - key: 'id', - title: 'Id', - sortable: true + { + type: 'text', + key: 'id', + title: 'Id', + sortable: true }, { - type: 'text', - key: 'name', - title: 'Name', + type: 'text', + key: 'name', + title: 'Name', sortable: true } ]; @@ -222,16 +222,16 @@ export class DataTableDemo { // columns this.schema = [ - { - type: 'text', - key: 'id', - title: 'Id', - sortable: true + { + type: 'text', + key: 'id', + title: 'Id', + sortable: true }, { - type: 'text', - key: 'name', - title: 'Name', + type: 'text', + key: 'name', + title: 'Name', sortable: true } ]; @@ -266,7 +266,7 @@ You can also supply a `` or an ``` ```html - + "'My custom Header'" "'My custom body'" @@ -296,7 +296,7 @@ while the data for the table is loading: ```js isLoading(): boolean { - //your custom logic to identify if you are in a loading state + //your custom logic to identify if you are in a loading state } ``` @@ -403,7 +403,7 @@ Set the `display` property to "gallery" to enable Card View mode: #### row-keyup DOM event -Emitted on the 'keyup' event for the focused row. +Emitted on the 'keyup' event for the focused row. This is an instance of `CustomEvent` with the `details` property containing the following object: @@ -420,7 +420,7 @@ Emitted when the user clicks a row. Event properties: ```ts -sender: any // DataTable instance +sender: any // DataTable instance value: DataRow, // row clicked event: Event // original HTML DOM event ``` @@ -442,7 +442,7 @@ Emitted when the user double-clicks a row. Event properties: ```ts -sender: any // DataTable instance +sender: any // DataTable instance value: DataRow, // row clicked event: Event // original HTML DOM event ``` @@ -515,7 +515,7 @@ This event is cancellable. You can use `event.preventDefault()` to prevent the d Emitted when the user executes a row action. -This usually accompanies a `showRowActionsMenu` event. +This usually accompanies a `showRowActionsMenu` event. The DataTable itself does not execute actions but provides support for external integration. If actions are provided using the `showRowActionsMenu` event then `executeRowAction` will be automatically executed when the user clicks a @@ -575,15 +575,15 @@ By default, the content of the cells is wrapped so you can see all the data insi ![](../../docassets/images/datatable-wrapped-text.png) -However, you can also truncate the text within these cells using the `adf-ellipsis-cell` class in the desired column: +However, you can also truncate the text within these cells using the `adf-ellipsis-cell` class in the desired column: ```js -{ - type: 'text', - key: 'createdOn', - title: 'Created On', - sortable: true, - cssClass: 'adf-ellipsis-cell' +{ + type: 'text', + key: 'createdOn', + title: 'Created On', + sortable: true, + cssClass: 'adf-ellipsis-cell' } ``` @@ -603,14 +603,14 @@ widths according to your needs: #### No-growing cells -As mentioned before, in the beginning, all cells have the same width. You can prevent cells from growing by using the `adf-no-grow-cell` class. +As mentioned before, in the beginning, all cells have the same width. You can prevent cells from growing by using the `adf-no-grow-cell` class. ```js -{ - type: 'date', - key: 'created', - title: 'Created On', - cssClass: 'adf-ellipsis-cell adf-no-grow-cell' +{ + type: 'date', + key: 'created', + title: 'Created On', + cssClass: 'adf-ellipsis-cell adf-no-grow-cell' } ``` @@ -623,11 +623,11 @@ Notice that this class is compatible with `adf-ellipsis-cell` and for that reaso You can combine the CSS classes described above to customize the table as needed: ```js -{ - type: 'text', - key: 'name', - title: 'Name', - cssClass: 'adf-ellipsis-cell adf-expand-cell-3' +{ + type: 'text', + key: 'name', + title: 'Name', + cssClass: 'adf-ellipsis-cell adf-expand-cell-3' } ``` @@ -639,7 +639,7 @@ always visible. You can do this using the following steps. First, set the `stickyHeader` property of your datatable to `true`: ```html - @@ -658,6 +658,27 @@ the total height of all rows exceeds the fixed height of the parent element.
``` +### CopyClipboardDirective example + +See the [Copy Content Directive ](../directives/clipboard.directive.md) page for full details of the directive + +Json config file: +```json +[ + {"type": "text", "key": "id", "title": "Id", "copyContent": "true"}, + {"type": "text", "key": "name", "title": "name"}, +] +``` +HTML data-columns +```html + + + + + + +``` + Once set up, the sticky header behaves as shown in the image below: ![](../../docassets/images/datatable-sticky-header.png) diff --git a/docs/core/directives/clipboard.directive.md b/docs/core/directives/clipboard.directive.md new file mode 100644 index 0000000000..f96560d451 --- /dev/null +++ b/docs/core/directives/clipboard.directive.md @@ -0,0 +1,36 @@ +--- +Title: Copy Clipboard directive +Added: v3.2.0 +Status: Active +Last reviewed: 2019-04-01 +--- + +# [Clipboard directive](../../../lib/core/clipboard/clipboard.directive.ts "Defined in clipboard.directive.ts") + +Copy text to clipboard + +## Basic Usage + +```html + + text to copy + + + +``` + + +## Class members + +### Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| target | `HTMLElement ref` | false | HTMLElement reference | +| clipboard-notification | `string` | | Translation key message for toast notification | + +## Details + +When the user hover the directive element a tooltip will will show up to inform that, when you click on the current element, the content or the reference content will be copied into the clipboard. diff --git a/lib/content-services/content-node-share/content-node-share.dialog.html b/lib/content-services/content-node-share/content-node-share.dialog.html index 607b2a2e37..cc5e893393 100644 --- a/lib/content-services/content-node-share/content-node-share.dialog.html +++ b/lib/content-services/content-node-share/content-node-share.dialog.html @@ -31,7 +31,7 @@ readonly="readonly"> + [adf-clipboard] target="sharedLinkInput"> link diff --git a/lib/content-services/document-list/components/document-list.component.scss b/lib/content-services/document-list/components/document-list.component.scss index 99a4178137..162c452e22 100644 --- a/lib/content-services/document-list/components/document-list.component.scss +++ b/lib/content-services/document-list/components/document-list.component.scss @@ -1,6 +1,8 @@ @mixin adf-document-list-theme($theme) { $foreground: map-get($theme, foreground); + $background: map-get($theme, background); $accent: map-get($theme, accent); + $primary: map-get($theme, primary); .mat-icon.adf-datatable-selected { height: 100%; @@ -186,4 +188,14 @@ } } } + + .adf-datatable-copy-tooltip { + position: absolute; + background: mat-color($primary); + color: mat-color($primary, default-contrast) !important; + padding: 5px 10px; + border-radius: 5px; + bottom: 88%; + left:0; + } } diff --git a/lib/core/clipboard/clipboard.directive.spec.ts b/lib/core/clipboard/clipboard.directive.spec.ts index c35a25ee4a..e9a0e11906 100644 --- a/lib/core/clipboard/clipboard.directive.spec.ts +++ b/lib/core/clipboard/clipboard.directive.spec.ts @@ -15,28 +15,30 @@ * limitations under the License. */ -import { Component } from '@angular/core'; -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Component, ViewChild } from '@angular/core'; +import { ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing'; import { setupTestBed } from '../testing/setupTestBed'; import { CoreModule } from '../core.module'; import { ClipboardService } from './clipboard.service'; +import { ClipboardDirective } from './clipboard.directive'; +import { RouterTestingModule } from '@angular/router/testing'; @Component({ selector: 'adf-test-component', template: ` ` }) -class TestComponent {} +class TestTargetClipboardComponent {} describe('ClipboardDirective', () => { - let fixture: ComponentFixture; + let fixture: ComponentFixture; let clipboardService: ClipboardService; setupTestBed({ @@ -44,7 +46,7 @@ describe('ClipboardDirective', () => { CoreModule.forRoot() ], declarations: [ - TestComponent + TestTargetClipboardComponent ], providers: [ ClipboardService @@ -52,7 +54,7 @@ describe('ClipboardDirective', () => { }); beforeEach(() => { - fixture = TestBed.createComponent(TestComponent); + fixture = TestBed.createComponent(TestTargetClipboardComponent); clipboardService = TestBed.get(ClipboardService); fixture.detectChanges(); }); @@ -65,3 +67,73 @@ describe('ClipboardDirective', () => { expect(clipboardService.copyToClipboard).toHaveBeenCalled(); }); }); + +describe('CopyClipboardDirective', () => { + + @Component({ + selector: 'adf-copy-conent-test-component', + template: `{{ mockText }}` + }) + class TestCopyClipboardComponent { + + mockText = 'text to copy'; + + @ViewChild(ClipboardDirective) + clipboardDirective: ClipboardDirective; + } + + let fixture: ComponentFixture; + let element: HTMLElement; + + setupTestBed({ + imports: [ + CoreModule.forRoot(), + RouterTestingModule + ], + declarations: [ + TestCopyClipboardComponent + ] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TestCopyClipboardComponent); + element = fixture.debugElement.nativeElement; + fixture.detectChanges(); + }); + + it('should show tooltip when hover element', (() => { + const spanHTMLElement: HTMLInputElement = element.querySelector('span'); + spanHTMLElement.dispatchEvent(new Event('mouseenter')); + fixture.detectChanges(); + expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).not.toBeNull(); + })); + + it('should not show tooltip when element it is not hovered', (() => { + const spanHTMLElement: HTMLInputElement = element.querySelector('span'); + spanHTMLElement.dispatchEvent(new Event('mouseenter')); + expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).not.toBeNull(); + + spanHTMLElement.dispatchEvent(new Event('mouseleave')); + expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).toBeNull(); + })); + + it('should copy the content of element when click it', fakeAsync(() => { + const spanHTMLElement: HTMLInputElement = element.querySelector('span'); + fixture.detectChanges(); + spyOn(document, 'execCommand'); + spanHTMLElement.dispatchEvent(new Event('click')); + tick(); + fixture.detectChanges(); + expect(document.execCommand).toHaveBeenCalledWith('copy'); + })); + + it('should not copy the content of element when click it', fakeAsync(() => { + const spanHTMLElement: HTMLInputElement = element.querySelector('span'); + fixture.detectChanges(); + spyOn(document, 'execCommand'); + spanHTMLElement.dispatchEvent(new Event('mouseleave')); + tick(); + fixture.detectChanges(); + expect(document.execCommand).not.toHaveBeenCalled(); + })); +}); diff --git a/lib/core/clipboard/clipboard.directive.ts b/lib/core/clipboard/clipboard.directive.ts index fe08de6d6d..0ede53291b 100644 --- a/lib/core/clipboard/clipboard.directive.ts +++ b/lib/core/clipboard/clipboard.directive.ts @@ -15,33 +15,78 @@ * limitations under the License. */ -import { Directive, Input, HostListener } from '@angular/core'; +import { Directive, Input, HostListener, Component, ViewContainerRef, ComponentFactoryResolver, AfterContentInit } from '@angular/core'; import { ClipboardService } from './clipboard.service'; @Directive({ selector: '[adf-clipboard]', exportAs: 'adfClipboard' }) -export class ClipboardDirective { +export class ClipboardDirective implements AfterContentInit { // tslint:disable-next-line:no-input-rename - @Input('adf-clipboard') target: HTMLInputElement | HTMLTextAreaElement; + @Input('adf-clipboard') + placeholder: string; + + @Input() + target: HTMLInputElement | HTMLTextAreaElement; // tslint:disable-next-line:no-input-rename @Input('clipboard-notification') message: string; + private value: string; + + constructor(private clipboardService: ClipboardService, + public viewContainerRef: ViewContainerRef, + private resolver: ComponentFactoryResolver) {} + @HostListener('click', ['$event']) handleClickEvent(event: MouseEvent) { event.preventDefault(); + event.stopPropagation(); this.copyToClipboard(); } - constructor(private clipboardService: ClipboardService) {} + @HostListener('mouseenter') + showTooltip() { + const componentFactory = this.resolver.resolveComponentFactory(ClipboardComponent); + const componentRef = this.viewContainerRef.createComponent(componentFactory).instance; + componentRef.copyText = this.value; + componentRef.placeholder = this.placeholder; + } + + @HostListener('mouseleave') + closeTooltip() { + this.viewContainerRef.remove(); + } private copyToClipboard() { const isValidTarget = this.clipboardService.isTargetValid(this.target); if (isValidTarget) { this.clipboardService.copyToClipboard(this.target, this.message); + } else { + this.copyContentToClipboard(this.viewContainerRef.element.nativeElement.innerHTML); } } + + private copyContentToClipboard(content) { + this.clipboardService.copyContentToClipboard(content, this.message); + } + + ngAfterContentInit() { + setTimeout( () => { + this.value = this.viewContainerRef.element.nativeElement.innerHTML; + }); + } +} + +@Component({ + selector: 'adf-datatable-highlight-tooltip', + template: ` + {{ placeholder | translate }} {{ copyText }} + ` +}) +export class ClipboardComponent { + copyText: string; + placeholder: string; } diff --git a/lib/core/clipboard/clipboard.module.ts b/lib/core/clipboard/clipboard.module.ts index 12104922f5..9ebc6fa490 100644 --- a/lib/core/clipboard/clipboard.module.ts +++ b/lib/core/clipboard/clipboard.module.ts @@ -17,22 +17,26 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; -import { ClipboardDirective } from './clipboard.directive'; +import { ClipboardDirective, ClipboardComponent } from './clipboard.directive'; import { ClipboardService } from './clipboard.service'; +import { TranslateModule } from '@ngx-translate/core'; @NgModule({ imports: [ - CommonModule + CommonModule, + TranslateModule.forChild() ], providers: [ ClipboardService ], declarations: [ - ClipboardDirective + ClipboardDirective, + ClipboardComponent ], exports: [ ClipboardDirective - ] + ], + entryComponents: [ClipboardComponent] }) export class ClipboardModule {} diff --git a/lib/core/clipboard/clipboard.service.ts b/lib/core/clipboard/clipboard.service.ts index 046dc19de2..53064a3beb 100644 --- a/lib/core/clipboard/clipboard.service.ts +++ b/lib/core/clipboard/clipboard.service.ts @@ -32,8 +32,6 @@ export class ClipboardService { if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) { return !target.hasAttribute('disabled'); } - - this.logService.error(`${target} should be input or textarea`); return false; } @@ -50,6 +48,20 @@ export class ClipboardService { } } + copyContentToClipboard(content: string, message: string) { + try { + document.addEventListener('copy', (e: ClipboardEvent) => { + e.clipboardData.setData('text/plain', (content)); + e.preventDefault(); + document.removeEventListener('copy', null); + }); + document.execCommand('copy'); + this.notify(message); + } catch (error) { + this.logService.error(error); + } + } + private notify(message) { if (message) { this.notificationService.openSnackMessage(message); diff --git a/lib/core/data-column/data-column.component.ts b/lib/core/data-column/data-column.component.ts index e1e2950528..345dace375 100644 --- a/lib/core/data-column/data-column.component.ts +++ b/lib/core/data-column/data-column.component.ts @@ -66,6 +66,10 @@ export class DataColumnComponent implements OnInit { @Input('class') cssClass: string; + /** flag to show the copy content directive */ + @Input() + copyContent: boolean; + ngOnInit() { if (!this.srTitle && this.key === '$thumbnail') { this.srTitle = 'Thumbnail'; diff --git a/lib/core/datatable/components/datatable/datatable-cell.component.ts b/lib/core/datatable/components/datatable/datatable-cell.component.ts index 3308688ad6..01b6f5cb45 100644 --- a/lib/core/datatable/components/datatable/datatable-cell.component.ts +++ b/lib/core/datatable/components/datatable/datatable-cell.component.ts @@ -35,13 +35,21 @@ import { Node } from '@alfresco/js-api'; changeDetection: ChangeDetectionStrategy.OnPush, template: ` + {{ value$ | async }} + + {{ value$ | async }} - + >{{ value$ | async }} + `, encapsulation: ViewEncapsulation.None, host: { class: 'adf-datatable-cell' } @@ -58,6 +66,9 @@ export class DataTableCellComponent implements OnInit, OnDestroy { value$ = new BehaviorSubject(''); + @Input() + copyContent: boolean; + @Input() tooltip: string; @@ -67,7 +78,6 @@ export class DataTableCellComponent implements OnInit, OnDestroy { ngOnInit() { this.updateValue(); - this.sub = this.alfrescoApiService.nodeUpdated.subscribe((node: Node) => { if (this.row) { const { entry } = this.row['node']; diff --git a/lib/core/datatable/components/datatable/datatable.component.html b/lib/core/datatable/components/datatable/datatable.component.html index 8feab73333..7a660d51fe 100644 --- a/lib/core/datatable/components/datatable/datatable.component.html +++ b/lib/core/datatable/components/datatable/datatable.component.html @@ -148,6 +148,7 @@
; formatTooltip?: Function; + copyContent?: boolean; } diff --git a/lib/core/datatable/data/object-datacolumn.model.ts b/lib/core/datatable/data/object-datacolumn.model.ts index 0227b4abc5..1ac706e1d6 100644 --- a/lib/core/datatable/data/object-datacolumn.model.ts +++ b/lib/core/datatable/data/object-datacolumn.model.ts @@ -29,6 +29,7 @@ export class ObjectDataColumn implements DataColumn { srTitle: string; cssClass: string; template?: TemplateRef; + copyContent?: boolean; constructor(input: any) { this.key = input.key; @@ -39,5 +40,6 @@ export class ObjectDataColumn implements DataColumn { this.srTitle = input.srTitle; this.cssClass = input.cssClass; this.template = input.template; + this.copyContent = input.copyContent; } } diff --git a/lib/core/datatable/datatable.module.ts b/lib/core/datatable/datatable.module.ts index 06caf66a76..3b1c21abd2 100644 --- a/lib/core/datatable/datatable.module.ts +++ b/lib/core/datatable/datatable.module.ts @@ -41,6 +41,7 @@ import { CustomEmptyContentTemplateDirective } from './directives/custom-empty-c import { CustomLoadingContentTemplateDirective } from './directives/custom-loading-template.directive'; import { CustomNoPermissionTemplateDirective } from './directives/custom-no-permission-template.directive'; import { JsonCellComponent } from './components/datatable/json-cell.component'; +import { ClipboardModule } from '../clipboard/clipboard.module'; @NgModule({ imports: [ @@ -50,7 +51,8 @@ import { JsonCellComponent } from './components/datatable/json-cell.component'; TranslateModule.forChild(), ContextMenuModule, PipeModule, - DirectiveModule + DirectiveModule, + ClipboardModule ], declarations: [ DataTableComponent, @@ -88,5 +90,6 @@ import { JsonCellComponent } from './components/datatable/json-cell.component'; CustomLoadingContentTemplateDirective, CustomNoPermissionTemplateDirective ] + }) export class DataTableModule {} diff --git a/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.spec.ts b/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.spec.ts index f0710d764c..73198619c4 100644 --- a/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.spec.ts +++ b/lib/process-services-cloud/src/lib/task/directives/claim-task.directive.spec.ts @@ -36,10 +36,6 @@ describe('ClaimTaskDirective', () => { @ViewChild(ClaimTaskDirective) claimTaskDirective: ClaimTaskDirective; - - onCompleteTask(event: any) { - return event; - } } let fixture: ComponentFixture; diff --git a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts index b9b7b42e30..2fc3d318b6 100644 --- a/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-list/components/task-list-cloud.component.spec.ts @@ -55,6 +55,20 @@ class CustomTaskListComponent { }) class EmptyTemplateComponent { } +@Component({ + template: ` + + + + + + ` +}) +class CustomCopyContentTaskListComponent { + @ViewChild(TaskListCloudComponent) + taskList: TaskListCloudComponent; +} + describe('TaskListCloudComponent', () => { let component: TaskListCloudComponent; let fixture: ComponentFixture; @@ -228,21 +242,29 @@ describe('TaskListCloudComponent', () => { describe('Injecting custom colums for tasklist - CustomTaskListComponent', () => { let fixtureCustom: ComponentFixture; let componentCustom: CustomTaskListComponent; + let customCopyComponent: CustomCopyContentTaskListComponent; + let element: any; + let copyFixture: ComponentFixture; setupTestBed({ imports: [CoreModule.forRoot()], - declarations: [TaskListCloudComponent, CustomTaskListComponent], + declarations: [TaskListCloudComponent, CustomTaskListComponent, CustomCopyContentTaskListComponent], providers: [TaskListCloudService] }); beforeEach(() => { + spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTask)); fixtureCustom = TestBed.createComponent(CustomTaskListComponent); + copyFixture = TestBed.createComponent(CustomCopyContentTaskListComponent); fixtureCustom.detectChanges(); componentCustom = fixtureCustom.componentInstance; + customCopyComponent = copyFixture.componentInstance; + element = copyFixture.debugElement.nativeElement; }); afterEach(() => { fixtureCustom.destroy(); + copyFixture.destroy(); }); it('should create instance of CustomTaskListComponent', () => { @@ -257,6 +279,37 @@ describe('TaskListCloudComponent', () => { expect(componentCustom.taskList.columns.length).toEqual(3); }); + it('it should show copy tooltip when key is present in data-colunn', async(() => { + copyFixture.detectChanges(); + const appName = new SimpleChange(null, 'FAKE-APP-NAME', true); + copyFixture.whenStable().then(() => { + copyFixture.detectChanges(); + const spanHTMLElement: HTMLInputElement = element.querySelector('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]'); + spanHTMLElement.dispatchEvent(new Event('mouseenter')); + copyFixture.detectChanges(); + expect(copyFixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).not.toBeNull(); + }); + customCopyComponent.taskList.appName = appName.currentValue; + customCopyComponent.taskList.ngOnChanges({ 'appName': appName }); + copyFixture.detectChanges(); + })); + + it('it should not show copy tooltip when key is not present in data-colunn', async(() => { + const appName = new SimpleChange(null, 'FAKE-APP-NAME', true); + customCopyComponent.taskList.success.subscribe( () => { + copyFixture.whenStable().then(() => { + copyFixture.detectChanges(); + const spanHTMLElement: HTMLInputElement = element.querySelector('span[title="standalone-subtask"]'); + spanHTMLElement.dispatchEvent(new Event('mouseenter')); + copyFixture.detectChanges(); + expect(copyFixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).toBeNull(); + }); + }); + customCopyComponent.taskList.appName = appName.currentValue; + customCopyComponent.taskList.ngOnChanges({ 'appName': appName }); + copyFixture.detectChanges(); + })); + }); describe('Creating an empty custom template - EmptyTemplateComponent', () => { @@ -285,4 +338,88 @@ describe('TaskListCloudComponent', () => { }); })); }); + + describe('Copy cell content directive from app.config specifications', () => { + + let element: any; + let taskSpy: jasmine.Spy; + + setupTestBed({ + imports: [ProcessServiceCloudTestingModule, TaskListCloudModule], + schemas: [CUSTOM_ELEMENTS_SCHEMA] + }); + + beforeEach( () => { + appConfig = TestBed.get(AppConfigService); + taskListCloudService = TestBed.get(TaskListCloudService); + appConfig.config = Object.assign(appConfig.config, { + 'adf-cloud-task-list': { + 'presets': { + 'fakeCustomSchema': [ + { + 'key': 'entry.id', + 'type': 'text', + 'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.FAKE', + 'sortable': true, + 'copyContent': true + }, + { + 'key': 'entry.name', + 'type': 'text', + 'title': 'ADF_CLOUD_TASK_LIST.PROPERTIES.TASK_FAKE', + 'sortable': true + } + ] + } + } + }); + fixture = TestBed.createComponent(TaskListCloudComponent); + component = fixture.componentInstance; + element = fixture.debugElement.nativeElement; + taskSpy = spyOn(taskListCloudService, 'getTaskByRequest').and.returnValue(of(fakeGlobalTask)); + + }); + afterEach(() => { + fixture.destroy(); + }); + + it('shoud show tooltip if config copyContent flag is true', async(() => { + taskSpy.and.returnValue(of(fakeGlobalTask)); + const appName = new SimpleChange(null, 'FAKE-APP-NAME', true); + + component.success.subscribe( () => { + fixture.whenStable().then(() => { + fixture.detectChanges(); + const spanHTMLElement: HTMLInputElement = element.querySelector('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]'); + spanHTMLElement.dispatchEvent(new Event('mouseenter')); + fixture.detectChanges(); + expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).not.toBeNull(); + }); + }); + + component.presetColumn = 'fakeCustomSchema'; + component.appName = appName.currentValue; + component.ngOnChanges({ 'appName': appName }); + component.ngAfterContentInit(); + })); + + it('shoud not show tooltip if config copyContent flag is true', async(() => { + taskSpy.and.returnValue(of(fakeGlobalTask)); + const appName = new SimpleChange(null, 'FAKE-APP-NAME', true); + component.success.subscribe( () => { + fixture.whenStable().then(() => { + fixture.detectChanges(); + const spanHTMLElement: HTMLInputElement = element.querySelector('span[title="standalone-subtask"]'); + spanHTMLElement.dispatchEvent(new Event('mouseenter')); + fixture.detectChanges(); + expect(fixture.debugElement.nativeElement.querySelector('.adf-datatable-copy-tooltip')).toBeNull(); + }); + }); + component.presetColumn = 'fakeCustomSchema'; + component.appName = appName.currentValue; + component.ngOnChanges({ 'appName': appName }); + component.ngAfterContentInit(); + })); + }); + });