@planeasyinc/le-angular 0.0.22 → 0.0.24

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.
@@ -16,14 +16,14 @@ import { NestedTreeControl, CdkTree, CdkNestedTreeNode, CdkTreeNodeDef, CdkTreeN
16
16
  import { ArrayDataSource, SelectionModel } from '@angular/cdk/collections';
17
17
  import { CdkMenuTrigger, CdkMenu, CdkMenuItem } from '@angular/cdk/menu';
18
18
  import { A11yModule } from '@angular/cdk/a11y';
19
+ import { createEngine } from '@planeasyinc/fe-core';
19
20
  import { adaptOld } from '@planeasyinc/fe-adapters-old';
20
21
  import { adaptSections } from '@planeasyinc/fe-adapters-sections';
21
- import { createEngine } from '@planeasyinc/fe-core';
22
22
  import { FeFieldHost } from '@planeasyinc/fe-angular';
23
23
  import * as i1 from '@angular/forms';
24
24
  import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
25
25
 
26
- const IS_LIBRARY_REQUEST = new HttpContextToken(() => false);
26
+ const LE_REQUEST_CONTEXT_TOKEN = new HttpContextToken(() => false);
27
27
 
28
28
  const defaultConfig = {
29
29
  apiUrl: '',
@@ -87,7 +87,7 @@ class LEApiService {
87
87
  const url = new UrlFragmentBuilder(this.apiUrl())
88
88
  .setFragment('api/contrib/frontend-config/dashboard/config')
89
89
  .build();
90
- return this.http.get(url, { context: new HttpContext().set(IS_LIBRARY_REQUEST, true) });
90
+ return this.http.get(url, { context: new HttpContext().set(LE_REQUEST_CONTEXT_TOKEN, true) });
91
91
  }
92
92
  getObject(className, query = '') {
93
93
  const url = new UrlFragmentBuilder(this.apiUrl())
@@ -97,7 +97,7 @@ class LEApiService {
97
97
  .setQuery(query)
98
98
  .build();
99
99
  return this.http.get(url, {
100
- context: new HttpContext().set(IS_LIBRARY_REQUEST, true),
100
+ context: new HttpContext().set(LE_REQUEST_CONTEXT_TOKEN, true),
101
101
  });
102
102
  }
103
103
  getObjectByAddress(address, params) {
@@ -106,7 +106,7 @@ class LEApiService {
106
106
  .setQuery(`all_versions=${params.includeVersions ?? false}&include_metadata=${params.includeMeta ?? false}&load_references=${params.loadReferences ?? false}&file_optimized=${params.fileOptimized ?? true}`)
107
107
  .build();
108
108
  return this.http.get(url, {
109
- context: new HttpContext().set(IS_LIBRARY_REQUEST, true),
109
+ context: new HttpContext().set(LE_REQUEST_CONTEXT_TOKEN, true),
110
110
  });
111
111
  }
112
112
  executeTransaction(name, body, query = '') {
@@ -115,20 +115,20 @@ class LEApiService {
115
115
  .setQuery(query)
116
116
  .build();
117
117
  return this.http.post(url, body ?? {}, {
118
- context: new HttpContext().set(IS_LIBRARY_REQUEST, true),
118
+ context: new HttpContext().set(LE_REQUEST_CONTEXT_TOKEN, true),
119
119
  });
120
120
  }
121
121
  request(method, path, body) {
122
122
  const url = new UrlFragmentBuilder(this.apiUrl()).setFragment(path).build();
123
123
  const request = new HttpRequest(method, url, body, {
124
124
  responseType: 'json',
125
- context: new HttpContext().set(IS_LIBRARY_REQUEST, true),
125
+ context: new HttpContext().set(LE_REQUEST_CONTEXT_TOKEN, true),
126
126
  });
127
127
  return this.http.request(request);
128
128
  }
129
129
  getBlob(path) {
130
130
  return this.http
131
- .get(path, { responseType: 'blob', context: new HttpContext().set(IS_LIBRARY_REQUEST, true) })
131
+ .get(path, { responseType: 'blob', context: new HttpContext().set(LE_REQUEST_CONTEXT_TOKEN, true) })
132
132
  .pipe(map((blob) => URL.createObjectURL(blob)));
133
133
  }
134
134
  normalizeApiUrl(url) {
@@ -165,7 +165,8 @@ class LeNavigationService {
165
165
  if (!this.config.withRouting)
166
166
  return;
167
167
  const path = this.mapNodeToLocationPath(node);
168
- this.location.go(`/v2/${path}`, undefined, { node });
168
+ const fullPath = [this.config.rootPath, path].filter(Boolean).join('/');
169
+ this.location.go(`/${fullPath}`, undefined, { node });
169
170
  }
170
171
  mapNodeToLocationPath(node) {
171
172
  let pathChunks = [];
@@ -173,13 +174,20 @@ class LeNavigationService {
173
174
  if (node.type === 'table') {
174
175
  pathChunks.push(node?.title || node?.dataSource?.entity);
175
176
  if (node?.dataSource?.params) {
176
- query = Object.entries(node.dataSource.params).map(entry => entry.join('=')).join('&');
177
+ query = Object.entries(node.dataSource.params)
178
+ .map((entry) => entry.join('='))
179
+ .join('&');
177
180
  }
178
181
  }
179
- if (node.type === 'form') {
182
+ else if (node.type === 'form') {
180
183
  pathChunks.push('details', node.controlSource?.kind, node.controlSource?.entity, node.controlSource?.params?.className, node.controlSource?.params?.address, node.controlSource?.params?.mode);
181
184
  }
182
- const path = pathChunks.filter(v => !!v).join('/');
185
+ else {
186
+ const title = (node.title ?? '').replace(' ', '-');
187
+ if (title)
188
+ pathChunks.push(title);
189
+ }
190
+ const path = pathChunks.filter((v) => !!v).join('/');
183
191
  return query ? `${path}?${query}` : path;
184
192
  }
185
193
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeNavigationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
@@ -249,7 +257,7 @@ class LEDataService {
249
257
  navigateByNodeId(id) {
250
258
  const node = this.getNodeById(id);
251
259
  if (node) {
252
- this._view.set(node);
260
+ this.setView(node);
253
261
  }
254
262
  }
255
263
  getNodeById(id, node = this._config()) {
@@ -1242,8 +1250,9 @@ class TableViewComponent {
1242
1250
  const result = [];
1243
1251
  const firstRow = this.data().getValueByIndex(0);
1244
1252
  const columnKeys = this.columns().map((column) => column.key);
1253
+ const hasMetadata = !!(firstRow && firstRow._metadata);
1245
1254
  const hasVersion = !!(firstRow && firstRow._metadata && firstRow._metadata.object_version);
1246
- if (firstRow && !this.config()?.hideInfo) {
1255
+ if (hasMetadata && !this.config()?.hideInfo) {
1247
1256
  result.push('info');
1248
1257
  }
1249
1258
  result.push(...columnKeys);
@@ -1342,11 +1351,11 @@ class TableViewComponent {
1342
1351
  injector: this.injector,
1343
1352
  })
1344
1353
  .subscribe({
1345
- next: event => {
1354
+ next: (event) => {
1346
1355
  if (event.type === 'cell_clicked') {
1347
1356
  this.onCellClicked(event.data);
1348
1357
  }
1349
- }
1358
+ },
1350
1359
  });
1351
1360
  }
1352
1361
  onCellClicked(data) {
@@ -1382,6 +1391,20 @@ class TableViewComponent {
1382
1391
  }
1383
1392
  });
1384
1393
  }
1394
+ else if (type === 'update_form') {
1395
+ if (clone.controlSource?.params) {
1396
+ clone.controlSource.params = this.interpolateRowValues(clone.controlSource.params, row);
1397
+ }
1398
+ this.setView({
1399
+ id: action.type,
1400
+ type: 'form',
1401
+ controlSource: {
1402
+ kind: clone.controlSource.kind,
1403
+ entity: clone.controlSource.entity,
1404
+ params: clone.controlSource.params,
1405
+ },
1406
+ });
1407
+ }
1385
1408
  }
1386
1409
  processTableAction(action) {
1387
1410
  if (action.type === 'update_form') {
@@ -1425,7 +1448,7 @@ class TableViewComponent {
1425
1448
  }
1426
1449
  if (node.dataSource?.kind === 'transaction') {
1427
1450
  const body = Object.assign({}, node.dataSource.params, buildRequestBody(ctx));
1428
- this.apiService.executeTransaction(node.dataSource.entity, body);
1451
+ return this.apiService.executeTransaction(node.dataSource.entity, body);
1429
1452
  }
1430
1453
  if (node.dataSource?.kind === 'object') {
1431
1454
  return this.apiService.getObjectByAddress(node.dataSource.entity, node.dataSource.params ?? {});
@@ -1849,17 +1872,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
1849
1872
  args: [{ imports: [ToastListItemComponent], template: "@if (toasts().length) {\n <div class=\"le-toast-list\">\n @for (toast of toasts(); track toast.id) {\n <div\n class=\"le-toast\"\n [class.le-toast--success]=\"toast.type === 'success'\"\n [class.le-toast--info]=\"toast.type === 'info'\"\n [class.le-toast--warning]=\"toast.type === 'warning'\"\n [class.le-toast--error]=\"toast.type === 'error'\"\n >\n <le-toast-list-item\n [controls]=\"toast.controls\"\n (actions)=\"onActions($event)\"\n ></le-toast-list-item>\n </div>\n }\n </div>\n}\n" }]
1850
1873
  }] });
1851
1874
 
1852
- let ID = 100_000_000;
1875
+ let ID$1 = 100_000_000;
1853
1876
  class LeToastService {
1854
1877
  overlayRef;
1855
1878
  overlay = inject(Overlay);
1856
1879
  _toasts = signal([]);
1857
1880
  toasts = this._toasts.asReadonly();
1881
+ hasToasts = computed(() => this._toasts().length > 0);
1858
1882
  action$ = new Subject();
1859
1883
  constructor() {
1860
1884
  effect(() => {
1861
- const toasts = this._toasts();
1862
- if (toasts.length > 0) {
1885
+ if (this.hasToasts()) {
1863
1886
  this.show();
1864
1887
  }
1865
1888
  else {
@@ -1899,7 +1922,7 @@ class LeToastService {
1899
1922
  this.overlayRef = undefined;
1900
1923
  }
1901
1924
  buildToast(type, messages) {
1902
- const id = `${type}_${ID++}`;
1925
+ const id = `${type}_${ID$1++}`;
1903
1926
  return {
1904
1927
  id,
1905
1928
  type,
@@ -2092,12 +2115,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
2092
2115
  type: Injectable
2093
2116
  }] });
2094
2117
 
2118
+ class LeActionsService {
2119
+ _queue = [];
2120
+ _data = null;
2121
+ get hasActions() {
2122
+ return this._queue.length > 0;
2123
+ }
2124
+ setActions(actions, data) {
2125
+ this._queue = actions;
2126
+ this._data = data;
2127
+ }
2128
+ getActions() {
2129
+ const actions = this._queue.slice();
2130
+ const data = Object.assign({}, this._data);
2131
+ this._queue = [];
2132
+ this._data = null;
2133
+ return {
2134
+ actions,
2135
+ data,
2136
+ };
2137
+ }
2138
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeActionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2139
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeActionsService, providedIn: 'root' });
2140
+ }
2141
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LeActionsService, decorators: [{
2142
+ type: Injectable,
2143
+ args: [{
2144
+ providedIn: 'root',
2145
+ }]
2146
+ }] });
2147
+
2148
+ let ID = 100_000_000;
2095
2149
  class FormViewComponent {
2096
2150
  apiService = inject(LEApiService);
2097
2151
  dataService = inject(LEDataService);
2098
2152
  attachmentService = inject(FormViewAttachmentService);
2099
2153
  viewportScroller = inject(ViewportScroller);
2100
2154
  toastService = inject(LeToastService);
2155
+ actionsService = inject(LeActionsService);
2101
2156
  _isLoading = signal(false);
2102
2157
  _form = signal(null);
2103
2158
  _sections = signal([]);
@@ -2172,15 +2227,20 @@ class FormViewComponent {
2172
2227
  return of(null);
2173
2228
  },
2174
2229
  show_popup: (action, response) => {
2230
+ const rawControls = this.normalizeControls(action.controls);
2231
+ const controls = this.populatePopupControlsWithResponseData(rawControls, response);
2175
2232
  this.toastService.notify({
2176
- controls: this.populatePopupControlsWithResponse(action.controls, response),
2233
+ controls,
2177
2234
  id: action.id,
2178
2235
  type: 'success',
2179
2236
  });
2180
2237
  return of(null);
2181
2238
  },
2182
2239
  close_popup: (action) => {
2183
- this.toastService.remove(action.target_id);
2240
+ // TODO: models alignment required (to target_id)
2241
+ // @ts-ignore
2242
+ const id = action.target_id || action.target;
2243
+ this.toastService.remove(id);
2184
2244
  return of(null);
2185
2245
  },
2186
2246
  open_url: (action) => {
@@ -2269,6 +2329,7 @@ class FormViewComponent {
2269
2329
  objectLatest: (className) => firstValueFrom(this.dataService.getObjectByClassName(className)),
2270
2330
  };
2271
2331
  this._engine.set(createEngine(form, {}, resolvers));
2332
+ this.checkDelayedActions();
2272
2333
  // this._engine()?.on('valueChanges', (value) => {
2273
2334
  // console.log('Value Changes', value);
2274
2335
  // // this.cdr.markForCheck();
@@ -2349,13 +2410,35 @@ class FormViewComponent {
2349
2410
  };
2350
2411
  }
2351
2412
  processActionList(items, response) {
2413
+ const updateViewActionIndex = items.findIndex((item) => item.type === 'update_form' || item.type === 'update_table');
2414
+ if (updateViewActionIndex !== -1) {
2415
+ const delayedActions = items.splice(updateViewActionIndex + 1);
2416
+ this.actionsService.setActions(delayedActions, response ?? null);
2417
+ }
2352
2418
  from(items)
2353
2419
  .pipe(concatMap((a) => this.processAction(a, response)), finalize(() => {
2354
2420
  this._isLoading.set(false);
2355
2421
  }))
2356
2422
  .subscribe();
2357
2423
  }
2358
- populatePopupControlsWithResponse(controls, response) {
2424
+ checkDelayedActions() {
2425
+ if (this.actionsService.hasActions) {
2426
+ const { actions, data } = this.actionsService.getActions();
2427
+ this.processActionList(actions, data);
2428
+ }
2429
+ }
2430
+ normalizeControls(controls) {
2431
+ return controls.map((control) => {
2432
+ if (!control.id) {
2433
+ return {
2434
+ ...control,
2435
+ id: `${control.type}_${ID++}`,
2436
+ };
2437
+ }
2438
+ return control;
2439
+ });
2440
+ }
2441
+ populatePopupControlsWithResponseData(controls, response) {
2359
2442
  return controls.map((control) => {
2360
2443
  if (isPlaceholder(control.value)) {
2361
2444
  const path = getPlaceholderValue(control.value);
@@ -2691,7 +2774,7 @@ const LEAuthInterceptor = (req, next) => {
2691
2774
  if (authService.isGuest()) {
2692
2775
  return next(req);
2693
2776
  }
2694
- if (req.context.get(IS_LIBRARY_REQUEST)) {
2777
+ if (req.context.get(LE_REQUEST_CONTEXT_TOKEN)) {
2695
2778
  try {
2696
2779
  authService.validateToken();
2697
2780
  return next(req.clone({ setHeaders: { Authorization: authService.token() } }));
@@ -2708,5 +2791,5 @@ const LEAuthInterceptor = (req, next) => {
2708
2791
  * Generated bundle index. Do not edit.
2709
2792
  */
2710
2793
 
2711
- export { CONFIG_TOKEN, LEAuthInterceptor, LEAuthService, LeContainerComponent, LeToastService, provideConfig };
2794
+ export { CONFIG_TOKEN, LEAuthInterceptor, LEAuthService, CONFIG_TOKEN as LE_CONFIG_TOKEN, LE_REQUEST_CONTEXT_TOKEN, LeContainerComponent, LeToastService, provideConfig };
2712
2795
  //# sourceMappingURL=planeasyinc-le-angular.mjs.map