This commit is contained in:
2026-08-29 21:09:42 +00:00
parent 10448e8b12
commit 85a063c1a7
132 changed files with 4377 additions and 3348 deletions
@@ -1,32 +1,38 @@
<h2>User</h2>
<form class="flex-col">
<div class="row-container">
<mat-form-field class="flex-auto">
<mat-label>Name</mat-label>
<input matInput [formField]="form.name" />
</mat-form-field>
</div>
<div class="row-container">
<mat-form-field class="flex-auto">
<mat-label>Password</mat-label>
<input matInput [formField]="form.password" [type]="hide ? 'password' : 'text'" />
<mat-icon matSuffix (click)="hide = !hide">{{ hide ? 'visibility' : 'visibility_off' }}</mat-icon>
</mat-form-field>
</div>
<div class="row-container">
<mat-checkbox [formField]="form.lockedOut">Is Locked Out?</mat-checkbox>
</div>
<mat-divider></mat-divider>
<div>
@for (r of form.roles; track r; let i = $index) {
<div class="row-container">
<mat-checkbox [formField]="r.enabled" class="flex-auto">{{ r.name().value() }}</mat-checkbox>
</div>
}
</div>
</form>
@if (itemResource.isLoading()) {
<app-skeleton-loader type="card" [count]="1" />
} @else if (itemResource.error()) {
<app-error-state (retryAction)="itemResource.reload()" />
} @else {
<h2>User</h2>
<form class="flex-col">
<div class="row-container">
<mat-form-field class="flex-auto">
<mat-label>Name</mat-label>
<input matInput [formField]="form.name" />
</mat-form-field>
</div>
<div class="row-container">
<mat-form-field class="flex-auto">
<mat-label>Password</mat-label>
<input matInput [formField]="form.password" [type]="hide ? 'password' : 'text'" />
<mat-icon matSuffix (click)="hide = !hide">{{ hide ? 'visibility' : 'visibility_off' }}</mat-icon>
</mat-form-field>
</div>
<div class="row-container">
<mat-checkbox [formField]="form.lockedOut">Is Locked Out?</mat-checkbox>
</div>
<mat-divider></mat-divider>
<div>
@for (r of form.roles; track r; let i = $index) {
<div class="row-container">
<mat-checkbox [formField]="r.enabled" class="flex-auto">{{ r.name().value() }}</mat-checkbox>
</div>
}
</div>
</form>
<div class="row-container">
<button type="button" mat-raised-button color="primary" class="" (click)="save()">Save</button>
<button type="button" mat-raised-button color="warn" (click)="confirmDelete()">Delete</button>
</div>
<div class="row-container">
<button type="button" mat-raised-button color="primary" class="" (click)="save()">Save</button>
<button type="button" mat-raised-button color="warn" (click)="confirmDelete()">Delete</button>
</div>
}
@@ -12,6 +12,8 @@ import { Router } from '@angular/router';
import { User } from '../../core/user';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import { ErrorStateComponent } from '../../shared/error-state/error-state.component';
import { SkeletonLoaderComponent } from '../../shared/skeleton-loader/skeleton-loader.component';
import { UserService } from '../user.service';
export interface UserDetailFormData {
@@ -33,6 +35,8 @@ export interface UserDetailFormData {
MatIconModule,
MatInputModule,
FormField,
ErrorStateComponent,
SkeletonLoaderComponent,
],
})
export class UserDetailComponent {
@@ -1,45 +1,51 @@
<h2 class="row-container space-between">
<span>Users</span>
<a mat-button [routerLink]="['/users', 'new']">
<mat-icon>add_box</mat-icon>
Add
</a>
</h2>
<mat-table #table [dataSource]="dataSource()" aria-label="Elements">
<!-- Name Column -->
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
<mat-cell *matCellDef="let row"
><a [routerLink]="['/users', row.id]">{{ row.name }}</a></mat-cell
>
</ng-container>
@if (listResource.isLoading()) {
<app-skeleton-loader type="table" [count]="5" />
} @else if (listResource.error()) {
<app-error-state (retryAction)="listResource.reload()" />
} @else {
<h2 class="row-container space-between">
<span>Users</span>
<a mat-button [routerLink]="['/users', 'new']">
<mat-icon>add_box</mat-icon>
Add
</a>
</h2>
<mat-table #table [dataSource]="dataSource()" aria-label="Elements">
<!-- Name Column -->
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
<mat-cell *matCellDef="let row"
><a [routerLink]="['/users', row.id]">{{ row.name }}</a></mat-cell
>
</ng-container>
<!-- Locked Out Column -->
<ng-container matColumnDef="lockedOut">
<mat-header-cell *matHeaderCellDef>Is Locked Out?</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.lockedOut }}</mat-cell>
</ng-container>
<!-- Locked Out Column -->
<ng-container matColumnDef="lockedOut">
<mat-header-cell *matHeaderCellDef>Is Locked Out?</mat-header-cell>
<mat-cell *matCellDef="let row">{{ row.lockedOut }}</mat-cell>
</ng-container>
<!-- Groups Column -->
<ng-container matColumnDef="roles">
<mat-header-cell *matHeaderCellDef>Roles</mat-header-cell>
<mat-cell *matCellDef="let row">
<ul>
@for (role of row.roles; track role) {
<li>{{ role }}</li>
}
</ul>
</mat-cell>
</ng-container>
<!-- Groups Column -->
<ng-container matColumnDef="roles">
<mat-header-cell *matHeaderCellDef>Roles</mat-header-cell>
<mat-cell *matCellDef="let row">
<ul>
@for (role of row.roles; track role) {
<li>{{ role }}</li>
}
</ul>
</mat-cell>
</ng-container>
<!-- Last Login Column -->
<ng-container matColumnDef="last">
<mat-header-cell *matHeaderCellDef>Last Login</mat-header-cell>
<mat-cell *matCellDef="let row"
>{{ row.lastDevice }} &#64; {{ row.lastDate ? (row.lastDate | localTime) : 'Never' }}</mat-cell
>
</ng-container>
<!-- Last Login Column -->
<ng-container matColumnDef="last">
<mat-header-cell *matHeaderCellDef>Last Login</mat-header-cell>
<mat-cell *matCellDef="let row"
>{{ row.lastDevice }} &#64; {{ row.lastDate ? (row.lastDate | localTime) : 'Never' }}</mat-cell
>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
</mat-table>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
</mat-table>
}
@@ -4,13 +4,23 @@ import { MatIconModule } from '@angular/material/icon';
import { MatTableModule } from '@angular/material/table';
import { RouterLink } from '@angular/router';
import { ErrorStateComponent } from '../../shared/error-state/error-state.component';
import { LocalTimePipe } from '../../shared/local-time.pipe';
import { SkeletonLoaderComponent } from '../../shared/skeleton-loader/skeleton-loader.component';
import { UserService } from '../user.service';
@Component({
selector: 'app-user-list',
templateUrl: './user-list.component.html',
styleUrls: ['./user-list.component.css'],
imports: [LocalTimePipe, MatButtonModule, MatIconModule, MatTableModule, RouterLink],
imports: [
LocalTimePipe,
MatButtonModule,
MatIconModule,
MatTableModule,
RouterLink,
ErrorStateComponent,
SkeletonLoaderComponent,
],
})
export class UserListComponent {
private userService = inject(UserService);