From 7897d7631293521ec41799d6e473d8339a4460e2 Mon Sep 17 00:00:00 2001 From: Dmitriy Potychkin Date: Fri, 29 Jan 2021 02:27:34 +0200 Subject: [PATCH 1/6] feat(description): create description component --- .../description/description.component.scss | 23 +++++++++++ .../description/description.component.test.ts | 33 ++++++++++++++++ .../src/description/description.component.ts | 39 +++++++++++++++++++ .../src/description/description.module.ts | 10 +++++ projects/components/src/public-api.ts | 4 ++ 5 files changed, 109 insertions(+) create mode 100644 projects/components/src/description/description.component.scss create mode 100644 projects/components/src/description/description.component.test.ts create mode 100644 projects/components/src/description/description.component.ts create mode 100644 projects/components/src/description/description.module.ts diff --git a/projects/components/src/description/description.component.scss b/projects/components/src/description/description.component.scss new file mode 100644 index 000000000..083cb4596 --- /dev/null +++ b/projects/components/src/description/description.component.scss @@ -0,0 +1,23 @@ +:host { + min-width: 0; +} + +.description { + display: flex; +} + +.description-text { + margin-right: 6px; +} + +.description-button { + cursor: pointer; + text-decoration: underline; + white-space: nowrap; +} + +.truncated-text { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} diff --git a/projects/components/src/description/description.component.test.ts b/projects/components/src/description/description.component.test.ts new file mode 100644 index 000000000..239552e93 --- /dev/null +++ b/projects/components/src/description/description.component.test.ts @@ -0,0 +1,33 @@ +import { createHostFactory, Spectator } from '@ngneat/spectator/jest'; +import { DescriptionComponent } from './description.component'; + +describe('Divider Component', () => { + let spectator: Spectator; + + const createHost = createHostFactory({ + component: DescriptionComponent, + shallow: true + }); + + test('should render the description', () => { + spectator = createHost(' ', { + hostProps: { + description: 'Description text' + } + }); + expect(spectator.query('.description')).toExist(); + expect(spectator.query('.description-text')).toHaveText('Description text'); + }); + + test('should show full description text if pressed button show more', () => { + spectator = createHost(' ', { + hostProps: { + description: 'Description text' + } + }); + + expect(spectator.component.isDescriptionTextToggled).toBeFalsy(); + spectator.component.toggleDescriptionText(); + expect(spectator.component.isDescriptionTextToggled).toBeTruthy(); + }); +}); diff --git a/projects/components/src/description/description.component.ts b/projects/components/src/description/description.component.ts new file mode 100644 index 000000000..93378dfc5 --- /dev/null +++ b/projects/components/src/description/description.component.ts @@ -0,0 +1,39 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; + +@Component({ + selector: 'ht-description', + changeDetection: ChangeDetectionStrategy.OnPush, + styleUrls: ['./description.component.scss'], + template: ` +
+
+ {{ description }} + show less +
+
+ show more +
+
+ ` +}) +export class DescriptionComponent { + public isDescriptionTextToggled: boolean = false; + + @Input() + public description!: string; + + public toggleDescriptionText(): void { + this.isDescriptionTextToggled = !this.isDescriptionTextToggled; + } +} diff --git a/projects/components/src/description/description.module.ts b/projects/components/src/description/description.module.ts new file mode 100644 index 000000000..964383eec --- /dev/null +++ b/projects/components/src/description/description.module.ts @@ -0,0 +1,10 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { DescriptionComponent } from './description.component'; + +@NgModule({ + imports: [CommonModule], + declarations: [DescriptionComponent], + exports: [DescriptionComponent] +}) +export class DescriptionModule {} diff --git a/projects/components/src/public-api.ts b/projects/components/src/public-api.ts index 1d2405f99..dadcba451 100644 --- a/projects/components/src/public-api.ts +++ b/projects/components/src/public-api.ts @@ -304,3 +304,7 @@ export * from './confirmation/confirmation.service'; // Notification export * from './notification/notification.service'; export * from './notification/notification.module'; + +// Description +export * from './description/description.component'; +export * from './description/description.module'; From 16dd16703b28c0b9ce78ad285c12fc8b9faa79a4 Mon Sep 17 00:00:00 2001 From: Dmitriy Potychkin Date: Mon, 1 Feb 2021 19:57:57 +0200 Subject: [PATCH 2/6] feat(description): add text truncation recalculate on resize --- .../description/description.component.scss | 7 +-- .../src/description/description.component.ts | 59 +++++++++++++++---- .../src/description/description.module.ts | 3 +- 3 files changed, 54 insertions(+), 15 deletions(-) diff --git a/projects/components/src/description/description.component.scss b/projects/components/src/description/description.component.scss index 083cb4596..2460441ea 100644 --- a/projects/components/src/description/description.component.scss +++ b/projects/components/src/description/description.component.scss @@ -6,14 +6,13 @@ display: flex; } -.description-text { - margin-right: 6px; -} - .description-button { cursor: pointer; text-decoration: underline; white-space: nowrap; + &-more { + margin-left: 5px; + } } .truncated-text { diff --git a/projects/components/src/description/description.component.ts b/projects/components/src/description/description.component.ts index 93378dfc5..49a239f13 100644 --- a/projects/components/src/description/description.component.ts +++ b/projects/components/src/description/description.component.ts @@ -1,39 +1,78 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + ViewChild, + AfterViewInit, + OnChanges, + ElementRef +} from '@angular/core'; +import { Subject } from 'rxjs'; @Component({ selector: 'ht-description', - changeDetection: ChangeDetectionStrategy.OnPush, styleUrls: ['./description.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, template: ` -
+
{{ description }} - show less
show more
` }) -export class DescriptionComponent { +export class DescriptionComponent implements OnChanges, AfterViewInit { + public isInitialized: boolean = false; public isDescriptionTextToggled: boolean = false; + public readonly isDescriptionTruncated$: Subject = new Subject(); + public fullDescriptionTextWidth!: number; + + @ViewChild('eventDescriptionText', { read: ElementRef }) + public readonly eventDescriptionText!: ElementRef; + + @ViewChild('eventDescriptionContainer', { read: ElementRef }) + public readonly eventDescriptionContainer!: ElementRef; @Input() public description!: string; + public ngOnChanges(): void { + if (this.isInitialized) { + this.remeasure(); + } + } + + ngAfterViewInit() { + this.fullDescriptionTextWidth = this.eventDescriptionText.nativeElement.scrollWidth; + this.isInitialized = true; + this.remeasure(); + } + public toggleDescriptionText(): void { this.isDescriptionTextToggled = !this.isDescriptionTextToggled; } + + public remeasure(): void { + this.isDescriptionTruncated$.next( + this.eventDescriptionContainer.nativeElement.offsetWidth < this.fullDescriptionTextWidth + ); + } } diff --git a/projects/components/src/description/description.module.ts b/projects/components/src/description/description.module.ts index 964383eec..b11f0acf2 100644 --- a/projects/components/src/description/description.module.ts +++ b/projects/components/src/description/description.module.ts @@ -1,9 +1,10 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { DescriptionComponent } from './description.component'; +import { LayoutChangeModule } from '../layout/layout-change.module'; @NgModule({ - imports: [CommonModule], + imports: [CommonModule, LayoutChangeModule], declarations: [DescriptionComponent], exports: [DescriptionComponent] }) From 6986dac991e750499da8779f20a727e3e4dc1758 Mon Sep 17 00:00:00 2001 From: Dmitriy Potychkin Date: Mon, 1 Feb 2021 22:43:33 +0200 Subject: [PATCH 3/6] fix(description): use cahngedetctionref --- .../components/src/description/description.component.test.ts | 3 ++- projects/components/src/description/description.component.ts | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/projects/components/src/description/description.component.test.ts b/projects/components/src/description/description.component.test.ts index 239552e93..d86b93520 100644 --- a/projects/components/src/description/description.component.test.ts +++ b/projects/components/src/description/description.component.test.ts @@ -1,7 +1,7 @@ import { createHostFactory, Spectator } from '@ngneat/spectator/jest'; import { DescriptionComponent } from './description.component'; -describe('Divider Component', () => { +describe('Description Component', () => { let spectator: Spectator; const createHost = createHostFactory({ @@ -15,6 +15,7 @@ describe('Divider Component', () => { description: 'Description text' } }); + expect(spectator.query('.description')).toExist(); expect(spectator.query('.description-text')).toHaveText('Description text'); }); diff --git a/projects/components/src/description/description.component.ts b/projects/components/src/description/description.component.ts index 49a239f13..25f30a373 100644 --- a/projects/components/src/description/description.component.ts +++ b/projects/components/src/description/description.component.ts @@ -1,5 +1,6 @@ import { ChangeDetectionStrategy, + ChangeDetectorRef, Component, Input, ViewChild, @@ -54,6 +55,8 @@ export class DescriptionComponent implements OnChanges, AfterViewInit { @Input() public description!: string; + constructor(private readonly cdr: ChangeDetectorRef) {} + public ngOnChanges(): void { if (this.isInitialized) { this.remeasure(); @@ -64,6 +67,7 @@ export class DescriptionComponent implements OnChanges, AfterViewInit { this.fullDescriptionTextWidth = this.eventDescriptionText.nativeElement.scrollWidth; this.isInitialized = true; this.remeasure(); + this.cdr.detectChanges(); } public toggleDescriptionText(): void { From 09afd6580690d92e63f60e9079f913e64f07b633 Mon Sep 17 00:00:00 2001 From: Dmitriy Potychkin Date: Mon, 1 Feb 2021 22:49:42 +0200 Subject: [PATCH 4/6] fix(description): linting --- .../src/description/description.component.ts | 10 +++++----- .../components/src/description/description.module.ts | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/projects/components/src/description/description.component.ts b/projects/components/src/description/description.component.ts index 25f30a373..ee785ff74 100644 --- a/projects/components/src/description/description.component.ts +++ b/projects/components/src/description/description.component.ts @@ -1,12 +1,12 @@ import { + AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, + ElementRef, Input, - ViewChild, - AfterViewInit, OnChanges, - ElementRef + ViewChild } from '@angular/core'; import { Subject } from 'rxjs'; @@ -55,7 +55,7 @@ export class DescriptionComponent implements OnChanges, AfterViewInit { @Input() public description!: string; - constructor(private readonly cdr: ChangeDetectorRef) {} + public constructor(private readonly cdr: ChangeDetectorRef) {} public ngOnChanges(): void { if (this.isInitialized) { @@ -63,7 +63,7 @@ export class DescriptionComponent implements OnChanges, AfterViewInit { } } - ngAfterViewInit() { + public ngAfterViewInit(): void { this.fullDescriptionTextWidth = this.eventDescriptionText.nativeElement.scrollWidth; this.isInitialized = true; this.remeasure(); diff --git a/projects/components/src/description/description.module.ts b/projects/components/src/description/description.module.ts index b11f0acf2..07ffde66d 100644 --- a/projects/components/src/description/description.module.ts +++ b/projects/components/src/description/description.module.ts @@ -1,7 +1,7 @@ -import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { DescriptionComponent } from './description.component'; +import { NgModule } from '@angular/core'; import { LayoutChangeModule } from '../layout/layout-change.module'; +import { DescriptionComponent } from './description.component'; @NgModule({ imports: [CommonModule, LayoutChangeModule], From 8f6040af7c428e059e62776f7ca8840857e3ef3e Mon Sep 17 00:00:00 2001 From: Dmitriy Potychkin Date: Tue, 2 Feb 2021 00:45:26 +0200 Subject: [PATCH 5/6] fix(description): resize event --- .../src/description/description.component.ts | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/projects/components/src/description/description.component.ts b/projects/components/src/description/description.component.ts index 25f30a373..7f2809150 100644 --- a/projects/components/src/description/description.component.ts +++ b/projects/components/src/description/description.component.ts @@ -8,7 +8,6 @@ import { OnChanges, ElementRef } from '@angular/core'; -import { Subject } from 'rxjs'; @Component({ selector: 'ht-description', @@ -24,7 +23,7 @@ import { Subject } from 'rxjs'; > {{ description }} show less
show more @@ -43,8 +42,7 @@ import { Subject } from 'rxjs'; export class DescriptionComponent implements OnChanges, AfterViewInit { public isInitialized: boolean = false; public isDescriptionTextToggled: boolean = false; - public readonly isDescriptionTruncated$: Subject = new Subject(); - public fullDescriptionTextWidth!: number; + public isDescriptionTruncated!: boolean; @ViewChild('eventDescriptionText', { read: ElementRef }) public readonly eventDescriptionText!: ElementRef; @@ -55,7 +53,7 @@ export class DescriptionComponent implements OnChanges, AfterViewInit { @Input() public description!: string; - constructor(private readonly cdr: ChangeDetectorRef) {} + constructor(private readonly cdRef: ChangeDetectorRef) {} public ngOnChanges(): void { if (this.isInitialized) { @@ -64,10 +62,8 @@ export class DescriptionComponent implements OnChanges, AfterViewInit { } ngAfterViewInit() { - this.fullDescriptionTextWidth = this.eventDescriptionText.nativeElement.scrollWidth; this.isInitialized = true; this.remeasure(); - this.cdr.detectChanges(); } public toggleDescriptionText(): void { @@ -75,8 +71,11 @@ export class DescriptionComponent implements OnChanges, AfterViewInit { } public remeasure(): void { - this.isDescriptionTruncated$.next( - this.eventDescriptionContainer.nativeElement.offsetWidth < this.fullDescriptionTextWidth - ); + this.isDescriptionTextToggled = false; + this.cdRef.detectChanges(); + + this.isDescriptionTruncated = + this.eventDescriptionContainer.nativeElement.offsetWidth < this.eventDescriptionText.nativeElement.scrollWidth; + this.cdRef.detectChanges(); } } From 9fd514c6e9f591dee1aa621456e33347b812fe16 Mon Sep 17 00:00:00 2001 From: Dmitriy Potychkin Date: Tue, 2 Feb 2021 00:52:56 +0200 Subject: [PATCH 6/6] fix(description): linting --- projects/components/src/description/description.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/components/src/description/description.component.ts b/projects/components/src/description/description.component.ts index d6e822100..ab3d11a58 100644 --- a/projects/components/src/description/description.component.ts +++ b/projects/components/src/description/description.component.ts @@ -53,7 +53,7 @@ export class DescriptionComponent implements OnChanges, AfterViewInit { @Input() public description!: string; - constructor(private readonly cdRef: ChangeDetectorRef) {} + public constructor(private readonly cdRef: ChangeDetectorRef) {} public ngOnChanges(): void { if (this.isInitialized) { @@ -61,7 +61,7 @@ export class DescriptionComponent implements OnChanges, AfterViewInit { } } - ngAfterViewInit() { + public ngAfterViewInit(): void { this.isInitialized = true; this.remeasure(); }