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