diff --git a/src/app/core/errors/error.component.ts b/src/app/core/errors/error.component.ts index f7af327a..9f96c841 100644 --- a/src/app/core/errors/error.component.ts +++ b/src/app/core/errors/error.component.ts @@ -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: `

{{ state.status }} {{ state.statusText }}

{{ state.url }}

{{ state.message }}

-

{{ state.stack }}

+ @if (isAdmin()) { +

{{ state.stack }}

+ }
` }) export class ErrorComponent { readonly #router = inject(Router); + readonly #session = inject(APP_SESSION); + + readonly isAdmin = computed(() => this.#session().isAdmin()); state: ErrorState = { status: 500, diff --git a/src/app/core/site-container/site-container.component.html b/src/app/core/site-container/site-container.component.html index ace5737f..9ee7be86 100644 --- a/src/app/core/site-container/site-container.component.html +++ b/src/app/core/site-container/site-container.component.html @@ -26,4 +26,6 @@ } - +@if (isAuthenticated() && showFeedbackFlyout()) { + +} diff --git a/src/app/core/site-container/site-container.component.ts b/src/app/core/site-container/site-container.component.ts index 57ff677f..29e8736e 100644 --- a/src/app/core/site-container/site-container.component.ts +++ b/src/app/core/site-container/site-container.component.ts @@ -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', @@ -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(); diff --git a/src/app/core/site-navbar/site-navbar.component.html b/src/app/core/site-navbar/site-navbar.component.html index 065f57bf..ca2778d9 100644 --- a/src/app/core/site-navbar/site-navbar.component.html +++ b/src/app/core/site-navbar/site-navbar.component.html @@ -257,14 +257,15 @@ } - + @if (isAuthenticated() && showFeedbackOption()) { + + } @if (showApiDocsLink()) { diff --git a/src/app/core/site-navbar/site-navbar.component.ts b/src/app/core/site-navbar/site-navbar.component.ts index 9c297b27..8fdc71e7 100644 --- a/src/app/core/site-navbar/site-navbar.component.ts +++ b/src/app/core/site-navbar/site-navbar.component.ts @@ -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( diff --git a/src/app/core/teams/list-team-members/list-team-members.component.html b/src/app/core/teams/list-team-members/list-team-members.component.html index e3fa95ac..efa86fc2 100644 --- a/src/app/core/teams/list-team-members/list-team-members.component.html +++ b/src/app/core/teams/list-team-members/list-team-members.component.html @@ -10,14 +10,11 @@
- + @if (isTeamAdmin()) { + + }
@@ -49,57 +46,57 @@ - - - - - - + {{ member.roleDisplay }} + + + + + } @else { {{ member.roleDisplay }} - + } - + @if (isTeamAdmin() && member.explicit) { + + } - - + + (); - readonly #user = computed(() => this.#session().user); + readonly isTeamAdmin = computed( + () => this.#session().isAdmin() || this.#session().hasTeamRole(this.team(), TeamRole.ADMIN) + ); readonly teamRoleOptions = TeamRole.ROLES; @@ -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( @@ -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?', diff --git a/src/app/core/teams/list-teams/base-list-teams.component.ts b/src/app/core/teams/list-teams/base-list-teams.component.ts index af384935..2955ab87 100644 --- a/src/app/core/teams/list-teams/base-list-teams.component.ts +++ b/src/app/core/teams/list-teams/base-list-teams.component.ts @@ -1,9 +1,6 @@ import { Directive, HostAttributeToken, - OnChanges, - OnInit, - SimpleChanges, booleanAttribute, computed, inject, @@ -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); @@ -35,18 +32,10 @@ export abstract class BaseListTeamsComponent implements OnChanges, OnInit { readonly displayedColumns = ['name', 'created', 'description']; - protected constructor(public dataSource: AsyTableDataSource) {} - - ngOnInit() { + protected constructor(public dataSource: AsyTableDataSource) { this.#alertService.clearAllAlerts(); } - ngOnChanges(changes: SimpleChanges) { - if (changes['parent']) { - this.dataSource.reload(); - } - } - loadData( pagingOptions: PagingOptions, search: string, diff --git a/src/app/core/teams/list-teams/list-sub-teams.component.ts b/src/app/core/teams/list-teams/list-sub-teams.component.ts index 85f0b0a0..94bb035b 100644 --- a/src/app/core/teams/list-teams/list-sub-teams.component.ts +++ b/src/app/core/teams/list-teams/list-sub-teams.component.ts @@ -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'; @@ -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( @@ -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(); + }); } } diff --git a/src/app/core/teams/list-teams/list-teams.component.ts b/src/app/core/teams/list-teams/list-teams.component.ts index 5f8da325..f4de30a7 100644 --- a/src/app/core/teams/list-teams/list-teams.component.ts +++ b/src/app/core/teams/list-teams/list-teams.component.ts @@ -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'; @@ -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( diff --git a/src/app/core/teams/view-team/general-details/general-details.component.html b/src/app/core/teams/view-team/general-details/general-details.component.html index a24537b9..5867535b 100644 --- a/src/app/core/teams/view-team/general-details/general-details.component.html +++ b/src/app/core/teams/view-team/general-details/general-details.component.html @@ -13,15 +13,16 @@

Members

Details

- + @if (isTeamAdmin()) { + + } @if (isEditing()) {
+ @if (isTeamAdmin()) { + + }