diff --git a/src/app/pages/main/editor-sidebar/editor-sidebar.ts b/src/app/pages/main/editor-sidebar/editor-sidebar.ts index f8589ed..86571e8 100644 --- a/src/app/pages/main/editor-sidebar/editor-sidebar.ts +++ b/src/app/pages/main/editor-sidebar/editor-sidebar.ts @@ -4,6 +4,7 @@ import { FlowsList } from '@shared/flows-list/flows-list'; import { EditorStateHolder } from '@stores/flow-editor'; import { CommonModule } from '@angular/common'; import { FlowsService } from '@services/flows/flows'; +import { ListState } from '@stores/list-state'; type OpenedId = 'flows' | 'blocks'; @@ -12,6 +13,7 @@ type OpenedId = 'flows' | 'blocks'; imports: [GroupHolder, FlowsList, CommonModule], templateUrl: './editor-sidebar.html', styleUrl: './editor-sidebar.css', + providers:[ListState] }) export class EditorSidebar { diff --git a/src/app/shared/flows-list/flows-list.html b/src/app/shared/flows-list/flows-list.html index 67d4522..21fc799 100644 --- a/src/app/shared/flows-list/flows-list.html +++ b/src/app/shared/flows-list/flows-list.html @@ -41,7 +41,7 @@
- +
@if (filteredFlows().length === 0) {
diff --git a/src/app/shared/flows-list/flows-list.ts b/src/app/shared/flows-list/flows-list.ts index 6cb0c20..d61c553 100644 --- a/src/app/shared/flows-list/flows-list.ts +++ b/src/app/shared/flows-list/flows-list.ts @@ -1,10 +1,11 @@ import { CommonModule } from '@angular/common'; -import { Component, computed, inject, model, output, signal, Signal, WritableSignal } from '@angular/core'; +import { Component, computed, effect, inject, model, output, signal, Signal, WritableSignal } from '@angular/core'; import { Flow } from '@models/flow'; import { FlowsService } from '@services/flows/flows'; import { FlowItem } from './flow-item/flow-item'; import { FormsModule } from '@angular/forms'; import { OrderEvent, OrderField, Ordering } from "@shared/ordering/ordering"; +import { ListStateViewHolder, OrderViewState } from '@utilities/list-state-holder'; type FlowFilter = 'all' | 'public' | 'private'; @@ -14,42 +15,71 @@ type FlowFilter = 'all' | 'public' | 'private'; templateUrl: './flows-list.html', styleUrl: './flows-list.css', }) -export class FlowsList { +export class FlowsList extends ListStateViewHolder { filter = signal('all'); - orderFields : OrderField[] = [ + + orderFields: OrderField[] = [ { field: 'name', label: 'Name' }, { field: 'updatedAt', label: 'Last Update Date' }, { field: 'createdAt', label: 'Creation Date' } ]; searchTerm = model(''); - + private flowsService = inject(FlowsService); loading: WritableSignal = signal(true); - flows: Signal = signal(null); + + get orderView() { + const existingState = this.view; + return existingState.order; + } + + flows?: Signal; detailOpenedId = signal(null); - ngOnInit() { - this.flowsService.getAllFlows().then(flowsSignal => { - this.flows = flowsSignal; - this.loading.set(false); + 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'); + console.log('FlowsList loaded from ListState'); + } else { + this.flowsService.getAllFlows().then(flowsSignal => { + this.flows = flowsSignal; + this.loading.set(false); + this.view.list = this.flows; + console.log('FlowsList initialized from service'); + }); + } + + } + filteredFlows = computed(() => { - const flows = this.flows(); + 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; 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) => { @@ -58,7 +88,7 @@ export class FlowsList { if (aValue < bValue) return orderDir === 'asc' ? -1 : 1; if (aValue > bValue) return orderDir === 'asc' ? 1 : -1; return 0; - }); + }); } - + } diff --git a/src/app/shared/ordering/ordering.ts b/src/app/shared/ordering/ordering.ts index 485dcf6..0a0d081 100644 --- a/src/app/shared/ordering/ordering.ts +++ b/src/app/shared/ordering/ordering.ts @@ -1,6 +1,6 @@ -import { Component, effect, input, model, output } from '@angular/core'; +import { Component, effect, Input, input, model, output } from '@angular/core'; import { FormsModule } from '@angular/forms'; - +import { OrderViewState } from '@utilities/list-state-holder'; export type OrderEvent = { orderBy: string | null; orderDir: orderDirType }; export type orderDirType = 'asc' | 'desc'; @@ -15,6 +15,8 @@ export type OrderField = { field: string; label?: string }; }) export class Ordering { + @Input({required : true}) orderView!: OrderViewState; + constructor() { effect(() => { this.orderChanged.emit({ orderBy: this.orderBy(), orderDir: this.orderDir() }); @@ -27,6 +29,13 @@ export class Ordering { orderBy = model(null); + ngOnInit() { + if (this.orderView.orderBy) { + this.orderBy.set(this.orderView.orderBy); + this.orderDir.set(this.orderView.orderDir); + } + } + orderChanged = output(); } diff --git a/src/app/stores/list-state.spec.ts b/src/app/stores/list-state.spec.ts new file mode 100644 index 0000000..63e7e93 --- /dev/null +++ b/src/app/stores/list-state.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ListState } from './list-state'; + +describe('ListState', () => { + let service: ListState; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ListState); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/stores/list-state.ts b/src/app/stores/list-state.ts new file mode 100644 index 0000000..9c0abdc --- /dev/null +++ b/src/app/stores/list-state.ts @@ -0,0 +1,34 @@ +import { Injectable, Signal, signal } from '@angular/core'; +import { ListView, OrderViewState } from '@utilities/list-state-holder'; + + + +@Injectable() +export class ListState { + + private states = new Map>(); + + get(kind?: string): ListView | null { + if (!this.states.has(kind || 'default')) { + return null; + } + return this.states.get(kind || 'default')!; + } + + create(kind?: string, options?: {defaultOrder?: OrderViewState, defaultFilter?: string}) { + if (!this.states.has(kind || 'default')) { + const view = new ListView(); + if (options) { + if (options.defaultOrder) { + view.order = options.defaultOrder; + } + if (options.defaultFilter) { + view.filter = options.defaultFilter; + } + } + this.states.set(kind || 'default', view); + } + } + + +} diff --git a/src/app/utilities/list-state-holder.ts b/src/app/utilities/list-state-holder.ts new file mode 100644 index 0000000..b4d9c72 --- /dev/null +++ b/src/app/utilities/list-state-holder.ts @@ -0,0 +1,38 @@ +import { inject, signal, Signal } from "@angular/core"; +import { ListState } from "@stores/list-state"; + +export class OrderViewState { + orderBy: string | null = null; + orderDir: 'asc' | 'desc' = 'asc'; +} + +export class ListView { + filter?: string; + list?: Signal; + order: OrderViewState = new OrderViewState(); +} + +export class ListStateViewHolder { + + private state: ListView = new ListView(); + + listName?: string; + + constructor(listName?: string, options?: {defaultOrder?: OrderViewState, defaultFilter?: string}) { + this.listName = listName; + const listState = inject(ListState); + if (listState.get(this.listName) == null) { + listState.create(this.listName, options); + } + this.state = listState.get(this.listName)!; + } + + get view(): ListView { + return this.state; + } + + create() { + this.state = new ListView(); + } + +} \ No newline at end of file