Skip to content

Commit

Permalink
refactor: misc updates (#393)
Browse files Browse the repository at this point in the history
* replace ngOnChange input monitoring with signals
* replace remaining auth directive usages with @if
  • Loading branch information
jrassa committed Jun 19, 2024
1 parent 40c7b9c commit 4e6f416
Show file tree
Hide file tree
Showing 14 changed files with 134 additions and 118 deletions.
13 changes: 9 additions & 4 deletions src/app/core/errors/error.component.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
import { Component, inject } from '@angular/core';
import { Component, computed, inject } from '@angular/core';
import { Router } from '@angular/router';

import { HasRoleDirective } from '../auth';
import { APP_SESSION } from '../tokens';
import { ErrorState } from './error-state.model';

@Component({
standalone: true,
imports: [HasRoleDirective],
imports: [],
template: `
<div class="p-5 bg-body-tertiary rounded-3">
<h1 class="text-body-emphasis">{{ state.status }} {{ state.statusText }}</h1>
<p class="load">{{ state.url }}</p>
<p class="load">{{ state.message }}</p>
<p class="load" *hasRole="'admin'">{{ state.stack }}</p>
@if (isAdmin()) {
<p class="load">{{ state.stack }}</p>
}
</div>
`
})
export class ErrorComponent {
readonly #router = inject(Router);
readonly #session = inject(APP_SESSION);

readonly isAdmin = computed(() => this.#session().isAdmin());

state: ErrorState = {
status: 500,
Expand Down
4 changes: 3 additions & 1 deletion src/app/core/site-container/site-container.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,6 @@
}
</footer>

<app-feedback-flyout *isAuthenticated="true; and: showFeedbackFlyout()"></app-feedback-flyout>
@if (isAuthenticated() && showFeedbackFlyout()) {
<app-feedback-flyout />
}
4 changes: 3 additions & 1 deletion src/app/core/site-container/site-container.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Component, computed, inject } from '@angular/core';
import { IsAuthenticatedDirective } from '../auth';
import { FeedbackFlyoutComponent } from '../feedback/feedback-flyout/feedback-flyout.component';
import { SiteNavbarComponent } from '../site-navbar/site-navbar.component';
import { APP_CONFIG } from '../tokens';
import { APP_CONFIG, APP_SESSION } from '../tokens';

@Component({
selector: 'site-container',
Expand All @@ -15,11 +15,13 @@ import { APP_CONFIG } from '../tokens';
imports: [SiteNavbarComponent, IsAuthenticatedDirective, FeedbackFlyoutComponent, CdkScrollable]
})
export class SiteContainerComponent {
readonly #session = inject(APP_SESSION);
readonly #config = inject(APP_CONFIG);

readonly bannerHtml = computed(() => this.#config()?.banner?.html);
readonly copyrightHtml = computed(() => this.#config()?.copyright?.html);
readonly showFeedbackFlyout = computed(() => this.#config()?.feedback?.showFlyout ?? false);
readonly isAuthenticated = computed(() => this.#session().isAuthenticated);

skipToMainContent(e: any) {
e.preventDefault();
Expand Down
17 changes: 9 additions & 8 deletions src/app/core/site-navbar/site-navbar.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -257,14 +257,15 @@
</button>
}
<!-- Feedback -->
<button
class="dropdown-item"
cdkMenuItem
*isAuthenticated="true; and: showFeedbackOption()"
(cdkMenuItemTriggered)="showFeedbackModal()"
>
Give Feedback
</button>
@if (isAuthenticated() && showFeedbackOption()) {
<button
class="dropdown-item"
cdkMenuItem
(cdkMenuItemTriggered)="showFeedbackModal()"
>
Give Feedback
</button>
}
<!-- API Docs -->
@if (showApiDocsLink()) {
<a class="dropdown-item" [href]="apiDocsLink()" cdkMenuItem target="_blank">
Expand Down
1 change: 1 addition & 0 deletions src/app/core/site-navbar/site-navbar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export class SiteNavbarComponent implements OnInit {
);
readonly userPreferencesLink = computed(() => this.#config()?.userPreferences?.path ?? '');
readonly canMasquerade = computed(() => this.session().user?.canMasquerade ?? false);
readonly isAuthenticated = computed(() => this.session().isAuthenticated);

readonly navbarOpen = toSignal(
inject(STORAGE_EVENT).pipe(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,11 @@
</div>

<div class="mb-3 ms-auto">
<button
class="btn btn-primary ms-auto"
type="button"
*hasTeamRole="team(); role: 'admin'"
(click)="addMembers()"
>
<span class="fa-solid fa-plus"></span> Add New
</button>
@if (isTeamAdmin()) {
<button class="btn btn-primary ms-auto" type="button" (click)="addMembers()">
<span class="fa-solid fa-plus"></span> Add New
</button>
}
</div>
</div>
</div>
Expand Down Expand Up @@ -49,57 +46,57 @@
</asy-header-filter>
</th>
<td cdk-cell *cdkCellDef="let member">
<button
class="btn dropdown-toggle p-0"
id="member-{{ member._id }}-role-menu-btn"
type="button"
attr.aria-controls="member-{{ member._id }}-role-menu"
*hasTeamRole="team(); role: 'admin'; else: readOnlyRole"
[cdkMenuTriggerFor]="roleMenu"
>
<span class="me-1">{{ member.roleDisplay }}</span>
</button>
<ng-template #roleMenu>
<div
class="dropdown-menu"
id="member-{{ member._id }}-role-menu"
attr.aria-labelledby="member-{{ member._id }}-role-menu-btn"
cdkMenu
@if (isTeamAdmin()) {
<button
class="btn dropdown-toggle p-0"
id="member-{{ member._id }}-role-menu-btn"
type="button"
attr.aria-controls="member-{{ member._id }}-role-menu"
[cdkMenuTriggerFor]="roleMenu"
>
@for (role of teamRoleOptions; track role) {
<button
class="dropdown-item"
cdkMenuItem
(cdkMenuItemTriggered)="updateRole(member, role.role)"
>
{{ role.label }}
</button>
}
</div>
</ng-template>

<ng-template #readOnlyRole>
<span class="me-1">{{ member.roleDisplay }}</span>
</button>
<ng-template #roleMenu>
<div
class="dropdown-menu"
id="member-{{ member._id }}-role-menu"
attr.aria-labelledby="member-{{ member._id }}-role-menu-btn"
cdkMenu
>
@for (role of teamRoleOptions; track role) {
<button
class="dropdown-item"
cdkMenuItem
(cdkMenuItemTriggered)="updateRole(member, role.role)"
>
{{ role.label }}
</button>
}
</div>
</ng-template>
} @else {
{{ member.roleDisplay }}
</ng-template>
}
</td>
</ng-container>
<ng-container cdkColumnDef="actions">
<th cdk-header-cell *cdkHeaderCellDef></th>
<td cdk-cell *cdkCellDef="let member">
<button
class="btn btn-link p-0"
container="body"
placement="left"
tooltip="Remove Member"
*hasTeamRole="team(); role: 'admin'; and: member.explicit"
(click)="removeMember(member)"
>
<span class="fa-solid fa-lg fa-trash"></span>
</button>
@if (isTeamAdmin() && member.explicit) {
<button
class="btn btn-link p-0"
container="body"
placement="left"
tooltip="Remove Member"
(click)="removeMember(member)"
>
<span class="fa-solid fa-lg fa-trash"></span>
</button>
}
</td>
</ng-container>
<tr cdk-header-row *cdkHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr cdk-row *cdkRowDef="let item; columns: displayedColumns"></tr>
<tr cdk-header-row *cdkHeaderRowDef="columns; sticky: true"></tr>
<tr cdk-row *cdkRowDef="let item; columns: columns"></tr>
</table>

<asy-table-empty-state
Expand Down
31 changes: 13 additions & 18 deletions src/app/core/teams/list-team-members/list-team-members.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@ import {
ChangeDetectionStrategy,
Component,
DestroyRef,
OnChanges,
OnInit,
SimpleChanges,
computed,
inject,
input,
viewChild
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
import { Router } from '@angular/router';

import { TooltipModule } from 'ngx-bootstrap/tooltip';
Expand Down Expand Up @@ -83,7 +80,7 @@ import { TeamsService } from '../teams.service';
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ListTeamMembersComponent implements OnChanges, OnInit {
export class ListTeamMembersComponent {
readonly #destroyRef = inject(DestroyRef);
readonly #dialogService = inject(DialogService);
readonly #router = inject(Router);
Expand All @@ -96,7 +93,9 @@ export class ListTeamMembersComponent implements OnChanges, OnInit {

readonly team = input.required<Team>();

readonly #user = computed(() => this.#session().user);
readonly isTeamAdmin = computed(
() => this.#session().isAdmin() || this.#session().hasTeamRole(this.team(), TeamRole.ADMIN)
);

readonly teamRoleOptions = TeamRole.ROLES;

Expand All @@ -123,22 +122,14 @@ export class ListTeamMembersComponent implements OnChanges, OnInit {
);

readonly columns = ['name', 'username', 'lastLogin', 'type', 'role', 'actions'];
displayedColumns: string[] = [];

constructor() {
this.#alertService.clearAllAlerts();
}

ngOnInit() {
this.displayedColumns = this.columns.filter(
(column) => this.team().implicitMembers || column !== 'explicit'
);
}

ngOnChanges(changes: SimpleChanges) {
if (changes['team']) {
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
toObservable(this.team).subscribe(() => {
this.dataSource.reload();
}
});
}

loadData(
Expand Down Expand Up @@ -203,7 +194,11 @@ export class ListTeamMembersComponent implements OnChanges, OnInit {
}

// If user is removing their own admin, verify that they know what they're doing
if (this.#user()?._id === member._id && member.role === 'admin' && role !== 'admin') {
if (
this.#session().user?._id === member._id &&
member.role === 'admin' &&
role !== 'admin'
) {
this.#dialogService
.confirm(
'Remove "Team Admin" role?',
Expand Down
15 changes: 2 additions & 13 deletions src/app/core/teams/list-teams/base-list-teams.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import {
Directive,
HostAttributeToken,
OnChanges,
OnInit,
SimpleChanges,
booleanAttribute,
computed,
inject,
Expand All @@ -21,7 +18,7 @@ import { Team } from '../team.model';
import { TeamsService } from '../teams.service';

@Directive()
export abstract class BaseListTeamsComponent implements OnChanges, OnInit {
export abstract class BaseListTeamsComponent {
readonly #teamsService = inject(TeamsService);
readonly #alertService = inject(SystemAlertService);
readonly #session = inject(APP_SESSION);
Expand All @@ -35,18 +32,10 @@ export abstract class BaseListTeamsComponent implements OnChanges, OnInit {

readonly displayedColumns = ['name', 'created', 'description'];

protected constructor(public dataSource: AsyTableDataSource<Team>) {}

ngOnInit() {
protected constructor(public dataSource: AsyTableDataSource<Team>) {
this.#alertService.clearAllAlerts();
}

ngOnChanges(changes: SimpleChanges) {
if (changes['parent']) {
this.dataSource.reload();
}
}

loadData(
pagingOptions: PagingOptions,
search: string,
Expand Down
10 changes: 8 additions & 2 deletions src/app/core/teams/list-teams/list-sub-teams.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CdkTableModule } from '@angular/cdk/table';
import { NgIf } from '@angular/common';
import { ChangeDetectionStrategy, Component, OnChanges, OnInit } from '@angular/core';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { toObservable } from '@angular/core/rxjs-interop';
import { RouterLink } from '@angular/router';

import { TooltipModule } from 'ngx-bootstrap/tooltip';
Expand Down Expand Up @@ -42,7 +43,7 @@ import { BaseListTeamsComponent } from './base-list-teams.component';
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ListSubTeamsComponent extends BaseListTeamsComponent implements OnChanges, OnInit {
export class ListSubTeamsComponent extends BaseListTeamsComponent {
constructor() {
super(
new AsyTableDataSource<Team>(
Expand All @@ -54,5 +55,10 @@ export class ListSubTeamsComponent extends BaseListTeamsComponent implements OnC
}
)
);

// eslint-disable-next-line rxjs-angular/prefer-takeuntil
toObservable(this.parent).subscribe(() => {
this.dataSource.reload();
});
}
}
4 changes: 2 additions & 2 deletions src/app/core/teams/list-teams/list-teams.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CdkTableModule } from '@angular/cdk/table';
import { ChangeDetectionStrategy, Component, OnChanges, OnInit } from '@angular/core';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterLink } from '@angular/router';

import { TooltipModule } from 'ngx-bootstrap/tooltip';
Expand Down Expand Up @@ -41,7 +41,7 @@ import { BaseListTeamsComponent } from './base-list-teams.component';
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ListTeamsComponent extends BaseListTeamsComponent implements OnChanges, OnInit {
export class ListTeamsComponent extends BaseListTeamsComponent {
constructor() {
super(
new AsyTableDataSource<Team>(
Expand Down
Loading

0 comments on commit 4e6f416

Please sign in to comment.