humainflow-web/src/app/shared/flows-list/flows-list.ts

108 lines
3.7 KiB
TypeScript

import { Component, computed, effect, inject, model, signal, Signal, WritableSignal } from '@angular/core';
import { Flow, FlowVisibility } from '@models/flow';
import { FlowsService } from '@services/flows/flows';
import { FlowItem } from './flow-item/flow-item';
import { FormsModule } from '@angular/forms';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatCardModule } from '@angular/material/card';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatListModule } from '@angular/material/list';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { OrderEvent, OrderField, Ordering } from "@shared/ordering/ordering";
import { ListStateViewHolder, OrderViewState } from '@utilities/list-state-holder';
type FlowFilter = FlowVisibility | 'FINALIZED' | 'all';
@Component({
selector: 'app-flows-list',
imports: [FlowItem, FormsModule, Ordering, MatButtonToggleModule, MatCardModule, MatFormFieldModule, MatIconModule, MatInputModule, MatListModule, MatProgressSpinnerModule],
templateUrl: './flows-list.html',
styleUrl: './flows-list.css',
})
export class FlowsList extends ListStateViewHolder<Flow> {
filter = signal<FlowFilter>('all');
orderFields: OrderField[] = [
{ field: 'name', label: 'Name' },
{ field: 'updatedAt', label: 'Last Update Date' },
{ field: 'createdAt', label: 'Creation Date' }
];
searchTerm = model<string>('');
private flowsService = inject(FlowsService);
loading: WritableSignal<boolean> = signal(true);
get orderView() {
const existingState = this.view;
return existingState.order;
}
flows?: Signal<Flow[]>;
detailOpenedId = signal<string | null>(null);
constructor() {
super('flowsList', {defaultOrder: { orderBy: 'name', orderDir: 'asc' } as OrderViewState, defaultFilter: 'all'});
effect(() => {
if (!!this.filter && this.filter() != null)
this.view.filter = this.filter();
});
}
ngOnInit() {
const existingState = this.view;
if (existingState.list) {
this.flows = existingState.list;
this.loading.set(false);
if (existingState.filter)
this.filter.set(existingState.filter as FlowFilter || 'all');
return;
}
if (this.flowsService.hasLoadedFlows()) {
this.flows = this.flowsService.flows;
this.view.list = this.flows;
this.loading.set(false);
return;
}
this.flowsService.getAllFlows().then(flowsSignal => {
this.flows = flowsSignal;
this.view.list = this.flows;
}).catch((err) => {
console.error('Error loading flows', err);
}).finally(() => {
this.loading.set(false);
});
}
filteredFlows = computed(() => {
const flows = this.flows ? this.flows() : [];
if (!flows) return [];
const filteredFlows = flows.filter(f => f.name.toLowerCase().includes(this.searchTerm().toLowerCase()));
if (this.filter() === 'all') return filteredFlows;
if (this.filter() === 'FINALIZED') return filteredFlows.filter(f => !!f.finalized);
return filteredFlows.filter(f => f.visibility === this.filter());
});
onOrderChanged(event: OrderEvent) {
const { orderBy, orderDir } = event;
this.view.order = { orderBy, orderDir };
const flows = this.filteredFlows();
if (!orderBy) return flows;
return flows.sort((a, b) => {
const aValue = (a as any)[orderBy];
const bValue = (b as any)[orderBy];
if (aValue < bValue) return orderDir === 'asc' ? -1 : 1;
if (aValue > bValue) return orderDir === 'asc' ? 1 : -1;
return 0;
});
}
}