Skip to content

Commit

Permalink
refactor: more updates to use signals
Browse files Browse the repository at this point in the history
  • Loading branch information
jrassa committed May 30, 2024
1 parent d4b0149 commit 0f2d3d1
Show file tree
Hide file tree
Showing 38 changed files with 362 additions and 378 deletions.
10 changes: 5 additions & 5 deletions src/app/common/breadcrumb/breadcrumb.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import { Breadcrumb, BreadcrumbService } from './breadcrumb.service';
imports: [RouterLink]
})
export class BreadcrumbComponent {
readonly #route = inject(ActivatedRoute);
readonly #router = inject(Router);

@Input({ required: true })
set homeBreadcrumb(hb: Breadcrumb) {
this._homeBreadcrumb = hb;
Expand All @@ -25,11 +28,8 @@ export class BreadcrumbComponent {

breadcrumbs: Breadcrumb[] = [];

private route = inject(ActivatedRoute);
private router = inject(Router);

constructor() {
const navEnd$: Observable<Event> = this.router.events.pipe(
const navEnd$: Observable<Event> = this.#router.events.pipe(
filter((event) => event instanceof NavigationEnd)
);
merge(navEnd$, this.homeBreadcrumbChanged$)
Expand All @@ -39,7 +39,7 @@ export class BreadcrumbComponent {
this.breadcrumbs = [this._homeBreadcrumb];
this.breadcrumbs = this.breadcrumbs.concat(
BreadcrumbService.getBreadcrumbs(
this.route.root.snapshot,
this.#route.root.snapshot,
this._homeBreadcrumb.url
)
);
Expand Down
7 changes: 2 additions & 5 deletions src/app/common/flyout/flyout.component.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
<section
class="flyout flyout-{{ placement }} d-flex text-nowrap"
[ngClass]="{ 'flyout-open': isOpen }"
>
<section class="flyout flyout-{{ placement() }} d-flex text-nowrap" [class.flyout-open]="isOpen()">
<button
class="btn btn-primary flyout-btn d-flex align-items-center"
data-inline="true"
(click)="toggle()"
>
{{ label }}
{{ label() }}
<span class="fa-solid fa-lg fa-angle-down ms-2" data-inline="true"></span>
</button>

Expand Down
50 changes: 24 additions & 26 deletions src/app/common/flyout/flyout.component.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { NgClass } from '@angular/common';
import {
Component,
ContentChild,
ElementRef,
Input,
Renderer2,
ViewChild,
inject
contentChild,
inject,
input,
signal,
viewChild
} from '@angular/core';

@Component({
Expand All @@ -17,44 +18,41 @@ import {
imports: [NgClass]
})
export class FlyoutComponent {
@ViewChild('flyoutContentContainer') container?: ElementRef;
@ContentChild('flyoutContent') content?: ElementRef;
readonly #renderer = inject(Renderer2);

@Input()
label = '';
readonly container = viewChild.required<ElementRef>('flyoutContentContainer');
readonly content = contentChild.required<ElementRef>('flyoutContent');

@Input()
placement: 'left' | 'right' | 'top' | 'bottom' = 'right';
readonly label = input('');
readonly placement = input<'left' | 'right' | 'top' | 'bottom'>('right');

isOpen = false;

private renderer = inject(Renderer2);
readonly isOpen = signal(false);

toggle() {
if (this.content && this.container) {
if (this.placement === 'top' || this.placement === 'bottom') {
if (this.isOpen) {
this.renderer.setStyle(this.container.nativeElement, 'height', 0);
if (this.content() && this.container()) {
if (this.placement() === 'top' || this.placement() === 'bottom') {
if (this.isOpen()) {
this.#renderer.setStyle(this.container().nativeElement, 'height', 0);
} else {
this.renderer.setStyle(
this.container.nativeElement,
this.#renderer.setStyle(
this.container().nativeElement,
'height',
`${this.content.nativeElement.clientHeight}px`
`${this.content().nativeElement.clientHeight}px`
);
}
} else {
if (this.isOpen) {
this.renderer.setStyle(this.container.nativeElement, 'width', 0);
if (this.isOpen()) {
this.#renderer.setStyle(this.container().nativeElement, 'width', 0);
} else {
this.renderer.setStyle(
this.container.nativeElement,
this.#renderer.setStyle(
this.container().nativeElement,
'width',
`${this.content.nativeElement.clientWidth}px`
`${this.content().nativeElement.clientWidth}px`
);
}
}

this.isOpen = !this.isOpen;
this.isOpen.set(!this.isOpen());
}
}
}
13 changes: 6 additions & 7 deletions src/app/common/loading-overlay/loading-overlay.component.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
@if (isLoading) {
@if (isLoading()) {
<div class="overlay">
@if (isError) {
<notification notificationType="danger" showActions [message]="errorMessage">
@if (isError()) {
<notification notificationType="danger" showActions [message]="errorMessage()">
<ng-template #notificationActions>
<button class="btn btn-primary" (click)="handleRetry()">Retry</button>
<button class="btn btn-primary" (click)="retry.emit()">Retry</button>
</ng-template>
</notification>
}
@if (!isError) {
} @else {
<div class="overlay-spinner">
<loading-spinner [message]="message"> </loading-spinner>
<loading-spinner [message]="message()"> </loading-spinner>
</div>
}
</div>
Expand Down
27 changes: 8 additions & 19 deletions src/app/common/loading-overlay/loading-overlay.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { ChangeDetectionStrategy, Component, input, output } from '@angular/core';

import { LoadingSpinnerComponent } from '../loading-spinner/loading-spinner.component';
import { NotificationComponent } from '../notification/notification.component';
Expand All @@ -8,25 +8,14 @@ import { NotificationComponent } from '../notification/notification.component';
templateUrl: 'loading-overlay.component.html',
styleUrls: ['loading-overlay.component.scss'],
standalone: true,
imports: [NotificationComponent, LoadingSpinnerComponent]
imports: [NotificationComponent, LoadingSpinnerComponent],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class LoadingOverlayComponent {
@Input()
message = 'Loading...';
readonly message = input('Loading...');
readonly isLoading = input(false);
readonly isError = input(false);
readonly errorMessage = input('');

@Input()
isLoading = false;

@Input()
isError = false;

@Input()
errorMessage = '';

@Output()
readonly retry = new EventEmitter();

handleRetry() {
this.retry.emit(true);
}
readonly retry = output();
}
10 changes: 5 additions & 5 deletions src/app/common/notification/notification.component.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<div class="alert alert-{{ notificationType }} d-flex" [class.small]="small">
<div class="flex-grow-1" [class.action-text]="showActions">
{{ message }}
<div class="alert alert-{{ notificationType() }} d-flex" [class.small]="small()">
<div class="flex-grow-1" [class.action-text]="showActions()">
{{ message() }}
</div>
@if (showActions) {
@if (showActions() && actionTemplate()) {
<div class="table-actions d-flex">
<ng-container *ngTemplateOutlet="actionTemplate"></ng-container>
<ng-container *ngTemplateOutlet="actionTemplate() ?? null"></ng-container>
</div>
}
</div>
30 changes: 15 additions & 15 deletions src/app/common/notification/notification.component.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import { NgTemplateOutlet } from '@angular/common';
import { Component, ContentChild, Input, TemplateRef, booleanAttribute } from '@angular/core';
import {
ChangeDetectionStrategy,
Component,
TemplateRef,
booleanAttribute,
contentChild,
input
} from '@angular/core';

@Component({
selector: 'notification',
templateUrl: 'notification.component.html',
styleUrls: ['notification.component.scss'],
standalone: true,
imports: [NgTemplateOutlet]
imports: [NgTemplateOutlet],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class NotificationComponent {
@ContentChild('notificationActions', { static: true }) actionTemplate: TemplateRef<any> | null =
null;
readonly actionTemplate = contentChild<TemplateRef<any>>('notificationActions');

@Input()
notificationType: 'info' | 'success' | 'warning' | 'danger' = 'info';

@Input()
message = '';

@Input({ transform: booleanAttribute })
showActions = false;

@Input({ transform: booleanAttribute })
small = false;
readonly notificationType = input<'info' | 'success' | 'warning' | 'danger'>('info');
readonly message = input('');
readonly showActions = input(false, { transform: booleanAttribute });
readonly small = input(false, { transform: booleanAttribute });
}
8 changes: 4 additions & 4 deletions src/app/common/search-input/search-input.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
class="form-control"
type="text"
[(ngModel)]="search"
[placeholder]="placeholder"
[placeholder]="placeholder()"
(input)="onInput()"
(keyup)="onKeyup()"
/>
@if (search.length === 0) {
@if (search().length === 0) {
<span class="icon fa-solid fa-search"></span>
} @else {
<span class="icon fa-solid fa-times" (click)="clearSearch($event)"></span>
}
</div>
@if (!disableMinCountMessage && showMinCountMessage) {
@if (!disableMinCountMessage() && showMinCountMessage()) {
<div class="text-muted pt-2" [@minCount]>
<div class="pt-2">
Searches require a minimum of {{ minSearchCharacterCount }} characters.
Searches require a minimum of {{ minSearchCharacterCount() }} characters.
</div>
</div>
}
56 changes: 31 additions & 25 deletions src/app/common/search-input/search-input.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { animate, style, transition, trigger } from '@angular/animations';
import { Component, EventEmitter, Input, Output, booleanAttribute } from '@angular/core';
import {
ChangeDetectionStrategy,
Component,
booleanAttribute,
input,
model,
output,
signal
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { FormsModule } from '@angular/forms';

Expand All @@ -23,69 +31,67 @@ import { debounceTime } from 'rxjs/operators';
])
],
standalone: true,
imports: [FormsModule]
imports: [FormsModule],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SearchInputComponent {
@Input()
placeholder = 'Search...';
search = model('');

@Input()
search = '';

@Output()
readonly applySearch: EventEmitter<string> = new EventEmitter();
readonly placeholder = input('Search...');

/**
* If true, searches will be made on `input` events, otherwise searches will be made on `keyup` events
*/
@Input({ transform: booleanAttribute })
preferInputEvent = true;
readonly preferInputEvent = input(true, { transform: booleanAttribute });

/**
* Specifies a minimum character count required to search.
* In the event the number of characters is between 0 and the minimum, a warning message is shown beneath the search bar
*/
@Input()
minSearchCharacterCount = 0;
readonly minSearchCharacterCount = input(0);

/**
* When set to true, the minimum search character
* message count will not be displayed, even if the search
* value is less than the minimum number of characters.
*/
@Input({ transform: booleanAttribute })
disableMinCountMessage = false;
readonly disableMinCountMessage = input(false, { transform: booleanAttribute });

searchInput$ = new Subject<void>();
readonly showMinCountMessage = signal(false);

showMinCountMessage = false;
readonly applySearch = output<string>();

searchInput$ = new Subject<void>();

constructor() {
this.searchInput$.pipe(debounceTime(350), takeUntilDestroyed()).subscribe(() => {
if (this.search.length === 0 || this.search.length >= this.minSearchCharacterCount) {
this.showMinCountMessage = false;
this.applySearch.emit(this.search);
if (
this.search().length === 0 ||
this.search().length >= this.minSearchCharacterCount()
) {
this.showMinCountMessage.set(false);
this.applySearch.emit(this.search());
} else {
this.showMinCountMessage = true;
this.showMinCountMessage.set(true);
}
});
}

onKeyup() {
if (!this.preferInputEvent) {
if (!this.preferInputEvent()) {
this.searchInput$.next();
}
}

onInput() {
if (this.preferInputEvent) {
if (this.preferInputEvent()) {
this.searchInput$.next();
}
}

clearSearch(event?: MouseEvent) {
this.search = '';
this.applySearch.emit(this.search);
this.search.set('');
this.applySearch.emit(this.search());
if (event) {
event.stopPropagation();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
cdkDrag
cdkDragBoundary=".column-drag-boundary"
[cdkDragData]="column"
[cdkDragDisabled]="sortingDisabled"
[cdkDragDisabled]="sortingDisabled()"
>
@if (!sortingDisabled) {
@if (!sortingDisabled()) {
<span class="fa-solid fa-lg fa-bars pe-1 me-2" cdkDragHandle></span>
}
<input
Expand Down
Loading

0 comments on commit 0f2d3d1

Please sign in to comment.