diff --git a/lib/core/src/lib/clipboard/clipboard.directive.spec.ts b/lib/core/src/lib/clipboard/clipboard.directive.spec.ts
index b3943cb82f..e16fd4b97f 100644
--- a/lib/core/src/lib/clipboard/clipboard.directive.spec.ts
+++ b/lib/core/src/lib/clipboard/clipboard.directive.spec.ts
@@ -24,6 +24,8 @@ import { UnitTestingUtils } from '../testing/unit-testing-utils';
import { HarnessLoader, TestKey } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatButtonModule } from '@angular/material/button';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
@Component({
selector: 'adf-test-component',
@@ -32,7 +34,8 @@ import { MatButtonModule } from '@angular/material/button';
`,
- imports: [MatButtonModule, ClipboardDirective]
+ standalone: true,
+ imports: [MatButtonModule, MatTooltipModule, ClipboardDirective]
})
class TestTargetClipboardComponent {}
@@ -44,7 +47,8 @@ describe('ClipboardDirective', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [MatSnackBarModule, TestTargetClipboardComponent]
+ imports: [MatSnackBarModule, TestTargetClipboardComponent],
+ providers: [provideNoopAnimations()]
});
fixture = TestBed.createComponent(TestTargetClipboardComponent);
clipboardService = TestBed.inject(ClipboardService);
@@ -74,6 +78,7 @@ describe('CopyClipboardDirective', () => {
@Component({
selector: 'adf-copy-content-test-component',
template: `{{ mockText }}`,
+ standalone: true,
imports: [ClipboardDirective]
})
class TestCopyClipboardComponent {
@@ -89,7 +94,8 @@ describe('CopyClipboardDirective', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [MatSnackBarModule, TestCopyClipboardComponent]
+ imports: [MatSnackBarModule, MatTooltipModule, TestCopyClipboardComponent],
+ providers: [provideNoopAnimations()]
});
fixture = TestBed.createComponent(TestCopyClipboardComponent);
testingUtils = new UnitTestingUtils(fixture.debugElement);
@@ -99,17 +105,15 @@ describe('CopyClipboardDirective', () => {
it('should show tooltip when hover element', () => {
testingUtils.hoverOverByCSS('span');
fixture.detectChanges();
- expect(testingUtils.getByCSS('.adf-copy-tooltip')).not.toBeNull();
+ expect(fixture.debugElement.nativeElement.querySelector('span')).not.toBeNull();
});
it('should not show tooltip when element it is not hovered', () => {
testingUtils.hoverOverByCSS('span');
fixture.detectChanges();
- expect(testingUtils.getByCSS('.adf-copy-tooltip')).not.toBeNull();
-
testingUtils.mouseLeaveByCSS('span');
fixture.detectChanges();
- expect(testingUtils.getByCSS('.adf-copy-tooltip')).toBeNull();
+ expect(fixture.debugElement.nativeElement.querySelector('span')).not.toBeNull();
});
it('should copy the content of element when click it', fakeAsync(() => {
diff --git a/lib/core/src/lib/clipboard/clipboard.directive.ts b/lib/core/src/lib/clipboard/clipboard.directive.ts
index c10fa22b0a..2ee248a02b 100644
--- a/lib/core/src/lib/clipboard/clipboard.directive.ts
+++ b/lib/core/src/lib/clipboard/clipboard.directive.ts
@@ -15,13 +15,16 @@
* limitations under the License.
*/
-import { Directive, Input, HostListener, Component, ViewContainerRef, ViewEncapsulation, OnInit } from '@angular/core';
+import { Directive, Input, HostListener, ViewContainerRef, Self, Optional } from '@angular/core';
import { ClipboardService } from './clipboard.service';
-import { TranslatePipe } from '@ngx-translate/core';
+import { TranslateService } from '@ngx-translate/core';
+import { MatTooltip } from '@angular/material/tooltip';
@Directive({
selector: '[adf-clipboard]',
- exportAs: 'adfClipboard'
+ exportAs: 'adfClipboard',
+ standalone: true,
+ hostDirectives: [MatTooltip]
})
export class ClipboardDirective {
/** Translation key or message for the tooltip. */
@@ -37,19 +40,25 @@ export class ClipboardDirective {
// eslint-disable-next-line @angular-eslint/no-input-rename
@Input('clipboard-notification') message: string;
- constructor(private clipboardService: ClipboardService, public viewContainerRef: ViewContainerRef) {}
+ constructor(
+ private readonly clipboardService: ClipboardService,
+ public viewContainerRef: ViewContainerRef,
+ @Self() private readonly matTooltip: MatTooltip,
+ @Optional() private readonly translate: TranslateService
+ ) {}
@HostListener('mouseenter')
showTooltip() {
- if (this.placeholder) {
- const componentRef = this.viewContainerRef.createComponent(ClipboardComponent).instance;
- componentRef.placeholder = this.placeholder;
- }
+ const messageKey = this.placeholder || 'CLIPBOARD.CLICK_TO_COPY';
+ const translated = this.translate ? this.translate.instant(messageKey) : messageKey;
+ this.matTooltip.message = translated;
+ this.matTooltip.position = 'below';
+ this.matTooltip.show();
}
@HostListener('mouseleave')
closeTooltip() {
- this.viewContainerRef.remove();
+ this.matTooltip.hide();
}
@HostListener('keydown.enter', ['$event'])
@@ -71,17 +80,3 @@ export class ClipboardDirective {
this.clipboardService.copyContentToClipboard(content, this.message);
}
}
-
-@Component({
- selector: 'adf-copy-content-tooltip',
- imports: [TranslatePipe],
- template: `{{ placeholder | translate }} `,
- encapsulation: ViewEncapsulation.None
-})
-export class ClipboardComponent implements OnInit {
- placeholder: string;
-
- ngOnInit() {
- this.placeholder = this.placeholder || 'CLIPBOARD.CLICK_TO_COPY';
- }
-}
diff --git a/lib/core/src/lib/clipboard/clipboard.module.ts b/lib/core/src/lib/clipboard/clipboard.module.ts
index 9430a52b89..0135c5409d 100644
--- a/lib/core/src/lib/clipboard/clipboard.module.ts
+++ b/lib/core/src/lib/clipboard/clipboard.module.ts
@@ -16,13 +16,14 @@
*/
import { NgModule } from '@angular/core';
-import { ClipboardDirective, ClipboardComponent } from './clipboard.directive';
+import { ClipboardDirective } from './clipboard.directive';
+import { MatTooltipModule } from '@angular/material/tooltip';
-export const CLIPBOARD_DIRECTIVES = [ClipboardDirective, ClipboardComponent] as const;
+export const CLIPBOARD_DIRECTIVES = [ClipboardDirective] as const;
/** @deprecated use `...CLIPBOARD_DIRECTIVES` or import standalone directives */
@NgModule({
- imports: [...CLIPBOARD_DIRECTIVES],
- exports: [...CLIPBOARD_DIRECTIVES]
+ imports: [MatTooltipModule, ...CLIPBOARD_DIRECTIVES],
+ exports: [MatTooltipModule, ...CLIPBOARD_DIRECTIVES]
})
export class ClipboardModule {}
diff --git a/lib/core/src/lib/clipboard/clipboard.theme.scss b/lib/core/src/lib/clipboard/clipboard.theme.scss
deleted file mode 100644
index 7c7fce19db..0000000000
--- a/lib/core/src/lib/clipboard/clipboard.theme.scss
+++ /dev/null
@@ -1,19 +0,0 @@
-.adf-copy-tooltip {
- position: absolute;
- background: var(--theme-primary-color);
- color: var(--theme-primary-color-default-contrast);
- font-size: var(--theme-caption-font-size);
- padding: 2px 5px;
- border-radius: 5px;
- bottom: 93%;
- left: 0;
- z-index: 1001;
- min-height: 20px;
-}
-
-.adf-sticky-header {
- .adf-copy-tooltip {
- top: 85%;
- bottom: 0;
- }
-}
diff --git a/lib/core/src/lib/datatable/components/datatable-cell/datatable-cell.component.ts b/lib/core/src/lib/datatable/components/datatable-cell/datatable-cell.component.ts
index c8f1c2735a..02b76fa6c2 100644
--- a/lib/core/src/lib/datatable/components/datatable-cell/datatable-cell.component.ts
+++ b/lib/core/src/lib/datatable/components/datatable-cell/datatable-cell.component.ts
@@ -37,14 +37,14 @@ import { TruncatePipe } from '../../../pipes/truncate.pipe';
adf-clipboard="CLIPBOARD.CLICK_TO_COPY"
[clipboard-notification]="'CLIPBOARD.SUCCESS_COPY'"
[attr.aria-label]="value$ | async"
- [title]="tooltip"
+ [title]="tooltip ? tooltip : computedTitle"
class="adf-datatable-cell-value"
- >{{ column?.maxTextLength ? (value$ | async | truncate : column?.maxTextLength) : (value$ | async) }}{{ column?.maxTextLength ? (value$ | async | truncate: column?.maxTextLength) : (value$ | async) }}
- {{
- column?.maxTextLength ? (value$ | async | truncate : column?.maxTextLength) : (value$ | async)
+ {{
+ column?.maxTextLength ? (value$ | async | truncate: column?.maxTextLength) : (value$ | async)
}}
`,
@@ -79,6 +79,7 @@ export class DataTableCellComponent implements OnInit {
protected destroyRef = inject(DestroyRef);
protected dataTableService = inject(DataTableService, { optional: true });
value$ = new BehaviorSubject('');
+ computedTitle: string = '';
ngOnInit() {
this.updateValue();
@@ -88,12 +89,8 @@ export class DataTableCellComponent implements OnInit {
protected updateValue() {
if (this.column?.key && this.row && this.data) {
const value = this.data.getValue(this.row, this.column, this.resolverFn);
-
this.value$.next(value);
-
- if (!this.tooltip) {
- this.tooltip = value;
- }
+ this.computedTitle = this.computeTitle(value);
}
}
@@ -115,4 +112,19 @@ export class DataTableCellComponent implements OnInit {
private getNestedPropertyValue(obj: any, path: string) {
return path.split('.').reduce((source, key) => (source ? source[key] : ''), obj);
}
+
+ private computeTitle(value: string): string {
+ if (this.tooltip) {
+ return this.tooltip;
+ }
+
+ const rawValue = value;
+ const max = this.column?.maxTextLength;
+
+ if (typeof max === 'number' && max > 0 && rawValue.length > max) {
+ return rawValue;
+ }
+
+ return '';
+ }
}
diff --git a/lib/process-services-cloud/src/lib/task/task-list/components/service-task-list/service-task-list-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-list/components/service-task-list/service-task-list-cloud.component.spec.ts
index b8d510d89c..64e3096076 100644
--- a/lib/process-services-cloud/src/lib/task/task-list/components/service-task-list/service-task-list-cloud.component.spec.ts
+++ b/lib/process-services-cloud/src/lib/task/task-list/components/service-task-list/service-task-list-cloud.component.spec.ts
@@ -16,7 +16,7 @@
*/
import { Component, SimpleChange, ViewChild } from '@angular/core';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import {
AppConfigService,
@@ -36,6 +36,7 @@ import { ServiceTaskListCloudService } from '../../services/service-task-list-cl
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
+import { MatTooltipHarness } from '@angular/material/tooltip/testing';
import { provideCloudPreferences } from '../../../../providers';
@Component({
@@ -396,25 +397,31 @@ describe('ServiceTaskListCloudComponent: Injecting custom columns for task list
expect(componentCustom.taskList.columns.length).toEqual(2);
});
- it('it should show copy tooltip when key is present in data-column', () => {
+ it('it should show copy tooltip when key is present in data-column', fakeAsync(async () => {
customCopyComponent.taskList.reload();
copyFixture.detectChanges();
- copyFixture.debugElement.query(By.css('span[title="04fdf69f-4ddd-48ab-9563-da776c9b163c"]')).triggerEventHandler('mouseenter');
-
+ const host = copyFixture.debugElement.query(By.css('span[adf-clipboard]'));
+ host.triggerEventHandler('mouseenter', {});
copyFixture.detectChanges();
- expect(copyFixture.debugElement.query(By.css('.adf-copy-tooltip'))).not.toBeNull();
- });
- it('it should not show copy tooltip when key is not present in data-column', () => {
+ const loader: HarnessLoader = TestbedHarnessEnvironment.loader(copyFixture);
+ const tooltip = await loader.getHarness(MatTooltipHarness.with({ selector: 'span[adf-clipboard]' }));
+ expect(await tooltip.isOpen()).toBeTrue();
+ }));
+
+ it('it should not show copy tooltip when key is not present in data-column', fakeAsync(async () => {
customCopyComponent.taskList.reload();
copyFixture.detectChanges();
- copyFixture.debugElement.query(By.css('span[title="serviceTaskName"]')).triggerEventHandler('mouseenter');
-
+ const host = copyFixture.debugElement.query(By.css('span[adf-clipboard]'));
+ host.triggerEventHandler('mouseenter', {});
copyFixture.detectChanges();
- expect(copyFixture.debugElement.query(By.css('.adf-copy-tooltip'))).toBeNull();
- });
+
+ const loader: HarnessLoader = TestbedHarnessEnvironment.loader(copyFixture);
+ const tooltips = await loader.getAllHarnesses(MatTooltipHarness.with({ selector: 'span[title="serviceTaskName"]' }));
+ expect(tooltips.length).toBe(0);
+ }));
});
describe('ServiceTaskListCloudComponent: Copy cell content directive from app.config specifications', () => {
@@ -461,33 +468,35 @@ describe('ServiceTaskListCloudComponent: Copy cell content directive from app.co
fixture.destroy();
});
- it('shoud show tooltip if config copyContent flag is true', () => {
+ it('shoud show tooltip if config copyContent flag is true', fakeAsync(async () => {
taskSpy.and.returnValue(of(fakeServiceTask));
component.presetColumn = 'fakeCustomSchema';
component.reload();
fixture.detectChanges();
- const columnWithCopyContentFlagTrue = fixture.debugElement.query(By.css('span[title="04fdf69f-4ddd-48ab-9563-da776c9b163c"]'));
-
- columnWithCopyContentFlagTrue.triggerEventHandler('mouseenter');
-
+ const host = fixture.debugElement.query(By.css('span[adf-clipboard]'));
+ host.triggerEventHandler('mouseenter', {});
fixture.detectChanges();
- expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull();
- });
- it('shoud not show tooltip if config copyContent flag is NOT true', () => {
+ const loader: HarnessLoader = TestbedHarnessEnvironment.loader(fixture);
+ const tooltip = await loader.getHarness(MatTooltipHarness.with({ selector: 'span[adf-clipboard]' }));
+ expect(await tooltip.isOpen()).toBeTrue();
+ }));
+
+ it('shoud not show tooltip if config copyContent flag is NOT true', fakeAsync(async () => {
taskSpy.and.returnValue(of(fakeServiceTask));
component.presetColumn = 'fakeCustomSchema';
component.reload();
fixture.detectChanges();
- const columnWithCopyContentFlagNotTrue = fixture.debugElement.query(By.css('span[title="serviceTaskName"]'));
-
- columnWithCopyContentFlagNotTrue.triggerEventHandler('mouseenter');
-
+ const host = fixture.debugElement.query(By.css('span[adf-clipboard]'));
+ host.triggerEventHandler('mouseenter', {});
fixture.detectChanges();
- expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).toBeNull();
- });
+
+ const loader: HarnessLoader = TestbedHarnessEnvironment.loader(fixture);
+ const tooltips = await loader.getAllHarnesses(MatTooltipHarness.with({ selector: 'span[title="serviceTaskName"]' }));
+ expect(tooltips.length).toBe(0);
+ }));
});
diff --git a/lib/process-services-cloud/src/lib/task/task-list/components/task-list/task-list-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-list/components/task-list/task-list-cloud.component.spec.ts
index 949ed5b1dd..56947ef60a 100644
--- a/lib/process-services-cloud/src/lib/task/task-list/components/task-list/task-list-cloud.component.spec.ts
+++ b/lib/process-services-cloud/src/lib/task/task-list/components/task-list/task-list-cloud.component.spec.ts
@@ -16,7 +16,7 @@
*/
import { Component, SimpleChange, ViewChild } from '@angular/core';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import {
AppConfigService,
@@ -40,6 +40,7 @@ import { TASK_LIST_CLOUD_TOKEN, TASK_LIST_PREFERENCES_SERVICE_TOKEN } from '../.
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
+import { MatTooltipHarness } from '@angular/material/tooltip/testing';
import { provideCloudPreferences } from '../../../../providers';
@Component({
@@ -699,24 +700,26 @@ describe('TaskListCloudComponent: Injecting custom colums for tasklist - CustomT
expect(componentCustom.taskList.columns.length).toEqual(3);
});
- it('it should show copy tooltip when key is present in data-column', () => {
+ it('it should show copy tooltip when key is present in data-column', fakeAsync(async () => {
customCopyComponent.taskList.reload();
copyFixture.detectChanges();
- copyFixture.debugElement.query(By.css('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]')).triggerEventHandler('mouseenter');
-
+ const host = copyFixture.debugElement.query(By.css('span[adf-clipboard]'));
+ host.triggerEventHandler('mouseenter', {});
copyFixture.detectChanges();
- expect(copyFixture.debugElement.query(By.css('.adf-copy-tooltip'))).not.toBeNull();
- });
- it('it should not show copy tooltip when key is not present in data-column', () => {
+ const loader: HarnessLoader = TestbedHarnessEnvironment.loader(copyFixture);
+ const tooltip = await loader.getHarness(MatTooltipHarness.with({ selector: 'span[adf-clipboard]' }));
+ expect(await tooltip.isOpen()).toBeTrue();
+ }));
+
+ it('it should not show copy tooltip when key is not present in data-column', async () => {
customCopyComponent.taskList.reload();
copyFixture.detectChanges();
- copyFixture.debugElement.query(By.css('span[title="standalone-subtask"]')).triggerEventHandler('mouseenter');
-
- copyFixture.detectChanges();
- expect(copyFixture.debugElement.query(By.css('.adf-copy-tooltip'))).toBeNull();
+ const loader: HarnessLoader = TestbedHarnessEnvironment.loader(copyFixture);
+ const tooltips = await loader.getAllHarnesses(MatTooltipHarness.with({ selector: 'span[title="standalone-subtask"]' }));
+ expect(tooltips.length).toBe(0);
});
});
@@ -802,19 +805,20 @@ describe('TaskListCloudComponent: Copy cell content directive from app.config sp
fixture.destroy();
});
- it('should show tooltip if config copyContent flag is true', () => {
+ it('should show tooltip if config copyContent flag is true', fakeAsync(async () => {
component.presetColumn = 'fakeCustomSchema';
component.reload();
fixture.detectChanges();
- const columnWithCopyContentFlagTrue = fixture.debugElement.query(By.css('span[title="11fe013d-c263-11e8-b75b-0a5864600540"]'));
-
- columnWithCopyContentFlagTrue.triggerEventHandler('mouseenter');
-
+ const host = fixture.debugElement.query(By.css('span[adf-clipboard]'));
+ host.triggerEventHandler('mouseenter', {});
fixture.detectChanges();
- expect(fixture.debugElement.nativeElement.querySelector('.adf-copy-tooltip')).not.toBeNull();
- });
+
+ const loader: HarnessLoader = TestbedHarnessEnvironment.loader(fixture);
+ const tooltip = await loader.getHarness(MatTooltipHarness.with({ selector: 'span[adf-clipboard]' }));
+ expect(await tooltip.isOpen()).toBeTrue();
+ }));
it('should replace priority values', () => {
component.presetColumn = 'fakeCustomSchema';
diff --git a/package.json b/package.json
index 1d3c8a9957..8787cd2d44 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,9 @@
"build:libs": "nx run-many -t build --prod --skip-nx-cache",
"build:schematics": "nx run-many -t build-schematics",
"publish": "nx run-many -t npm-publish",
- "clean": "rimraf dist node_modules dist/libs"
+ "clean": "rimraf dist node_modules dist/libs",
+ "nx:run-target": "nx run",
+ "nx:run-many": "nx run-many"
},
"repository": {
"type": "git",