From 3ee3ec8d520ee2cf676f2020aef5a403d299e7bc Mon Sep 17 00:00:00 2001 From: John Rassa Date: Thu, 14 Mar 2024 11:35:21 -0400 Subject: [PATCH] refactor: update components to enforce required inputs --- .../common/breadcrumb/breadcrumb.component.ts | 2 +- .../loading-overlay.component.ts | 18 +++++++++++++----- .../multi-select-input.component.ts | 8 +++++--- .../notification/notification.component.ts | 17 ++++++++++++----- .../search-input/search-input.component.ts | 11 ++++++++--- src/app/common/table/asy-table-data-source.ts | 2 +- .../column-chooser/column-chooser.component.ts | 2 +- .../table/filter/asy-filter.directive.ts | 2 +- .../asy-header-list-filter.component.ts | 6 ++++-- .../asy-skeleton-rows.component.ts | 3 ++- .../asy-sort-header.component.ts | 9 ++++++--- .../list-cache-entries.component.ts | 2 +- src/app/core/audit/audit-object.component.ts | 10 +++++++--- .../directives/has-every-role.directive.ts | 2 +- .../core/auth/directives/has-role.directive.ts | 2 +- .../directives/has-some-roles.directive.ts | 2 +- src/app/core/help/help-topic.component.ts | 2 +- .../has-some-team-roles.directive.ts | 2 +- .../directives/has-team-role.directive.ts | 2 +- .../list-team-members.component.ts | 7 ++----- .../general-details.component.ts | 4 ++-- .../teams/view-team/view-team.component.ts | 4 ++-- 22 files changed, 74 insertions(+), 45 deletions(-) diff --git a/src/app/common/breadcrumb/breadcrumb.component.ts b/src/app/common/breadcrumb/breadcrumb.component.ts index 123099e3..6ce5739c 100644 --- a/src/app/common/breadcrumb/breadcrumb.component.ts +++ b/src/app/common/breadcrumb/breadcrumb.component.ts @@ -16,7 +16,7 @@ import { Breadcrumb, BreadcrumbService } from './breadcrumb.service'; imports: [NgFor, NgIf, RouterLink] }) export class BreadcrumbComponent { - @Input() + @Input({ required: true }) set homeBreadcrumb(hb: Breadcrumb) { this._homeBreadcrumb = hb; this.homeBreadcrumbChanged$.next(hb); diff --git a/src/app/common/loading-overlay/loading-overlay.component.ts b/src/app/common/loading-overlay/loading-overlay.component.ts index 202cf865..b83c87d0 100644 --- a/src/app/common/loading-overlay/loading-overlay.component.ts +++ b/src/app/common/loading-overlay/loading-overlay.component.ts @@ -12,12 +12,20 @@ import { NotificationComponent } from '../notification/notification.component'; imports: [NgIf, NotificationComponent, LoadingSpinnerComponent] }) export class LoadingOverlayComponent { - @Input() message = 'Loading...'; - @Input() isLoading = false; - @Input() isError = false; - @Input() errorMessage = ''; + @Input() + message = 'Loading...'; - @Output() readonly retry = new EventEmitter(); + @Input() + isLoading = false; + + @Input() + isError = false; + + @Input() + errorMessage = ''; + + @Output() + readonly retry = new EventEmitter(); handleRetry() { this.retry.emit(true); diff --git a/src/app/common/multi-select-input/multi-select-input.component.ts b/src/app/common/multi-select-input/multi-select-input.component.ts index 3d3f9a70..01c8361a 100644 --- a/src/app/common/multi-select-input/multi-select-input.component.ts +++ b/src/app/common/multi-select-input/multi-select-input.component.ts @@ -31,11 +31,13 @@ import { NgSelectModule } from '@ng-select/ng-select'; imports: [NgSelectModule, FormsModule] }) export class MultiSelectInputComponent implements ControlValueAccessor { - @Input() placeholder = ''; + @ViewChild(NgModel) model?: NgModel; - @Input() readonly = false; + @Input() + placeholder = ''; - @ViewChild(NgModel) model?: NgModel; + @Input() + readonly = false; autocompleteOpen = false; diff --git a/src/app/common/notification/notification.component.ts b/src/app/common/notification/notification.component.ts index 91d82fbe..7325461d 100644 --- a/src/app/common/notification/notification.component.ts +++ b/src/app/common/notification/notification.component.ts @@ -9,11 +9,18 @@ import { Component, ContentChild, Input, TemplateRef } from '@angular/core'; imports: [NgIf, NgTemplateOutlet] }) export class NotificationComponent { - @Input() notificationType: 'info' | 'success' | 'warning' | 'danger' = 'info'; - @Input() message = ''; - @Input() showActions = false; - @Input() small = false; - @ContentChild('notificationActions', { static: true }) actionTemplate: TemplateRef | null = null; + + @Input() + notificationType: 'info' | 'success' | 'warning' | 'danger' = 'info'; + + @Input() + message = ''; + + @Input() + showActions = false; + + @Input() + small = false; } diff --git a/src/app/common/search-input/search-input.component.ts b/src/app/common/search-input/search-input.component.ts index 5794ab00..8a7d9ef0 100644 --- a/src/app/common/search-input/search-input.component.ts +++ b/src/app/common/search-input/search-input.component.ts @@ -27,9 +27,14 @@ import { debounceTime } from 'rxjs/operators'; imports: [FormsModule, NgIf] }) export class SearchInputComponent { - @Input() placeholder = 'Search...'; - @Output() readonly applySearch: EventEmitter = new EventEmitter(); - @Input() search = ''; + @Input() + placeholder = 'Search...'; + + @Input() + search = ''; + + @Output() + readonly applySearch: EventEmitter = new EventEmitter(); /** * If true, searches will be made on `input` events, otherwise searches will be made on `keyup` events diff --git a/src/app/common/table/asy-table-data-source.ts b/src/app/common/table/asy-table-data-source.ts index 45420725..e3a15ff0 100644 --- a/src/app/common/table/asy-table-data-source.ts +++ b/src/app/common/table/asy-table-data-source.ts @@ -35,7 +35,7 @@ export class AsyTableDataSource extends DataSource { constructor( private loadPageFunc: LoadPageFunction, - public storageKey: string | null = null, + public storageKey?: string, initialSort: SortChange = {} as SortChange, initialSearch = '', initialFilter: any = {}, diff --git a/src/app/common/table/column-chooser/column-chooser.component.ts b/src/app/common/table/column-chooser/column-chooser.component.ts index b09497df..62648072 100644 --- a/src/app/common/table/column-chooser/column-chooser.component.ts +++ b/src/app/common/table/column-chooser/column-chooser.component.ts @@ -35,7 +35,7 @@ export class ColumnChooserComponent implements OnInit { _defaultColumns: ColumnDefinition[] = []; @Input() - storageKey: string | null; + storageKey?: string; @Input() sortingDisabled = false; diff --git a/src/app/common/table/filter/asy-filter.directive.ts b/src/app/common/table/filter/asy-filter.directive.ts index f6185c24..7ea606f1 100644 --- a/src/app/common/table/filter/asy-filter.directive.ts +++ b/src/app/common/table/filter/asy-filter.directive.ts @@ -24,7 +24,7 @@ export class AsyFilterDirective { filters = new Map(); - @Input() + @Input({ required: true }) dataSource: AsyTableDataSource; /** diff --git a/src/app/common/table/filter/asy-header-list-filter/asy-header-list-filter.component.ts b/src/app/common/table/filter/asy-header-list-filter/asy-header-list-filter.component.ts index e24a669b..e5535942 100644 --- a/src/app/common/table/filter/asy-header-list-filter/asy-header-list-filter.component.ts +++ b/src/app/common/table/filter/asy-header-list-filter/asy-header-list-filter.component.ts @@ -49,9 +49,11 @@ export class AsyHeaderListFilterComponent extends AsyAbstractHeaderFilterCompone matchAll = false; - @Input() showSearch = false; + @Input() + showSearch = false; - @Input() showMatch = false; + @Input() + showMatch = false; @Input() buildFilterFunc?: BuildFilterFunction; diff --git a/src/app/common/table/skeleton-rows/asy-skeleton-rows.component.ts b/src/app/common/table/skeleton-rows/asy-skeleton-rows.component.ts index c024c5e8..0487165a 100644 --- a/src/app/common/table/skeleton-rows/asy-skeleton-rows.component.ts +++ b/src/app/common/table/skeleton-rows/asy-skeleton-rows.component.ts @@ -11,7 +11,8 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; }) export class AsySkeletonRowsComponent { _rows: Array = []; - @Input() + + @Input({ required: true }) set rows(numRows: number) { this._rows = Array(numRows).fill(0); } diff --git a/src/app/common/table/sort/asy-sort-header/asy-sort-header.component.ts b/src/app/common/table/sort/asy-sort-header/asy-sort-header.component.ts index d848b6eb..d0564d2d 100644 --- a/src/app/common/table/sort/asy-sort-header/asy-sort-header.component.ts +++ b/src/app/common/table/sort/asy-sort-header/asy-sort-header.component.ts @@ -46,12 +46,15 @@ export class AsySortHeaderComponent implements AsySortable, OnDestroy, OnInit { * ID of this sort header. If used within the context of a CdkColumnDef, this will default to * the column's name. */ - @Input('asy-sort-header') id: string; + @Input('asy-sort-header') + id: string; /** Overrides the sort start value of the containing AsySort for this AsySortable. */ - @Input() start: SortDir; + @Input() + start: SortDir; - @Input() sortable = true; + @Input() + sortable = true; private destroyRef = inject(DestroyRef); private changeDetectorRef = inject(ChangeDetectorRef); diff --git a/src/app/core/admin/cache-entries/list-cache-entries/list-cache-entries.component.ts b/src/app/core/admin/cache-entries/list-cache-entries/list-cache-entries.component.ts index 61f41b6c..8bd3bbaf 100644 --- a/src/app/core/admin/cache-entries/list-cache-entries/list-cache-entries.component.ts +++ b/src/app/core/admin/cache-entries/list-cache-entries/list-cache-entries.component.ts @@ -60,7 +60,7 @@ export class ListCacheEntriesComponent implements OnDestroy, OnInit { dataSource = new AsyTableDataSource( (request) => this.loadData(request.pagingOptions, request.search, request.filter), - null, + undefined, { sortField: 'ts', sortDir: SortDirection.desc diff --git a/src/app/core/audit/audit-object.component.ts b/src/app/core/audit/audit-object.component.ts index a6894f0d..8c83b8e6 100644 --- a/src/app/core/audit/audit-object.component.ts +++ b/src/app/core/audit/audit-object.component.ts @@ -10,7 +10,8 @@ import { AuditObjectTypes } from './audit.classes'; imports: [JsonPipe] }) export class DefaultAuditObjectComponent { - @Input() auditObject: any = {}; + @Input() + auditObject: any = {}; } AuditObjectTypes.registerType('default', DefaultAuditObjectComponent); @@ -57,8 +58,11 @@ AuditObjectTypes.registerType('export', ExportAuditObjectComponent); export class AuditObjectComponent implements OnInit { @ViewChild('content', { read: ViewContainerRef, static: true }) content?: ViewContainerRef; - @Input() auditObject: any = {}; - @Input() auditType = ''; + @Input() + auditObject: any = {}; + + @Input() + auditType = ''; ngOnInit() { if (!AuditObjectTypes.objects.hasOwnProperty(this.auditType)) { diff --git a/src/app/core/auth/directives/has-every-role.directive.ts b/src/app/core/auth/directives/has-every-role.directive.ts index 67dd1787..ae483d60 100644 --- a/src/app/core/auth/directives/has-every-role.directive.ts +++ b/src/app/core/auth/directives/has-every-role.directive.ts @@ -26,7 +26,7 @@ export class HasEveryRoleDirective implements OnInit { private sessionService = inject(SessionService); private authorizationService = inject(AuthorizationService); - @Input() + @Input({ required: true }) set hasEveryRole(roles: Array) { this.roles = roles; this.updateNgIf(); diff --git a/src/app/core/auth/directives/has-role.directive.ts b/src/app/core/auth/directives/has-role.directive.ts index 9a2744c4..149eadaa 100644 --- a/src/app/core/auth/directives/has-role.directive.ts +++ b/src/app/core/auth/directives/has-role.directive.ts @@ -26,7 +26,7 @@ export class HasRoleDirective implements OnInit { private sessionService = inject(SessionService); private authorizationService = inject(AuthorizationService); - @Input() + @Input({ required: true }) set hasRole(role: string | Role) { this.role = role; this.updateNgIf(); diff --git a/src/app/core/auth/directives/has-some-roles.directive.ts b/src/app/core/auth/directives/has-some-roles.directive.ts index 566b9158..359722c3 100644 --- a/src/app/core/auth/directives/has-some-roles.directive.ts +++ b/src/app/core/auth/directives/has-some-roles.directive.ts @@ -26,7 +26,7 @@ export class HasSomeRolesDirective implements OnInit { private sessionService = inject(SessionService); private authorizationService = inject(AuthorizationService); - @Input() + @Input({ required: true }) set hasSomeRoles(roles: Array) { this.roles = roles; this.updateNgIf(); diff --git a/src/app/core/help/help-topic.component.ts b/src/app/core/help/help-topic.component.ts index 75decddd..bb3e48ae 100644 --- a/src/app/core/help/help-topic.component.ts +++ b/src/app/core/help/help-topic.component.ts @@ -38,7 +38,7 @@ export class HelpTopicComponent { helpTopics = getHelpTopicsMap(); - @Input() + @Input({ required: true }) set key(key: string) { if (this.componentRef) { this.componentRef.destroy(); diff --git a/src/app/core/teams/directives/has-some-team-roles.directive.ts b/src/app/core/teams/directives/has-some-team-roles.directive.ts index 02c6a7a6..2803df8a 100644 --- a/src/app/core/teams/directives/has-some-team-roles.directive.ts +++ b/src/app/core/teams/directives/has-some-team-roles.directive.ts @@ -30,7 +30,7 @@ export class HasSomeTeamRolesDirective implements OnInit { private authorizationService = inject(AuthorizationService); private teamAuthorizationService = inject(TeamAuthorizationService); - @Input() + @Input({ required: true }) set hasSomeTeamRoles(team: Pick) { this.team = team; this.updateNgIf(); diff --git a/src/app/core/teams/directives/has-team-role.directive.ts b/src/app/core/teams/directives/has-team-role.directive.ts index da5ec787..d489eafb 100644 --- a/src/app/core/teams/directives/has-team-role.directive.ts +++ b/src/app/core/teams/directives/has-team-role.directive.ts @@ -30,7 +30,7 @@ export class HasTeamRoleDirective implements OnInit { private authorizationService = inject(AuthorizationService); private teamAuthorizationService = inject(TeamAuthorizationService); - @Input() + @Input({ required: true }) set hasTeamRole(team: Pick) { this.team = team; this.updateNgIf(); diff --git a/src/app/core/teams/list-team-members/list-team-members.component.ts b/src/app/core/teams/list-team-members/list-team-members.component.ts index e99ae9b0..19e3476d 100644 --- a/src/app/core/teams/list-team-members/list-team-members.component.ts +++ b/src/app/core/teams/list-team-members/list-team-members.component.ts @@ -85,7 +85,7 @@ export class ListTeamMembersComponent implements OnChanges, OnDestroy, OnInit { @ViewChild(AsyFilterDirective) filter: AsyFilterDirective; - @Input() + @Input({ required: true }) team!: Team; isUserAdmin = false; @@ -111,7 +111,7 @@ export class ListTeamMembersComponent implements OnChanges, OnDestroy, OnInit { dataSource = new AsyTableDataSource( (request) => this.loadData(request.pagingOptions, request.search, request.filter), - null, + undefined, { sortField: 'name', sortDir: SortDirection.asc @@ -127,9 +127,6 @@ export class ListTeamMembersComponent implements OnChanges, OnDestroy, OnInit { private alertService = inject(SystemAlertService); ngOnInit() { - if (!this.team) { - throw new TypeError(`'Team' is required`); - } this.alertService.clearAllAlerts(); this.sessionService diff --git a/src/app/core/teams/view-team/general-details/general-details.component.ts b/src/app/core/teams/view-team/general-details/general-details.component.ts index bd16a377..bd2f116c 100644 --- a/src/app/core/teams/view-team/general-details/general-details.component.ts +++ b/src/app/core/teams/view-team/general-details/general-details.component.ts @@ -41,8 +41,8 @@ import { TeamsService } from '../../teams.service'; ] }) export class GeneralDetailsComponent implements OnInit { - @Input() - team?: Team; + @Input({ required: true }) + team!: Team; _team: Team; diff --git a/src/app/core/teams/view-team/view-team.component.ts b/src/app/core/teams/view-team/view-team.component.ts index 55228283..dc9f2641 100644 --- a/src/app/core/teams/view-team/view-team.component.ts +++ b/src/app/core/teams/view-team/view-team.component.ts @@ -31,8 +31,8 @@ import { TeamsService } from '../teams.service'; export class ViewTeamComponent { topics = getTeamTopics(); - @Input() - team?: Team; + @Input({ required: true }) + team!: Team; private destroyRef = inject(DestroyRef); private dialogService = inject(DialogService);