@masterteam/properties 0.0.29 → 0.0.31

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.
@@ -5,8 +5,9 @@ import { Table } from '@masterteam/components/table';
5
5
  import { Router, ActivatedRoute } from '@angular/router';
6
6
  import { HttpClient, HttpContextToken } from '@angular/common/http';
7
7
  import { Action, Selector, State, Store, select } from '@ngxs/store';
8
- import { of, finalize as finalize$1, startWith, map, distinctUntilChanged, Subscription } from 'rxjs';
9
- import { tap, catchError, finalize, switchMap } from 'rxjs/operators';
8
+ import { of, finalize, startWith, map, distinctUntilChanged, Subscription } from 'rxjs';
9
+ import { switchMap, tap } from 'rxjs/operators';
10
+ import { CrudStateBase, handleApiRequest, PickListFieldConfig, ValidatorConfig } from '@masterteam/components';
10
11
  import { Breadcrumb } from '@masterteam/components/breadcrumb';
11
12
  import { Card } from '@masterteam/components/card';
12
13
  import { Avatar } from '@masterteam/components/avatar';
@@ -17,7 +18,6 @@ import { TranslocoService, TranslocoModule } from '@jsverse/transloco';
17
18
  import { toSignal } from '@angular/core/rxjs-interop';
18
19
  import { Page } from '@masterteam/components/page';
19
20
  import { DynamicForm } from '@masterteam/forms/dynamic-form';
20
- import { PickListFieldConfig, ValidatorConfig } from '@masterteam/components';
21
21
  import * as i1$1 from '@angular/forms';
22
22
  import { FormGroup, FormControl, FormArray, Validators, ReactiveFormsModule, NG_VALUE_ACCESSOR, ControlContainer, FormGroupDirective } from '@angular/forms';
23
23
  import * as i2 from 'primeng/skeleton';
@@ -27,30 +27,20 @@ import { SelectField } from '@masterteam/components/select-field';
27
27
  import { TextField } from '@masterteam/components/text-field';
28
28
  import { ToggleField } from '@masterteam/components/toggle-field';
29
29
 
30
- function startLoading(ctx, loadingName) {
31
- const { loadingActive, errors } = ctx.getState();
32
- if (!loadingActive.includes(loadingName)) {
33
- ctx.patchState({
34
- loadingActive: [...loadingActive, loadingName],
35
- });
36
- }
37
- if (errors && errors[loadingName]) {
38
- const { [loadingName]: _removed, ...rest } = errors;
39
- ctx.patchState({ errors: rest });
40
- }
41
- }
42
- function endLoading(ctx, loadingName) {
43
- const { loadingActive } = ctx.getState();
44
- ctx.patchState({
45
- loadingActive: loadingActive.filter((name) => name !== loadingName),
46
- });
47
- }
48
- function setLoadingError(ctx, loadingName, message) {
49
- const { errors } = ctx.getState();
50
- ctx.patchState({
51
- errors: { ...errors, [loadingName]: message },
52
- });
53
- }
30
+ var PropertiesActionKey;
31
+ (function (PropertiesActionKey) {
32
+ PropertiesActionKey["GetAll"] = "getAll";
33
+ PropertiesActionKey["GetOne"] = "getOne";
34
+ PropertiesActionKey["Create"] = "create";
35
+ PropertiesActionKey["Update"] = "update";
36
+ PropertiesActionKey["Delete"] = "delete";
37
+ PropertiesActionKey["GetLookups"] = "getLookups";
38
+ PropertiesActionKey["GetGroups"] = "getGroups";
39
+ PropertiesActionKey["GetConfigProperties"] = "getConfigProperties";
40
+ PropertiesActionKey["GetConfigAsType"] = "getConfigAsType";
41
+ PropertiesActionKey["GetCountries"] = "getCountries";
42
+ PropertiesActionKey["TestApiConfiguration"] = "testApiConfiguration";
43
+ })(PropertiesActionKey || (PropertiesActionKey = {}));
54
44
 
55
45
  class GetProperties {
56
46
  params;
@@ -198,7 +188,7 @@ const DEFAULT_STATE = {
198
188
  breadcrumbItems: [],
199
189
  defaultViewType: null,
200
190
  };
201
- let PropertiesState = class PropertiesState {
191
+ let PropertiesState = class PropertiesState extends CrudStateBase {
202
192
  http = inject(HttpClient);
203
193
  baseUrl = 'Properties';
204
194
  lookupsUrl = 'Lookups';
@@ -207,6 +197,9 @@ let PropertiesState = class PropertiesState {
207
197
  countriesUrl = '/assets/countries/countries.json';
208
198
  apiTestUrl = 'app/testAPI';
209
199
  apiDetectUrl = 'app/detect';
200
+ // ============================================================================
201
+ // Data Selectors - Individual for fine-grained reactivity
202
+ // ============================================================================
210
203
  static properties(state) {
211
204
  return state.properties;
212
205
  }
@@ -241,7 +234,7 @@ let PropertiesState = class PropertiesState {
241
234
  return state.apiProperties;
242
235
  }
243
236
  static propertyTypes(state) {
244
- return state.propertyTypes ?? [];
237
+ return state.propertyTypes ?? {};
245
238
  }
246
239
  static breadcrumbItems(state) {
247
240
  return state.breadcrumbItems;
@@ -249,86 +242,93 @@ let PropertiesState = class PropertiesState {
249
242
  static defaultViewType(state) {
250
243
  return state.defaultViewType;
251
244
  }
252
- static isLoadingFactory(state) {
253
- return (loadingName) => state.loadingActive.includes(loadingName);
245
+ // ============================================================================
246
+ // Loading/Error Slice Selectors - REQUIRED for optimal performance
247
+ // ============================================================================
248
+ static getLoadingActive(state) {
249
+ return state.loadingActive;
254
250
  }
255
- static errorFactory(state) {
256
- return (loadingName) => state.errors?.[loadingName] ?? null;
251
+ static getErrors(state) {
252
+ return state.errors;
257
253
  }
254
+ // ============================================================================
255
+ // Derived Selectors
256
+ // ============================================================================
258
257
  static propertyById(state) {
259
258
  return (id) => state.properties.find((property) => property.id === Number(id)) ?? null;
260
259
  }
260
+ // ============================================================================
261
+ // CRUD Actions
262
+ // ============================================================================
261
263
  getAll(ctx, action) {
262
- startLoading(ctx, 'getAll');
263
264
  const state = ctx.getState();
264
- const moduleType = state.moduleType ?? undefined;
265
- const moduleId = state.moduleId ?? undefined;
266
- const parentPath = state.parentPath ?? '';
267
- const params = { ...action.params };
268
265
  ctx.patchState({
269
- lastQueryParams: params ?? null,
266
+ lastQueryParams: action.params ?? null,
267
+ });
268
+ // Build contextKey in format "Level:5/Module:10" or "Level:5" or "Module:10"
269
+ const contextParts = [];
270
+ if (state.parentModuleType && state.parentModuleId) {
271
+ contextParts.push(`${state.parentModuleType}:${state.parentModuleId}`);
272
+ }
273
+ if (state.moduleType && state.moduleId) {
274
+ contextParts.push(`${state.moduleType}:${state.moduleId}`);
275
+ }
276
+ const contextKey = contextParts.join('/');
277
+ const params = {
278
+ ...action.params,
279
+ contextKey,
280
+ };
281
+ const req$ = this.http.get(`${this.baseUrl}/catalog`, { params });
282
+ return handleApiRequest({
283
+ ctx,
284
+ key: PropertiesActionKey.GetAll,
285
+ request$: req$,
286
+ onSuccess: (response) => ({
287
+ properties: response.data ?? [],
288
+ }),
270
289
  });
271
- return this.http
272
- .get(`${this.baseUrl}${parentPath}/${moduleType}/${moduleId}`, {
273
- params: params,
274
- })
275
- .pipe(tap((response) => {
276
- const properties = Array.isArray(response?.data) ? response.data : [];
277
- ctx.patchState({ properties });
278
- }), catchError((error) => {
279
- const message = error?.error?.message ??
280
- error?.message ??
281
- 'Failed to load properties';
282
- setLoadingError(ctx, 'getAll', message);
283
- return of(null);
284
- }), finalize(() => endLoading(ctx, 'getAll')));
285
290
  }
286
291
  getOne(ctx, action) {
287
- startLoading(ctx, 'getOne');
288
292
  const params = { mode: action.mode ?? 'edit' };
289
- return this.http
290
- .get(`${this.baseUrl}/${action.id}`, { params })
291
- .pipe(tap((response) => {
292
- ctx.patchState({
293
- selectedProperty: response?.data ?? null,
294
- });
295
- }), catchError((error) => {
296
- const message = error?.error?.message ??
297
- error?.message ??
298
- 'Failed to load property';
299
- setLoadingError(ctx, 'getOne', message);
300
- return of(null);
301
- }), finalize(() => endLoading(ctx, 'getOne')));
293
+ const req$ = this.http.get(`${this.baseUrl}/${action.id}`, { params });
294
+ return handleApiRequest({
295
+ ctx,
296
+ key: PropertiesActionKey.GetOne,
297
+ request$: req$,
298
+ onSuccess: (response) => ({
299
+ selectedProperty: response.data ?? null,
300
+ }),
301
+ });
302
302
  }
303
303
  getLookups(ctx, _action) {
304
304
  const state = ctx.getState();
305
305
  if (state.lookups.length) {
306
306
  return of(state.lookups);
307
307
  }
308
- startLoading(ctx, 'getLookups');
309
- return this.http.get(this.lookupsUrl).pipe(tap((response) => {
310
- const lookups = Array.isArray(response?.data) ? response.data : [];
311
- ctx.patchState({ lookups });
312
- }), catchError((error) => {
313
- const message = error?.error?.message ?? error?.message ?? 'Failed to load lookups';
314
- setLoadingError(ctx, 'getLookups', message);
315
- return of([]);
316
- }), finalize(() => endLoading(ctx, 'getLookups')));
308
+ const req$ = this.http.get(this.lookupsUrl);
309
+ return handleApiRequest({
310
+ ctx,
311
+ key: PropertiesActionKey.GetLookups,
312
+ request$: req$,
313
+ onSuccess: (response) => ({
314
+ lookups: response.data ?? [],
315
+ }),
316
+ });
317
317
  }
318
318
  getGroups(ctx, _action) {
319
319
  const state = ctx.getState();
320
320
  if (state.groups.length) {
321
321
  return of(state.groups);
322
322
  }
323
- startLoading(ctx, 'getGroups');
324
- return this.http.get(this.groupsUrl).pipe(tap((response) => {
325
- const groups = Array.isArray(response?.data) ? response.data : [];
326
- ctx.patchState({ groups });
327
- }), catchError((error) => {
328
- const message = error?.error?.message ?? error?.message ?? 'Failed to load groups';
329
- setLoadingError(ctx, 'getGroups', message);
330
- return of([]);
331
- }), finalize(() => endLoading(ctx, 'getGroups')));
323
+ const req$ = this.http.get(this.groupsUrl);
324
+ return handleApiRequest({
325
+ ctx,
326
+ key: PropertiesActionKey.GetGroups,
327
+ request$: req$,
328
+ onSuccess: (response) => ({
329
+ groups: response.data ?? [],
330
+ }),
331
+ });
332
332
  }
333
333
  getConfigAsType(ctx, action) {
334
334
  const state = ctx.getState();
@@ -336,41 +336,41 @@ let PropertiesState = class PropertiesState {
336
336
  if (state.configScopes.length) {
337
337
  return of(state.configScopes);
338
338
  }
339
- startLoading(ctx, 'getConfigAsType');
340
339
  const url = `${this.baseUrl}/${action.viewType}/GetViewTypeProperties`;
341
- return this.http.get(url).pipe(tap((response) => {
342
- const configScopes = Array.isArray(response?.data) ? response.data : [];
343
- ctx.patchState({ configScopes });
344
- }), catchError((error) => {
345
- const message = error?.error?.message ??
346
- error?.message ??
347
- 'Failed to load configuration scopes';
348
- setLoadingError(ctx, 'getConfigAsType', message);
349
- return of([]);
350
- }), finalize(() => endLoading(ctx, 'getConfigAsType')));
340
+ const req$ = this.http.get(url);
341
+ return handleApiRequest({
342
+ ctx,
343
+ key: PropertiesActionKey.GetConfigAsType,
344
+ request$: req$,
345
+ onSuccess: (response) => ({
346
+ configScopes: response.data ?? [],
347
+ }),
348
+ });
351
349
  }
352
350
  getCountries(ctx, _action) {
353
351
  const state = ctx.getState();
354
352
  if (state.countries.length) {
355
353
  return of(state.countries);
356
354
  }
357
- startLoading(ctx, 'getCountries');
358
- return this.http.get(this.countriesUrl).pipe(tap((response) => {
359
- const countries = Array.isArray(response) ? response : [];
360
- ctx.patchState({ countries });
361
- }), catchError((error) => {
362
- const message = error?.error?.message ?? error?.message ?? 'Failed to load countries';
363
- setLoadingError(ctx, 'getCountries', message);
364
- return of([]);
365
- }), finalize(() => endLoading(ctx, 'getCountries')));
355
+ const req$ = this.http.get(this.countriesUrl);
356
+ return handleApiRequest({
357
+ ctx,
358
+ key: PropertiesActionKey.GetCountries,
359
+ request$: req$,
360
+ onSuccess: (response) => ({
361
+ countries: Array.isArray(response) ? response : [],
362
+ }),
363
+ errorMessage: 'Failed to load countries',
364
+ });
366
365
  }
367
366
  testApiConfiguration(ctx, action) {
368
- startLoading(ctx, 'testApiConfiguration');
369
367
  ctx.patchState({
370
368
  apiSchema: null,
371
369
  apiProperties: [],
372
370
  });
373
- return this.http.post(this.apiTestUrl, action.payload).pipe(switchMap((testResponse) => {
371
+ const req$ = this.http
372
+ .post(this.apiTestUrl, action.payload)
373
+ .pipe(switchMap((testResponse) => {
374
374
  const rawData = testResponse?.data;
375
375
  if (!rawData) {
376
376
  return of(null);
@@ -387,49 +387,29 @@ let PropertiesState = class PropertiesState {
387
387
  apiProperties,
388
388
  });
389
389
  }));
390
- }), catchError((error) => {
391
- const message = error?.error?.message ?? error?.message ?? 'Failed to test API';
392
- setLoadingError(ctx, 'testApiConfiguration', message);
393
- return of(null);
394
- }), finalize(() => endLoading(ctx, 'testApiConfiguration')));
395
- }
396
- resetApiConfiguration(ctx) {
397
- ctx.patchState({
398
- apiSchema: null,
399
- apiProperties: [],
400
- });
401
- }
402
- mapSchemaToOptions(schema) {
403
- if (!schema?.properties) {
404
- return [];
405
- }
406
- return Object.entries(schema.properties).map(([key, definition]) => {
407
- const typeLabel = definition?.type ? ` | ${definition.type}` : '';
408
- return {
409
- key,
410
- name: `${key}${typeLabel}`,
411
- type: definition?.type,
412
- };
390
+ }));
391
+ return handleApiRequest({
392
+ ctx,
393
+ key: PropertiesActionKey.TestApiConfiguration,
394
+ request$: req$,
395
+ onSuccess: () => ({}),
413
396
  });
414
397
  }
415
398
  getPropertiesForConfigType(ctx, action) {
416
- startLoading(ctx, 'getConfigProperties');
417
399
  const { moduleType, moduleId } = action;
418
- return this.http
419
- .get(`${this.configPropertiesUrl}/${moduleType}/${moduleId}`)
420
- .pipe(tap((response) => {
421
- const configTypeProperties = Array.isArray(response?.data)
422
- ? response.data
423
- : [];
424
- ctx.patchState({ configTypeProperties });
425
- }), catchError((error) => {
426
- const message = error?.error?.message ??
427
- error?.message ??
428
- 'Failed to load properties';
429
- setLoadingError(ctx, 'getConfigProperties', message);
430
- return of([]);
431
- }), finalize(() => endLoading(ctx, 'getConfigProperties')));
400
+ const req$ = this.http.get(`${this.configPropertiesUrl}/${moduleType}/${moduleId}`);
401
+ return handleApiRequest({
402
+ ctx,
403
+ key: PropertiesActionKey.GetConfigProperties,
404
+ request$: req$,
405
+ onSuccess: (response) => ({
406
+ configTypeProperties: response.data ?? [],
407
+ }),
408
+ });
432
409
  }
410
+ // ============================================================================
411
+ // Simple State Updates (No HTTP)
412
+ // ============================================================================
433
413
  resetConfigProperties(ctx) {
434
414
  ctx.patchState({ configTypeProperties: [] });
435
415
  }
@@ -439,6 +419,12 @@ let PropertiesState = class PropertiesState {
439
419
  resetSelectedProperty(ctx) {
440
420
  ctx.patchState({ selectedProperty: null });
441
421
  }
422
+ resetApiConfiguration(ctx) {
423
+ ctx.patchState({
424
+ apiSchema: null,
425
+ apiProperties: [],
426
+ });
427
+ }
442
428
  setModuleInfo(ctx, action) {
443
429
  let parentPath = '';
444
430
  if (action.parentModuleType && action.parentModuleId) {
@@ -455,106 +441,107 @@ let PropertiesState = class PropertiesState {
455
441
  parentPath: parentPath ?? '',
456
442
  });
457
443
  }
458
- create(ctx, action) {
459
- startLoading(ctx, 'create');
444
+ SetPropertyTypes(ctx, action) {
445
+ ctx.patchState({
446
+ propertyTypes: action.payload,
447
+ });
448
+ }
449
+ setBreadcrumb(ctx, action) {
450
+ ctx.patchState({
451
+ breadcrumbItems: action.items,
452
+ });
453
+ }
454
+ setDefaultViewType(ctx, action) {
455
+ ctx.patchState({
456
+ defaultViewType: action.viewType,
457
+ });
458
+ }
459
+ createProperty(ctx, action) {
460
460
  const state = ctx.getState();
461
461
  const moduleType = state.moduleType ?? undefined;
462
462
  const moduleId = state.moduleId ?? undefined;
463
463
  const parentPath = state.parentPath ?? '';
464
464
  if (!moduleType || moduleId === undefined || moduleId === null) {
465
- const message = 'Missing module context for creating property';
466
- setLoadingError(ctx, 'create', message);
467
- endLoading(ctx, 'create');
465
+ console.error('Missing module context for creating property');
468
466
  return of(null);
469
467
  }
470
- return this.http
471
- .post(`${this.baseUrl}${parentPath}/${moduleType}/${moduleId}`, action.payload)
472
- .pipe(tap((response) => {
473
- const created = response?.data;
474
- if (!created) {
475
- return;
476
- }
477
- const state = ctx.getState();
478
- ctx.patchState({
479
- properties: [...state.properties, created],
480
- selectedProperty: created,
481
- });
482
- }), finalize(() => endLoading(ctx, 'create')));
468
+ const req$ = this.http.post(`${this.baseUrl}${parentPath}/${moduleType}/${moduleId}`, action.payload);
469
+ return handleApiRequest({
470
+ ctx,
471
+ key: PropertiesActionKey.Create,
472
+ request$: req$,
473
+ onSuccess: (response, state) => {
474
+ const created = response.data;
475
+ if (!created)
476
+ return {};
477
+ return {
478
+ properties: this.adapter.addOne(state.properties, created),
479
+ selectedProperty: created,
480
+ };
481
+ },
482
+ });
483
483
  }
484
- update(ctx, action) {
485
- startLoading(ctx, 'update');
484
+ updateProperty(ctx, action) {
486
485
  const state = ctx.getState();
487
486
  const moduleType = state.moduleType ?? undefined;
488
487
  const moduleId = state.moduleId ?? undefined;
489
488
  const parentPath = state.parentPath ?? '';
490
489
  if (!moduleType || moduleId === undefined || moduleId === null) {
491
- const message = 'Missing module context for updating property';
492
- setLoadingError(ctx, 'update', message);
493
- endLoading(ctx, 'update');
490
+ console.error('Missing module context for updating property');
494
491
  return of(null);
495
492
  }
496
- return this.http
497
- .put(`${this.baseUrl}${parentPath}/${moduleType}/${moduleId}/${action.id}`, action.payload)
498
- .pipe(tap((response) => {
499
- const updated = response?.data;
500
- if (!updated) {
501
- return;
502
- }
503
- const updatedId = updated.id ?? Number(action.id);
504
- const state = ctx.getState();
505
- const properties = state.properties.some((item) => item.id === updatedId)
506
- ? state.properties.map((item) => item.id === updatedId ? { ...item, ...updated } : item)
507
- : [...state.properties, updated];
508
- ctx.patchState({
509
- properties,
510
- selectedProperty: updated,
511
- });
512
- }), catchError((error) => {
513
- const message = error?.error?.message ??
514
- error?.message ??
515
- 'Failed to update property';
516
- setLoadingError(ctx, 'update', message);
517
- return of(null);
518
- }), finalize(() => endLoading(ctx, 'update')));
519
- }
520
- delete(ctx, action) {
521
- startLoading(ctx, 'delete');
522
- return this.http
523
- .delete(`${this.baseUrl}/${encodeURIComponent(String(action.id))}`)
524
- .pipe(tap(() => {
525
- const { properties, selectedProperty } = ctx.getState();
526
- const remaining = properties.filter((item) => item.id !== Number(action.id));
527
- const nextSelected = selectedProperty && selectedProperty.id === Number(action.id)
528
- ? null
529
- : selectedProperty;
530
- ctx.patchState({
531
- properties: remaining,
532
- selectedProperty: nextSelected,
533
- });
534
- }), catchError((error) => {
535
- const message = error?.error?.message ??
536
- error?.message ??
537
- 'Failed to delete property';
538
- setLoadingError(ctx, 'delete', message);
539
- return of(null);
540
- }), finalize(() => endLoading(ctx, 'delete')));
541
- }
542
- SetPropertyTypes(ctx, action) {
543
- ctx.patchState({
544
- propertyTypes: action.payload,
493
+ const req$ = this.http.put(`${this.baseUrl}${parentPath}/${moduleType}/${moduleId}/${action.id}`, action.payload);
494
+ return handleApiRequest({
495
+ ctx,
496
+ key: PropertiesActionKey.Update,
497
+ request$: req$,
498
+ onSuccess: (response, state) => {
499
+ const updated = response.data;
500
+ if (!updated)
501
+ return {};
502
+ return {
503
+ properties: this.adapter.upsertOne(state.properties, updated, 'id'),
504
+ selectedProperty: updated,
505
+ };
506
+ },
545
507
  });
546
508
  }
547
- setBreadcrumb(ctx, action) {
548
- ctx.patchState({
549
- breadcrumbItems: action.items,
509
+ deleteProperty(ctx, action) {
510
+ const req$ = this.http.delete(`${this.baseUrl}/${encodeURIComponent(String(action.id))}`);
511
+ return handleApiRequest({
512
+ ctx,
513
+ key: PropertiesActionKey.Delete,
514
+ request$: req$,
515
+ onSuccess: (_, state) => {
516
+ const remaining = this.adapter.removeOne(state.properties, Number(action.id), 'id');
517
+ const nextSelected = state.selectedProperty &&
518
+ state.selectedProperty.id === Number(action.id)
519
+ ? null
520
+ : state.selectedProperty;
521
+ return {
522
+ properties: remaining,
523
+ selectedProperty: nextSelected,
524
+ };
525
+ },
550
526
  });
551
527
  }
552
- setDefaultViewType(ctx, action) {
553
- ctx.patchState({
554
- defaultViewType: action.viewType,
528
+ // ============================================================================
529
+ // Helper Methods
530
+ // ============================================================================
531
+ mapSchemaToOptions(schema) {
532
+ if (!schema?.properties) {
533
+ return [];
534
+ }
535
+ return Object.entries(schema.properties).map(([key, definition]) => {
536
+ const typeLabel = definition?.type ? ` | ${definition.type}` : '';
537
+ return {
538
+ key,
539
+ name: `${key}${typeLabel}`,
540
+ type: definition?.type,
541
+ };
555
542
  });
556
543
  }
557
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertiesState, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
544
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertiesState, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
558
545
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertiesState });
559
546
  };
560
547
  __decorate([
@@ -578,9 +565,6 @@ __decorate([
578
565
  __decorate([
579
566
  Action(TestApiConfiguration)
580
567
  ], PropertiesState.prototype, "testApiConfiguration", null);
581
- __decorate([
582
- Action(ResetApiConfiguration)
583
- ], PropertiesState.prototype, "resetApiConfiguration", null);
584
568
  __decorate([
585
569
  Action(GetPropertiesForConfigType)
586
570
  ], PropertiesState.prototype, "getPropertiesForConfigType", null);
@@ -593,18 +577,12 @@ __decorate([
593
577
  __decorate([
594
578
  Action(ResetSelectedProperty)
595
579
  ], PropertiesState.prototype, "resetSelectedProperty", null);
580
+ __decorate([
581
+ Action(ResetApiConfiguration)
582
+ ], PropertiesState.prototype, "resetApiConfiguration", null);
596
583
  __decorate([
597
584
  Action(SetPropertiesModuleInfo)
598
585
  ], PropertiesState.prototype, "setModuleInfo", null);
599
- __decorate([
600
- Action(CreateProperty)
601
- ], PropertiesState.prototype, "create", null);
602
- __decorate([
603
- Action(UpdateProperty)
604
- ], PropertiesState.prototype, "update", null);
605
- __decorate([
606
- Action(DeleteProperty)
607
- ], PropertiesState.prototype, "delete", null);
608
586
  __decorate([
609
587
  Action(SetPropertyTypes)
610
588
  ], PropertiesState.prototype, "SetPropertyTypes", null);
@@ -614,6 +592,15 @@ __decorate([
614
592
  __decorate([
615
593
  Action(SetDefaultViewType)
616
594
  ], PropertiesState.prototype, "setDefaultViewType", null);
595
+ __decorate([
596
+ Action(CreateProperty)
597
+ ], PropertiesState.prototype, "createProperty", null);
598
+ __decorate([
599
+ Action(UpdateProperty)
600
+ ], PropertiesState.prototype, "updateProperty", null);
601
+ __decorate([
602
+ Action(DeleteProperty)
603
+ ], PropertiesState.prototype, "deleteProperty", null);
617
604
  __decorate([
618
605
  Selector()
619
606
  ], PropertiesState, "properties", null);
@@ -658,10 +645,10 @@ __decorate([
658
645
  ], PropertiesState, "defaultViewType", null);
659
646
  __decorate([
660
647
  Selector()
661
- ], PropertiesState, "isLoadingFactory", null);
648
+ ], PropertiesState, "getLoadingActive", null);
662
649
  __decorate([
663
650
  Selector()
664
- ], PropertiesState, "errorFactory", null);
651
+ ], PropertiesState, "getErrors", null);
665
652
  __decorate([
666
653
  Selector()
667
654
  ], PropertiesState, "propertyById", null);
@@ -673,10 +660,13 @@ PropertiesState = __decorate([
673
660
  ], PropertiesState);
674
661
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertiesState, decorators: [{
675
662
  type: Injectable
676
- }], propDecorators: { getAll: [], getOne: [], getLookups: [], getGroups: [], getConfigAsType: [], getCountries: [], testApiConfiguration: [], resetApiConfiguration: [], getPropertiesForConfigType: [], resetConfigProperties: [], resetConfigScopes: [], resetSelectedProperty: [], setModuleInfo: [], create: [], update: [], delete: [], SetPropertyTypes: [], setBreadcrumb: [], setDefaultViewType: [] } });
663
+ }], propDecorators: { getAll: [], getOne: [], getLookups: [], getGroups: [], getConfigAsType: [], getCountries: [], testApiConfiguration: [], getPropertiesForConfigType: [], resetConfigProperties: [], resetConfigScopes: [], resetSelectedProperty: [], resetApiConfiguration: [], setModuleInfo: [], SetPropertyTypes: [], setBreadcrumb: [], setDefaultViewType: [], createProperty: [], updateProperty: [], deleteProperty: [] } });
677
664
 
678
665
  class PropertiesFacade {
679
666
  store = inject(Store);
667
+ // ============================================================================
668
+ // Data Selectors - Memoized by NGXS (fine-grained reactivity)
669
+ // ============================================================================
680
670
  list = select(PropertiesState.properties);
681
671
  propertyTypes = select(PropertiesState.propertyTypes);
682
672
  selected = select(PropertiesState.selectedProperty);
@@ -691,12 +681,47 @@ class PropertiesFacade {
691
681
  apiProperties = select(PropertiesState.apiProperties);
692
682
  breadcrumbItems = select(PropertiesState.breadcrumbItems);
693
683
  defaultViewType = select(PropertiesState.defaultViewType);
684
+ // ============================================================================
685
+ // Loading/Error Slices - Memoized by NGXS
686
+ // ============================================================================
687
+ loadingActive = select(PropertiesState.getLoadingActive);
688
+ errors = select(PropertiesState.getErrors);
689
+ // ============================================================================
690
+ // Loading Signals - Computed from slice (minimal reactivity)
691
+ // ============================================================================
692
+ isLoadingAll = computed(() => this.loadingActive().includes(PropertiesActionKey.GetAll), ...(ngDevMode ? [{ debugName: "isLoadingAll" }] : []));
693
+ isLoadingOne = computed(() => this.loadingActive().includes(PropertiesActionKey.GetOne), ...(ngDevMode ? [{ debugName: "isLoadingOne" }] : []));
694
+ isCreating = computed(() => this.loadingActive().includes(PropertiesActionKey.Create), ...(ngDevMode ? [{ debugName: "isCreating" }] : []));
695
+ isUpdating = computed(() => this.loadingActive().includes(PropertiesActionKey.Update), ...(ngDevMode ? [{ debugName: "isUpdating" }] : []));
696
+ isDeleting = computed(() => this.loadingActive().includes(PropertiesActionKey.Delete), ...(ngDevMode ? [{ debugName: "isDeleting" }] : []));
697
+ isLoadingLookups = computed(() => this.loadingActive().includes(PropertiesActionKey.GetLookups), ...(ngDevMode ? [{ debugName: "isLoadingLookups" }] : []));
698
+ isLoadingGroups = computed(() => this.loadingActive().includes(PropertiesActionKey.GetGroups), ...(ngDevMode ? [{ debugName: "isLoadingGroups" }] : []));
699
+ isLoadingConfigProperties = computed(() => this.loadingActive().includes(PropertiesActionKey.GetConfigProperties), ...(ngDevMode ? [{ debugName: "isLoadingConfigProperties" }] : []));
700
+ isLoadingConfigAsType = computed(() => this.loadingActive().includes(PropertiesActionKey.GetConfigAsType), ...(ngDevMode ? [{ debugName: "isLoadingConfigAsType" }] : []));
701
+ isLoadingCountries = computed(() => this.loadingActive().includes(PropertiesActionKey.GetCountries), ...(ngDevMode ? [{ debugName: "isLoadingCountries" }] : []));
702
+ isTestingApi = computed(() => this.loadingActive().includes(PropertiesActionKey.TestApiConfiguration), ...(ngDevMode ? [{ debugName: "isTestingApi" }] : []));
703
+ // ============================================================================
704
+ // Error Signals - Computed from slice (minimal reactivity)
705
+ // ============================================================================
706
+ allError = computed(() => this.errors()[PropertiesActionKey.GetAll] ?? null, ...(ngDevMode ? [{ debugName: "allError" }] : []));
707
+ oneError = computed(() => this.errors()[PropertiesActionKey.GetOne] ?? null, ...(ngDevMode ? [{ debugName: "oneError" }] : []));
708
+ createError = computed(() => this.errors()[PropertiesActionKey.Create] ?? null, ...(ngDevMode ? [{ debugName: "createError" }] : []));
709
+ updateError = computed(() => this.errors()[PropertiesActionKey.Update] ?? null, ...(ngDevMode ? [{ debugName: "updateError" }] : []));
710
+ deleteError = computed(() => this.errors()[PropertiesActionKey.Delete] ?? null, ...(ngDevMode ? [{ debugName: "deleteError" }] : []));
711
+ lookupsError = computed(() => this.errors()[PropertiesActionKey.GetLookups] ?? null, ...(ngDevMode ? [{ debugName: "lookupsError" }] : []));
712
+ groupsError = computed(() => this.errors()[PropertiesActionKey.GetGroups] ?? null, ...(ngDevMode ? [{ debugName: "groupsError" }] : []));
713
+ configPropertiesError = computed(() => this.errors()[PropertiesActionKey.GetConfigProperties] ?? null, ...(ngDevMode ? [{ debugName: "configPropertiesError" }] : []));
714
+ configAsTypeError = computed(() => this.errors()[PropertiesActionKey.GetConfigAsType] ?? null, ...(ngDevMode ? [{ debugName: "configAsTypeError" }] : []));
715
+ countriesError = computed(() => this.errors()[PropertiesActionKey.GetCountries] ?? null, ...(ngDevMode ? [{ debugName: "countriesError" }] : []));
716
+ apiTestError = computed(() => this.errors()[PropertiesActionKey.TestApiConfiguration] ?? null, ...(ngDevMode ? [{ debugName: "apiTestError" }] : []));
717
+ // ============================================================================
718
+ // Derived Data - Computed from data selectors
719
+ // ============================================================================
694
720
  systemProperties = computed(() => this.list().filter((property) => Boolean(property.isSystem)), ...(ngDevMode ? [{ debugName: "systemProperties" }] : []));
695
721
  customProperties = computed(() => this.list().filter((property) => !Boolean(property.isSystem)), ...(ngDevMode ? [{ debugName: "customProperties" }] : []));
696
- isLoading(loadingName) {
697
- const loadingFactory = select(PropertiesState.isLoadingFactory);
698
- return computed(() => loadingFactory()(loadingName));
699
- }
722
+ // ============================================================================
723
+ // Action Dispatchers
724
+ // ============================================================================
700
725
  loadAll(params) {
701
726
  return this.store.dispatch(new GetProperties(params));
702
727
  }
@@ -843,7 +868,7 @@ class PropertiesList {
843
868
  ], ...(ngDevMode ? [{ debugName: "propertyTypes" }] : []));
844
869
  tableColumns = signal([
845
870
  {
846
- key: 'name',
871
+ key: 'name.display',
847
872
  label: this.transloco.translate('properties.list.columnName'),
848
873
  filterConfig: {
849
874
  type: 'text',
@@ -911,7 +936,7 @@ class PropertiesList {
911
936
  loading: (row) => this.deletingRowIds().includes(row.id),
912
937
  },
913
938
  ], ...(ngDevMode ? [{ debugName: "rowActions" }] : []));
914
- loading = this.facade.isLoading('getAll');
939
+ loading = this.facade.isLoadingAll;
915
940
  tableData = computed(() => {
916
941
  const tab = this.activeTab();
917
942
  const allProperties = this.facade.list();
@@ -939,7 +964,7 @@ class PropertiesList {
939
964
  this.deletingRowIds.update((ids) => [...ids, row.id]);
940
965
  this.facade
941
966
  .delete(row.id)
942
- .pipe(finalize$1(() => {
967
+ .pipe(finalize(() => {
943
968
  this.deletingRowIds.update((ids) => ids.filter((id) => id !== row.id));
944
969
  }))
945
970
  .subscribe();
@@ -996,7 +1021,7 @@ class ApiConfiguration {
996
1021
  schema = signal(null, ...(ngDevMode ? [{ debugName: "schema" }] : []));
997
1022
  isWriting = false;
998
1023
  touched = false;
999
- isTesting = this.facade.isLoading('testApiConfiguration');
1024
+ isTesting = this.facade.isTestingApi;
1000
1025
  apiProperties = this.facade.apiProperties;
1001
1026
  hasDetectedSchema = computed(() => this.apiProperties().length > 0, ...(ngDevMode ? [{ debugName: "hasDetectedSchema" }] : []));
1002
1027
  form = new FormGroup({
@@ -1215,7 +1240,7 @@ class CheckListFormConfiguration {
1215
1240
  key: 'properties',
1216
1241
  cssClass: 'md:col-span-2',
1217
1242
  options: this.configProperties(),
1218
- optionLabel: 'name',
1243
+ optionLabel: 'name.display',
1219
1244
  optionValue: 'key',
1220
1245
  sourceHeader: this.transloco.translate('properties.form.availableProperties'),
1221
1246
  targetHeader: this.transloco.translate('properties.form.selectedProperties'),
@@ -1291,7 +1316,7 @@ class DynamicListConfiguration {
1291
1316
  key: 'properties',
1292
1317
  cssClass: 'md:col-span-2',
1293
1318
  options: this.configProperties(),
1294
- optionLabel: 'name',
1319
+ optionLabel: 'name.display',
1295
1320
  optionValue: 'key',
1296
1321
  sourceHeader: this.transloco.translate('properties.form.availableProperties'),
1297
1322
  targetHeader: this.transloco.translate('properties.form.selectedProperties'),
@@ -1367,7 +1392,7 @@ class EditableListViewConfiguration {
1367
1392
  key: 'Properties',
1368
1393
  cssClass: 'md:col-span-2',
1369
1394
  options: this.configProperties(),
1370
- optionLabel: 'name',
1395
+ optionLabel: 'name.display',
1371
1396
  optionValue: 'key',
1372
1397
  sourceHeader: this.transloco.translate('properties.form.availableProperties'),
1373
1398
  targetHeader: this.transloco.translate('properties.form.selectedProperties'),
@@ -1463,7 +1488,7 @@ class InternalModuleConfiguration {
1463
1488
  type: 'select',
1464
1489
  key: 'property',
1465
1490
  label: this.transloco.translate('properties.form.valueProperty'),
1466
- optionLabel: 'name',
1491
+ optionLabel: 'name.display',
1467
1492
  optionValue: 'key',
1468
1493
  options: this.configProperties(),
1469
1494
  },
@@ -1471,7 +1496,7 @@ class InternalModuleConfiguration {
1471
1496
  cssClass: 'md:col-span-2 mt-2',
1472
1497
  key: 'propertyDetails',
1473
1498
  options: this.configProperties(),
1474
- optionLabel: 'name',
1499
+ optionLabel: 'name.display',
1475
1500
  optionValue: 'key',
1476
1501
  sourceHeader: this.transloco.translate('properties.form.availableProperties'),
1477
1502
  targetHeader: this.transloco.translate('properties.form.selectedProperties'),
@@ -1582,7 +1607,7 @@ class LookupConfiguration {
1582
1607
  key: 'lookup',
1583
1608
  type: 'select',
1584
1609
  label: this.transloco.translate('properties.form.selectLookup'),
1585
- optionLabel: 'name',
1610
+ optionLabel: 'name.display',
1586
1611
  optionValue: 'id',
1587
1612
  options: this.lookups(),
1588
1613
  filter: true,
@@ -1663,7 +1688,7 @@ class UserConfiguration {
1663
1688
  key: 'group',
1664
1689
  type: 'select',
1665
1690
  label: this.transloco.translate('properties.form.selectGroup'),
1666
- optionLabel: 'name',
1691
+ optionLabel: 'name.display',
1667
1692
  optionValue: 'id',
1668
1693
  options: this.groups(),
1669
1694
  filter: true,
@@ -1861,7 +1886,7 @@ class PropertyForm {
1861
1886
  isCalculated: false,
1862
1887
  viewType: null,
1863
1888
  name: { ar: '', en: '' },
1864
- description: '',
1889
+ description: { ar: '', en: '' },
1865
1890
  }),
1866
1891
  configuration: new FormControl(null),
1867
1892
  formula: new FormControl(null),
@@ -1869,9 +1894,9 @@ class PropertyForm {
1869
1894
  mainControl = this.propertyForm.get('main');
1870
1895
  configurationControl = this.propertyForm.get('configuration');
1871
1896
  formulaControl = this.propertyForm.get('formula');
1872
- creating = this.facade.isLoading('create');
1873
- updating = this.facade.isLoading('update');
1874
- loading = this.facade.isLoading('getOne');
1897
+ creating = this.facade.isCreating;
1898
+ updating = this.facade.isUpdating;
1899
+ loading = this.facade.isLoadingOne;
1875
1900
  submitting = computed(() => this.creating() || this.updating(), ...(ngDevMode ? [{ debugName: "submitting" }] : []));
1876
1901
  propertyType = toSignal(this.mainControl.valueChanges.pipe(map((v) => v?.viewType), distinctUntilChanged()));
1877
1902
  isCalculated = toSignal(this.mainControl.valueChanges.pipe(map((v) => Boolean(v?.isCalculated)), distinctUntilChanged()), {
@@ -2002,10 +2027,14 @@ class PropertyForm {
2002
2027
  validators: [new ValidatorConfig({ type: 'required' })],
2003
2028
  },
2004
2029
  {
2005
- key: 'description',
2006
- label: this.transloco.translate('properties.form.description'),
2030
+ key: 'description.en',
2031
+ label: this.transloco.translate('properties.form.englishDescription'),
2032
+ type: 'textarea',
2033
+ },
2034
+ {
2035
+ key: 'description.ar',
2036
+ label: this.transloco.translate('properties.form.arabicDescription'),
2007
2037
  type: 'textarea',
2008
- cssClass: 'md:col-span-2',
2009
2038
  },
2010
2039
  // {
2011
2040
  // key: 'defaultValue',
@@ -2240,5 +2269,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
2240
2269
  * Generated bundle index. Do not edit.
2241
2270
  */
2242
2271
 
2243
- export { CreateProperty, DeleteProperty, GetConfigAsType, GetCountries, GetGroups, GetLookups, GetProperties, GetPropertiesForConfigType, GetProperty, PropertiesFacade, PropertiesList, PropertiesState, PropertyForm, REQUEST_CONTEXT, ResetApiConfiguration, ResetConfigProperties, ResetConfigScopes, ResetSelectedProperty, SetBreadcrumb, SetDefaultViewType, SetPropertiesModuleInfo, SetPropertyTypes, TestApiConfiguration, UpdateProperty };
2272
+ export { CreateProperty, DeleteProperty, GetConfigAsType, GetCountries, GetGroups, GetLookups, GetProperties, GetPropertiesForConfigType, GetProperty, PropertiesActionKey, PropertiesFacade, PropertiesList, PropertiesState, PropertyForm, REQUEST_CONTEXT, ResetApiConfiguration, ResetConfigProperties, ResetConfigScopes, ResetSelectedProperty, SetBreadcrumb, SetDefaultViewType, SetPropertiesModuleInfo, SetPropertyTypes, TestApiConfiguration, UpdateProperty };
2244
2273
  //# sourceMappingURL=masterteam-properties.mjs.map