@mysteryinfosolutions/api-core 1.6.2 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Component } from '@angular/core';
|
|
3
|
-
import { BehaviorSubject } from 'rxjs';
|
|
3
|
+
import { BehaviorSubject, map } from 'rxjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* BaseResourceConfig<T>
|
|
@@ -53,6 +53,12 @@ class BaseResourceConfig {
|
|
|
53
53
|
* Modal configuration: fullscreen setting for summary modal.
|
|
54
54
|
*/
|
|
55
55
|
summaryModalFullscreen = false;
|
|
56
|
+
/**
|
|
57
|
+
* Determines the default view when viewing details of a record.
|
|
58
|
+
* 'overview' = navigates to a new page
|
|
59
|
+
* 'summary' = opens a modal with summary component
|
|
60
|
+
*/
|
|
61
|
+
defaultDetailView = 'summary';
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
class ApiCore {
|
|
@@ -136,7 +142,7 @@ class BaseStateService {
|
|
|
136
142
|
recordsSubject = new BehaviorSubject([]);
|
|
137
143
|
pagerSubject = new BehaviorSubject(null);
|
|
138
144
|
selectedSubject = new BehaviorSubject(null);
|
|
139
|
-
|
|
145
|
+
loadingMapSubject = new BehaviorSubject({});
|
|
140
146
|
savingSubject = new BehaviorSubject(false);
|
|
141
147
|
errorSubject = new BehaviorSubject(null);
|
|
142
148
|
/** Observable stream of current filter. */
|
|
@@ -148,7 +154,7 @@ class BaseStateService {
|
|
|
148
154
|
/** Observable stream of the currently selected record. */
|
|
149
155
|
selected$ = this.selectedSubject.asObservable();
|
|
150
156
|
/** Observable stream of loading state. */
|
|
151
|
-
loading$ = this.
|
|
157
|
+
loading$ = this.loadingMapSubject.asObservable();
|
|
152
158
|
/** Observable stream of saving state. */
|
|
153
159
|
saving$ = this.savingSubject.asObservable();
|
|
154
160
|
/** Observable stream of current error message. */
|
|
@@ -246,11 +252,25 @@ class BaseStateService {
|
|
|
246
252
|
});
|
|
247
253
|
}
|
|
248
254
|
/**
|
|
249
|
-
*
|
|
250
|
-
*
|
|
255
|
+
* Returns an observable boolean for a specific loading key.
|
|
256
|
+
* Useful for tracking loading state in a specific view or feature.
|
|
257
|
+
*
|
|
258
|
+
* @param key A unique key representing the loading context (e.g., "list", "detail")
|
|
259
|
+
* @returns Observable emitting `true` if the given context is loading, `false` otherwise.
|
|
260
|
+
*/
|
|
261
|
+
isLoading$(key) {
|
|
262
|
+
return this.loading$.pipe(map(state => !!state[key]));
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Sets the loading state for a specific key.
|
|
266
|
+
* This allows you to control multiple concurrent loading states independently.
|
|
267
|
+
*
|
|
268
|
+
* @param key The loading context name (e.g., "list", "form", "detail")
|
|
269
|
+
* @param value The loading status (`true` for loading, `false` for done)
|
|
251
270
|
*/
|
|
252
|
-
setLoading(
|
|
253
|
-
this.
|
|
271
|
+
setLoading(key, value) {
|
|
272
|
+
const current = this.loadingMapSubject.value;
|
|
273
|
+
this.loadingMapSubject.next({ ...current, [key]: value });
|
|
254
274
|
}
|
|
255
275
|
/**
|
|
256
276
|
* Sets the saving flag.
|
|
@@ -277,13 +297,27 @@ class BaseStateService {
|
|
|
277
297
|
clearSelection() {
|
|
278
298
|
this.selectedSubject.next(null);
|
|
279
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Clears the loading state for a specific key or all keys if none is provided.
|
|
302
|
+
*
|
|
303
|
+
* @param key Optional. If provided, only that loading key is cleared. If omitted, all are cleared.
|
|
304
|
+
*/
|
|
305
|
+
clearLoading(key) {
|
|
306
|
+
if (key) {
|
|
307
|
+
const { [key]: _, ...rest } = this.loadingMapSubject.value;
|
|
308
|
+
this.loadingMapSubject.next(rest);
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
this.loadingMapSubject.next({});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
280
314
|
/** Resets the entire state to initial values. */
|
|
281
315
|
reset() {
|
|
282
316
|
this.recordsSubject.next([]);
|
|
283
317
|
this.pagerSubject.next(null);
|
|
284
318
|
this.selectedSubject.next(null);
|
|
285
319
|
this.setFilter({ page: 1, pageLength: 10 });
|
|
286
|
-
this.
|
|
320
|
+
this.clearLoading();
|
|
287
321
|
this.setSaving(false);
|
|
288
322
|
this.setError(null);
|
|
289
323
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysteryinfosolutions-api-core.mjs","sources":["../../../projects/api-core/src/lib/configs/base-resource-config.ts","../../../projects/api-core/src/lib/api-core.ts","../../../projects/api-core/src/lib/enums/selectmodes.enum.ts","../../../projects/api-core/src/lib/utils/query-utils.ts","../../../projects/api-core/src/lib/models/filter.model.ts","../../../projects/api-core/src/lib/models/sort.model.ts","../../../projects/api-core/src/lib/services/base-state.service.ts","../../../projects/api-core/src/lib/services/base.service.ts","../../../projects/api-core/src/public-api.ts","../../../projects/api-core/src/mysteryinfosolutions-api-core.ts"],"sourcesContent":["// base-resource-config.ts\nimport { TableColumn } from \"../models\";\n\n/**\n * BaseResourceConfig<T>\n *\n * A generic configuration class to standardize table-based resource UIs.\n * Extend this in feature modules (e.g., Users, Roles, Genders) to reuse core settings.\n */\nexport abstract class BaseResourceConfig<T> {\n /**\n * Table columns definition for the resource.\n */\n columns: TableColumn<T>[] = [];\n\n /**\n * The column used for date-range filtering (e.g., in filters or reporting).\n */\n dateRangeColumn: keyof T | string = 'updated_at';\n\n /**\n * Default column used to sort the table data.\n */\n defaultSortColumn: keyof T | string = 'updated_at';\n\n /**\n * Default sorting order (ASC or DESC).\n */\n defaultSortOrder: 'ASC' | 'DESC' = 'DESC';\n\n /**\n * Page size options for the table paginator.\n */\n pageLengthOptions: number[] = [10, 25, 50, 100];\n\n /**\n * Default page size.\n */\n defaultPageLength: number = 10;\n\n /**\n * Keys (fields) to apply search filter on.\n */\n searchColumns: (keyof T | string)[] = [];\n\n /**\n * Modal configuration: size for the create/update (modify) modal.\n */\n modifyModalSize: 'sm' | 'md' | 'lg' | 'xl' | string = 'md';\n\n /**\n * Modal configuration: fullscreen setting for modify modal.\n */\n modifyModalFullscreen: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | boolean | string = false;\n\n /**\n * Modal configuration: size for the view/summary modal.\n */\n summaryModalSize: 'sm' | 'lg' | 'xl' | string = 'md';\n\n /**\n * Modal configuration: fullscreen setting for summary modal.\n */\n summaryModalFullscreen: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | boolean | string = false;\n}\n","import { Component } from '@angular/core';\n\n@Component({\n selector: 'lib-api-core',\n imports: [],\n template: `\n <p>\n api-core works!\n </p>\n `,\n styles: ``\n})\nexport class ApiCore {\n\n}\n","export enum SELECT_MODE {\n ALL = 1,\n ONLYCOLUMNS = 2,\n};\n","import { SortItem } from '../models';\n\nexport const sortObjectToString = (sortItems: SortItem[]): string => {\n if (!Array.isArray(sortItems) || sortItems.length === 0) return '';\n return sortItems.map(s => `${s.field}:${s.order}`).join(',');\n};\n\nexport const jsonToQueryString = (json: any): string => {\n if (!json || typeof json !== 'object') return '';\n\n if (json.hasOwnProperty('sort')) {\n json.sort = sortObjectToString(json.sort);\n }\n\n const queryArray = Object.keys(json)\n .filter(key => json[key] !== undefined && json[key] !== null)\n .map(key => {\n if (Array.isArray(json[key])) {\n return `${encodeURIComponent(key)}=${encodeURIComponent('[' + json[key].toString() + ']')}`;\n } else {\n return `${encodeURIComponent(key)}=${encodeURIComponent(json[key])}`;\n }\n });\n\n return queryArray.length > 0 ? `?${queryArray.join('&')}` : '';\n};\n\nexport const isEmpty = (obj: any): boolean => {\n return !obj || Object.keys(obj).length === 0;\n};\n","import { SortItem } from './';\nimport { SELECT_MODE } from '../enums';\n\nexport abstract class Filter {\n dateRangeColumn?: string;\n dateRangeFrom?: string;\n dateRangeTo?: string;\n\n page?: number = 1;\n pageLength?: number = 10;\n\n sort?: SortItem[] = [];\n\n search?: string;\n searchColumns?: string;\n selectColumns?: string;\n selectMode?: SELECT_MODE;\n}","export class SortItem {\n constructor(\n public field: string,\n public order: 'ASC' | 'DESC'\n ) {}\n}\n\n","import { BehaviorSubject } from \"rxjs\";\nimport { Filter, IMultiresult, IMultiresultMetaData, SortItem } from \"../models\";\n\n/**\n * A generic state management service for handling filters, pagination, and records.\n */\nexport class BaseStateService<\n TRecord,\n TFilter extends Partial<TRecord> & Filter = Partial<TRecord> & Filter\n> {\n private readonly filterSubject = new BehaviorSubject<TFilter>({ page: 1, pageLength: 10 } as TFilter);\n private readonly recordsSubject = new BehaviorSubject<TRecord[]>([]);\n private readonly pagerSubject = new BehaviorSubject<IMultiresultMetaData | null>(null);\n private readonly selectedSubject = new BehaviorSubject<TRecord | null>(null);\n private readonly loadingSubject = new BehaviorSubject<boolean>(false);\n private readonly savingSubject = new BehaviorSubject<boolean>(false);\n private readonly errorSubject = new BehaviorSubject<string | null>(null);\n\n /** Observable stream of current filter. */\n filter$ = this.filterSubject.asObservable();\n\n /** Observable stream of current records. */\n records$ = this.recordsSubject.asObservable();\n\n /** Observable stream of current pager metadata. */\n pager$ = this.pagerSubject.asObservable();\n\n /** Observable stream of the currently selected record. */\n selected$ = this.selectedSubject.asObservable();\n\n /** Observable stream of loading state. */\n loading$ = this.loadingSubject.asObservable();\n\n /** Observable stream of saving state. */\n saving$ = this.savingSubject.asObservable();\n\n /** Observable stream of current error message. */\n error$ = this.errorSubject.asObservable();\n\n /** Returns the current filter. */\n get currentFilter(): TFilter {\n return this.filterSubject.value;\n }\n\n /** Returns the currently loaded records. */\n get currentRecords(): TRecord[] {\n return this.recordsSubject.value;\n }\n\n /** Returns the currently selected record, if any. */\n get selected(): TRecord | null {\n return this.selectedSubject.value;\n }\n\n /**\n * Updates the current filter with new values.\n * @param update Partial filter to merge.\n */\n setFilter(update: Partial<TFilter>) {\n const current = this.filterSubject.value;\n this.filterSubject.next({ ...current, ...update });\n }\n\n /**\n * Replaces all records in the current state.\n * @param records Array of new records.\n */\n setRecords(records: TRecord[]) {\n this.recordsSubject.next(records);\n }\n\n /**\n * Appends records to the current record list.\n * @param records Records to add.\n */\n appendRecords(records: TRecord[]) {\n this.recordsSubject.next([...this.currentRecords, ...records]);\n }\n\n /**\n * Sets the pagination metadata.\n * @param pager Metadata to use.\n */\n setPager(pager: IMultiresultMetaData) {\n this.pagerSubject.next(pager);\n }\n\n /**\n * Sets records and pager data from API response.\n * @param response API response containing records and pager.\n */\n setApiResponse(response: IMultiresult<TRecord>) {\n this.setRecords(response.records);\n this.setPager(response.pager);\n }\n\n /**\n * Updates the sort order in the current filter.\n * Toggles order if column already exists, or adds it otherwise.\n * @param column Column name to sort by.\n */\n setSort(column: string, sort: \"ASC\" | \"DESC\" = \"ASC\") {\n const current = this.filterSubject.value;\n\n let sortItems = [...(current.sort ?? [])];\n\n const index = sortItems.findIndex(item => item.field === column);\n\n if (index !== -1) {\n const currentOrder = sortItems[index].order;\n sortItems[index] = new SortItem(\n sortItems[index].field,\n currentOrder === 'ASC' ? 'DESC' : 'ASC'\n );\n } else {\n sortItems.push(new SortItem(column, sort));\n }\n\n this.filterSubject.next({\n ...current,\n sort: sortItems\n });\n }\n\n /**\n * Removes a specific column from the current sort.\n * @param column Column name to remove from sorting.\n */\n removeSort(column: string) {\n const current = this.filterSubject.value;\n const sortItems = [...(current.sort ?? [])].filter(item => item.field !== column);\n\n this.filterSubject.next({\n ...current,\n sort: sortItems\n });\n }\n\n /**\n * Clears all sorting from the current filter.\n */\n clearSort() {\n const current = this.filterSubject.value;\n\n this.filterSubject.next({\n ...current,\n sort: []\n });\n }\n\n /**\n * Sets the loading flag.\n * @param loading Whether loading is active.\n */\n setLoading(loading: boolean) {\n this.loadingSubject.next(loading);\n }\n\n /**\n * Sets the saving flag.\n * @param saving Whether a save operation is in progress.\n */\n setSaving(saving: boolean) {\n this.savingSubject.next(saving);\n }\n\n /**\n * Sets the error state.\n * @param error Error message or null.\n */\n setError(error: string | null) {\n this.errorSubject.next(error);\n }\n\n /**\n * Selects a record.\n * @param record The record to select.\n */\n select(record: TRecord) {\n this.selectedSubject.next(record);\n }\n\n /** Clears the current selection. */\n clearSelection() {\n this.selectedSubject.next(null);\n }\n\n /** Resets the entire state to initial values. */\n reset() {\n this.recordsSubject.next([]);\n this.pagerSubject.next(null);\n this.selectedSubject.next(null);\n this.setFilter({ page: 1, pageLength: 10 } as Partial<TFilter>);\n this.setLoading(false);\n this.setSaving(false);\n this.setError(null);\n }\n\n /**\n * Removes a record by its ID field.\n * @param id The ID to remove.\n * @param idKey The record property key used as ID (default: 'id').\n */\n removeRecordById(id: number | string, idKey: keyof TRecord = 'id' as keyof TRecord) {\n this.recordsSubject.next(this.currentRecords.filter(r => r[idKey] !== id));\n }\n\n /**\n * Replaces a record by matching its ID field.\n * @param updated The updated record.\n * @param idKey The record property key used as ID (default: 'id').\n */\n replaceRecord(updated: TRecord, idKey: keyof TRecord = 'id' as keyof TRecord) {\n this.recordsSubject.next(\n this.currentRecords.map(r => r[idKey] === updated[idKey] ? updated : r)\n );\n }\n\n /**\n * Checks if a specific record is currently selected.\n * @param record Record to check.\n * @param idKey Key to use for comparison (default: 'id').\n */\n isSelected(record: TRecord, idKey: keyof TRecord = 'id' as keyof TRecord): boolean {\n const selected = this.selectedSubject.value;\n return selected ? selected[idKey] === record[idKey] : false;\n }\n\n /**\n * Updates the current page number in the filter.\n * @param page Page number.\n */\n setPage(page: number) {\n this.setFilter({ page } as Partial<TFilter>);\n }\n\n /**\n * Updates the page length in the filter.\n * @param pageLength Number of records per page.\n */\n setPageLength(pageLength: number) {\n this.setFilter({ pageLength } as Partial<TFilter>);\n }\n\n /**\n * Resets the filter to default values.\n * @param defaults Default filter values.\n */\n resetFilter(defaults: Partial<TFilter> = { page: 1, pageLength: 10 } as Partial<TFilter>) {\n this.filterSubject.next(defaults as TFilter);\n }\n\n /** Returns true if there are more pages after the current one. */\n hasMorePages(): boolean {\n const pager = this.pagerSubject.value;\n return !!pager && pager.currentPage! < pager.lastPage!;\n }\n\n /** Returns true if a previous page exists. */\n hasPreviousPage(): boolean {\n const pager = this.pagerSubject.value;\n return !!pager && pager.currentPage! > 0;\n }\n\n /** Resets and clears all managed state. */\n destroy() {\n this.reset();\n }\n}\n","import { HttpClient } from '@angular/common/http';\nimport { Observable } from 'rxjs';\nimport { jsonToQueryString, isEmpty } from '../utils/query-utils';\nimport { IMultiresult, IResponse, Filter } from '../models';\n\nexport abstract class BaseService<\n T, // Full model type\n TFilter extends Partial<T> & Filter = Partial<T> & Filter, // Filter: model fields + pagination/sorting\n TCreate = Partial<T>, // DTO for create\n TUpdate = Partial<T> // DTO for update\n> {\n constructor(\n protected http: HttpClient,\n protected baseUrl: string\n ) { }\n\n getAll(filter: TFilter = {} as TFilter): Observable<IResponse<IMultiresult<T>>> {\n const clonedFilter = structuredClone(filter);\n const query = !isEmpty(filter) ? jsonToQueryString(clonedFilter) : '';\n return this.http.get<IResponse<IMultiresult<T>>>(`${this.baseUrl}${query}`);\n }\n\n getDetails(id: number): Observable<IResponse<T>> {\n return this.http.get<IResponse<T>>(`${this.baseUrl}/${id}`);\n }\n\n create(data: TCreate): Observable<IResponse<T>> {\n return this.http.post<IResponse<T>>(this.baseUrl, data);\n }\n\n update(id: number, data: TUpdate): Observable<IResponse<T>> {\n return this.http.put<IResponse<T>>(`${this.baseUrl}/${id}`, data);\n }\n\n delete(id: number, method: 'soft' | 'hard' = 'soft'): Observable<any> {\n const methodQuery = `?method=${method}`;\n if (method === 'soft') {\n return this.http.delete(`${this.baseUrl}/${id}${methodQuery}`, {});\n }\n return this.http.delete(`${this.baseUrl}/${id}${methodQuery}`);\n }\n}\n","/*\n * Public API Surface of api-core\n */\n\nexport * from './lib/configs';\nexport * from './lib/api-core';\nexport * from './lib/enums';\nexport * from './lib/utils';\nexport * from './lib/models';\nexport * from './lib/services';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mysteryinfosolutions-api-core.mjs","sources":["../../../projects/api-core/src/lib/configs/base-resource-config.ts","../../../projects/api-core/src/lib/api-core.ts","../../../projects/api-core/src/lib/enums/selectmodes.enum.ts","../../../projects/api-core/src/lib/utils/query-utils.ts","../../../projects/api-core/src/lib/models/filter.model.ts","../../../projects/api-core/src/lib/models/sort.model.ts","../../../projects/api-core/src/lib/services/base-state.service.ts","../../../projects/api-core/src/lib/services/base.service.ts","../../../projects/api-core/src/public-api.ts","../../../projects/api-core/src/mysteryinfosolutions-api-core.ts"],"sourcesContent":["// base-resource-config.ts\nimport { TableColumn } from \"../models\";\n\n/**\n * BaseResourceConfig<T>\n *\n * A generic configuration class to standardize table-based resource UIs.\n * Extend this in feature modules (e.g., Users, Roles, Genders) to reuse core settings.\n */\nexport abstract class BaseResourceConfig<T> {\n /**\n * Table columns definition for the resource.\n */\n columns: TableColumn<T>[] = [];\n\n /**\n * The column used for date-range filtering (e.g., in filters or reporting).\n */\n dateRangeColumn: keyof T | string = 'updated_at';\n\n /**\n * Default column used to sort the table data.\n */\n defaultSortColumn: keyof T | string = 'updated_at';\n\n /**\n * Default sorting order (ASC or DESC).\n */\n defaultSortOrder: 'ASC' | 'DESC' = 'DESC';\n\n /**\n * Page size options for the table paginator.\n */\n pageLengthOptions: number[] = [10, 25, 50, 100];\n\n /**\n * Default page size.\n */\n defaultPageLength: number = 10;\n\n /**\n * Keys (fields) to apply search filter on.\n */\n searchColumns: (keyof T | string)[] = [];\n\n /**\n * Modal configuration: size for the create/update (modify) modal.\n */\n modifyModalSize: 'sm' | 'md' | 'lg' | 'xl' | string = 'md';\n\n /**\n * Modal configuration: fullscreen setting for modify modal.\n */\n modifyModalFullscreen: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | boolean | string = false;\n\n /**\n * Modal configuration: size for the view/summary modal.\n */\n summaryModalSize: 'sm' | 'lg' | 'xl' | string = 'md';\n\n /**\n * Modal configuration: fullscreen setting for summary modal.\n */\n summaryModalFullscreen: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | boolean | string = false;\n\n /**\n * Determines the default view when viewing details of a record.\n * 'overview' = navigates to a new page\n * 'summary' = opens a modal with summary component\n */\n defaultDetailView: 'overview' | 'summary' = 'summary';\n}\n","import { Component } from '@angular/core';\n\n@Component({\n selector: 'lib-api-core',\n imports: [],\n template: `\n <p>\n api-core works!\n </p>\n `,\n styles: ``\n})\nexport class ApiCore {\n\n}\n","export enum SELECT_MODE {\n ALL = 1,\n ONLYCOLUMNS = 2,\n};\n","import { SortItem } from '../models';\n\nexport const sortObjectToString = (sortItems: SortItem[]): string => {\n if (!Array.isArray(sortItems) || sortItems.length === 0) return '';\n return sortItems.map(s => `${s.field}:${s.order}`).join(',');\n};\n\nexport const jsonToQueryString = (json: any): string => {\n if (!json || typeof json !== 'object') return '';\n\n if (json.hasOwnProperty('sort')) {\n json.sort = sortObjectToString(json.sort);\n }\n\n const queryArray = Object.keys(json)\n .filter(key => json[key] !== undefined && json[key] !== null)\n .map(key => {\n if (Array.isArray(json[key])) {\n return `${encodeURIComponent(key)}=${encodeURIComponent('[' + json[key].toString() + ']')}`;\n } else {\n return `${encodeURIComponent(key)}=${encodeURIComponent(json[key])}`;\n }\n });\n\n return queryArray.length > 0 ? `?${queryArray.join('&')}` : '';\n};\n\nexport const isEmpty = (obj: any): boolean => {\n return !obj || Object.keys(obj).length === 0;\n};\n","import { SortItem } from './';\nimport { SELECT_MODE } from '../enums';\n\nexport abstract class Filter {\n dateRangeColumn?: string;\n dateRangeFrom?: string;\n dateRangeTo?: string;\n\n page?: number = 1;\n pageLength?: number = 10;\n\n sort?: SortItem[] = [];\n\n search?: string;\n searchColumns?: string;\n selectColumns?: string;\n selectMode?: SELECT_MODE;\n}","export class SortItem {\n constructor(\n public field: string,\n public order: 'ASC' | 'DESC'\n ) {}\n}\n\n","import { BehaviorSubject, map, Observable } from \"rxjs\";\nimport { Filter, IMultiresult, IMultiresultMetaData, SortItem } from \"../models\";\n\n/**\n * A generic state management service for handling filters, pagination, and records.\n */\nexport class BaseStateService<\n TRecord,\n TFilter extends Partial<TRecord> & Filter = Partial<TRecord> & Filter\n> {\n private readonly filterSubject = new BehaviorSubject<TFilter>({ page: 1, pageLength: 10 } as TFilter);\n private readonly recordsSubject = new BehaviorSubject<TRecord[]>([]);\n private readonly pagerSubject = new BehaviorSubject<IMultiresultMetaData | null>(null);\n private readonly selectedSubject = new BehaviorSubject<TRecord | null>(null);\n private readonly loadingMapSubject = new BehaviorSubject<Record<string, boolean>>({});\n private readonly savingSubject = new BehaviorSubject<boolean>(false);\n private readonly errorSubject = new BehaviorSubject<string | null>(null);\n\n /** Observable stream of current filter. */\n filter$ = this.filterSubject.asObservable();\n\n /** Observable stream of current records. */\n records$ = this.recordsSubject.asObservable();\n\n /** Observable stream of current pager metadata. */\n pager$ = this.pagerSubject.asObservable();\n\n /** Observable stream of the currently selected record. */\n selected$ = this.selectedSubject.asObservable();\n\n /** Observable stream of loading state. */\n loading$ = this.loadingMapSubject.asObservable();\n\n /** Observable stream of saving state. */\n saving$ = this.savingSubject.asObservable();\n\n /** Observable stream of current error message. */\n error$ = this.errorSubject.asObservable();\n\n /** Returns the current filter. */\n get currentFilter(): TFilter {\n return this.filterSubject.value;\n }\n\n /** Returns the currently loaded records. */\n get currentRecords(): TRecord[] {\n return this.recordsSubject.value;\n }\n\n /** Returns the currently selected record, if any. */\n get selected(): TRecord | null {\n return this.selectedSubject.value;\n }\n\n /**\n * Updates the current filter with new values.\n * @param update Partial filter to merge.\n */\n setFilter(update: Partial<TFilter>) {\n const current = this.filterSubject.value;\n this.filterSubject.next({ ...current, ...update });\n }\n\n /**\n * Replaces all records in the current state.\n * @param records Array of new records.\n */\n setRecords(records: TRecord[]) {\n this.recordsSubject.next(records);\n }\n\n /**\n * Appends records to the current record list.\n * @param records Records to add.\n */\n appendRecords(records: TRecord[]) {\n this.recordsSubject.next([...this.currentRecords, ...records]);\n }\n\n /**\n * Sets the pagination metadata.\n * @param pager Metadata to use.\n */\n setPager(pager: IMultiresultMetaData) {\n this.pagerSubject.next(pager);\n }\n\n /**\n * Sets records and pager data from API response.\n * @param response API response containing records and pager.\n */\n setApiResponse(response: IMultiresult<TRecord>) {\n this.setRecords(response.records);\n this.setPager(response.pager);\n }\n\n /**\n * Updates the sort order in the current filter.\n * Toggles order if column already exists, or adds it otherwise.\n * @param column Column name to sort by.\n */\n setSort(column: string, sort: \"ASC\" | \"DESC\" = \"ASC\") {\n const current = this.filterSubject.value;\n\n let sortItems = [...(current.sort ?? [])];\n\n const index = sortItems.findIndex(item => item.field === column);\n\n if (index !== -1) {\n const currentOrder = sortItems[index].order;\n sortItems[index] = new SortItem(\n sortItems[index].field,\n currentOrder === 'ASC' ? 'DESC' : 'ASC'\n );\n } else {\n sortItems.push(new SortItem(column, sort));\n }\n\n this.filterSubject.next({\n ...current,\n sort: sortItems\n });\n }\n\n /**\n * Removes a specific column from the current sort.\n * @param column Column name to remove from sorting.\n */\n removeSort(column: string) {\n const current = this.filterSubject.value;\n const sortItems = [...(current.sort ?? [])].filter(item => item.field !== column);\n\n this.filterSubject.next({\n ...current,\n sort: sortItems\n });\n }\n\n /**\n * Clears all sorting from the current filter.\n */\n clearSort() {\n const current = this.filterSubject.value;\n\n this.filterSubject.next({\n ...current,\n sort: []\n });\n }\n\n /**\n * Returns an observable boolean for a specific loading key.\n * Useful for tracking loading state in a specific view or feature.\n *\n * @param key A unique key representing the loading context (e.g., \"list\", \"detail\")\n * @returns Observable emitting `true` if the given context is loading, `false` otherwise.\n */\n isLoading$(key: string): Observable<boolean> {\n return this.loading$.pipe(map(state => !!state[key]));\n }\n\n /**\n * Sets the loading state for a specific key.\n * This allows you to control multiple concurrent loading states independently.\n *\n * @param key The loading context name (e.g., \"list\", \"form\", \"detail\")\n * @param value The loading status (`true` for loading, `false` for done)\n */\n setLoading(key: string, value: boolean): void {\n const current = this.loadingMapSubject.value;\n this.loadingMapSubject.next({ ...current, [key]: value });\n }\n\n /**\n * Sets the saving flag.\n * @param saving Whether a save operation is in progress.\n */\n setSaving(saving: boolean) {\n this.savingSubject.next(saving);\n }\n\n /**\n * Sets the error state.\n * @param error Error message or null.\n */\n setError(error: string | null) {\n this.errorSubject.next(error);\n }\n\n /**\n * Selects a record.\n * @param record The record to select.\n */\n select(record: TRecord) {\n this.selectedSubject.next(record);\n }\n\n /** Clears the current selection. */\n clearSelection() {\n this.selectedSubject.next(null);\n }\n\n /**\n * Clears the loading state for a specific key or all keys if none is provided.\n *\n * @param key Optional. If provided, only that loading key is cleared. If omitted, all are cleared.\n */\n clearLoading(key?: string): void {\n if (key) {\n const { [key]: _, ...rest } = this.loadingMapSubject.value;\n this.loadingMapSubject.next(rest);\n } else {\n this.loadingMapSubject.next({});\n }\n }\n\n /** Resets the entire state to initial values. */\n reset() {\n this.recordsSubject.next([]);\n this.pagerSubject.next(null);\n this.selectedSubject.next(null);\n this.setFilter({ page: 1, pageLength: 10 } as Partial<TFilter>);\n this.clearLoading();\n this.setSaving(false);\n this.setError(null);\n }\n\n /**\n * Removes a record by its ID field.\n * @param id The ID to remove.\n * @param idKey The record property key used as ID (default: 'id').\n */\n removeRecordById(id: number | string, idKey: keyof TRecord = 'id' as keyof TRecord) {\n this.recordsSubject.next(this.currentRecords.filter(r => r[idKey] !== id));\n }\n\n /**\n * Replaces a record by matching its ID field.\n * @param updated The updated record.\n * @param idKey The record property key used as ID (default: 'id').\n */\n replaceRecord(updated: TRecord, idKey: keyof TRecord = 'id' as keyof TRecord) {\n this.recordsSubject.next(\n this.currentRecords.map(r => r[idKey] === updated[idKey] ? updated : r)\n );\n }\n\n /**\n * Checks if a specific record is currently selected.\n * @param record Record to check.\n * @param idKey Key to use for comparison (default: 'id').\n */\n isSelected(record: TRecord, idKey: keyof TRecord = 'id' as keyof TRecord): boolean {\n const selected = this.selectedSubject.value;\n return selected ? selected[idKey] === record[idKey] : false;\n }\n\n /**\n * Updates the current page number in the filter.\n * @param page Page number.\n */\n setPage(page: number) {\n this.setFilter({ page } as Partial<TFilter>);\n }\n\n /**\n * Updates the page length in the filter.\n * @param pageLength Number of records per page.\n */\n setPageLength(pageLength: number) {\n this.setFilter({ pageLength } as Partial<TFilter>);\n }\n\n /**\n * Resets the filter to default values.\n * @param defaults Default filter values.\n */\n resetFilter(defaults: Partial<TFilter> = { page: 1, pageLength: 10 } as Partial<TFilter>) {\n this.filterSubject.next(defaults as TFilter);\n }\n\n /** Returns true if there are more pages after the current one. */\n hasMorePages(): boolean {\n const pager = this.pagerSubject.value;\n return !!pager && pager.currentPage! < pager.lastPage!;\n }\n\n /** Returns true if a previous page exists. */\n hasPreviousPage(): boolean {\n const pager = this.pagerSubject.value;\n return !!pager && pager.currentPage! > 0;\n }\n\n /** Resets and clears all managed state. */\n destroy() {\n this.reset();\n }\n}\n","import { HttpClient } from '@angular/common/http';\nimport { Observable } from 'rxjs';\nimport { jsonToQueryString, isEmpty } from '../utils/query-utils';\nimport { IMultiresult, IResponse, Filter } from '../models';\n\nexport abstract class BaseService<\n T, // Full model type\n TFilter extends Partial<T> & Filter = Partial<T> & Filter, // Filter: model fields + pagination/sorting\n TCreate = Partial<T>, // DTO for create\n TUpdate = Partial<T> // DTO for update\n> {\n constructor(\n protected http: HttpClient,\n protected baseUrl: string\n ) { }\n\n getAll(filter: TFilter = {} as TFilter): Observable<IResponse<IMultiresult<T>>> {\n const clonedFilter = structuredClone(filter);\n const query = !isEmpty(filter) ? jsonToQueryString(clonedFilter) : '';\n return this.http.get<IResponse<IMultiresult<T>>>(`${this.baseUrl}${query}`);\n }\n\n getDetails(id: number): Observable<IResponse<T>> {\n return this.http.get<IResponse<T>>(`${this.baseUrl}/${id}`);\n }\n\n create(data: TCreate): Observable<IResponse<T>> {\n return this.http.post<IResponse<T>>(this.baseUrl, data);\n }\n\n update(id: number, data: TUpdate): Observable<IResponse<T>> {\n return this.http.put<IResponse<T>>(`${this.baseUrl}/${id}`, data);\n }\n\n delete(id: number, method: 'soft' | 'hard' = 'soft'): Observable<any> {\n const methodQuery = `?method=${method}`;\n if (method === 'soft') {\n return this.http.delete(`${this.baseUrl}/${id}${methodQuery}`, {});\n }\n return this.http.delete(`${this.baseUrl}/${id}${methodQuery}`);\n }\n}\n","/*\n * Public API Surface of api-core\n */\n\nexport * from './lib/configs';\nexport * from './lib/api-core';\nexport * from './lib/enums';\nexport * from './lib/utils';\nexport * from './lib/models';\nexport * from './lib/services';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;AAGA;;;;;AAKG;MACmB,kBAAkB,CAAA;AACpC;;AAEG;IACH,OAAO,GAAqB,EAAE;AAE9B;;AAEG;IACH,eAAe,GAAqB,YAAY;AAEhD;;AAEG;IACH,iBAAiB,GAAqB,YAAY;AAElD;;AAEG;IACH,gBAAgB,GAAmB,MAAM;AAEzC;;AAEG;IACH,iBAAiB,GAAa,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC;AAE/C;;AAEG;IACH,iBAAiB,GAAW,EAAE;AAE9B;;AAEG;IACH,aAAa,GAAyB,EAAE;AAExC;;AAEG;IACH,eAAe,GAAuC,IAAI;AAE1D;;AAEG;IACH,qBAAqB,GAAyD,KAAK;AAEnF;;AAEG;IACH,gBAAgB,GAAgC,IAAI;AAEpD;;AAEG;IACH,sBAAsB,GAAyD,KAAK;AAEpF;;;;AAIG;IACH,iBAAiB,GAA2B,SAAS;AACxD;;MC3DY,OAAO,CAAA;uGAAP,OAAO,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAP,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,OAAO,EAPR,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,cAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAAA;;;;AAIT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;2FAGU,OAAO,EAAA,UAAA,EAAA,CAAA;kBAVnB,SAAS;+BACE,cAAc,EAAA,OAAA,EACf,EAAE,EACD,QAAA,EAAA;;;;AAIT,EAAA,CAAA,EAAA;;;ICTS;AAAZ,CAAA,UAAY,WAAW,EAAA;AACrB,IAAA,WAAA,CAAA,WAAA,CAAA,KAAA,CAAA,GAAA,CAAA,CAAA,GAAA,KAAO;AACP,IAAA,WAAA,CAAA,WAAA,CAAA,aAAA,CAAA,GAAA,CAAA,CAAA,GAAA,aAAe;AACjB,CAAC,EAHW,WAAW,KAAX,WAAW,GAGtB,EAAA,CAAA,CAAA;AAAA;;ACDY,MAAA,kBAAkB,GAAG,CAAC,SAAqB,KAAY;AAChE,IAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;AAAE,QAAA,OAAO,EAAE;IAClE,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,CAAA,EAAG,CAAC,CAAC,KAAK,CAAI,CAAA,EAAA,CAAC,CAAC,KAAK,CAAE,CAAA,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;AAChE;AAEa,MAAA,iBAAiB,GAAG,CAAC,IAAS,KAAY;AACnD,IAAA,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;AAAE,QAAA,OAAO,EAAE;AAEhD,IAAA,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE;QAC7B,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;;AAG7C,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI;AAC9B,SAAA,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI;SAC3D,GAAG,CAAC,GAAG,IAAG;QACP,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE;YAC1B,OAAO,CAAA,EAAG,kBAAkB,CAAC,GAAG,CAAC,CAAI,CAAA,EAAA,kBAAkB,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,GAAG,GAAG,CAAC,CAAA,CAAE;;aACxF;AACH,YAAA,OAAO,CAAG,EAAA,kBAAkB,CAAC,GAAG,CAAC,CAAI,CAAA,EAAA,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE;;AAE5E,KAAC,CAAC;IAEN,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,CAAI,CAAA,EAAA,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA,CAAE,GAAG,EAAE;AAClE;AAEa,MAAA,OAAO,GAAG,CAAC,GAAQ,KAAa;AACzC,IAAA,OAAO,CAAC,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC;AAChD;;MC1BsB,MAAM,CAAA;AACxB,IAAA,eAAe;AACf,IAAA,aAAa;AACb,IAAA,WAAW;IAEX,IAAI,GAAY,CAAC;IACjB,UAAU,GAAY,EAAE;IAExB,IAAI,GAAgB,EAAE;AAEtB,IAAA,MAAM;AACN,IAAA,aAAa;AACb,IAAA,aAAa;AACb,IAAA,UAAU;AACb;;MCjBY,QAAQ,CAAA;AAEV,IAAA,KAAA;AACA,IAAA,KAAA;IAFT,WACS,CAAA,KAAa,EACb,KAAqB,EAAA;QADrB,IAAK,CAAA,KAAA,GAAL,KAAK;QACL,IAAK,CAAA,KAAA,GAAL,KAAK;;AAEf;;ACFD;;AAEG;MACU,gBAAgB,CAAA;AAIR,IAAA,aAAa,GAAG,IAAI,eAAe,CAAU,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAa,CAAC;AACpF,IAAA,cAAc,GAAG,IAAI,eAAe,CAAY,EAAE,CAAC;AACnD,IAAA,YAAY,GAAG,IAAI,eAAe,CAA8B,IAAI,CAAC;AACrE,IAAA,eAAe,GAAG,IAAI,eAAe,CAAiB,IAAI,CAAC;AAC3D,IAAA,iBAAiB,GAAG,IAAI,eAAe,CAA0B,EAAE,CAAC;AACpE,IAAA,aAAa,GAAG,IAAI,eAAe,CAAU,KAAK,CAAC;AACnD,IAAA,YAAY,GAAG,IAAI,eAAe,CAAgB,IAAI,CAAC;;AAGxE,IAAA,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE;;AAG3C,IAAA,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,YAAY,EAAE;;AAG7C,IAAA,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE;;AAGzC,IAAA,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE;;AAG/C,IAAA,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,YAAY,EAAE;;AAGhD,IAAA,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE;;AAG3C,IAAA,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE;;AAGzC,IAAA,IAAI,aAAa,GAAA;AACb,QAAA,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK;;;AAInC,IAAA,IAAI,cAAc,GAAA;AACd,QAAA,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK;;;AAIpC,IAAA,IAAI,QAAQ,GAAA;AACR,QAAA,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK;;AAGrC;;;AAGG;AACH,IAAA,SAAS,CAAC,MAAwB,EAAA;AAC9B,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK;AACxC,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC;;AAGtD;;;AAGG;AACH,IAAA,UAAU,CAAC,OAAkB,EAAA;AACzB,QAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC;;AAGrC;;;AAGG;AACH,IAAA,aAAa,CAAC,OAAkB,EAAA;AAC5B,QAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,GAAG,OAAO,CAAC,CAAC;;AAGlE;;;AAGG;AACH,IAAA,QAAQ,CAAC,KAA2B,EAAA;AAChC,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;;AAGjC;;;AAGG;AACH,IAAA,cAAc,CAAC,QAA+B,EAAA;AAC1C,QAAA,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC;AACjC,QAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;;AAGjC;;;;AAID;AACC,IAAA,OAAO,CAAC,MAAc,EAAE,IAAA,GAAuB,KAAK,EAAA;AAChD,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK;AAExC,QAAA,IAAI,SAAS,GAAG,CAAC,IAAI,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;AAEzC,QAAA,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC;AAEhE,QAAA,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;YACd,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,KAAK;YAC3C,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,QAAQ,CAC3B,SAAS,CAAC,KAAK,CAAC,CAAC,KAAK,EACtB,YAAY,KAAK,KAAK,GAAG,MAAM,GAAG,KAAK,CAC1C;;aACE;YACH,SAAS,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;;AAG9C,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;AACpB,YAAA,GAAG,OAAO;AACV,YAAA,IAAI,EAAE;AACT,SAAA,CAAC;;AAGN;;;AAGG;AACH,IAAA,UAAU,CAAC,MAAc,EAAA;AACrB,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK;QACxC,MAAM,SAAS,GAAG,CAAC,IAAI,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC;AAEjF,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;AACpB,YAAA,GAAG,OAAO;AACV,YAAA,IAAI,EAAE;AACT,SAAA,CAAC;;AAGN;;AAEG;IACH,SAAS,GAAA;AACL,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK;AAExC,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;AACpB,YAAA,GAAG,OAAO;AACV,YAAA,IAAI,EAAE;AACT,SAAA,CAAC;;AAGN;;;;;;AAMG;AACH,IAAA,UAAU,CAAC,GAAW,EAAA;QAClB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;;AAGzD;;;;;;AAMG;IACH,UAAU,CAAC,GAAW,EAAE,KAAc,EAAA;AAClC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK;AAC5C,QAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,GAAG,GAAG,KAAK,EAAE,CAAC;;AAG7D;;;AAGG;AACH,IAAA,SAAS,CAAC,MAAe,EAAA;AACrB,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;;AAGnC;;;AAGG;AACH,IAAA,QAAQ,CAAC,KAAoB,EAAA;AACzB,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;;AAGjC;;;AAGG;AACH,IAAA,MAAM,CAAC,MAAe,EAAA;AAClB,QAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;;;IAIrC,cAAc,GAAA;AACV,QAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;;AAGnC;;;;AAIC;AACD,IAAA,YAAY,CAAC,GAAY,EAAA;QACrB,IAAI,GAAG,EAAE;AACL,YAAA,MAAM,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK;AAC1D,YAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC;;aAC9B;AACH,YAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;;;;IAKvC,KAAK,GAAA;AACD,QAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;AAC5B,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;AAC5B,QAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;AAC/B,QAAA,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAsB,CAAC;QAC/D,IAAI,CAAC,YAAY,EAAE;AACnB,QAAA,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;AACrB,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;;AAGvB;;;;AAIG;AACH,IAAA,gBAAgB,CAAC,EAAmB,EAAE,KAAA,GAAuB,IAAqB,EAAA;QAC9E,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;;AAG9E;;;;AAIG;AACH,IAAA,aAAa,CAAC,OAAgB,EAAE,KAAA,GAAuB,IAAqB,EAAA;AACxE,QAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CACpB,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC,CAC1E;;AAGL;;;;AAIG;AACH,IAAA,UAAU,CAAC,MAAe,EAAE,KAAA,GAAuB,IAAqB,EAAA;AACpE,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK;AAC3C,QAAA,OAAO,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK;;AAG/D;;;AAGG;AACH,IAAA,OAAO,CAAC,IAAY,EAAA;AAChB,QAAA,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAsB,CAAC;;AAGhD;;;AAGG;AACH,IAAA,aAAa,CAAC,UAAkB,EAAA;AAC5B,QAAA,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAsB,CAAC;;AAGtD;;;AAGG;IACH,WAAW,CAAC,QAA6B,GAAA,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAsB,EAAA;AACpF,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAmB,CAAC;;;IAIhD,YAAY,GAAA;AACR,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK;QACrC,OAAO,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,WAAY,GAAG,KAAK,CAAC,QAAS;;;IAI1D,eAAe,GAAA;AACX,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK;QACrC,OAAO,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,WAAY,GAAG,CAAC;;;IAI5C,OAAO,GAAA;QACH,IAAI,CAAC,KAAK,EAAE;;AAEnB;;MCpSqB,WAAW,CAAA;AAOf,IAAA,IAAA;AACA,IAAA,OAAA;IAFd,WACc,CAAA,IAAgB,EAChB,OAAe,EAAA;QADf,IAAI,CAAA,IAAA,GAAJ,IAAI;QACJ,IAAO,CAAA,OAAA,GAAP,OAAO;;IAGrB,MAAM,CAAC,SAAkB,EAAa,EAAA;AAClC,QAAA,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC;AAC5C,QAAA,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,iBAAiB,CAAC,YAAY,CAAC,GAAG,EAAE;AACrE,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAA6B,CAAA,EAAG,IAAI,CAAC,OAAO,CAAA,EAAG,KAAK,CAAA,CAAE,CAAC;;AAG/E,IAAA,UAAU,CAAC,EAAU,EAAA;AACjB,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAe,CAAA,EAAG,IAAI,CAAC,OAAO,CAAA,CAAA,EAAI,EAAE,CAAA,CAAE,CAAC;;AAG/D,IAAA,MAAM,CAAC,IAAa,EAAA;AAChB,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAe,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC;;IAG3D,MAAM,CAAC,EAAU,EAAE,IAAa,EAAA;AAC5B,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAe,CAAG,EAAA,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA,CAAE,EAAE,IAAI,CAAC;;AAGrE,IAAA,MAAM,CAAC,EAAU,EAAE,MAAA,GAA0B,MAAM,EAAA;AAC/C,QAAA,MAAM,WAAW,GAAG,CAAW,QAAA,EAAA,MAAM,EAAE;AACvC,QAAA,IAAI,MAAM,KAAK,MAAM,EAAE;AACnB,YAAA,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAA,CAAA,EAAI,EAAE,CAAG,EAAA,WAAW,EAAE,EAAE,EAAE,CAAC;;AAEtE,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAG,EAAA,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA,EAAG,WAAW,CAAA,CAAE,CAAC;;AAErE;;ACzCD;;AAEG;;ACFH;;AAEG;;;;"}
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import * as rxjs from 'rxjs';
|
|
3
2
|
import { Observable } from 'rxjs';
|
|
4
3
|
import { HttpClient } from '@angular/common/http';
|
|
5
4
|
|
|
@@ -122,6 +121,12 @@ declare abstract class BaseResourceConfig<T> {
|
|
|
122
121
|
* Modal configuration: fullscreen setting for summary modal.
|
|
123
122
|
*/
|
|
124
123
|
summaryModalFullscreen: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | boolean | string;
|
|
124
|
+
/**
|
|
125
|
+
* Determines the default view when viewing details of a record.
|
|
126
|
+
* 'overview' = navigates to a new page
|
|
127
|
+
* 'summary' = opens a modal with summary component
|
|
128
|
+
*/
|
|
129
|
+
defaultDetailView: 'overview' | 'summary';
|
|
125
130
|
}
|
|
126
131
|
|
|
127
132
|
declare class ApiCore {
|
|
@@ -141,23 +146,23 @@ declare class BaseStateService<TRecord, TFilter extends Partial<TRecord> & Filte
|
|
|
141
146
|
private readonly recordsSubject;
|
|
142
147
|
private readonly pagerSubject;
|
|
143
148
|
private readonly selectedSubject;
|
|
144
|
-
private readonly
|
|
149
|
+
private readonly loadingMapSubject;
|
|
145
150
|
private readonly savingSubject;
|
|
146
151
|
private readonly errorSubject;
|
|
147
152
|
/** Observable stream of current filter. */
|
|
148
|
-
filter$:
|
|
153
|
+
filter$: Observable<TFilter>;
|
|
149
154
|
/** Observable stream of current records. */
|
|
150
|
-
records$:
|
|
155
|
+
records$: Observable<TRecord[]>;
|
|
151
156
|
/** Observable stream of current pager metadata. */
|
|
152
|
-
pager$:
|
|
157
|
+
pager$: Observable<IMultiresultMetaData | null>;
|
|
153
158
|
/** Observable stream of the currently selected record. */
|
|
154
|
-
selected$:
|
|
159
|
+
selected$: Observable<TRecord | null>;
|
|
155
160
|
/** Observable stream of loading state. */
|
|
156
|
-
loading$:
|
|
161
|
+
loading$: Observable<Record<string, boolean>>;
|
|
157
162
|
/** Observable stream of saving state. */
|
|
158
|
-
saving$:
|
|
163
|
+
saving$: Observable<boolean>;
|
|
159
164
|
/** Observable stream of current error message. */
|
|
160
|
-
error$:
|
|
165
|
+
error$: Observable<string | null>;
|
|
161
166
|
/** Returns the current filter. */
|
|
162
167
|
get currentFilter(): TFilter;
|
|
163
168
|
/** Returns the currently loaded records. */
|
|
@@ -205,10 +210,21 @@ declare class BaseStateService<TRecord, TFilter extends Partial<TRecord> & Filte
|
|
|
205
210
|
*/
|
|
206
211
|
clearSort(): void;
|
|
207
212
|
/**
|
|
208
|
-
*
|
|
209
|
-
*
|
|
213
|
+
* Returns an observable boolean for a specific loading key.
|
|
214
|
+
* Useful for tracking loading state in a specific view or feature.
|
|
215
|
+
*
|
|
216
|
+
* @param key A unique key representing the loading context (e.g., "list", "detail")
|
|
217
|
+
* @returns Observable emitting `true` if the given context is loading, `false` otherwise.
|
|
210
218
|
*/
|
|
211
|
-
|
|
219
|
+
isLoading$(key: string): Observable<boolean>;
|
|
220
|
+
/**
|
|
221
|
+
* Sets the loading state for a specific key.
|
|
222
|
+
* This allows you to control multiple concurrent loading states independently.
|
|
223
|
+
*
|
|
224
|
+
* @param key The loading context name (e.g., "list", "form", "detail")
|
|
225
|
+
* @param value The loading status (`true` for loading, `false` for done)
|
|
226
|
+
*/
|
|
227
|
+
setLoading(key: string, value: boolean): void;
|
|
212
228
|
/**
|
|
213
229
|
* Sets the saving flag.
|
|
214
230
|
* @param saving Whether a save operation is in progress.
|
|
@@ -226,6 +242,12 @@ declare class BaseStateService<TRecord, TFilter extends Partial<TRecord> & Filte
|
|
|
226
242
|
select(record: TRecord): void;
|
|
227
243
|
/** Clears the current selection. */
|
|
228
244
|
clearSelection(): void;
|
|
245
|
+
/**
|
|
246
|
+
* Clears the loading state for a specific key or all keys if none is provided.
|
|
247
|
+
*
|
|
248
|
+
* @param key Optional. If provided, only that loading key is cleared. If omitted, all are cleared.
|
|
249
|
+
*/
|
|
250
|
+
clearLoading(key?: string): void;
|
|
229
251
|
/** Resets the entire state to initial values. */
|
|
230
252
|
reset(): void;
|
|
231
253
|
/**
|