@cxtms/cx-schema 1.9.66 → 1.9.241
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.
- package/dist/cli.js +43 -9
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/schemas/actions/all.json +5 -1
- package/schemas/actions/reload.json +17 -0
- package/schemas/actions/setSessionStorage.json +38 -0
- package/schemas/actions/sound.json +39 -0
- package/schemas/actions/vibrate.json +48 -0
- package/schemas/components/avatar.json +1 -0
- package/schemas/components/badge.json +79 -0
- package/schemas/components/barcodeScanner.json +28 -0
- package/schemas/components/camera.json +177 -0
- package/schemas/components/card.json +78 -0
- package/schemas/components/dashboard-widget.json +39 -0
- package/schemas/components/dashboard.json +46 -0
- package/schemas/components/dataGrid.json +15 -0
- package/schemas/components/field-collection.json +86 -2
- package/schemas/components/field.json +39 -4
- package/schemas/components/form.json +4 -0
- package/schemas/components/index.json +17 -1
- package/schemas/components/infoLine.json +1 -0
- package/schemas/components/map.json +167 -0
- package/schemas/components/module.json +32 -0
- package/schemas/components/planner.json +1 -0
- package/schemas/components/progressBar.json +1 -0
- package/schemas/components/timeline.json +216 -74
- package/schemas/components/timelineGrid.json +5 -1
- package/schemas/fields/autocomplete-googleplaces.json +2 -2
- package/schemas/fields/datetime.json +2 -2
- package/schemas/fields/index.json +4 -0
- package/schemas/fields/number-select.json +88 -0
- package/schemas/fields/rangedatetime.json +10 -2
- package/schemas/fields/select-async.json +2 -2
- package/schemas/fields/toggle.json +91 -0
- package/schemas/schema.graphql +11016 -12171
- package/schemas/schemas.json +131 -4
- package/schemas/workflows/flow/entity.json +3 -1
- package/schemas/workflows/input.json +1 -1
- package/schemas/workflows/output.json +1 -1
- package/schemas/workflows/tasks/all.json +9 -0
- package/schemas/workflows/tasks/commodity.json +8 -0
- package/schemas/workflows/tasks/contact-address.json +25 -0
- package/schemas/workflows/tasks/dispatch-routes.json +64 -0
- package/schemas/workflows/tasks/edi.json +15 -0
- package/schemas/workflows/tasks/export.json +21 -0
- package/schemas/workflows/tasks/httpRequest.json +4 -0
- package/schemas/workflows/tasks/import.json +5 -0
- package/schemas/workflows/tasks/order-move.json +38 -0
- package/schemas/workflows/tasks/order.json +6 -0
- package/schemas/workflows/tasks/organization-config.json +101 -0
- package/schemas/workflows/tasks/tracking-event.json +11 -3
- package/schemas/workflows/tasks/workflow-execute.json +4 -0
- package/schemas/workflows/variable.json +2 -2
- package/schemas/workflows/workflow.json +39 -2
- package/skills/cxtms-developer/SKILL.md +5 -2
- package/skills/cxtms-developer/ref-cli-auth.md +2 -0
- package/skills/cxtms-developer/ref-entity-commodity.md +41 -5
- package/skills/cxtms-developer/ref-entity-contact.md +46 -0
- package/skills/cxtms-developer/ref-entity-dispatch-routing.md +195 -0
- package/skills/cxtms-developer/ref-entity-geography.md +26 -1
- package/skills/cxtms-developer/ref-entity-job.md +6 -2
- package/skills/cxtms-developer/ref-entity-order-sub.md +1 -1
- package/skills/cxtms-developer/ref-entity-order.md +36 -3
- package/skills/cxtms-developer/ref-entity-organization.md +4 -2
- package/skills/cxtms-developer/ref-entity-shared.md +79 -3
- package/skills/cxtms-developer/ref-graphql-query.md +246 -4
- package/skills/cxtms-module-builder/SKILL.md +33 -6
- package/skills/cxtms-module-builder/ref-components-data.md +85 -0
- package/skills/cxtms-module-builder/ref-components-display.md +282 -8
- package/skills/cxtms-module-builder/ref-components-forms.md +386 -21
- package/skills/cxtms-module-builder/ref-components-interactive.md +2 -0
- package/skills/cxtms-module-builder/ref-components-layout.md +288 -29
- package/skills/cxtms-module-builder/ref-components-specialized.md +168 -20
- package/skills/cxtms-workflow-builder/SKILL.md +45 -6
- package/skills/cxtms-workflow-builder/ref-entity.md +100 -4
- package/skills/cxtms-workflow-builder/ref-expressions-ncalc.md +35 -2
- package/skills/cxtms-workflow-builder/ref-expressions-template.md +15 -1
- package/skills/cxtms-workflow-builder/ref-flow.md +6 -1
- package/skills/cxtms-workflow-builder/ref-query.md +16 -0
- package/skills/cxtms-workflow-builder/ref-utilities.md +32 -2
- package/templates/workflow-public-api.yaml +1 -0
|
@@ -20,6 +20,7 @@ Full-featured data table with views, filtering, sorting, pagination, and row act
|
|
|
20
20
|
**Responsive layout:**
|
|
21
21
|
- **Toolbar**: ViewSelector and search input stack full-width on mobile (`xs`), then collapse to auto-width on `sm` and above. Search input enforces a `20ch` minimum width on `sm+`.
|
|
22
22
|
- **Filters**: Filter inputs use a responsive grid — 1 per row on `xs`/`sm`, 2 per row on `md`, 3 per row on `lg`, 4 per row on `xl`.
|
|
23
|
+
- **Pagination**: Below the MUI `sm` breakpoint, the pager tightens inline padding and narrows the page-size select so short pagers stay on one row inside dialogs. Do not add extra mobile-only wrapper padding around embedded grids unless the content needs it.
|
|
23
24
|
|
|
24
25
|
**Props:**
|
|
25
26
|
| Prop | Type | Description |
|
|
@@ -27,6 +28,8 @@ Full-featured data table with views, filtering, sorting, pagination, and row act
|
|
|
27
28
|
| `toolbar` | `component[]` | Header toolbar components |
|
|
28
29
|
| `dotsMenu` | `{items[]}` | Three-dot menu per row |
|
|
29
30
|
| `dotsMenu.items[]` | `{label, icon, onClick, permission, isHidden, disabled}` | Menu item |
|
|
31
|
+
|
|
32
|
+
**Row-aware dots menu expressions:** `dotsMenu.items[].disabled` and `isHidden` are evaluated with component props plus the current row data. Reference row fields directly, e.g. `disabled: "{{ eval status !== 'Ready' || isLocked }}"`.
|
|
30
33
|
| `views` | `ITableViewProps[]` | View definitions |
|
|
31
34
|
| `enableSelect` | `Single \| Multiple` | Row selection mode |
|
|
32
35
|
| `isInDialog` | `boolean` | Optimize for dialog (10 rows) |
|
|
@@ -38,6 +41,7 @@ Full-featured data table with views, filtering, sorting, pagination, and row act
|
|
|
38
41
|
| `query` | `string` | — | **Required.** GraphQL entity name |
|
|
39
42
|
| `rootEntityName` | `string` | — | **Required.** Entity name for dynamic grid |
|
|
40
43
|
| `entityKeys` | `string[]` | — | **Required.** Primary key fields |
|
|
44
|
+
| `includeEntityKeysInExport` | `boolean` | `true` | Force `entityKeys`/primary keys into exports even when hidden, preserving ID-first re-import matching. Set `false` for id-less templates or cross-space copies. |
|
|
41
45
|
| `navigationType` | `navigate \| dialog \| store` | — | **Required.** Row click behavior |
|
|
42
46
|
| `enableDynamicGrid` | `boolean` | — | Enable dynamic columns |
|
|
43
47
|
| `enableViews` | `boolean` | — | Show view selector |
|
|
@@ -53,10 +57,15 @@ Full-featured data table with views, filtering, sorting, pagination, and row act
|
|
|
53
57
|
| `highlightNew` | `boolean` | `true` | Highlight newly added rows |
|
|
54
58
|
| `highlightUpdated` | `boolean` | `true` | Highlight rows with updated values |
|
|
55
59
|
| `highlightForRefreshes` | `number` | `1` | Per-row TTL — refresh cycles a highlight persists |
|
|
60
|
+
| `defaultExpandedRows` | `boolean` | `false` | Pre-expand parent rows once on first load when `childViews` exist; refreshes preserve user collapse/expand choices |
|
|
56
61
|
| `onRowClick` | `action[]` | — | Default row click action |
|
|
57
62
|
| `onDataLoad` | `action[]` | — | Action after data loads |
|
|
58
63
|
| `items` | `any` | — | Static data (instead of query) |
|
|
59
64
|
|
|
65
|
+
**Pagination display:** when `totalCount` is `0`, DataGrid shows `Showing 0 to 0 of 0 entries` instead of starting at row `1`.
|
|
66
|
+
|
|
67
|
+
**Store navigation state:** with `navigationType: store`, DataGrid keeps `{gridName}_limit`, `{gridName}_offset`, and search state in the local UI context store, not URL variables. Use it for embedded/stateful grids where dialogs or parent re-renders must not reset pagination back to page 1.
|
|
68
|
+
|
|
60
69
|
**View definition:**
|
|
61
70
|
| Prop | Type | Description |
|
|
62
71
|
|------|------|-------------|
|
|
@@ -64,20 +73,34 @@ Full-featured data table with views, filtering, sorting, pagination, and row act
|
|
|
64
73
|
| `displayName` | `ILocalizeString` | View label |
|
|
65
74
|
| `columns` | `IColumn[]` | Column definitions |
|
|
66
75
|
| `filter` | `string` | View-level filter |
|
|
76
|
+
| `search` | `string` | Default search term seeded once on initial load; supports `{{ }}` templates; URL/user search wins |
|
|
67
77
|
| `orderBy` | `{name, direction}[]` | Default sort |
|
|
78
|
+
| `paginationPosition` | `top \| bottom` | Place pagination controls above or below rows (`bottom` default) |
|
|
68
79
|
| `onRowClick` | `action[]` | Per-view row click |
|
|
69
80
|
| `enableSelect` | `Single \| Multiple` | Per-view selection |
|
|
81
|
+
| `includeEntityKeysInExport` | `boolean` | Per-view override for exporting entity keys |
|
|
82
|
+
| `stickyColumns` | `{left: string[], right: string[]}` | User-pinned columns for the view. Left-pinned columns render first, normal columns next, right-pinned columns last |
|
|
70
83
|
| `childViews` | `object` | Expandable child views |
|
|
71
84
|
|
|
72
85
|
**Column definition:**
|
|
73
86
|
| Prop | Type | Description |
|
|
74
87
|
|------|------|-------------|
|
|
75
|
-
| `name` | `string` | Field name |
|
|
88
|
+
| `name` | `string` | Field name or resolver expression |
|
|
76
89
|
| `label` | `ILocalizeString` | Column header |
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
90
|
+
| `description` | `ILocalizeString` | Header and column-picker tooltip; dynamic entity columns inherit the field description |
|
|
91
|
+
| `isHidden` | `boolean \| template` | Available in picker but hidden by default; also excluded from export when truthy |
|
|
92
|
+
| `isVisible` | `boolean \| template` | Inverse visibility flag; excluded from export when false |
|
|
93
|
+
| `showAs` | `{component, props, queries}` | Custom cell renderer |
|
|
79
94
|
| `width` | `number` | Column width |
|
|
80
95
|
| `sticky` | `left \| right` | Pin column |
|
|
96
|
+
| `enableEdit` | `boolean` | Enable inline editing (requires `editor`) |
|
|
97
|
+
| `editor` | `{component, props}` | Editor component (required with `enableEdit`) |
|
|
98
|
+
| `onEdit` | `action[]` | Action on edit commit. Variables: `changedValues`, `value`, `index`, + row data |
|
|
99
|
+
| `exportPath` | `string` | Export key/path override (top-level or `props.exportPath`). Fallback: `exportPath ?? path ?? name` |
|
|
100
|
+
| `exportTemplate` | `string` | Template expression for export-only formatted value (top-level or `props.exportTemplate`); exposed at `store.<gridName>.exportTemplates` |
|
|
101
|
+
| `path` | `string` | Data path for column value. Fallback for `exportPath` |
|
|
102
|
+
| `subQueries` | `string[]` | Extra GraphQL field paths to fetch without displaying them as columns |
|
|
103
|
+
| `excludeFromQuery` | `boolean` | Exclude from GraphQL query and CSV export |
|
|
81
104
|
|
|
82
105
|
```yaml
|
|
83
106
|
component: dataGrid
|
|
@@ -101,13 +124,20 @@ props:
|
|
|
101
124
|
views:
|
|
102
125
|
- name: all
|
|
103
126
|
displayName: { en-US: "All Orders" }
|
|
127
|
+
paginationPosition: top
|
|
104
128
|
columns:
|
|
105
129
|
- name: id
|
|
106
130
|
isHidden: true
|
|
107
131
|
- name: orderNumber
|
|
108
132
|
label: { en-US: "Order #" }
|
|
133
|
+
subQueries:
|
|
134
|
+
- customer.name
|
|
109
135
|
- name: customerName
|
|
110
136
|
label: { en-US: "Customer" }
|
|
137
|
+
exportPath: customer.displayName
|
|
138
|
+
- name: totalAmount
|
|
139
|
+
label: { en-US: "Total" }
|
|
140
|
+
exportTemplate: "{{ formatCurrency totalAmount currencyCode }}"
|
|
111
141
|
- name: status
|
|
112
142
|
label: { en-US: "Status" }
|
|
113
143
|
showAs:
|
|
@@ -124,6 +154,7 @@ props:
|
|
|
124
154
|
- name: active
|
|
125
155
|
displayName: { en-US: "Active" }
|
|
126
156
|
filter: "status:Active"
|
|
157
|
+
search: "{{ inputs.customerName }}"
|
|
127
158
|
columns:
|
|
128
159
|
- name: id
|
|
129
160
|
isHidden: true
|
|
@@ -143,6 +174,8 @@ props:
|
|
|
143
174
|
enableColumns: true
|
|
144
175
|
enableFilter: true
|
|
145
176
|
defaultView: all
|
|
177
|
+
defaultExpandedRows: true
|
|
178
|
+
includeEntityKeysInExport: true
|
|
146
179
|
onRowClick:
|
|
147
180
|
- navigate: "orders/{{ id }}"
|
|
148
181
|
toolbar:
|
|
@@ -156,6 +189,221 @@ props:
|
|
|
156
189
|
- notification: { message: { en-US: "Exporting..." }, type: success }
|
|
157
190
|
```
|
|
158
191
|
|
|
192
|
+
### Entity Fields & Column Visibility
|
|
193
|
+
|
|
194
|
+
When `rootEntityName` is set in datagrid options, the component fetches entity field definitions via GraphQL at runtime. Entity fields become "available columns" in the column picker — they are **not visible by default**. To make an entity field visible by default, add it to a view's `columns` array.
|
|
195
|
+
|
|
196
|
+
**Entity field properties** (in `entities[].fields[]`):
|
|
197
|
+
|
|
198
|
+
| Property | Location | Effect |
|
|
199
|
+
|----------|----------|--------|
|
|
200
|
+
| `allowOrderBy: false` | `props` (preferred) or top-level legacy | Disables sorting; runtime falls back to top-level `allowOrderBy` when `props.allowOrderBy` is absent |
|
|
201
|
+
| `allowFilter: false` | `props` | Hides from filter picker |
|
|
202
|
+
| `allowSelect: false` | `props` | Hides from standard column picker; filter picker still uses `allowFilter` |
|
|
203
|
+
| `filterByProperty` | `props` | Filter against a different field/path than the display column; nested filter paths honor parent `filterByProperty` values |
|
|
204
|
+
| `isInactive: true` | top-level | Marks field as inactive |
|
|
205
|
+
| `isCustomField: true` | top-level | Marks as custom field |
|
|
206
|
+
| `priority: <int>` | top-level | Resolves duplicate field definitions across app modules; highest active priority wins |
|
|
207
|
+
|
|
208
|
+
**Visibility rules:**
|
|
209
|
+
|
|
210
|
+
- Do **not** use `fieldType: select` for new entity fields. It is a legacy pattern that requires `props.showAs` to appear in the column picker and causes rendering conflicts on editable columns (see pitfalls below). Use the appropriate non-select fieldType instead (`text`, `number`, `date`, `enhanced-rangedatetime`, `checkbox`, etc.). All non-select types appear in the picker without needing `showAs`.
|
|
211
|
+
- `fieldType: Entity` is filtered out of the column picker entirely by the runtime — do not use it.
|
|
212
|
+
- `isHidden` is only valid on view columns, not entity field definitions.
|
|
213
|
+
- View column `name` must exactly match entity field `name`. If they differ (e.g., using a GraphQL alias prefix), the datagrid treats them as two separate columns — one always visible from the view, one hidden in the picker from the entity field.
|
|
214
|
+
- Saved database views override YAML definitions. User customizations take priority. If a user has saved a view, YAML visibility changes have no effect until the saved view is deleted.
|
|
215
|
+
|
|
216
|
+
**Correct pattern** (resolver column, sortable, filterable, in picker):
|
|
217
|
+
|
|
218
|
+
```yaml
|
|
219
|
+
entities:
|
|
220
|
+
- name: MyEntity
|
|
221
|
+
entityKind: Order
|
|
222
|
+
fields:
|
|
223
|
+
- name: 'getTerminal(idPropertyName:"terminalId").name'
|
|
224
|
+
displayName: { en-US: Terminal }
|
|
225
|
+
description: { en-US: Terminal }
|
|
226
|
+
fieldType: text
|
|
227
|
+
isInactive: false
|
|
228
|
+
isCustomField: true
|
|
229
|
+
props:
|
|
230
|
+
orderByProperty: "customValues.terminalId->terminal.name"
|
|
231
|
+
filterByProperty: "customValues.terminalId"
|
|
232
|
+
filter:
|
|
233
|
+
component: Terminals/Select
|
|
234
|
+
|
|
235
|
+
views:
|
|
236
|
+
- name: all
|
|
237
|
+
columns:
|
|
238
|
+
- name: 'getTerminal(idPropertyName:"terminalId").name' # matches entity field exactly
|
|
239
|
+
label: { en-US: Terminal }
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Export + Re-import Keys
|
|
243
|
+
|
|
244
|
+
DataGrid export configuration now prepends missing `options.entityKeys` by default. This is intentional: import tasks can match by primary key first, so users can export a grid, edit business-key columns, and re-import without creating duplicate records.
|
|
245
|
+
|
|
246
|
+
Disable key injection only for clean/template exports:
|
|
247
|
+
|
|
248
|
+
```yaml
|
|
249
|
+
props:
|
|
250
|
+
options:
|
|
251
|
+
entityKeys: [contactAddressId]
|
|
252
|
+
includeEntityKeysInExport: false
|
|
253
|
+
views:
|
|
254
|
+
- name: publicTemplate
|
|
255
|
+
includeEntityKeysInExport: false
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Inline Cell Editing
|
|
259
|
+
|
|
260
|
+
**Both `enableEdit: true` AND `editor` are required** for inline editing to activate.
|
|
261
|
+
|
|
262
|
+
Example with built-in field editor:
|
|
263
|
+
|
|
264
|
+
```yaml
|
|
265
|
+
columns:
|
|
266
|
+
- name: trackingNumber
|
|
267
|
+
enableEdit: true
|
|
268
|
+
editor: { component: field }
|
|
269
|
+
onEdit:
|
|
270
|
+
- mutation:
|
|
271
|
+
variables:
|
|
272
|
+
trackingNumber: "{{ changedValues }}"
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Example with select-async editor — use `{{ value }}` in `onEdit`:
|
|
276
|
+
|
|
277
|
+
```yaml
|
|
278
|
+
columns:
|
|
279
|
+
- name: customValues.returnLocation
|
|
280
|
+
enableEdit: true
|
|
281
|
+
editor:
|
|
282
|
+
component: Terminals/Select
|
|
283
|
+
onEdit:
|
|
284
|
+
- mutation:
|
|
285
|
+
variables:
|
|
286
|
+
input:
|
|
287
|
+
values:
|
|
288
|
+
customValues:
|
|
289
|
+
returnLocationId: "{{ number value }}"
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Entity Field Pitfalls
|
|
293
|
+
|
|
294
|
+
**Pitfall 1 — `fieldType: select` is legacy (do not use for new fields)**
|
|
295
|
+
|
|
296
|
+
`fieldType: select` requires `props.showAs` to appear in the column picker — without it, the column is invisible. Non-select types always appear.
|
|
297
|
+
|
|
298
|
+
When editing existing modules that use `fieldType: select` with inline editing: `showAs` changes how EditableCell renders in display mode. The cell goes through ComponentRender template evaluation instead of raw value display. This produces different visual output than the original grid column definition. Be aware of this dual behavior when maintaining legacy `select` fields.
|
|
299
|
+
|
|
300
|
+
**Pitfall 2 — Entity field `onEdit` must match grid column `onEdit` verbatim**
|
|
301
|
+
|
|
302
|
+
When a user re-adds an editable column from the picker, the entity field's `onEdit` replaces the grid column's `onEdit` entirely. If they differ (different mutation, different variable names, different `onSuccess`), the re-added column saves differently. Always copy `onEdit` from the grid view column definition into the entity field definition verbatim.
|
|
303
|
+
|
|
304
|
+
**Pitfall 3 — Edit properties go inside `props` in entity fields**
|
|
305
|
+
|
|
306
|
+
Unlike grid view columns where `enableEdit`, `editor`, and `onEdit` are top-level, entity field definitions must place them inside `props`. The runtime automatically promotes them to top-level when building available columns.
|
|
307
|
+
|
|
308
|
+
**Example — entity field with inline editing:**
|
|
309
|
+
|
|
310
|
+
```yaml
|
|
311
|
+
entities:
|
|
312
|
+
- name: MyEntity
|
|
313
|
+
entityKind: Order
|
|
314
|
+
fields:
|
|
315
|
+
- name: 'getTerminal(idPropertyName:"terminalId").name'
|
|
316
|
+
displayName: { en-US: Terminal }
|
|
317
|
+
description: { en-US: Terminal }
|
|
318
|
+
fieldType: text
|
|
319
|
+
isInactive: false
|
|
320
|
+
isCustomField: true
|
|
321
|
+
props:
|
|
322
|
+
enableEdit: true # inside props, not top-level
|
|
323
|
+
editor:
|
|
324
|
+
component: Terminals/Select
|
|
325
|
+
onEdit: # must match grid column onEdit exactly
|
|
326
|
+
- mutation:
|
|
327
|
+
command: |
|
|
328
|
+
mutation UpdateOrderMutation($input: UpdateOrderInput!) {
|
|
329
|
+
updateOrder(input: $input) { order { orderId } }
|
|
330
|
+
}
|
|
331
|
+
variables:
|
|
332
|
+
input:
|
|
333
|
+
organizationId: "{{number organizationId}}"
|
|
334
|
+
orderId: "{{number orderId}}"
|
|
335
|
+
values:
|
|
336
|
+
customValues:
|
|
337
|
+
terminalId: "{{ number value }}"
|
|
338
|
+
onSuccess:
|
|
339
|
+
- refresh: orders
|
|
340
|
+
orderByProperty: "customValues.terminalId->terminal.name"
|
|
341
|
+
filterByProperty: "customValues.terminalId"
|
|
342
|
+
filter:
|
|
343
|
+
component: Terminals/Select
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Sorting Resolver Columns
|
|
347
|
+
|
|
348
|
+
Resolver columns (e.g., `getTerminal(idPropertyName:"terminalId").name`) cannot be sorted by default — the backend rejects them as invalid entity properties. Use `orderByProperty` in column `props` to override the sort field:
|
|
349
|
+
|
|
350
|
+
```yaml
|
|
351
|
+
- name: 'getTerminal(idPropertyName:"terminalId").name'
|
|
352
|
+
label: { en-US: Terminal }
|
|
353
|
+
props:
|
|
354
|
+
orderByProperty: "customValues.terminalId->terminal.name"
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Join syntax format: `customValues.{idPropertyName}->{entityAlias}.{property}`
|
|
358
|
+
|
|
359
|
+
Single-level property access only (`terminal.name` works, `contact.address.city` does not).
|
|
360
|
+
|
|
361
|
+
Registered join entities: `contact`, `order`, `modeOfTransportation`, `country`, `terminal`, `contactAddress`.
|
|
362
|
+
|
|
363
|
+
Contact-address custom values can use the same override pattern, for example `customValues.deliveryLocationId->contactAddress.name` or `customValues.returnLocationId->contactAddress.name`.
|
|
364
|
+
|
|
365
|
+
Alternative: disable sorting with `allowOrderBy: false` in column props.
|
|
366
|
+
|
|
367
|
+
### Hidden Query Dependencies
|
|
368
|
+
|
|
369
|
+
Use column-level `subQueries` when a column renderer, action, conditional style, or export needs related GraphQL fields that should not appear as visible columns. The runtime appends these paths to the query selection and preserves them when users add the column in view settings.
|
|
370
|
+
|
|
371
|
+
```yaml
|
|
372
|
+
- name: orderNumber
|
|
373
|
+
label: { en-US: Order # }
|
|
374
|
+
subQueries:
|
|
375
|
+
- customer.name
|
|
376
|
+
- customer.primaryContact.email
|
|
377
|
+
showAs:
|
|
378
|
+
component: text
|
|
379
|
+
props:
|
|
380
|
+
value: "{{ orderNumber }} — {{ customer.name }}"
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### CSV Export
|
|
384
|
+
|
|
385
|
+
`exportPath` controls the column key used for CSV export. Fallback chain: `exportPath ?? path ?? name`.
|
|
386
|
+
|
|
387
|
+
For resolver columns, `exportPath` must use the GraphQL response key **without arguments**:
|
|
388
|
+
|
|
389
|
+
```yaml
|
|
390
|
+
# Correct — GraphQL response uses "getTerminal" as the key
|
|
391
|
+
- name: 'getTerminal(idPropertyName:"terminalId").name'
|
|
392
|
+
exportPath: "getTerminal.name"
|
|
393
|
+
label: { en-US: Terminal }
|
|
394
|
+
|
|
395
|
+
# Wrong — response key does not include arguments, CSV values will be empty
|
|
396
|
+
- name: 'getTerminal(idPropertyName:"terminalId").name'
|
|
397
|
+
exportPath: 'getTerminal(idPropertyName:"terminalId").name'
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
For aliased resolver fields, use the alias as the response key:
|
|
401
|
+
|
|
402
|
+
```yaml
|
|
403
|
+
- name: 'returnLocation : getTerminal(idPropertyName:"returnLocationId").name'
|
|
404
|
+
exportPath: "returnLocation.name"
|
|
405
|
+
```
|
|
406
|
+
|
|
159
407
|
---
|
|
160
408
|
|
|
161
409
|
## text
|
|
@@ -169,6 +417,10 @@ Typography text display with template interpolation.
|
|
|
169
417
|
| `type` | `h1-h6 \| p \| span \| block` | `span` | HTML element / MUI variant |
|
|
170
418
|
| `color` | `string` | `text` | MUI color |
|
|
171
419
|
| `options` | `object` | — | Additional MUI Typography props |
|
|
420
|
+
| `label` | `string \| localized \| template` | — | Optional label rendered with the text |
|
|
421
|
+
| `labelPosition` | `top \| left` | `top` | Label placement |
|
|
422
|
+
| `labelColor` | `string` | `text.secondary` | MUI color for label |
|
|
423
|
+
| `labelWidth` | `string \| number` | `auto` | Minimum label width when `labelPosition: left` |
|
|
172
424
|
| `stopPropagation` | `boolean` | — | Stop click propagation |
|
|
173
425
|
|
|
174
426
|
**Events:** `onClick`
|
|
@@ -184,6 +436,9 @@ Typography text display with template interpolation.
|
|
|
184
436
|
- component: text
|
|
185
437
|
name: statusLabel
|
|
186
438
|
props:
|
|
439
|
+
label: { en-US: "Last updated" }
|
|
440
|
+
labelPosition: left
|
|
441
|
+
labelWidth: 8rem
|
|
187
442
|
value: "{{ format lastModified LLL }}"
|
|
188
443
|
type: span
|
|
189
444
|
color: text.secondary
|
|
@@ -219,14 +474,33 @@ props:
|
|
|
219
474
|
|
|
220
475
|
## badge
|
|
221
476
|
|
|
222
|
-
|
|
477
|
+
Compact theme-aware badge. Prefer semantic variants for new modules; the dot is opt-in.
|
|
478
|
+
|
|
479
|
+
## avatar, infoLine, and progressBar
|
|
480
|
+
|
|
481
|
+
Use these template-aware display components for compact entity cards and planner headers.
|
|
482
|
+
|
|
483
|
+
```yaml
|
|
484
|
+
- component: avatar
|
|
485
|
+
props: { name: '{{ row.record.name }}', colorSeed: '{{ row.record.id }}', size: 40 }
|
|
486
|
+
- component: infoLine
|
|
487
|
+
props: { icon: tabler-phone, value: '{{ row.record.phone }}', href: 'tel:{{ row.record.phone }}' }
|
|
488
|
+
- component: progressBar
|
|
489
|
+
props: { items: '{{ row.items }}', completedPath: status, completedValue: Completed }
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
`avatar` derives initials from names/email and uses `src` as an optional image. `infoLine` renders nothing for an empty value and only links allowlisted URL schemes. `progressBar` accepts direct `value`/`max` or derives counts from `items`; choose `count`/`percent` and `linear`/`circular`/`segmented` display modes. On mobile, `activeColor` and `trackColor` customize segmented progress; `tooltip` is exposed to assistive technology rather than hover UI.
|
|
223
493
|
|
|
224
494
|
**Props:**
|
|
225
495
|
| Prop | Type | Description |
|
|
226
496
|
|------|------|-------------|
|
|
227
|
-
| `label` | `string` | Badge text (template-parsed) |
|
|
228
|
-
| `colorKey` | `string` | Color lookup key (template-parsed; defaults to lowercased label) |
|
|
229
|
-
| `
|
|
497
|
+
| `label` | `string` | Badge text (template-parsed with store, component variables, and form values) |
|
|
498
|
+
| `colorKey` | `string` | Color lookup key (template-parsed with store, component variables, and form values; defaults to lowercased label) |
|
|
499
|
+
| `color` / `variant` | `string` | Seed hex or semantic variant (`danger`, `warning`, `info`, `success`, `primary`, `neutral`) |
|
|
500
|
+
| `size` / `appearance` | `string` | `xs|sm|md`; `soft|outline|solid|ghost` |
|
|
501
|
+
| `uppercase`, `dot` | `boolean` | Both default to `false` |
|
|
502
|
+
| `icon`, `maxWidth` | `string`, `string \| number` | Optional icon and ellipsis width |
|
|
503
|
+
| `options.colors` | `Record<string, string \| object>` | Optional variants, hexes, token objects, or legacy triples |
|
|
230
504
|
| `onClick` | `Action[]` | Actions to dispatch when the badge is clicked. Makes the badge interactive (pointer cursor). |
|
|
231
505
|
|
|
232
506
|
```yaml
|
|
@@ -361,7 +635,7 @@ props:
|
|
|
361
635
|
|
|
362
636
|
## diff
|
|
363
637
|
|
|
364
|
-
Side-by-side diff viewer for comparing text.
|
|
638
|
+
Side-by-side diff viewer for comparing text. Long lines wrap within each pane, and gutters/markers keep fixed widths so the two columns stay balanced.
|
|
365
639
|
|
|
366
640
|
**Props:**
|
|
367
641
|
| Prop | Type | Default | Description |
|