Compare commits

...

2 commits

Author SHA1 Message Date
Joe Arndt
dbb4c1ed38 support for editing category 2026-02-26 11:35:18 -06:00
Joe Arndt
5c48a6f4e7 added metadata form validation 2026-02-26 11:22:09 -06:00
5 changed files with 75 additions and 11 deletions

View file

@ -18,6 +18,7 @@ export class CategoriesComponent {
public constructor(private readonly categoryService: CategoryService) { } public constructor(private readonly categoryService: CategoryService) { }
public async updateCategory(category: Category): Promise<void> { public async updateCategory(category: Category): Promise<void> {
console.log('updated category', category); // TODO: Remove await this.categoryService.updateCategory(category);
await this.categoryService.fetchCategories();
} }
} }

View file

@ -1,7 +1,25 @@
<div class="metadata-form-container"> <div class="metadata-form-container">
<div>{{ metadata().name }}</div> @if (!editing()) {
<div>{{ metadata().name }}</div>
<button matIconButton> <button matIconButton (click)="editing.set(true)">
<mat-icon>edit</mat-icon> <mat-icon>edit</mat-icon>
</button> </button>
} @else {
<div class="metadata-edit">
<mat-form-field appearance="outline">
<input type="text" matInput [(ngModel)]="name">
</mat-form-field>
<div class="metadata-edit-buttons">
<button matIconButton (click)="reset()">
<mat-icon>undo</mat-icon>
</button>
<button matIconButton (click)="saveMetaData()" [disabled]="!nameValid()">
<mat-icon>save</mat-icon>
</button>
</div>
</div>
}
</div> </div>

View file

@ -3,3 +3,14 @@
gap: 0.5rem; gap: 0.5rem;
align-items: center; align-items: center;
} }
.metadata-edit {
display: flex;
gap: 0.5rem;
.metadata-edit-buttons {
padding-top: 0.5rem;
display: flex;
gap: 0.5rem;
}
}

View file

@ -1,7 +1,8 @@
import {Component, input, output, signal} from '@angular/core'; import { Component, computed, input, model, OnInit, output, signal } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatFormField, MatInput } from '@angular/material/input';
import { FormsModule } from '@angular/forms';
interface MetaData { interface MetaData {
id: string; id: string;
@ -11,17 +12,42 @@ interface MetaData {
@Component({ @Component({
selector: 'app-metadata-form', selector: 'app-metadata-form',
imports: [ imports: [
MatCardModule,
MatIconModule, MatIconModule,
MatButtonModule MatButtonModule,
MatFormField,
MatInput,
FormsModule
], ],
templateUrl: './metadata-form.component.html', templateUrl: './metadata-form.component.html',
styleUrl: './metadata-form.component.scss' styleUrl: './metadata-form.component.scss'
}) })
export class MetadataFormComponent { export class MetadataFormComponent implements OnInit {
public metadata = input.required<MetaData>(); public metadata = input.required<MetaData>();
public newMetaData = output<MetaData>(); public newMetaData = output<MetaData>();
public name = model('');
public nameValid = computed(() => {
const existingName = this.metadata().name;
const newName = this.name();
return !!newName && newName !== existingName;
});
public editing = signal(false); public editing = signal(false);
public ngOnInit(): void {
this.reset();
}
public saveMetaData(): void {
this.editing.set(false);
this.newMetaData.emit({
...this.metadata(),
name: this.name()
});
}
public reset(): void {
this.editing.set(false);
this.name.set(this.metadata().name);
}
} }

View file

@ -16,9 +16,17 @@ export class CategoryService {
public async fetchCategories(): Promise<void> { public async fetchCategories(): Promise<void> {
this.internalCategories.set(await this.http.get<Category[]>(this.categoryPath)); this.internalCategories.set(await this.http.get<Category[]>(this.categoryPath));
} }
public async updateCategory(category: Category): Promise<Category> {
return await this.http.put<Category>(this.categoryPath, category);
}
} }
export interface Category { export interface Category {
id: string; id: string;
name: string; name: string;
} }
export interface CreateCategory {
name: string;
}