@maro-tech/card 0.2.7 → 0.2.9

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.
@@ -9,7 +9,7 @@ import { DomSanitizer } from '@angular/platform-browser';
9
9
  import Panzoom from '@panzoom/panzoom';
10
10
  import { LucideDownload, LucideDynamicIcon, LucideEye, LucideFileText, LucidePlus, LucideSparkles, LucideTrash } from '@lucide/angular';
11
11
  import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
12
- import { map, shareReplay, forkJoin, switchMap, timer, of, firstValueFrom } from 'rxjs';
12
+ import { map, shareReplay, forkJoin, switchMap, timer, of } from 'rxjs';
13
13
  import { UiTableComponent, UiPaginatorComponent } from '@maro-tech/table';
14
14
  import { ActivatedRoute, Router, RouterLink } from '@angular/router';
15
15
  import { map as map$1, exhaustMap, catchError, takeWhile, takeUntil, finalize } from 'rxjs/operators';
@@ -707,19 +707,24 @@ class TableComponent {
707
707
  this.emitAction(event.action, event.row);
708
708
  }
709
709
  onCellChange(event) {
710
- const config = this.editableColumns().find((item) => item.key === event.column.key);
711
- if (!config?.api)
710
+ const config = this.editableColumn(event.column.key);
711
+ if (!config)
712
712
  return;
713
+ const editAction = Array.isArray(event.row['actions'])
714
+ ? event.row['actions'].find((action) => String(action.id || '') === 'edit')
715
+ : undefined;
716
+ const formId = String(editAction?.formId || '').trim();
717
+ const api = config.api || (formId
718
+ ? `/api/${encodeURIComponent(formId)}`
719
+ : `/api/crud/${encodeURIComponent(this.tableName())}/${encodeURIComponent(String(event.row['id'] || ''))}`);
713
720
  this.emitAction({
714
721
  id: `edit:${config.key}`,
715
722
  label: 'Зберегти',
716
723
  type: 'api',
717
- api: config.api,
724
+ api,
718
725
  method: config.method || 'PATCH',
719
726
  payload: {
720
- ...event.row,
721
727
  ...(config.payload || {}),
722
- id: event.row['id'],
723
728
  [config.bindKey || config.key]: event.value,
724
729
  },
725
730
  }, event.row);
@@ -783,10 +788,9 @@ class TableComponent {
783
788
  });
784
789
  }
785
790
  setColumns() {
786
- const editable = this.editableColumns();
787
791
  this.columnsSignal.set(this.sourceColumns.filter((column) => !column['hidden']).map((column) => {
788
792
  const key = String(column['id'] || '');
789
- const config = editable.find((item) => item.key === key);
793
+ const config = this.editableConfig(column);
790
794
  return {
791
795
  key,
792
796
  labelKey: String(column['label'] || key),
@@ -796,12 +800,14 @@ class TableComponent {
796
800
  sortable: true,
797
801
  link: column['link'],
798
802
  editable: !!config,
799
- editableCondition: String(this.config?.props?.['editableCondition'] || config?.['condition'] || ''),
803
+ editableCondition: String(config?.['condition'] || ''),
800
804
  editor: config?.editor,
801
805
  bindKey: config?.bindKey || key,
802
806
  options: config?.options || [],
803
807
  data: config?.data,
804
- dataParams: config?.dataParams,
808
+ dataParams: config?.dataParams
809
+ ? resolveTemplateValue(config.dataParams, this.data, { interpolate: true })
810
+ : undefined,
805
811
  placeholder: config?.placeholder,
806
812
  };
807
813
  }));
@@ -870,11 +876,25 @@ class TableComponent {
870
876
  tableName() {
871
877
  return String(this.config?.props?.['table'] || this.config?.props?.['entity'] || '').trim();
872
878
  }
873
- editableColumns() {
874
- const value = this.config?.props?.['editableColumns'];
875
- return Array.isArray(value)
876
- ? value.filter((item) => !!item && typeof item === 'object' && !!String(item.key || '').trim())
877
- : [];
879
+ editableConfig(column) {
880
+ const value = column['editable'];
881
+ if (value === true) {
882
+ const key = String(column['id'] || '');
883
+ return {
884
+ key,
885
+ bindKey: key,
886
+ editor: column['data'] ? 'select' : 'text',
887
+ data: column['data'],
888
+ };
889
+ }
890
+ return value && typeof value === 'object' && !Array.isArray(value)
891
+ ? value
892
+ : undefined;
893
+ }
894
+ editableColumn(key) {
895
+ const column = this.sourceColumns.find((item) => String(item['id'] || '') === key);
896
+ const config = column ? this.editableConfig(column) : undefined;
897
+ return config ? { ...config, key } : undefined;
878
898
  }
879
899
  tableEndpoint(table) {
880
900
  const params = new URLSearchParams({
@@ -1623,7 +1643,6 @@ class HistoryTabComponent {
1623
1643
  destroyRef = inject(DestroyRef);
1624
1644
  refreshSequence = signal(0, ...(ngDevMode ? [{ debugName: "refreshSequence" }] : /* istanbul ignore next */ []));
1625
1645
  lastRequestKey = '';
1626
- dictionaryCache = new Map();
1627
1646
  constructor() {
1628
1647
  this.eventBus.on(ENTITY_UPDATED)
1629
1648
  .pipe(takeUntilDestroyed(this.destroyRef))
@@ -1749,8 +1768,8 @@ class HistoryTabComponent {
1749
1768
  label: config.label || field,
1750
1769
  type: config.type || 'text',
1751
1770
  summary: values.summary,
1752
- from: await this.toDisplayValue(values.from, config),
1753
- to: await this.toDisplayValue(values.to, config),
1771
+ from: await this.toDisplayValue(values.from, config, values.from_data),
1772
+ to: await this.toDisplayValue(values.to, config, values.to_data),
1754
1773
  };
1755
1774
  }
1756
1775
  return { ...change, changedFields };
@@ -1764,6 +1783,8 @@ class HistoryTabComponent {
1764
1783
  return [key, {
1765
1784
  from: from && typeof from === 'object' && 'value' in from ? from.value : from,
1766
1785
  to: to && typeof to === 'object' && 'value' in to ? to.value : to,
1786
+ from_data: field?.from_data,
1787
+ to_data: field?.to_data,
1767
1788
  summary: typeof field?.changeSummary === 'string' ? field.changeSummary : undefined,
1768
1789
  }];
1769
1790
  }));
@@ -1778,10 +1799,10 @@ class HistoryTabComponent {
1778
1799
  }
1779
1800
  return undefined;
1780
1801
  }
1781
- async toDisplayValue(value, config) {
1802
+ async toDisplayValue(value, config, data) {
1782
1803
  const display = config.type === 'boolean' && value !== null && value !== undefined && value !== ''
1783
1804
  ? (value === true || value === 'true' || value === 1 ? 'Так' : 'Ні')
1784
- : await this.resolveDisplay(value, config);
1805
+ : await this.resolveDisplay(value, config, data);
1785
1806
  const structured = config.displayMode === 'structured' ? await this.toStructuredItems(value, config.itemFields) : undefined;
1786
1807
  const result = {
1787
1808
  value: value ?? null,
@@ -1794,23 +1815,24 @@ class HistoryTabComponent {
1794
1815
  result.url = `/api/files/${encodeURIComponent(String(value))}`;
1795
1816
  return result;
1796
1817
  }
1797
- async resolveDisplay(value, config) {
1818
+ async resolveDisplay(value, config, data) {
1798
1819
  if (value === null || value === undefined || value === '')
1799
1820
  return 'Не задано';
1821
+ const dataLabel = this.getDataLabel(data);
1822
+ if (dataLabel !== null)
1823
+ return dataLabel;
1800
1824
  const values = Array.isArray(value) ? value : [value];
1801
- return (await Promise.all(values.map(async (item) => config.data && item !== null && item !== undefined && item !== ''
1802
- ? this.resolveDictionary(config.data, String(item))
1803
- : typeof item === 'object' ? JSON.stringify(item) : String(item)))).filter(Boolean).join(', ') || 'Не задано';
1804
- }
1805
- resolveDictionary(name, key) {
1806
- const cacheKey = `${name}:${key}`;
1807
- const cached = this.dictionaryCache.get(cacheKey);
1808
- if (cached)
1809
- return cached;
1810
- const request = firstValueFrom(this.http.get(cardApiResourceUrl(this.baseUrl, `/api/suggest/${encodeURIComponent(name)}/${encodeURIComponent(key)}`)))
1811
- .then((item) => item?.label || key).catch(() => key);
1812
- this.dictionaryCache.set(cacheKey, request);
1813
- return request;
1825
+ return values
1826
+ .filter((item) => item !== null && item !== undefined && item !== '')
1827
+ .map((item) => typeof item === 'object' ? JSON.stringify(item) : String(item))
1828
+ .filter(Boolean).join(', ') || 'Не задано';
1829
+ }
1830
+ getDataLabel(data) {
1831
+ const values = Array.isArray(data) ? data : [data];
1832
+ const labels = values
1833
+ .map((item) => item && typeof item === 'object' && 'label' in item ? String(item.label ?? '') : '')
1834
+ .filter(Boolean);
1835
+ return labels.length ? labels.join(', ') : null;
1814
1836
  }
1815
1837
  async toStructuredItems(value, itemFields) {
1816
1838
  const values = Array.isArray(value) ? value : value && typeof value === 'object' ? [value] : [];
@@ -1831,7 +1853,8 @@ class HistoryTabComponent {
1831
1853
  if (value === null || value === undefined || value === '' || seenLabels.has(label))
1832
1854
  return null;
1833
1855
  seenLabels.add(label);
1834
- const display = fieldConfig.data ? await this.resolveDictionary(fieldConfig.data, String(value)) : typeof value === 'object' ? JSON.stringify(value) : String(value);
1856
+ const display = this.getDataLabel(record[`${key}_data`])
1857
+ || (typeof value === 'object' ? JSON.stringify(value) : String(value));
1835
1858
  return { key, label, value, display };
1836
1859
  }))).filter((field) => field !== null),
1837
1860
  };