@masterteam/properties 0.0.28 → 0.0.30

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,39 +18,29 @@ 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';
24
24
  import { SkeletonModule } from 'primeng/skeleton';
25
+ import { FormulaBuilder } from '@masterteam/formula-builder';
25
26
  import { SelectField } from '@masterteam/components/select-field';
26
27
  import { TextField } from '@masterteam/components/text-field';
27
28
  import { ToggleField } from '@masterteam/components/toggle-field';
28
29
 
29
- function startLoading(ctx, loadingName) {
30
- const { loadingActive, errors } = ctx.getState();
31
- if (!loadingActive.includes(loadingName)) {
32
- ctx.patchState({
33
- loadingActive: [...loadingActive, loadingName],
34
- });
35
- }
36
- if (errors && errors[loadingName]) {
37
- const { [loadingName]: _removed, ...rest } = errors;
38
- ctx.patchState({ errors: rest });
39
- }
40
- }
41
- function endLoading(ctx, loadingName) {
42
- const { loadingActive } = ctx.getState();
43
- ctx.patchState({
44
- loadingActive: loadingActive.filter((name) => name !== loadingName),
45
- });
46
- }
47
- function setLoadingError(ctx, loadingName, message) {
48
- const { errors } = ctx.getState();
49
- ctx.patchState({
50
- errors: { ...errors, [loadingName]: message },
51
- });
52
- }
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 = {}));
53
44
 
54
45
  class GetProperties {
55
46
  params;
@@ -197,7 +188,7 @@ const DEFAULT_STATE = {
197
188
  breadcrumbItems: [],
198
189
  defaultViewType: null,
199
190
  };
200
- let PropertiesState = class PropertiesState {
191
+ let PropertiesState = class PropertiesState extends CrudStateBase {
201
192
  http = inject(HttpClient);
202
193
  baseUrl = 'Properties';
203
194
  lookupsUrl = 'Lookups';
@@ -206,12 +197,21 @@ let PropertiesState = class PropertiesState {
206
197
  countriesUrl = '/assets/countries/countries.json';
207
198
  apiTestUrl = 'app/testAPI';
208
199
  apiDetectUrl = 'app/detect';
200
+ // ============================================================================
201
+ // Data Selectors - Individual for fine-grained reactivity
202
+ // ============================================================================
209
203
  static properties(state) {
210
204
  return state.properties;
211
205
  }
212
206
  static selectedProperty(state) {
213
207
  return state.selectedProperty;
214
208
  }
209
+ static moduleId(state) {
210
+ return state.moduleId;
211
+ }
212
+ static parentModuleId(state) {
213
+ return state.parentModuleId ?? null;
214
+ }
215
215
  static lookups(state) {
216
216
  return state.lookups;
217
217
  }
@@ -234,7 +234,7 @@ let PropertiesState = class PropertiesState {
234
234
  return state.apiProperties;
235
235
  }
236
236
  static propertyTypes(state) {
237
- return state.propertyTypes ?? [];
237
+ return state.propertyTypes ?? {};
238
238
  }
239
239
  static breadcrumbItems(state) {
240
240
  return state.breadcrumbItems;
@@ -242,17 +242,25 @@ let PropertiesState = class PropertiesState {
242
242
  static defaultViewType(state) {
243
243
  return state.defaultViewType;
244
244
  }
245
- static isLoadingFactory(state) {
246
- 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;
247
250
  }
248
- static errorFactory(state) {
249
- return (loadingName) => state.errors?.[loadingName] ?? null;
251
+ static getErrors(state) {
252
+ return state.errors;
250
253
  }
254
+ // ============================================================================
255
+ // Derived Selectors
256
+ // ============================================================================
251
257
  static propertyById(state) {
252
258
  return (id) => state.properties.find((property) => property.id === Number(id)) ?? null;
253
259
  }
260
+ // ============================================================================
261
+ // CRUD Actions
262
+ // ============================================================================
254
263
  getAll(ctx, action) {
255
- startLoading(ctx, 'getAll');
256
264
  const state = ctx.getState();
257
265
  const moduleType = state.moduleType ?? undefined;
258
266
  const moduleId = state.moduleId ?? undefined;
@@ -261,67 +269,57 @@ let PropertiesState = class PropertiesState {
261
269
  ctx.patchState({
262
270
  lastQueryParams: params ?? null,
263
271
  });
264
- return this.http
265
- .get(`${this.baseUrl}${parentPath}/${moduleType}/${moduleId}`, {
266
- params: params,
267
- })
268
- .pipe(tap((response) => {
269
- const properties = Array.isArray(response?.data) ? response.data : [];
270
- ctx.patchState({ properties });
271
- }), catchError((error) => {
272
- const message = error?.error?.message ??
273
- error?.message ??
274
- 'Failed to load properties';
275
- setLoadingError(ctx, 'getAll', message);
276
- return of(null);
277
- }), finalize(() => endLoading(ctx, 'getAll')));
272
+ const req$ = this.http.get(`${this.baseUrl}${parentPath}/${moduleType}/${moduleId}`, { params });
273
+ return handleApiRequest({
274
+ ctx,
275
+ key: PropertiesActionKey.GetAll,
276
+ request$: req$,
277
+ onSuccess: (response) => ({
278
+ properties: response.data ?? [],
279
+ }),
280
+ });
278
281
  }
279
282
  getOne(ctx, action) {
280
- startLoading(ctx, 'getOne');
281
283
  const params = { mode: action.mode ?? 'edit' };
282
- return this.http
283
- .get(`${this.baseUrl}/${action.id}`, { params })
284
- .pipe(tap((response) => {
285
- ctx.patchState({
286
- selectedProperty: response?.data ?? null,
287
- });
288
- }), catchError((error) => {
289
- const message = error?.error?.message ??
290
- error?.message ??
291
- 'Failed to load property';
292
- setLoadingError(ctx, 'getOne', message);
293
- return of(null);
294
- }), finalize(() => endLoading(ctx, 'getOne')));
284
+ const req$ = this.http.get(`${this.baseUrl}/${action.id}`, { params });
285
+ return handleApiRequest({
286
+ ctx,
287
+ key: PropertiesActionKey.GetOne,
288
+ request$: req$,
289
+ onSuccess: (response) => ({
290
+ selectedProperty: response.data ?? null,
291
+ }),
292
+ });
295
293
  }
296
294
  getLookups(ctx, _action) {
297
295
  const state = ctx.getState();
298
296
  if (state.lookups.length) {
299
297
  return of(state.lookups);
300
298
  }
301
- startLoading(ctx, 'getLookups');
302
- return this.http.get(this.lookupsUrl).pipe(tap((response) => {
303
- const lookups = Array.isArray(response?.data) ? response.data : [];
304
- ctx.patchState({ lookups });
305
- }), catchError((error) => {
306
- const message = error?.error?.message ?? error?.message ?? 'Failed to load lookups';
307
- setLoadingError(ctx, 'getLookups', message);
308
- return of([]);
309
- }), finalize(() => endLoading(ctx, 'getLookups')));
299
+ const req$ = this.http.get(this.lookupsUrl);
300
+ return handleApiRequest({
301
+ ctx,
302
+ key: PropertiesActionKey.GetLookups,
303
+ request$: req$,
304
+ onSuccess: (response) => ({
305
+ lookups: response.data ?? [],
306
+ }),
307
+ });
310
308
  }
311
309
  getGroups(ctx, _action) {
312
310
  const state = ctx.getState();
313
311
  if (state.groups.length) {
314
312
  return of(state.groups);
315
313
  }
316
- startLoading(ctx, 'getGroups');
317
- return this.http.get(this.groupsUrl).pipe(tap((response) => {
318
- const groups = Array.isArray(response?.data) ? response.data : [];
319
- ctx.patchState({ groups });
320
- }), catchError((error) => {
321
- const message = error?.error?.message ?? error?.message ?? 'Failed to load groups';
322
- setLoadingError(ctx, 'getGroups', message);
323
- return of([]);
324
- }), finalize(() => endLoading(ctx, 'getGroups')));
314
+ const req$ = this.http.get(this.groupsUrl);
315
+ return handleApiRequest({
316
+ ctx,
317
+ key: PropertiesActionKey.GetGroups,
318
+ request$: req$,
319
+ onSuccess: (response) => ({
320
+ groups: response.data ?? [],
321
+ }),
322
+ });
325
323
  }
326
324
  getConfigAsType(ctx, action) {
327
325
  const state = ctx.getState();
@@ -329,41 +327,41 @@ let PropertiesState = class PropertiesState {
329
327
  if (state.configScopes.length) {
330
328
  return of(state.configScopes);
331
329
  }
332
- startLoading(ctx, 'getConfigAsType');
333
330
  const url = `${this.baseUrl}/${action.viewType}/GetViewTypeProperties`;
334
- return this.http.get(url).pipe(tap((response) => {
335
- const configScopes = Array.isArray(response?.data) ? response.data : [];
336
- ctx.patchState({ configScopes });
337
- }), catchError((error) => {
338
- const message = error?.error?.message ??
339
- error?.message ??
340
- 'Failed to load configuration scopes';
341
- setLoadingError(ctx, 'getConfigAsType', message);
342
- return of([]);
343
- }), finalize(() => endLoading(ctx, 'getConfigAsType')));
331
+ const req$ = this.http.get(url);
332
+ return handleApiRequest({
333
+ ctx,
334
+ key: PropertiesActionKey.GetConfigAsType,
335
+ request$: req$,
336
+ onSuccess: (response) => ({
337
+ configScopes: response.data ?? [],
338
+ }),
339
+ });
344
340
  }
345
341
  getCountries(ctx, _action) {
346
342
  const state = ctx.getState();
347
343
  if (state.countries.length) {
348
344
  return of(state.countries);
349
345
  }
350
- startLoading(ctx, 'getCountries');
351
- return this.http.get(this.countriesUrl).pipe(tap((response) => {
352
- const countries = Array.isArray(response) ? response : [];
353
- ctx.patchState({ countries });
354
- }), catchError((error) => {
355
- const message = error?.error?.message ?? error?.message ?? 'Failed to load countries';
356
- setLoadingError(ctx, 'getCountries', message);
357
- return of([]);
358
- }), finalize(() => endLoading(ctx, 'getCountries')));
346
+ const req$ = this.http.get(this.countriesUrl);
347
+ return handleApiRequest({
348
+ ctx,
349
+ key: PropertiesActionKey.GetCountries,
350
+ request$: req$,
351
+ onSuccess: (response) => ({
352
+ countries: Array.isArray(response) ? response : [],
353
+ }),
354
+ errorMessage: 'Failed to load countries',
355
+ });
359
356
  }
360
357
  testApiConfiguration(ctx, action) {
361
- startLoading(ctx, 'testApiConfiguration');
362
358
  ctx.patchState({
363
359
  apiSchema: null,
364
360
  apiProperties: [],
365
361
  });
366
- return this.http.post(this.apiTestUrl, action.payload).pipe(switchMap((testResponse) => {
362
+ const req$ = this.http
363
+ .post(this.apiTestUrl, action.payload)
364
+ .pipe(switchMap((testResponse) => {
367
365
  const rawData = testResponse?.data;
368
366
  if (!rawData) {
369
367
  return of(null);
@@ -380,49 +378,29 @@ let PropertiesState = class PropertiesState {
380
378
  apiProperties,
381
379
  });
382
380
  }));
383
- }), catchError((error) => {
384
- const message = error?.error?.message ?? error?.message ?? 'Failed to test API';
385
- setLoadingError(ctx, 'testApiConfiguration', message);
386
- return of(null);
387
- }), finalize(() => endLoading(ctx, 'testApiConfiguration')));
388
- }
389
- resetApiConfiguration(ctx) {
390
- ctx.patchState({
391
- apiSchema: null,
392
- apiProperties: [],
393
- });
394
- }
395
- mapSchemaToOptions(schema) {
396
- if (!schema?.properties) {
397
- return [];
398
- }
399
- return Object.entries(schema.properties).map(([key, definition]) => {
400
- const typeLabel = definition?.type ? ` | ${definition.type}` : '';
401
- return {
402
- key,
403
- name: `${key}${typeLabel}`,
404
- type: definition?.type,
405
- };
381
+ }));
382
+ return handleApiRequest({
383
+ ctx,
384
+ key: PropertiesActionKey.TestApiConfiguration,
385
+ request$: req$,
386
+ onSuccess: () => ({}),
406
387
  });
407
388
  }
408
389
  getPropertiesForConfigType(ctx, action) {
409
- startLoading(ctx, 'getConfigProperties');
410
390
  const { moduleType, moduleId } = action;
411
- return this.http
412
- .get(`${this.configPropertiesUrl}/${moduleType}/${moduleId}`)
413
- .pipe(tap((response) => {
414
- const configTypeProperties = Array.isArray(response?.data)
415
- ? response.data
416
- : [];
417
- ctx.patchState({ configTypeProperties });
418
- }), catchError((error) => {
419
- const message = error?.error?.message ??
420
- error?.message ??
421
- 'Failed to load properties';
422
- setLoadingError(ctx, 'getConfigProperties', message);
423
- return of([]);
424
- }), finalize(() => endLoading(ctx, 'getConfigProperties')));
391
+ const req$ = this.http.get(`${this.configPropertiesUrl}/${moduleType}/${moduleId}`);
392
+ return handleApiRequest({
393
+ ctx,
394
+ key: PropertiesActionKey.GetConfigProperties,
395
+ request$: req$,
396
+ onSuccess: (response) => ({
397
+ configTypeProperties: response.data ?? [],
398
+ }),
399
+ });
425
400
  }
401
+ // ============================================================================
402
+ // Simple State Updates (No HTTP)
403
+ // ============================================================================
426
404
  resetConfigProperties(ctx) {
427
405
  ctx.patchState({ configTypeProperties: [] });
428
406
  }
@@ -432,6 +410,12 @@ let PropertiesState = class PropertiesState {
432
410
  resetSelectedProperty(ctx) {
433
411
  ctx.patchState({ selectedProperty: null });
434
412
  }
413
+ resetApiConfiguration(ctx) {
414
+ ctx.patchState({
415
+ apiSchema: null,
416
+ apiProperties: [],
417
+ });
418
+ }
435
419
  setModuleInfo(ctx, action) {
436
420
  let parentPath = '';
437
421
  if (action.parentModuleType && action.parentModuleId) {
@@ -448,106 +432,107 @@ let PropertiesState = class PropertiesState {
448
432
  parentPath: parentPath ?? '',
449
433
  });
450
434
  }
451
- create(ctx, action) {
452
- startLoading(ctx, 'create');
435
+ SetPropertyTypes(ctx, action) {
436
+ ctx.patchState({
437
+ propertyTypes: action.payload,
438
+ });
439
+ }
440
+ setBreadcrumb(ctx, action) {
441
+ ctx.patchState({
442
+ breadcrumbItems: action.items,
443
+ });
444
+ }
445
+ setDefaultViewType(ctx, action) {
446
+ ctx.patchState({
447
+ defaultViewType: action.viewType,
448
+ });
449
+ }
450
+ createProperty(ctx, action) {
453
451
  const state = ctx.getState();
454
452
  const moduleType = state.moduleType ?? undefined;
455
453
  const moduleId = state.moduleId ?? undefined;
456
454
  const parentPath = state.parentPath ?? '';
457
455
  if (!moduleType || moduleId === undefined || moduleId === null) {
458
- const message = 'Missing module context for creating property';
459
- setLoadingError(ctx, 'create', message);
460
- endLoading(ctx, 'create');
456
+ console.error('Missing module context for creating property');
461
457
  return of(null);
462
458
  }
463
- return this.http
464
- .post(`${this.baseUrl}${parentPath}/${moduleType}/${moduleId}`, action.payload)
465
- .pipe(tap((response) => {
466
- const created = response?.data;
467
- if (!created) {
468
- return;
469
- }
470
- const state = ctx.getState();
471
- ctx.patchState({
472
- properties: [...state.properties, created],
473
- selectedProperty: created,
474
- });
475
- }), finalize(() => endLoading(ctx, 'create')));
459
+ const req$ = this.http.post(`${this.baseUrl}${parentPath}/${moduleType}/${moduleId}`, action.payload);
460
+ return handleApiRequest({
461
+ ctx,
462
+ key: PropertiesActionKey.Create,
463
+ request$: req$,
464
+ onSuccess: (response, state) => {
465
+ const created = response.data;
466
+ if (!created)
467
+ return {};
468
+ return {
469
+ properties: this.adapter.addOne(state.properties, created),
470
+ selectedProperty: created,
471
+ };
472
+ },
473
+ });
476
474
  }
477
- update(ctx, action) {
478
- startLoading(ctx, 'update');
475
+ updateProperty(ctx, action) {
479
476
  const state = ctx.getState();
480
477
  const moduleType = state.moduleType ?? undefined;
481
478
  const moduleId = state.moduleId ?? undefined;
482
479
  const parentPath = state.parentPath ?? '';
483
480
  if (!moduleType || moduleId === undefined || moduleId === null) {
484
- const message = 'Missing module context for updating property';
485
- setLoadingError(ctx, 'update', message);
486
- endLoading(ctx, 'update');
481
+ console.error('Missing module context for updating property');
487
482
  return of(null);
488
483
  }
489
- return this.http
490
- .put(`${this.baseUrl}${parentPath}/${moduleType}/${moduleId}/${action.id}`, action.payload)
491
- .pipe(tap((response) => {
492
- const updated = response?.data;
493
- if (!updated) {
494
- return;
495
- }
496
- const updatedId = updated.id ?? Number(action.id);
497
- const state = ctx.getState();
498
- const properties = state.properties.some((item) => item.id === updatedId)
499
- ? state.properties.map((item) => item.id === updatedId ? { ...item, ...updated } : item)
500
- : [...state.properties, updated];
501
- ctx.patchState({
502
- properties,
503
- selectedProperty: updated,
504
- });
505
- }), catchError((error) => {
506
- const message = error?.error?.message ??
507
- error?.message ??
508
- 'Failed to update property';
509
- setLoadingError(ctx, 'update', message);
510
- return of(null);
511
- }), finalize(() => endLoading(ctx, 'update')));
512
- }
513
- delete(ctx, action) {
514
- startLoading(ctx, 'delete');
515
- return this.http
516
- .delete(`${this.baseUrl}/${encodeURIComponent(String(action.id))}`)
517
- .pipe(tap(() => {
518
- const { properties, selectedProperty } = ctx.getState();
519
- const remaining = properties.filter((item) => item.id !== Number(action.id));
520
- const nextSelected = selectedProperty && selectedProperty.id === Number(action.id)
521
- ? null
522
- : selectedProperty;
523
- ctx.patchState({
524
- properties: remaining,
525
- selectedProperty: nextSelected,
526
- });
527
- }), catchError((error) => {
528
- const message = error?.error?.message ??
529
- error?.message ??
530
- 'Failed to delete property';
531
- setLoadingError(ctx, 'delete', message);
532
- return of(null);
533
- }), finalize(() => endLoading(ctx, 'delete')));
534
- }
535
- SetPropertyTypes(ctx, action) {
536
- ctx.patchState({
537
- propertyTypes: action.payload,
484
+ const req$ = this.http.put(`${this.baseUrl}${parentPath}/${moduleType}/${moduleId}/${action.id}`, action.payload);
485
+ return handleApiRequest({
486
+ ctx,
487
+ key: PropertiesActionKey.Update,
488
+ request$: req$,
489
+ onSuccess: (response, state) => {
490
+ const updated = response.data;
491
+ if (!updated)
492
+ return {};
493
+ return {
494
+ properties: this.adapter.upsertOne(state.properties, updated, 'id'),
495
+ selectedProperty: updated,
496
+ };
497
+ },
538
498
  });
539
499
  }
540
- setBreadcrumb(ctx, action) {
541
- ctx.patchState({
542
- breadcrumbItems: action.items,
500
+ deleteProperty(ctx, action) {
501
+ const req$ = this.http.delete(`${this.baseUrl}/${encodeURIComponent(String(action.id))}`);
502
+ return handleApiRequest({
503
+ ctx,
504
+ key: PropertiesActionKey.Delete,
505
+ request$: req$,
506
+ onSuccess: (_, state) => {
507
+ const remaining = this.adapter.removeOne(state.properties, Number(action.id), 'id');
508
+ const nextSelected = state.selectedProperty &&
509
+ state.selectedProperty.id === Number(action.id)
510
+ ? null
511
+ : state.selectedProperty;
512
+ return {
513
+ properties: remaining,
514
+ selectedProperty: nextSelected,
515
+ };
516
+ },
543
517
  });
544
518
  }
545
- setDefaultViewType(ctx, action) {
546
- ctx.patchState({
547
- defaultViewType: action.viewType,
519
+ // ============================================================================
520
+ // Helper Methods
521
+ // ============================================================================
522
+ mapSchemaToOptions(schema) {
523
+ if (!schema?.properties) {
524
+ return [];
525
+ }
526
+ return Object.entries(schema.properties).map(([key, definition]) => {
527
+ const typeLabel = definition?.type ? ` | ${definition.type}` : '';
528
+ return {
529
+ key,
530
+ name: `${key}${typeLabel}`,
531
+ type: definition?.type,
532
+ };
548
533
  });
549
534
  }
550
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertiesState, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
535
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertiesState, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
551
536
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertiesState });
552
537
  };
553
538
  __decorate([
@@ -571,9 +556,6 @@ __decorate([
571
556
  __decorate([
572
557
  Action(TestApiConfiguration)
573
558
  ], PropertiesState.prototype, "testApiConfiguration", null);
574
- __decorate([
575
- Action(ResetApiConfiguration)
576
- ], PropertiesState.prototype, "resetApiConfiguration", null);
577
559
  __decorate([
578
560
  Action(GetPropertiesForConfigType)
579
561
  ], PropertiesState.prototype, "getPropertiesForConfigType", null);
@@ -586,18 +568,12 @@ __decorate([
586
568
  __decorate([
587
569
  Action(ResetSelectedProperty)
588
570
  ], PropertiesState.prototype, "resetSelectedProperty", null);
571
+ __decorate([
572
+ Action(ResetApiConfiguration)
573
+ ], PropertiesState.prototype, "resetApiConfiguration", null);
589
574
  __decorate([
590
575
  Action(SetPropertiesModuleInfo)
591
576
  ], PropertiesState.prototype, "setModuleInfo", null);
592
- __decorate([
593
- Action(CreateProperty)
594
- ], PropertiesState.prototype, "create", null);
595
- __decorate([
596
- Action(UpdateProperty)
597
- ], PropertiesState.prototype, "update", null);
598
- __decorate([
599
- Action(DeleteProperty)
600
- ], PropertiesState.prototype, "delete", null);
601
577
  __decorate([
602
578
  Action(SetPropertyTypes)
603
579
  ], PropertiesState.prototype, "SetPropertyTypes", null);
@@ -607,12 +583,27 @@ __decorate([
607
583
  __decorate([
608
584
  Action(SetDefaultViewType)
609
585
  ], PropertiesState.prototype, "setDefaultViewType", null);
586
+ __decorate([
587
+ Action(CreateProperty)
588
+ ], PropertiesState.prototype, "createProperty", null);
589
+ __decorate([
590
+ Action(UpdateProperty)
591
+ ], PropertiesState.prototype, "updateProperty", null);
592
+ __decorate([
593
+ Action(DeleteProperty)
594
+ ], PropertiesState.prototype, "deleteProperty", null);
610
595
  __decorate([
611
596
  Selector()
612
597
  ], PropertiesState, "properties", null);
613
598
  __decorate([
614
599
  Selector()
615
600
  ], PropertiesState, "selectedProperty", null);
601
+ __decorate([
602
+ Selector()
603
+ ], PropertiesState, "moduleId", null);
604
+ __decorate([
605
+ Selector()
606
+ ], PropertiesState, "parentModuleId", null);
616
607
  __decorate([
617
608
  Selector()
618
609
  ], PropertiesState, "lookups", null);
@@ -645,10 +636,10 @@ __decorate([
645
636
  ], PropertiesState, "defaultViewType", null);
646
637
  __decorate([
647
638
  Selector()
648
- ], PropertiesState, "isLoadingFactory", null);
639
+ ], PropertiesState, "getLoadingActive", null);
649
640
  __decorate([
650
641
  Selector()
651
- ], PropertiesState, "errorFactory", null);
642
+ ], PropertiesState, "getErrors", null);
652
643
  __decorate([
653
644
  Selector()
654
645
  ], PropertiesState, "propertyById", null);
@@ -660,13 +651,18 @@ PropertiesState = __decorate([
660
651
  ], PropertiesState);
661
652
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertiesState, decorators: [{
662
653
  type: Injectable
663
- }], propDecorators: { getAll: [], getOne: [], getLookups: [], getGroups: [], getConfigAsType: [], getCountries: [], testApiConfiguration: [], resetApiConfiguration: [], getPropertiesForConfigType: [], resetConfigProperties: [], resetConfigScopes: [], resetSelectedProperty: [], setModuleInfo: [], create: [], update: [], delete: [], SetPropertyTypes: [], setBreadcrumb: [], setDefaultViewType: [] } });
654
+ }], propDecorators: { getAll: [], getOne: [], getLookups: [], getGroups: [], getConfigAsType: [], getCountries: [], testApiConfiguration: [], getPropertiesForConfigType: [], resetConfigProperties: [], resetConfigScopes: [], resetSelectedProperty: [], resetApiConfiguration: [], setModuleInfo: [], SetPropertyTypes: [], setBreadcrumb: [], setDefaultViewType: [], createProperty: [], updateProperty: [], deleteProperty: [] } });
664
655
 
665
656
  class PropertiesFacade {
666
657
  store = inject(Store);
658
+ // ============================================================================
659
+ // Data Selectors - Memoized by NGXS (fine-grained reactivity)
660
+ // ============================================================================
667
661
  list = select(PropertiesState.properties);
668
662
  propertyTypes = select(PropertiesState.propertyTypes);
669
663
  selected = select(PropertiesState.selectedProperty);
664
+ moduleId = select(PropertiesState.moduleId);
665
+ parentModuleId = select(PropertiesState.parentModuleId);
670
666
  lookups = select(PropertiesState.lookups);
671
667
  configProperties = select(PropertiesState.configTypeProperties);
672
668
  groups = select(PropertiesState.groups);
@@ -676,12 +672,47 @@ class PropertiesFacade {
676
672
  apiProperties = select(PropertiesState.apiProperties);
677
673
  breadcrumbItems = select(PropertiesState.breadcrumbItems);
678
674
  defaultViewType = select(PropertiesState.defaultViewType);
675
+ // ============================================================================
676
+ // Loading/Error Slices - Memoized by NGXS
677
+ // ============================================================================
678
+ loadingActive = select(PropertiesState.getLoadingActive);
679
+ errors = select(PropertiesState.getErrors);
680
+ // ============================================================================
681
+ // Loading Signals - Computed from slice (minimal reactivity)
682
+ // ============================================================================
683
+ isLoadingAll = computed(() => this.loadingActive().includes(PropertiesActionKey.GetAll), ...(ngDevMode ? [{ debugName: "isLoadingAll" }] : []));
684
+ isLoadingOne = computed(() => this.loadingActive().includes(PropertiesActionKey.GetOne), ...(ngDevMode ? [{ debugName: "isLoadingOne" }] : []));
685
+ isCreating = computed(() => this.loadingActive().includes(PropertiesActionKey.Create), ...(ngDevMode ? [{ debugName: "isCreating" }] : []));
686
+ isUpdating = computed(() => this.loadingActive().includes(PropertiesActionKey.Update), ...(ngDevMode ? [{ debugName: "isUpdating" }] : []));
687
+ isDeleting = computed(() => this.loadingActive().includes(PropertiesActionKey.Delete), ...(ngDevMode ? [{ debugName: "isDeleting" }] : []));
688
+ isLoadingLookups = computed(() => this.loadingActive().includes(PropertiesActionKey.GetLookups), ...(ngDevMode ? [{ debugName: "isLoadingLookups" }] : []));
689
+ isLoadingGroups = computed(() => this.loadingActive().includes(PropertiesActionKey.GetGroups), ...(ngDevMode ? [{ debugName: "isLoadingGroups" }] : []));
690
+ isLoadingConfigProperties = computed(() => this.loadingActive().includes(PropertiesActionKey.GetConfigProperties), ...(ngDevMode ? [{ debugName: "isLoadingConfigProperties" }] : []));
691
+ isLoadingConfigAsType = computed(() => this.loadingActive().includes(PropertiesActionKey.GetConfigAsType), ...(ngDevMode ? [{ debugName: "isLoadingConfigAsType" }] : []));
692
+ isLoadingCountries = computed(() => this.loadingActive().includes(PropertiesActionKey.GetCountries), ...(ngDevMode ? [{ debugName: "isLoadingCountries" }] : []));
693
+ isTestingApi = computed(() => this.loadingActive().includes(PropertiesActionKey.TestApiConfiguration), ...(ngDevMode ? [{ debugName: "isTestingApi" }] : []));
694
+ // ============================================================================
695
+ // Error Signals - Computed from slice (minimal reactivity)
696
+ // ============================================================================
697
+ allError = computed(() => this.errors()[PropertiesActionKey.GetAll] ?? null, ...(ngDevMode ? [{ debugName: "allError" }] : []));
698
+ oneError = computed(() => this.errors()[PropertiesActionKey.GetOne] ?? null, ...(ngDevMode ? [{ debugName: "oneError" }] : []));
699
+ createError = computed(() => this.errors()[PropertiesActionKey.Create] ?? null, ...(ngDevMode ? [{ debugName: "createError" }] : []));
700
+ updateError = computed(() => this.errors()[PropertiesActionKey.Update] ?? null, ...(ngDevMode ? [{ debugName: "updateError" }] : []));
701
+ deleteError = computed(() => this.errors()[PropertiesActionKey.Delete] ?? null, ...(ngDevMode ? [{ debugName: "deleteError" }] : []));
702
+ lookupsError = computed(() => this.errors()[PropertiesActionKey.GetLookups] ?? null, ...(ngDevMode ? [{ debugName: "lookupsError" }] : []));
703
+ groupsError = computed(() => this.errors()[PropertiesActionKey.GetGroups] ?? null, ...(ngDevMode ? [{ debugName: "groupsError" }] : []));
704
+ configPropertiesError = computed(() => this.errors()[PropertiesActionKey.GetConfigProperties] ?? null, ...(ngDevMode ? [{ debugName: "configPropertiesError" }] : []));
705
+ configAsTypeError = computed(() => this.errors()[PropertiesActionKey.GetConfigAsType] ?? null, ...(ngDevMode ? [{ debugName: "configAsTypeError" }] : []));
706
+ countriesError = computed(() => this.errors()[PropertiesActionKey.GetCountries] ?? null, ...(ngDevMode ? [{ debugName: "countriesError" }] : []));
707
+ apiTestError = computed(() => this.errors()[PropertiesActionKey.TestApiConfiguration] ?? null, ...(ngDevMode ? [{ debugName: "apiTestError" }] : []));
708
+ // ============================================================================
709
+ // Derived Data - Computed from data selectors
710
+ // ============================================================================
679
711
  systemProperties = computed(() => this.list().filter((property) => Boolean(property.isSystem)), ...(ngDevMode ? [{ debugName: "systemProperties" }] : []));
680
712
  customProperties = computed(() => this.list().filter((property) => !Boolean(property.isSystem)), ...(ngDevMode ? [{ debugName: "customProperties" }] : []));
681
- isLoading(loadingName) {
682
- const loadingFactory = select(PropertiesState.isLoadingFactory);
683
- return computed(() => loadingFactory()(loadingName));
684
- }
713
+ // ============================================================================
714
+ // Action Dispatchers
715
+ // ============================================================================
685
716
  loadAll(params) {
686
717
  return this.store.dispatch(new GetProperties(params));
687
718
  }
@@ -828,7 +859,7 @@ class PropertiesList {
828
859
  ], ...(ngDevMode ? [{ debugName: "propertyTypes" }] : []));
829
860
  tableColumns = signal([
830
861
  {
831
- key: 'name',
862
+ key: 'name.display',
832
863
  label: this.transloco.translate('properties.list.columnName'),
833
864
  filterConfig: {
834
865
  type: 'text',
@@ -896,7 +927,7 @@ class PropertiesList {
896
927
  loading: (row) => this.deletingRowIds().includes(row.id),
897
928
  },
898
929
  ], ...(ngDevMode ? [{ debugName: "rowActions" }] : []));
899
- loading = this.facade.isLoading('getAll');
930
+ loading = this.facade.isLoadingAll;
900
931
  tableData = computed(() => {
901
932
  const tab = this.activeTab();
902
933
  const allProperties = this.facade.list();
@@ -924,7 +955,7 @@ class PropertiesList {
924
955
  this.deletingRowIds.update((ids) => [...ids, row.id]);
925
956
  this.facade
926
957
  .delete(row.id)
927
- .pipe(finalize$1(() => {
958
+ .pipe(finalize(() => {
928
959
  this.deletingRowIds.update((ids) => ids.filter((id) => id !== row.id));
929
960
  }))
930
961
  .subscribe();
@@ -981,7 +1012,7 @@ class ApiConfiguration {
981
1012
  schema = signal(null, ...(ngDevMode ? [{ debugName: "schema" }] : []));
982
1013
  isWriting = false;
983
1014
  touched = false;
984
- isTesting = this.facade.isLoading('testApiConfiguration');
1015
+ isTesting = this.facade.isTestingApi;
985
1016
  apiProperties = this.facade.apiProperties;
986
1017
  hasDetectedSchema = computed(() => this.apiProperties().length > 0, ...(ngDevMode ? [{ debugName: "hasDetectedSchema" }] : []));
987
1018
  form = new FormGroup({
@@ -1200,7 +1231,7 @@ class CheckListFormConfiguration {
1200
1231
  key: 'properties',
1201
1232
  cssClass: 'md:col-span-2',
1202
1233
  options: this.configProperties(),
1203
- optionLabel: 'name',
1234
+ optionLabel: 'name.display',
1204
1235
  optionValue: 'key',
1205
1236
  sourceHeader: this.transloco.translate('properties.form.availableProperties'),
1206
1237
  targetHeader: this.transloco.translate('properties.form.selectedProperties'),
@@ -1276,7 +1307,7 @@ class DynamicListConfiguration {
1276
1307
  key: 'properties',
1277
1308
  cssClass: 'md:col-span-2',
1278
1309
  options: this.configProperties(),
1279
- optionLabel: 'name',
1310
+ optionLabel: 'name.display',
1280
1311
  optionValue: 'key',
1281
1312
  sourceHeader: this.transloco.translate('properties.form.availableProperties'),
1282
1313
  targetHeader: this.transloco.translate('properties.form.selectedProperties'),
@@ -1352,7 +1383,7 @@ class EditableListViewConfiguration {
1352
1383
  key: 'Properties',
1353
1384
  cssClass: 'md:col-span-2',
1354
1385
  options: this.configProperties(),
1355
- optionLabel: 'name',
1386
+ optionLabel: 'name.display',
1356
1387
  optionValue: 'key',
1357
1388
  sourceHeader: this.transloco.translate('properties.form.availableProperties'),
1358
1389
  targetHeader: this.transloco.translate('properties.form.selectedProperties'),
@@ -1448,7 +1479,7 @@ class InternalModuleConfiguration {
1448
1479
  type: 'select',
1449
1480
  key: 'property',
1450
1481
  label: this.transloco.translate('properties.form.valueProperty'),
1451
- optionLabel: 'name',
1482
+ optionLabel: 'name.display',
1452
1483
  optionValue: 'key',
1453
1484
  options: this.configProperties(),
1454
1485
  },
@@ -1456,7 +1487,7 @@ class InternalModuleConfiguration {
1456
1487
  cssClass: 'md:col-span-2 mt-2',
1457
1488
  key: 'propertyDetails',
1458
1489
  options: this.configProperties(),
1459
- optionLabel: 'name',
1490
+ optionLabel: 'name.display',
1460
1491
  optionValue: 'key',
1461
1492
  sourceHeader: this.transloco.translate('properties.form.availableProperties'),
1462
1493
  targetHeader: this.transloco.translate('properties.form.selectedProperties'),
@@ -1567,7 +1598,7 @@ class LookupConfiguration {
1567
1598
  key: 'lookup',
1568
1599
  type: 'select',
1569
1600
  label: this.transloco.translate('properties.form.selectLookup'),
1570
- optionLabel: 'name',
1601
+ optionLabel: 'name.display',
1571
1602
  optionValue: 'id',
1572
1603
  options: this.lookups(),
1573
1604
  filter: true,
@@ -1648,7 +1679,7 @@ class UserConfiguration {
1648
1679
  key: 'group',
1649
1680
  type: 'select',
1650
1681
  label: this.transloco.translate('properties.form.selectGroup'),
1651
- optionLabel: 'name',
1682
+ optionLabel: 'name.display',
1652
1683
  optionValue: 'id',
1653
1684
  options: this.groups(),
1654
1685
  filter: true,
@@ -1849,14 +1880,20 @@ class PropertyForm {
1849
1880
  description: '',
1850
1881
  }),
1851
1882
  configuration: new FormControl(null),
1883
+ formula: new FormControl(null),
1852
1884
  });
1853
1885
  mainControl = this.propertyForm.get('main');
1854
1886
  configurationControl = this.propertyForm.get('configuration');
1855
- creating = this.facade.isLoading('create');
1856
- updating = this.facade.isLoading('update');
1857
- loading = this.facade.isLoading('getOne');
1887
+ formulaControl = this.propertyForm.get('formula');
1888
+ creating = this.facade.isCreating;
1889
+ updating = this.facade.isUpdating;
1890
+ loading = this.facade.isLoadingOne;
1858
1891
  submitting = computed(() => this.creating() || this.updating(), ...(ngDevMode ? [{ debugName: "submitting" }] : []));
1859
1892
  propertyType = toSignal(this.mainControl.valueChanges.pipe(map((v) => v?.viewType), distinctUntilChanged()));
1893
+ isCalculated = toSignal(this.mainControl.valueChanges.pipe(map((v) => Boolean(v?.isCalculated)), distinctUntilChanged()), {
1894
+ initialValue: Boolean(this.mainControl.value?.isCalculated),
1895
+ });
1896
+ formulaSchemaId = computed(() => this.resolveSchemaId(this.facade.parentModuleId() ?? this.facade.moduleId()), ...(ngDevMode ? [{ debugName: "formulaSchemaId" }] : []));
1860
1897
  selectedPropertyTypeConfiguration = computed(() => {
1861
1898
  const propertyTypesSetting = this.propertyTypes();
1862
1899
  const selectedViewType = this.propertyType();
@@ -2135,12 +2172,20 @@ class PropertyForm {
2135
2172
  // Direct component type
2136
2173
  this.configurationComponentType.set(result);
2137
2174
  }
2175
+ resolveSchemaId(value) {
2176
+ if (value === null || value === undefined) {
2177
+ return undefined;
2178
+ }
2179
+ const parsed = typeof value === 'string' ? Number(value) : value;
2180
+ return Number.isFinite(parsed) ? parsed : undefined;
2181
+ }
2138
2182
  createOrEditProperty() {
2139
2183
  const mainValue = this.mainControl.value;
2140
2184
  if (!mainValue)
2141
2185
  return;
2142
2186
  const payload = {
2143
2187
  ...mainValue,
2188
+ formula: mainValue.isCalculated ? this.formulaControl.value : null,
2144
2189
  Configuration: this.configurationControl.value ?? mainValue.Configuration ?? null,
2145
2190
  };
2146
2191
  const request$ = this.propertyId()
@@ -2155,6 +2200,9 @@ class PropertyForm {
2155
2200
  emitEvent: false,
2156
2201
  });
2157
2202
  this.configurationControl.setValue(property?.configuration);
2203
+ this.formulaControl.setValue(property.formula ?? null, {
2204
+ emitEvent: false,
2205
+ });
2158
2206
  }
2159
2207
  goBack() {
2160
2208
  const path = this.isEditing()
@@ -2171,15 +2219,17 @@ class PropertyForm {
2171
2219
  this.destroyConfigurationComponent();
2172
2220
  }
2173
2221
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertyForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
2174
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: PropertyForm, isStandalone: true, selector: "mt-property-form", inputs: { propertyId: { classPropertyName: "propertyId", publicName: "propertyId", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "configurationHost", first: true, predicate: ["configurationHost"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<mt-page\r\n [title]=\"\r\n propertyId()\r\n ? ('properties.form.editProperty' | transloco)\r\n : ('properties.form.createNewProperty' | transloco)\r\n \"\r\n avatarIcon=\"custom.products-and-services\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-sky-50)',\r\n '--p-avatar-color': 'var(--p-sky-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n class=\"h-full\"\r\n>\r\n <ng-template #headerEnd>\r\n <mt-button\r\n class=\"mx-2\"\r\n [label]=\"submitLabel()\"\r\n [icon]=\"isEditing() ? 'custom.pencil' : 'general.plus'\"\r\n [loading]=\"submitting()\"\r\n [disabled]=\"submitDisabled() || this.propertyForm.invalid\"\r\n (click)=\"createOrEditProperty()\"\r\n />\r\n </ng-template>\r\n <div\r\n [formGroup]=\"propertyForm\"\r\n class=\"h-full py-4 h-full overflow-y-auto flex justify-center\"\r\n >\r\n <div class=\"w-1/2 flex flex-col gap-6\">\r\n @if (loading()) {\r\n <!-- Skeleton Loading State -->\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <div class=\"flex justify-between items-center gap-6\">\r\n <p-skeleton width=\"50%\" height=\"3rem\"></p-skeleton>\r\n <p-skeleton width=\"8rem\" height=\"2.5rem\"></p-skeleton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <p-skeleton\r\n width=\"12rem\"\r\n height=\"1.5rem\"\r\n styleClass=\"mb-4\"\r\n ></p-skeleton>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"6rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n <p-skeleton height=\"3rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <p-skeleton\r\n width=\"10rem\"\r\n height=\"1.5rem\"\r\n styleClass=\"mb-4\"\r\n ></p-skeleton>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"8rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n } @else {\r\n <mt-dynamic-form\r\n [formConfig]=\"dynamicFormConfigMain()\"\r\n [formControlName]=\"'main'\"\r\n />\r\n @if (configurationFormConfig()) {\r\n <mt-dynamic-form\r\n formControlName=\"configuration\"\r\n [formConfig]=\"configurationFormConfig()!\"\r\n />\r\n } @else {\r\n <ng-container #configurationHost></ng-container>\r\n @if (!configurationComponentExists()) {\r\n @switch (propertyType()) {\r\n @case (\"User\") {\r\n <mt-user-configuration />\r\n }\r\n @case (\"Percentage\") {\r\n <mt-percentage-configuration />\r\n }\r\n @case (\"Lookup\") {\r\n <mt-lookup-configuration />\r\n }\r\n @case (\"LookupMultiSelect\") {\r\n <mt-lookup-configuration />\r\n }\r\n @case (\"InternalModule\") {\r\n <mt-internal-module-configuration />\r\n }\r\n @case (\"DynamicList\") {\r\n <mt-dynamic-list-configuration />\r\n }\r\n @case (\"API\") {\r\n <mt-api-configuration formControlName=\"configuration\" />\r\n }\r\n <!-- @case('ViewList') { REMOVED FOR NOW\r\n <mt-view-list-configuration />\r\n } -->\r\n @case (\"Attachment\") {\r\n <mt-attachment-configuration />\r\n }\r\n <!-- @case('ReferenceProperty') { REMOVED FOR NOW\r\n } -->\r\n @case (\"EditableListView\") {\r\n <mt-editable-list-view-configuration />\r\n }\r\n @case (\"LookupLog\") {\r\n <mt-check-list-form-configuration />\r\n }\r\n <!-- @case('LookupMatrix') { REMOVED FOR NOW\r\n <mt-lookup-configuration />\r\n } -->\r\n @case (\"Location\") {\r\n <mt-location-configuration />\r\n }\r\n }\r\n }\r\n }\r\n }\r\n </div>\r\n </div>\r\n</mt-page>\r\n", styles: [""], dependencies: [{ kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: ApiConfiguration, selector: "mt-api-configuration" }, { kind: "component", type: CheckListFormConfiguration, selector: "mt-check-list-form-configuration" }, { kind: "component", type: DynamicListConfiguration, selector: "mt-dynamic-list-configuration" }, { kind: "component", type: EditableListViewConfiguration, selector: "mt-editable-list-view-configuration" }, { kind: "component", type: InternalModuleConfiguration, selector: "mt-internal-module-configuration" }, { kind: "component", type: LocationConfiguration, selector: "mt-location-configuration" }, { kind: "component", type: LookupConfiguration, selector: "mt-lookup-configuration" }, { kind: "component", type: PercentageConfiguration, selector: "mt-percentage-configuration" }, { kind: "component", type: UserConfiguration, selector: "mt-user-configuration" }, { kind: "component", type: AttachmentConfiguration, selector: "mt-attachment-configuration" }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i1.TranslocoPipe, name: "transloco" }] });
2222
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: PropertyForm, isStandalone: true, selector: "mt-property-form", inputs: { propertyId: { classPropertyName: "propertyId", publicName: "propertyId", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "configurationHost", first: true, predicate: ["configurationHost"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<mt-page\r\n [title]=\"\r\n propertyId()\r\n ? ('properties.form.editProperty' | transloco)\r\n : ('properties.form.createNewProperty' | transloco)\r\n \"\r\n avatarIcon=\"custom.products-and-services\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-sky-50)',\r\n '--p-avatar-color': 'var(--p-sky-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n class=\"h-full\"\r\n>\r\n <ng-template #headerEnd>\r\n <mt-button\r\n class=\"mx-2\"\r\n [label]=\"submitLabel()\"\r\n [icon]=\"isEditing() ? 'custom.pencil' : 'general.plus'\"\r\n [loading]=\"submitting()\"\r\n [disabled]=\"submitDisabled() || this.propertyForm.invalid\"\r\n (click)=\"createOrEditProperty()\"\r\n />\r\n </ng-template>\r\n <div\r\n [formGroup]=\"propertyForm\"\r\n class=\"h-full py-4 h-full overflow-y-auto flex justify-center\"\r\n >\r\n <div class=\"w-2/3 flex flex-col gap-6\">\r\n @if (loading()) {\r\n <!-- Skeleton Loading State -->\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <div class=\"flex justify-between items-center gap-6\">\r\n <p-skeleton width=\"50%\" height=\"3rem\"></p-skeleton>\r\n <p-skeleton width=\"8rem\" height=\"2.5rem\"></p-skeleton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <p-skeleton\r\n width=\"12rem\"\r\n height=\"1.5rem\"\r\n styleClass=\"mb-4\"\r\n ></p-skeleton>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"6rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n <p-skeleton height=\"3rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <p-skeleton\r\n width=\"10rem\"\r\n height=\"1.5rem\"\r\n styleClass=\"mb-4\"\r\n ></p-skeleton>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"8rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n } @else {\r\n <mt-dynamic-form\r\n [formConfig]=\"dynamicFormConfigMain()\"\r\n [formControlName]=\"'main'\"\r\n />\r\n @if (configurationFormConfig()) {\r\n <mt-dynamic-form\r\n formControlName=\"configuration\"\r\n [formConfig]=\"configurationFormConfig()!\"\r\n />\r\n } @else {\r\n <ng-container #configurationHost></ng-container>\r\n @if (!configurationComponentExists()) {\r\n @switch (propertyType()) {\r\n @case (\"User\") {\r\n <mt-user-configuration />\r\n }\r\n @case (\"Percentage\") {\r\n <mt-percentage-configuration />\r\n }\r\n @case (\"Lookup\") {\r\n <mt-lookup-configuration />\r\n }\r\n @case (\"LookupMultiSelect\") {\r\n <mt-lookup-configuration />\r\n }\r\n @case (\"InternalModule\") {\r\n <mt-internal-module-configuration />\r\n }\r\n @case (\"DynamicList\") {\r\n <mt-dynamic-list-configuration />\r\n }\r\n @case (\"API\") {\r\n <mt-api-configuration formControlName=\"configuration\" />\r\n }\r\n <!-- @case('ViewList') { REMOVED FOR NOW\r\n <mt-view-list-configuration />\r\n } -->\r\n @case (\"Attachment\") {\r\n <mt-attachment-configuration />\r\n }\r\n <!-- @case('ReferenceProperty') { REMOVED FOR NOW\r\n } -->\r\n @case (\"EditableListView\") {\r\n <mt-editable-list-view-configuration />\r\n }\r\n @case (\"LookupLog\") {\r\n <mt-check-list-form-configuration />\r\n }\r\n <!-- @case('LookupMatrix') { REMOVED FOR NOW\r\n <mt-lookup-configuration />\r\n } -->\r\n @case (\"Location\") {\r\n <mt-location-configuration />\r\n }\r\n }\r\n }\r\n }\r\n @if (isCalculated()) {\r\n <mt-card title=\"Formula\">\r\n <mt-formula-builder\r\n formControlName=\"formula\"\r\n [levelSchemaId]=\"formulaSchemaId()\"\r\n />\r\n </mt-card>\r\n }\r\n }\r\n </div>\r\n </div>\r\n</mt-page>\r\n", styles: [""], dependencies: [{ kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: FormulaBuilder, selector: "mt-formula-builder", inputs: ["propertiesByPath", "levelSchemaId", "templateId", "placeholder", "hideToolbar", "hideStatusBar"], outputs: ["validationChange", "tokensChange"] }, { kind: "component", type: ApiConfiguration, selector: "mt-api-configuration" }, { kind: "component", type: CheckListFormConfiguration, selector: "mt-check-list-form-configuration" }, { kind: "component", type: DynamicListConfiguration, selector: "mt-dynamic-list-configuration" }, { kind: "component", type: EditableListViewConfiguration, selector: "mt-editable-list-view-configuration" }, { kind: "component", type: InternalModuleConfiguration, selector: "mt-internal-module-configuration" }, { kind: "component", type: LocationConfiguration, selector: "mt-location-configuration" }, { kind: "component", type: LookupConfiguration, selector: "mt-lookup-configuration" }, { kind: "component", type: PercentageConfiguration, selector: "mt-percentage-configuration" }, { kind: "component", type: UserConfiguration, selector: "mt-user-configuration" }, { kind: "component", type: AttachmentConfiguration, selector: "mt-attachment-configuration" }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i1.TranslocoPipe, name: "transloco" }] });
2175
2223
  }
2176
2224
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: PropertyForm, decorators: [{
2177
2225
  type: Component,
2178
2226
  args: [{ selector: 'mt-property-form', imports: [
2179
2227
  Page,
2180
2228
  Button,
2229
+ Card,
2181
2230
  DynamicForm,
2182
2231
  ReactiveFormsModule,
2232
+ FormulaBuilder,
2183
2233
  ApiConfiguration,
2184
2234
  CheckListFormConfiguration,
2185
2235
  DynamicListConfiguration,
@@ -2192,7 +2242,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
2192
2242
  AttachmentConfiguration,
2193
2243
  SkeletonModule,
2194
2244
  TranslocoModule,
2195
- ], template: "<mt-page\r\n [title]=\"\r\n propertyId()\r\n ? ('properties.form.editProperty' | transloco)\r\n : ('properties.form.createNewProperty' | transloco)\r\n \"\r\n avatarIcon=\"custom.products-and-services\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-sky-50)',\r\n '--p-avatar-color': 'var(--p-sky-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n class=\"h-full\"\r\n>\r\n <ng-template #headerEnd>\r\n <mt-button\r\n class=\"mx-2\"\r\n [label]=\"submitLabel()\"\r\n [icon]=\"isEditing() ? 'custom.pencil' : 'general.plus'\"\r\n [loading]=\"submitting()\"\r\n [disabled]=\"submitDisabled() || this.propertyForm.invalid\"\r\n (click)=\"createOrEditProperty()\"\r\n />\r\n </ng-template>\r\n <div\r\n [formGroup]=\"propertyForm\"\r\n class=\"h-full py-4 h-full overflow-y-auto flex justify-center\"\r\n >\r\n <div class=\"w-1/2 flex flex-col gap-6\">\r\n @if (loading()) {\r\n <!-- Skeleton Loading State -->\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <div class=\"flex justify-between items-center gap-6\">\r\n <p-skeleton width=\"50%\" height=\"3rem\"></p-skeleton>\r\n <p-skeleton width=\"8rem\" height=\"2.5rem\"></p-skeleton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <p-skeleton\r\n width=\"12rem\"\r\n height=\"1.5rem\"\r\n styleClass=\"mb-4\"\r\n ></p-skeleton>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"6rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n <p-skeleton height=\"3rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <p-skeleton\r\n width=\"10rem\"\r\n height=\"1.5rem\"\r\n styleClass=\"mb-4\"\r\n ></p-skeleton>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"8rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n } @else {\r\n <mt-dynamic-form\r\n [formConfig]=\"dynamicFormConfigMain()\"\r\n [formControlName]=\"'main'\"\r\n />\r\n @if (configurationFormConfig()) {\r\n <mt-dynamic-form\r\n formControlName=\"configuration\"\r\n [formConfig]=\"configurationFormConfig()!\"\r\n />\r\n } @else {\r\n <ng-container #configurationHost></ng-container>\r\n @if (!configurationComponentExists()) {\r\n @switch (propertyType()) {\r\n @case (\"User\") {\r\n <mt-user-configuration />\r\n }\r\n @case (\"Percentage\") {\r\n <mt-percentage-configuration />\r\n }\r\n @case (\"Lookup\") {\r\n <mt-lookup-configuration />\r\n }\r\n @case (\"LookupMultiSelect\") {\r\n <mt-lookup-configuration />\r\n }\r\n @case (\"InternalModule\") {\r\n <mt-internal-module-configuration />\r\n }\r\n @case (\"DynamicList\") {\r\n <mt-dynamic-list-configuration />\r\n }\r\n @case (\"API\") {\r\n <mt-api-configuration formControlName=\"configuration\" />\r\n }\r\n <!-- @case('ViewList') { REMOVED FOR NOW\r\n <mt-view-list-configuration />\r\n } -->\r\n @case (\"Attachment\") {\r\n <mt-attachment-configuration />\r\n }\r\n <!-- @case('ReferenceProperty') { REMOVED FOR NOW\r\n } -->\r\n @case (\"EditableListView\") {\r\n <mt-editable-list-view-configuration />\r\n }\r\n @case (\"LookupLog\") {\r\n <mt-check-list-form-configuration />\r\n }\r\n <!-- @case('LookupMatrix') { REMOVED FOR NOW\r\n <mt-lookup-configuration />\r\n } -->\r\n @case (\"Location\") {\r\n <mt-location-configuration />\r\n }\r\n }\r\n }\r\n }\r\n }\r\n </div>\r\n </div>\r\n</mt-page>\r\n" }]
2245
+ ], template: "<mt-page\r\n [title]=\"\r\n propertyId()\r\n ? ('properties.form.editProperty' | transloco)\r\n : ('properties.form.createNewProperty' | transloco)\r\n \"\r\n avatarIcon=\"custom.products-and-services\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-sky-50)',\r\n '--p-avatar-color': 'var(--p-sky-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n class=\"h-full\"\r\n>\r\n <ng-template #headerEnd>\r\n <mt-button\r\n class=\"mx-2\"\r\n [label]=\"submitLabel()\"\r\n [icon]=\"isEditing() ? 'custom.pencil' : 'general.plus'\"\r\n [loading]=\"submitting()\"\r\n [disabled]=\"submitDisabled() || this.propertyForm.invalid\"\r\n (click)=\"createOrEditProperty()\"\r\n />\r\n </ng-template>\r\n <div\r\n [formGroup]=\"propertyForm\"\r\n class=\"h-full py-4 h-full overflow-y-auto flex justify-center\"\r\n >\r\n <div class=\"w-2/3 flex flex-col gap-6\">\r\n @if (loading()) {\r\n <!-- Skeleton Loading State -->\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <div class=\"flex justify-between items-center gap-6\">\r\n <p-skeleton width=\"50%\" height=\"3rem\"></p-skeleton>\r\n <p-skeleton width=\"8rem\" height=\"2.5rem\"></p-skeleton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <p-skeleton\r\n width=\"12rem\"\r\n height=\"1.5rem\"\r\n styleClass=\"mb-4\"\r\n ></p-skeleton>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"6rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n <p-skeleton height=\"3rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <p-skeleton\r\n width=\"10rem\"\r\n height=\"1.5rem\"\r\n styleClass=\"mb-4\"\r\n ></p-skeleton>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"8rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n } @else {\r\n <mt-dynamic-form\r\n [formConfig]=\"dynamicFormConfigMain()\"\r\n [formControlName]=\"'main'\"\r\n />\r\n @if (configurationFormConfig()) {\r\n <mt-dynamic-form\r\n formControlName=\"configuration\"\r\n [formConfig]=\"configurationFormConfig()!\"\r\n />\r\n } @else {\r\n <ng-container #configurationHost></ng-container>\r\n @if (!configurationComponentExists()) {\r\n @switch (propertyType()) {\r\n @case (\"User\") {\r\n <mt-user-configuration />\r\n }\r\n @case (\"Percentage\") {\r\n <mt-percentage-configuration />\r\n }\r\n @case (\"Lookup\") {\r\n <mt-lookup-configuration />\r\n }\r\n @case (\"LookupMultiSelect\") {\r\n <mt-lookup-configuration />\r\n }\r\n @case (\"InternalModule\") {\r\n <mt-internal-module-configuration />\r\n }\r\n @case (\"DynamicList\") {\r\n <mt-dynamic-list-configuration />\r\n }\r\n @case (\"API\") {\r\n <mt-api-configuration formControlName=\"configuration\" />\r\n }\r\n <!-- @case('ViewList') { REMOVED FOR NOW\r\n <mt-view-list-configuration />\r\n } -->\r\n @case (\"Attachment\") {\r\n <mt-attachment-configuration />\r\n }\r\n <!-- @case('ReferenceProperty') { REMOVED FOR NOW\r\n } -->\r\n @case (\"EditableListView\") {\r\n <mt-editable-list-view-configuration />\r\n }\r\n @case (\"LookupLog\") {\r\n <mt-check-list-form-configuration />\r\n }\r\n <!-- @case('LookupMatrix') { REMOVED FOR NOW\r\n <mt-lookup-configuration />\r\n } -->\r\n @case (\"Location\") {\r\n <mt-location-configuration />\r\n }\r\n }\r\n }\r\n }\r\n @if (isCalculated()) {\r\n <mt-card title=\"Formula\">\r\n <mt-formula-builder\r\n formControlName=\"formula\"\r\n [levelSchemaId]=\"formulaSchemaId()\"\r\n />\r\n </mt-card>\r\n }\r\n }\r\n </div>\r\n </div>\r\n</mt-page>\r\n" }]
2196
2246
  }], ctorParameters: () => [], propDecorators: { propertyId: [{ type: i0.Input, args: [{ isSignal: true, alias: "propertyId", required: false }] }], configurationHost: [{
2197
2247
  type: ViewChild,
2198
2248
  args: ['configurationHost', { read: ViewContainerRef }]
@@ -2206,5 +2256,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
2206
2256
  * Generated bundle index. Do not edit.
2207
2257
  */
2208
2258
 
2209
- 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 };
2259
+ 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 };
2210
2260
  //# sourceMappingURL=masterteam-properties.mjs.map