@globalbrain/sefirot 4.41.1 → 4.42.0
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.
|
@@ -61,7 +61,18 @@ export interface Props {
|
|
|
61
61
|
// Whether to hide the condition blocks.
|
|
62
62
|
hideConditions?: boolean
|
|
63
63
|
|
|
64
|
-
// Field name to be used as
|
|
64
|
+
// Field name to be used as the row identifier. When set, the field is
|
|
65
|
+
// automatically included in the request `select` so every row carries
|
|
66
|
+
// its value, and the corresponding column is hidden from the rendered
|
|
67
|
+
// table — *unless* the caller explicitly listed it in `select`, in
|
|
68
|
+
// which case the caller's intent wins and the column is shown
|
|
69
|
+
// normally. The value remains accessible via `record[indexField]` in
|
|
70
|
+
// `cell-clicked` events and through the `selected` model regardless.
|
|
71
|
+
//
|
|
72
|
+
// If the caller's `select` is empty or `null` (i.e. "use server
|
|
73
|
+
// defaults"), the index field is **not** auto-appended — that would
|
|
74
|
+
// narrow the result to just that single column on backends that treat
|
|
75
|
+
// an empty `select` as "use defaults".
|
|
65
76
|
indexField?: string
|
|
66
77
|
|
|
67
78
|
// Fields that are clickable to emit `cell-clicked` event when clicked.
|
|
@@ -125,6 +136,11 @@ const hasInitialResults = ref(false)
|
|
|
125
136
|
let prevFetchInput: LensQuery | null = null
|
|
126
137
|
let prevFetchResult: LensResult | null = null
|
|
127
138
|
|
|
139
|
+
// `_select` carries the caller's intent. The index field is preserved
|
|
140
|
+
// here if it was listed explicitly so the corresponding column gets
|
|
141
|
+
// rendered, and is only added to the request payload separately (see
|
|
142
|
+
// `withIndexField`). When `_select` is empty, the auto-fetched index
|
|
143
|
+
// field is stripped out of the table's column list further down.
|
|
128
144
|
const _select = ref(props.select ?? [])
|
|
129
145
|
const _selectable = ref(props.selectable ?? props.select ?? [])
|
|
130
146
|
|
|
@@ -152,7 +168,7 @@ const perPage = ref(100)
|
|
|
152
168
|
const { data: result, execute: refresh, loading } = useQuery(async (http) => {
|
|
153
169
|
const input = {
|
|
154
170
|
entity: props.entity ?? '__no_entity__',
|
|
155
|
-
select: _select.value,
|
|
171
|
+
select: withIndexField(_select.value),
|
|
156
172
|
filters: createInputFilters(queryFilter.value, _filters.value),
|
|
157
173
|
sort: _sort.value.length > 0 ? _sort.value : defaultSort.value ?? [],
|
|
158
174
|
page: page.value,
|
|
@@ -231,19 +247,55 @@ const tableMaxHeight = computed(() => {
|
|
|
231
247
|
return `--table-max-height: calc(${props.height} - ${controlHeight} - ${conditionBlocksHeight.value} - ${columnsHeight} - ${footerHeight})`
|
|
232
248
|
})
|
|
233
249
|
|
|
234
|
-
// Initial setup when the result is loaded for the first time.
|
|
250
|
+
// Initial setup when the result is loaded for the first time. When the
|
|
251
|
+
// caller didn't pass a `select`, we initialise from the response, but
|
|
252
|
+
// we strip out the index field — anything pulled in by `withIndexField`
|
|
253
|
+
// on the way out shouldn't pretend to be caller-declared on the way
|
|
254
|
+
// back in.
|
|
235
255
|
watch(result, (res) => {
|
|
236
256
|
if (!hasInitialResults.value && res!.data.length > 0) {
|
|
237
257
|
hasInitialResults.value = true
|
|
238
258
|
}
|
|
239
259
|
if (_select.value.length === 0) {
|
|
240
|
-
_select.value = res!.query.select
|
|
260
|
+
_select.value = withoutIndexField(res!.query.select)
|
|
241
261
|
}
|
|
242
262
|
if (_selectable.value.length === 0) {
|
|
243
|
-
_selectable.value = res!.query.select
|
|
263
|
+
_selectable.value = withoutIndexField(res!.query.select)
|
|
244
264
|
}
|
|
245
265
|
}, { once: true })
|
|
246
266
|
|
|
267
|
+
// Columns to render in the table. We always defer to `_select` (caller
|
|
268
|
+
// or user intent) once we have it; before the first response we use the
|
|
269
|
+
// raw response select with the index field filtered out so an
|
|
270
|
+
// auto-fetched index field doesn't accidentally appear as a column.
|
|
271
|
+
const tableSelect = computed(() => {
|
|
272
|
+
if (_select.value.length > 0) {
|
|
273
|
+
return _select.value
|
|
274
|
+
}
|
|
275
|
+
return withoutIndexField(result.value?.query.select ?? [])
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
// The `indexField` is appended to the request `select` so the server
|
|
279
|
+
// returns its value on every row, but it is kept out of the internal
|
|
280
|
+
// `_select` / `_selectable` state so the caller-facing concept of
|
|
281
|
+
// "selected columns" stays clean (the index field is a row identifier,
|
|
282
|
+
// not a column the user picked). The corresponding column is also
|
|
283
|
+
// hidden from the rendered table by `LensTable`.
|
|
284
|
+
//
|
|
285
|
+
// When the caller has no concrete select list, the index field is
|
|
286
|
+
// *not* added either — leaving the request empty lets the server use
|
|
287
|
+
// its own defaults. See `indexField` prop docs above.
|
|
288
|
+
function withIndexField(fields: string[]): string[] {
|
|
289
|
+
if (fields.length === 0) { return [] }
|
|
290
|
+
if (!props.indexField || fields.includes(props.indexField)) { return [...fields] }
|
|
291
|
+
return [...fields, props.indexField]
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function withoutIndexField(fields: string[]): string[] {
|
|
295
|
+
if (!props.indexField) { return [...fields] }
|
|
296
|
+
return fields.filter((f) => f !== props.indexField)
|
|
297
|
+
}
|
|
298
|
+
|
|
247
299
|
// Create lens filters option by combining query (free search) filters,
|
|
248
300
|
// user selected filters, and fixed filters.
|
|
249
301
|
function createInputFilters(queryFilters: any[], filters: any[]) {
|
|
@@ -313,6 +365,8 @@ function onResetSorts() {
|
|
|
313
365
|
}
|
|
314
366
|
|
|
315
367
|
function onViewUpdated(newSelect: string[], newSelectable: string[], overrides: Record<string, Partial<FieldData>>) {
|
|
368
|
+
// Treat updates from the view form as deliberate user intent: if the
|
|
369
|
+
// user picked the index field on purpose, surface its column.
|
|
316
370
|
_select.value = newSelect
|
|
317
371
|
_selectable.value = newSelectable
|
|
318
372
|
_overrides.value = overrides
|
|
@@ -423,6 +477,7 @@ defineExpose({
|
|
|
423
477
|
:result
|
|
424
478
|
:loading
|
|
425
479
|
:overrides="_overrides"
|
|
480
|
+
:select="tableSelect"
|
|
426
481
|
:index-field
|
|
427
482
|
:selected
|
|
428
483
|
:clickable-fields
|
|
@@ -14,6 +14,11 @@ const props = defineProps<{
|
|
|
14
14
|
result?: LensResult
|
|
15
15
|
overrides?: Record<string, Partial<FieldData>>
|
|
16
16
|
loading: boolean
|
|
17
|
+
// The list of field keys to actually render as columns, in order.
|
|
18
|
+
// Falls back to `result.query.select` if not provided. The catalog
|
|
19
|
+
// uses this to control whether an auto-fetched `indexField` shows up
|
|
20
|
+
// as a column.
|
|
21
|
+
select?: string[]
|
|
17
22
|
selected?: any[]
|
|
18
23
|
indexField?: string
|
|
19
24
|
}>()
|
|
@@ -29,8 +34,10 @@ const fieldFactory = useFieldFactory()
|
|
|
29
34
|
|
|
30
35
|
const records = computed(() => props.result?.data ?? [])
|
|
31
36
|
|
|
37
|
+
const columnKeys = computed(() => props.select ?? props.result?.query.select ?? [])
|
|
38
|
+
|
|
32
39
|
const orders = computed(() => [
|
|
33
|
-
...
|
|
40
|
+
...columnKeys.value,
|
|
34
41
|
'__last_empty__'
|
|
35
42
|
])
|
|
36
43
|
|
|
@@ -48,9 +55,9 @@ const columns = computedAsync(async () => {
|
|
|
48
55
|
}
|
|
49
56
|
}
|
|
50
57
|
|
|
51
|
-
// Build the
|
|
52
|
-
for (const i in
|
|
53
|
-
const key =
|
|
58
|
+
// Build the list of columns based on the resolved column key list.
|
|
59
|
+
for (const i in columnKeys.value) {
|
|
60
|
+
const key = columnKeys.value[i]
|
|
54
61
|
|
|
55
62
|
const _fieldData = cloneDeep(r.fields[key])
|
|
56
63
|
|
package/lib/styles/variables.css
CHANGED
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
--c-neutral-dark-dimm-a1: rgba(255, 255, 255, 0.08);
|
|
35
35
|
--c-neutral-dark-dimm-a2: rgba(255, 255, 255, 0.16);
|
|
36
36
|
|
|
37
|
-
--c-text-light-1: #
|
|
38
|
-
--c-text-light-2:
|
|
39
|
-
--c-text-light-3:
|
|
37
|
+
--c-text-light-1: #22201d;
|
|
38
|
+
--c-text-light-2: #656260;
|
|
39
|
+
--c-text-light-3: #8f8c89;
|
|
40
40
|
|
|
41
|
-
--c-text-dark-1: #
|
|
42
|
-
--c-text-dark-2:
|
|
43
|
-
--c-text-dark-3:
|
|
41
|
+
--c-text-dark-1: #ededed;
|
|
42
|
+
--c-text-dark-2: #b3b3b3;
|
|
43
|
+
--c-text-dark-3: #6c6c6c;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
@@ -232,8 +232,8 @@
|
|
|
232
232
|
|
|
233
233
|
:root {
|
|
234
234
|
--c-bg-1: var(--c-white);
|
|
235
|
-
--c-bg-2:
|
|
236
|
-
--c-bg-3:
|
|
235
|
+
--c-bg-2: #fbfaf9;
|
|
236
|
+
--c-bg-3: #f3f1f1;
|
|
237
237
|
|
|
238
238
|
--c-bg-elv-1: #ffffff;
|
|
239
239
|
--c-bg-elv-2: #f5f5f7;
|
|
@@ -270,22 +270,14 @@
|
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
.dark {
|
|
273
|
-
--c-bg-1:
|
|
274
|
-
--c-bg-2:
|
|
275
|
-
--c-bg-3:
|
|
273
|
+
--c-bg-1: #0a0a0a;
|
|
274
|
+
--c-bg-2: #171717;
|
|
275
|
+
--c-bg-3: #262626;
|
|
276
276
|
|
|
277
277
|
--c-bg-elv-1: #000000;
|
|
278
278
|
--c-bg-elv-2: #151517;
|
|
279
279
|
--c-bg-elv-3: #1b1b1f;
|
|
280
280
|
--c-bg-elv-4: #232429;
|
|
281
|
-
|
|
282
|
-
--c-text-1: var(--c-text-dark-1);
|
|
283
|
-
--c-text-2: var(--c-text-dark-2);
|
|
284
|
-
--c-text-3: var(--c-text-dark-3);
|
|
285
|
-
|
|
286
|
-
--c-text-inverse-1: var(--c-text-light-1);
|
|
287
|
-
--c-text-inverse-2: var(--c-text-light-2);
|
|
288
|
-
--c-text-inverse-3: var(--c-text-light-3);
|
|
289
281
|
}
|
|
290
282
|
|
|
291
283
|
/**
|