@svgrid/enterprise 3.1.7 → 3.1.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.
- package/README.md +1 -0
- package/dist/SvAlertRuleEditor.svelte +16 -5
- package/dist/SvGridAlerts.svelte +8 -0
- package/dist/SvGridAlerts.svelte.d.ts +4 -0
- package/dist/SvGridBoard.svelte +69 -10
- package/dist/SvGridBulkEditDrawer.svelte +13 -5
- package/dist/SvGridGallery.svelte +286 -0
- package/dist/SvGridGallery.svelte.d.ts +30 -0
- package/dist/SvGridScheduler.svelte +33 -11
- package/dist/SvGridSelectionBar.svelte +47 -0
- package/dist/advanced-filter/expr-columns-from-grid.d.ts +1 -0
- package/dist/advanced-filter/expr-columns-from-grid.js +11 -7
- package/dist/advanced-filter-enable.d.ts +6 -0
- package/dist/advanced-filter-enable.js +8 -0
- package/dist/alerts/alert-engine.d.ts +7 -0
- package/dist/alerts/alert-engine.js +5 -2
- package/dist/alerts/condition-editor.d.ts +26 -0
- package/dist/alerts/condition-editor.js +17 -0
- package/dist/base/index.d.ts +20 -0
- package/dist/base/index.js +20 -0
- package/dist/bulk-edit.d.ts +11 -0
- package/dist/bulk-edit.js +18 -1
- package/dist/cdn/svgrid-enterprise.svelte-external.js +11375 -10805
- package/dist/designer/assets/GridFooter-Cu8_yBlQ.js +2 -0
- package/dist/designer/assets/GridMenus-BUjkkAU2.js +6 -0
- package/dist/designer/assets/PinSplitter-BgTpgh1d.css +1 -0
- package/dist/designer/assets/PinSplitter-C5AwA1xV.js +1 -0
- package/dist/designer/assets/SvGrid.helpers-CIrmIo9U.js +1 -0
- package/dist/designer/assets/SvGridCellEditor-CJxThKL_.js +4 -0
- package/dist/designer/assets/SvListBox-CS7oUAiX.js +2 -0
- package/dist/designer/assets/conditional-formatting-MDWbF8_Y.js +1 -0
- package/dist/designer/assets/grid-extension.svelte-BZ7AqyJI.js +1 -0
- package/dist/designer/assets/{index-DtBIaQno.js → index-BPU2KNc5.js} +396 -395
- package/dist/designer/assets/index-BmvG99kR.css +1 -0
- package/dist/designer/assets/sparkline-C-NcnB2i.js +1 -0
- package/dist/designer/assets/src-C_U1NKOY.js +58 -0
- package/dist/designer/assets/sv-grid-scrollbar-B9N6Wuj0.js +109 -0
- package/dist/designer/assets/validate-H5u2HEQh.js +1 -0
- package/dist/designer/index.html +11 -7
- package/dist/expressions/compile.js +10 -0
- package/dist/expressions/evaluate.js +18 -0
- package/dist/expressions/expression-types.d.ts +10 -0
- package/dist/expressions/kinds.d.ts +28 -0
- package/dist/expressions/kinds.js +19 -0
- package/dist/expressions/parse.js +9 -1
- package/dist/fields/AttachmentCell.svelte +242 -0
- package/dist/fields/AttachmentCell.svelte.d.ts +5 -0
- package/dist/fields/AttachmentDialog.svelte +357 -0
- package/dist/fields/AttachmentDialog.svelte.d.ts +13 -0
- package/dist/fields/AttachmentEditor.svelte +41 -0
- package/dist/fields/AttachmentEditor.svelte.d.ts +11 -0
- package/dist/fields/AttachmentPreview.svelte +72 -0
- package/dist/fields/AttachmentPreview.svelte.d.ts +8 -0
- package/dist/fields/BarcodeCell.svelte +20 -0
- package/dist/fields/BarcodeCell.svelte.d.ts +5 -0
- package/dist/fields/BaseAutomations.svelte +558 -0
- package/dist/fields/BaseAutomations.svelte.d.ts +18 -0
- package/dist/fields/BaseChartView.svelte +47 -0
- package/dist/fields/BaseChartView.svelte.d.ts +8 -0
- package/dist/fields/BaseTableView.svelte +185 -0
- package/dist/fields/BaseTableView.svelte.d.ts +37 -0
- package/dist/fields/BaseTabs.svelte +308 -0
- package/dist/fields/BaseTabs.svelte.d.ts +21 -0
- package/dist/fields/ButtonCell.svelte +47 -0
- package/dist/fields/ButtonCell.svelte.d.ts +20 -0
- package/dist/fields/CheckboxCell.svelte +46 -0
- package/dist/fields/CheckboxCell.svelte.d.ts +14 -0
- package/dist/fields/DeleteFieldConfirm.svelte +80 -0
- package/dist/fields/DeleteFieldConfirm.svelte.d.ts +8 -0
- package/dist/fields/DeleteRecordConfirm.svelte +48 -0
- package/dist/fields/DeleteRecordConfirm.svelte.d.ts +9 -0
- package/dist/fields/FieldCell.svelte +80 -0
- package/dist/fields/FieldCell.svelte.d.ts +9 -0
- package/dist/fields/FieldEditor.svelte +321 -0
- package/dist/fields/FieldEditor.svelte.d.ts +10 -0
- package/dist/fields/FieldInput.svelte +188 -0
- package/dist/fields/FieldInput.svelte.d.ts +29 -0
- package/dist/fields/FieldsHeaderEnd.svelte +146 -0
- package/dist/fields/FieldsHeaderEnd.svelte.d.ts +6 -0
- package/dist/fields/FootRowAdder.svelte +8 -0
- package/dist/fields/FootRowAdder.svelte.d.ts +6 -0
- package/dist/fields/GroupHeader.svelte +127 -0
- package/dist/fields/GroupHeader.svelte.d.ts +24 -0
- package/dist/fields/LinkCell.svelte +46 -0
- package/dist/fields/LinkCell.svelte.d.ts +9 -0
- package/dist/fields/LinkPickerEditor.svelte +172 -0
- package/dist/fields/LinkPickerEditor.svelte.d.ts +9 -0
- package/dist/fields/LinkPreview.svelte +60 -0
- package/dist/fields/LinkPreview.svelte.d.ts +7 -0
- package/dist/fields/LinkedRecordView.svelte +94 -0
- package/dist/fields/LinkedRecordView.svelte.d.ts +9 -0
- package/dist/fields/LinkedRecordsCell.svelte +59 -0
- package/dist/fields/LinkedRecordsCell.svelte.d.ts +11 -0
- package/dist/fields/LongTextEditor.svelte +157 -0
- package/dist/fields/LongTextEditor.svelte.d.ts +11 -0
- package/dist/fields/NumberEditor.svelte +309 -0
- package/dist/fields/NumberEditor.svelte.d.ts +12 -0
- package/dist/fields/OptionsEditor.svelte +117 -0
- package/dist/fields/OptionsEditor.svelte.d.ts +11 -0
- package/dist/fields/PercentCell.svelte +21 -0
- package/dist/fields/PercentCell.svelte.d.ts +8 -0
- package/dist/fields/PropertyInput.svelte +204 -0
- package/dist/fields/PropertyInput.svelte.d.ts +11 -0
- package/dist/fields/RatingCell.svelte +75 -0
- package/dist/fields/RatingCell.svelte.d.ts +16 -0
- package/dist/fields/RatingEditor.svelte +82 -0
- package/dist/fields/RatingEditor.svelte.d.ts +9 -0
- package/dist/fields/RecordView.svelte +310 -0
- package/dist/fields/RecordView.svelte.d.ts +11 -0
- package/dist/fields/RichTextCell.svelte +30 -0
- package/dist/fields/RichTextCell.svelte.d.ts +5 -0
- package/dist/fields/RowAdder.svelte +93 -0
- package/dist/fields/RowAdder.svelte.d.ts +7 -0
- package/dist/fields/RowHeader.svelte +99 -0
- package/dist/fields/RowHeader.svelte.d.ts +11 -0
- package/dist/fields/SelectCell.svelte +35 -0
- package/dist/fields/SelectCell.svelte.d.ts +15 -0
- package/dist/fields/SelectEditor.svelte +350 -0
- package/dist/fields/SelectEditor.svelte.d.ts +17 -0
- package/dist/fields/SummaryCell.svelte +160 -0
- package/dist/fields/SummaryCell.svelte.d.ts +11 -0
- package/dist/fields/SvBase.svelte +545 -0
- package/dist/fields/SvBase.svelte.d.ts +30 -0
- package/dist/fields/SvBaseForm.svelte +295 -0
- package/dist/fields/SvBaseForm.svelte.d.ts +22 -0
- package/dist/fields/SvBaseViewBar.svelte +644 -0
- package/dist/fields/SvBaseViewBar.svelte.d.ts +26 -0
- package/dist/fields/UserCell.svelte +39 -0
- package/dist/fields/UserCell.svelte.d.ts +9 -0
- package/dist/fields/UserFace.svelte +30 -0
- package/dist/fields/UserFace.svelte.d.ts +12 -0
- package/dist/fields/activity.svelte.d.ts +50 -0
- package/dist/fields/activity.svelte.js +110 -0
- package/dist/fields/attachments.d.ts +95 -0
- package/dist/fields/attachments.js +145 -0
- package/dist/fields/automation-outbound.d.ts +46 -0
- package/dist/fields/automation-outbound.js +61 -0
- package/dist/fields/automation-server.d.ts +53 -0
- package/dist/fields/automation-server.js +333 -0
- package/dist/fields/automations.svelte.d.ts +208 -0
- package/dist/fields/automations.svelte.js +437 -0
- package/dist/fields/bar-request.svelte.d.ts +16 -0
- package/dist/fields/bar-request.svelte.js +15 -0
- package/dist/fields/base-alerts.d.ts +24 -0
- package/dist/fields/base-alerts.js +64 -0
- package/dist/fields/base-connect.d.ts +82 -0
- package/dist/fields/base-connect.js +271 -0
- package/dist/fields/base-schema.d.ts +104 -0
- package/dist/fields/base-schema.js +266 -0
- package/dist/fields/base-sql.d.ts +62 -0
- package/dist/fields/base-sql.js +251 -0
- package/dist/fields/base-sync.d.ts +142 -0
- package/dist/fields/base-sync.js +499 -0
- package/dist/fields/base-tables.d.ts +89 -0
- package/dist/fields/base-tables.js +349 -0
- package/dist/fields/builtin-types.d.ts +13 -0
- package/dist/fields/builtin-types.js +773 -0
- package/dist/fields/button.d.ts +2 -0
- package/dist/fields/button.js +17 -0
- package/dist/fields/chart-view.d.ts +35 -0
- package/dist/fields/chart-view.js +154 -0
- package/dist/fields/column-order.d.ts +6 -0
- package/dist/fields/column-order.js +12 -0
- package/dist/fields/convert.d.ts +16 -0
- package/dist/fields/convert.js +176 -0
- package/dist/fields/copy-text.d.ts +13 -0
- package/dist/fields/copy-text.js +45 -0
- package/dist/fields/editor-request.svelte.d.ts +71 -0
- package/dist/fields/editor-request.svelte.js +52 -0
- package/dist/fields/field-ops.d.ts +72 -0
- package/dist/fields/field-ops.js +334 -0
- package/dist/fields/filter-model.d.ts +84 -0
- package/dist/fields/filter-model.js +446 -0
- package/dist/fields/format.d.ts +109 -0
- package/dist/fields/format.js +288 -0
- package/dist/fields/formula.d.ts +50 -0
- package/dist/fields/formula.js +530 -0
- package/dist/fields/grid-access.d.ts +60 -0
- package/dist/fields/grid-access.js +120 -0
- package/dist/fields/index.d.ts +34 -0
- package/dist/fields/index.js +312 -0
- package/dist/fields/linked-fields.d.ts +8 -0
- package/dist/fields/linked-fields.js +40 -0
- package/dist/fields/links.d.ts +10 -0
- package/dist/fields/links.js +46 -0
- package/dist/fields/name-list.d.ts +16 -0
- package/dist/fields/name-list.js +49 -0
- package/dist/fields/palette.d.ts +47 -0
- package/dist/fields/palette.js +69 -0
- package/dist/fields/record-delete.svelte.d.ts +12 -0
- package/dist/fields/record-delete.svelte.js +5 -0
- package/dist/fields/record-menu.d.ts +9 -0
- package/dist/fields/record-menu.js +78 -0
- package/dist/fields/registry.svelte.d.ts +176 -0
- package/dist/fields/registry.svelte.js +51 -0
- package/dist/fields/rich-text.d.ts +23 -0
- package/dist/fields/rich-text.js +48 -0
- package/dist/fields/row-color-choice.svelte.d.ts +31 -0
- package/dist/fields/row-color-choice.svelte.js +25 -0
- package/dist/fields/row-colors.d.ts +36 -0
- package/dist/fields/row-colors.js +90 -0
- package/dist/fields/row-height.d.ts +28 -0
- package/dist/fields/row-height.js +50 -0
- package/dist/fields/sources.svelte.d.ts +80 -0
- package/dist/fields/sources.svelte.js +131 -0
- package/dist/fields/summaries.d.ts +18 -0
- package/dist/fields/summaries.js +138 -0
- package/dist/fields/view-model.d.ts +129 -0
- package/dist/fields/view-model.js +492 -0
- package/dist/fields/viewbar/ChartPanel.svelte +61 -0
- package/dist/fields/viewbar/ChartPanel.svelte.d.ts +9 -0
- package/dist/fields/viewbar/ColorPanel.svelte +112 -0
- package/dist/fields/viewbar/ColorPanel.svelte.d.ts +9 -0
- package/dist/fields/viewbar/ConditionValue.svelte +153 -0
- package/dist/fields/viewbar/ConditionValue.svelte.d.ts +15 -0
- package/dist/fields/viewbar/FieldIcon.svelte +18 -0
- package/dist/fields/viewbar/FieldIcon.svelte.d.ts +9 -0
- package/dist/fields/viewbar/FilterPanel.svelte +192 -0
- package/dist/fields/viewbar/FilterPanel.svelte.d.ts +13 -0
- package/dist/fields/viewbar/GanttPanel.svelte +60 -0
- package/dist/fields/viewbar/GanttPanel.svelte.d.ts +10 -0
- package/dist/fields/viewbar/HideFieldsPanel.svelte +104 -0
- package/dist/fields/viewbar/HideFieldsPanel.svelte.d.ts +7 -0
- package/dist/fields/viewbar/SortPanel.svelte +85 -0
- package/dist/fields/viewbar/SortPanel.svelte.d.ts +8 -0
- package/dist/fields/viewbar/ViewsMenu.svelte +250 -0
- package/dist/fields/viewbar/ViewsMenu.svelte.d.ts +15 -0
- package/dist/fields/viewbar/panel-focus.d.ts +3 -0
- package/dist/fields/viewbar/panel-focus.js +22 -0
- package/dist/fields/viewbar/sort-state.d.ts +20 -0
- package/dist/fields/viewbar/sort-state.js +24 -0
- package/dist/gallery.d.ts +7 -0
- package/dist/gallery.js +36 -0
- package/dist/gantt/SvGridGantt.svelte +88 -16
- package/dist/gantt/gantt-config.d.ts +28 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +6 -0
- package/dist/install.js +3 -0
- package/dist/license-core.d.ts +3 -3
- package/dist/license.js +1 -0
- package/dist/node/studio.js +141 -20
- package/dist/scheduler-config.d.ts +11 -0
- package/dist/sources/introspect-supabase.js +4 -1
- package/dist/sources/rest.js +6 -2
- package/dist/studio/emit-project.js +25 -6
- package/dist/studio/sveltekit3.js +13 -7
- package/dist/studio/ui-components.generated.js +94 -2
- package/dist/upgrade-prompt.d.ts +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/dist/wc/GridFooter-f5K0aLe_.js +145 -0
- package/dist/wc/GridMenus-FtSN_8t9.js +1369 -0
- package/dist/wc/PinSplitter-D-qtDhSM.js +132 -0
- package/dist/wc/{SvGrid.helpers-zBkDTryR.js → SvGrid.helpers-B2GEKrxS.js} +84 -36
- package/dist/wc/{SvGridCellEditor-CzUKEbkI.js → SvGridCellEditor-B_cLJrsp.js} +20 -9
- package/dist/wc/conditional-formatting-BXis_oP1.js +189 -0
- package/dist/wc/grid-extension.svelte-Bufq4B4C.js +20 -0
- package/dist/wc/sv-sheet-element.js +7561 -7618
- package/dist/wc/svelte-virtualizer.svelte-ehwOupl-.js +360 -0
- package/dist/wc/{validate-43C03DLP.js → validate-BaMO8UPE.js} +1 -1
- package/package.json +14 -3
- package/dist/designer/assets/GridMenus-CvcASlKv.js +0 -8
- package/dist/designer/assets/SvGrid.helpers-DE5mmORW.js +0 -1
- package/dist/designer/assets/SvGridCellEditor-C7NWcnNC.js +0 -4
- package/dist/designer/assets/SvListBox-BlmmzYcU.js +0 -110
- package/dist/designer/assets/index-KmSEY7Lb.css +0 -1
- package/dist/designer/assets/src-DqHCqori.js +0 -58
- package/dist/designer/assets/validate-B71dE1Cs.js +0 -1
- package/dist/wc/GridMenus-fWbBUiRH.js +0 -1088
- package/dist/wc/svelte-virtualizer.svelte-Dntdh8Ms.js +0 -581
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* SvBase - a table database: one table with views, or several tables as
|
|
4
|
+
* tabs with links between them.
|
|
5
|
+
*
|
|
6
|
+
* ```svelte
|
|
7
|
+
* <SvBase {data} {columns} primaryField="name" bind:views editable />
|
|
8
|
+
* <SvBase bind:tables editable onTablesChange={save} />
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* With `tables`, a link field from one table to another gets a field in the
|
|
12
|
+
* other table that links back, and the two stay in step: linking a record
|
|
13
|
+
* on one side lists it on the other, deleting records unlinks them, pointing
|
|
14
|
+
* the field at another table moves the field back, and deleting either
|
|
15
|
+
* field or a table removes what links to it. `onTablesChange` hands over the
|
|
16
|
+
* whole list after every change, so the app can store it.
|
|
17
|
+
*
|
|
18
|
+
* A table with a `source` (`baseSource`) loads its records from a database
|
|
19
|
+
* or an API and writes each change back (`base-sync.ts`); the end of the
|
|
20
|
+
* tab bar says when it is loading, saving, or a save failed.
|
|
21
|
+
*/
|
|
22
|
+
import { onMount, untrack } from 'svelte'
|
|
23
|
+
import { toast } from '@svgrid/grid'
|
|
24
|
+
import { createBaseSync, type BaseSyncStatus } from './base-sync'
|
|
25
|
+
import BaseTableView from './BaseTableView.svelte'
|
|
26
|
+
import BaseTabs from './BaseTabs.svelte'
|
|
27
|
+
import { registerLinkedTable, unregisterLinkedTable } from './sources.svelte'
|
|
28
|
+
import { gridOf } from './grid-access'
|
|
29
|
+
import { openRecord, closeRecord } from './editor-request.svelte'
|
|
30
|
+
import {
|
|
31
|
+
addInverse,
|
|
32
|
+
blankTable,
|
|
33
|
+
checkLinks,
|
|
34
|
+
colId,
|
|
35
|
+
copyTable,
|
|
36
|
+
fieldChanged,
|
|
37
|
+
newRecordId,
|
|
38
|
+
primaryOf,
|
|
39
|
+
removeLinkField,
|
|
40
|
+
removeTable,
|
|
41
|
+
rowIdOf,
|
|
42
|
+
syncAllInverses,
|
|
43
|
+
syncInverse,
|
|
44
|
+
type BaseTable,
|
|
45
|
+
} from './base-tables'
|
|
46
|
+
import type { FieldView, FieldViewType } from './view-model'
|
|
47
|
+
import { baseToSql } from './base-sql'
|
|
48
|
+
import { createAutomationRunner, type AutomationRun, type BaseAutomation } from './automations.svelte'
|
|
49
|
+
|
|
50
|
+
type Row = Record<string, unknown>
|
|
51
|
+
// A table without views shows one grid view; one list, so it never reads as a change.
|
|
52
|
+
const GRID_ONLY: FieldView[] = [{ id: 'grid', name: 'Grid view', type: 'grid' }]
|
|
53
|
+
|
|
54
|
+
let {
|
|
55
|
+
tables = $bindable<BaseTable[] | undefined>(undefined),
|
|
56
|
+
activeTable = $bindable<string>(''),
|
|
57
|
+
onTablesChange,
|
|
58
|
+
data,
|
|
59
|
+
columns,
|
|
60
|
+
views = $bindable<FieldView[]>([{ id: 'grid', name: 'Grid view', type: 'grid' }]),
|
|
61
|
+
activeView = $bindable<string>(''),
|
|
62
|
+
onViewsChange,
|
|
63
|
+
viewTypes,
|
|
64
|
+
rowHeights,
|
|
65
|
+
containerHeight = 560,
|
|
66
|
+
onApiReady,
|
|
67
|
+
serverRuns,
|
|
68
|
+
automations = true,
|
|
69
|
+
...grid
|
|
70
|
+
}: {
|
|
71
|
+
/** Several tables, shown as tabs. Without it, `data` and `columns` are the one table. */
|
|
72
|
+
tables?: BaseTable[]
|
|
73
|
+
activeTable?: string
|
|
74
|
+
onTablesChange?: (tables: BaseTable[]) => void
|
|
75
|
+
data?: any[]
|
|
76
|
+
columns?: any[]
|
|
77
|
+
views?: FieldView[]
|
|
78
|
+
activeView?: string
|
|
79
|
+
onViewsChange?: (views: FieldView[]) => void
|
|
80
|
+
viewTypes?: ReadonlyArray<FieldViewType>
|
|
81
|
+
/** The row heights the view bar's row height menu offers. */
|
|
82
|
+
rowHeights?: ReadonlyArray<{ label: string; height: number }>
|
|
83
|
+
containerHeight?: number | string
|
|
84
|
+
onApiReady?: (api: any) => void
|
|
85
|
+
/** The server runner's latest runs, shown with this page's under Runs (an endpoint returning `server.runs`). */
|
|
86
|
+
serverRuns?: () => Promise<ReadonlyArray<AutomationRun>>
|
|
87
|
+
/** The view bar's Automations; false hides it (automations already set still run). */
|
|
88
|
+
automations?: boolean
|
|
89
|
+
[prop: string]: any
|
|
90
|
+
} = $props()
|
|
91
|
+
|
|
92
|
+
// ---- Several tables ------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
const current = $derived(tables ? (tables.find((t) => t.id === activeTable) ?? tables[0]) : undefined)
|
|
95
|
+
const currentId = $derived(current?.id ?? '')
|
|
96
|
+
// Raw: the fields module finds the grid by the api object itself.
|
|
97
|
+
let api = $state.raw<any>(null)
|
|
98
|
+
// The rows handed to the grid. They change when another table is shown, not
|
|
99
|
+
// on every edit: the grid writes edits into these rows and owns the array.
|
|
100
|
+
// svelte-ignore state_referenced_locally
|
|
101
|
+
let gridData = $state.raw<Row[]>(current?.data ?? [])
|
|
102
|
+
// svelte-ignore state_referenced_locally
|
|
103
|
+
let shownId = current?.id ?? ''
|
|
104
|
+
// A record to open once the table it is in has its grid (from "Open in").
|
|
105
|
+
let pendingOpen: string | null = null
|
|
106
|
+
// The view each table showed last ('' is its first view).
|
|
107
|
+
// svelte-ignore state_referenced_locally
|
|
108
|
+
let viewOf = $state<Record<string, string>>(Object.fromEntries((tables ?? []).map((t) => [t.id, ''])))
|
|
109
|
+
|
|
110
|
+
// Another table shown: its rows go to the grid, and it remembers its view.
|
|
111
|
+
$effect.pre(() => {
|
|
112
|
+
const t = current
|
|
113
|
+
if (!t) return
|
|
114
|
+
untrack(() => {
|
|
115
|
+
if (viewOf[t.id] === undefined) viewOf[t.id] = ''
|
|
116
|
+
if (t.id === shownId) return
|
|
117
|
+
shownId = t.id
|
|
118
|
+
gridData = t.data
|
|
119
|
+
if (activeTable !== t.id) activeTable = t.id
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
const height = $derived(typeof containerHeight === 'number' ? `${containerHeight}px` : containerHeight)
|
|
124
|
+
|
|
125
|
+
const tableOf = (id: string) => tables?.find((t) => t.id === id)
|
|
126
|
+
|
|
127
|
+
function commit(next: BaseTable[]) {
|
|
128
|
+
const before = tables
|
|
129
|
+
put(next)
|
|
130
|
+
// Tables with a source: what changed goes to the database.
|
|
131
|
+
sync.push(next)
|
|
132
|
+
linkedChanges(before, next)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Records of other tables a change reached through a link (a task added to
|
|
137
|
+
* a project lists it on the project): they changed too, so their
|
|
138
|
+
* automations hear of it. The shown table's own edits are heard from the
|
|
139
|
+
* grid. A link sync gives a changed record a new object, so identity tells
|
|
140
|
+
* which ones moved.
|
|
141
|
+
*/
|
|
142
|
+
function linkedChanges(prev: BaseTable[] | undefined, next: BaseTable[]) {
|
|
143
|
+
if (!prev) return
|
|
144
|
+
for (const t of next) {
|
|
145
|
+
if (t.id === current?.id || t.id === chainWrote || !(t.automations ?? []).length) continue
|
|
146
|
+
const old = prev.find((x) => x.id === t.id)
|
|
147
|
+
if (!old || old.data === t.data) continue
|
|
148
|
+
const byId = new Map(old.data.map((r) => [rowIdOf(old, r), r]))
|
|
149
|
+
for (const r of t.data) {
|
|
150
|
+
const was = byId.get(rowIdOf(t, r))
|
|
151
|
+
if (!was || was === r) continue
|
|
152
|
+
const fields = t.columns.filter((d) => d.field != null && JSON.stringify(was[String(d.field)] ?? null) !== JSON.stringify(r[String(d.field)] ?? null)).map((d) => colId(d))
|
|
153
|
+
if (fields.length) void runner.handle({ type: 'updated', table: t.id, record: r, before: was, fields, depth: chainDepth })
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** The tables in the page; the shown grid takes its table's rows when they changed outside it. */
|
|
159
|
+
function put(next: BaseTable[]) {
|
|
160
|
+
const before = current
|
|
161
|
+
tables = next
|
|
162
|
+
// The shown table's rows changed outside its grid (a link pointed
|
|
163
|
+
// elsewhere and its values were cleared): the grid takes the new rows.
|
|
164
|
+
const after = next.find((t) => t.id === before?.id)
|
|
165
|
+
if (after && before && after.data !== before.data && after.data !== liveRows()) gridData = after.data
|
|
166
|
+
onTablesChange?.(next)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ---- Tables on a database ---------------------------------------------------
|
|
170
|
+
|
|
171
|
+
let syncState = $state<BaseSyncStatus>({ state: 'idle' })
|
|
172
|
+
let savedOnce = $state(false)
|
|
173
|
+
const sync = createBaseSync({
|
|
174
|
+
// The shown table as its grid holds it: an edit is in its rows already.
|
|
175
|
+
getTables: () => (tables ? pulled() : undefined),
|
|
176
|
+
apply: put,
|
|
177
|
+
onStatus: (s) => {
|
|
178
|
+
if (s.state === 'saving') savedOnce = true
|
|
179
|
+
syncState = s
|
|
180
|
+
},
|
|
181
|
+
onError: (e) => toast.error(`Could not ${e.action === 'load' ? 'load' : 'save'} ${e.table}: ${e.message}`),
|
|
182
|
+
})
|
|
183
|
+
onMount(() => {
|
|
184
|
+
void sync.load()
|
|
185
|
+
return () => {
|
|
186
|
+
sync.dispose()
|
|
187
|
+
runner.stop()
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
// ---- Automations --------------------------------------------------------------
|
|
192
|
+
|
|
193
|
+
// What an automation changes goes through commit, so a table with a source
|
|
194
|
+
// writes it to the database like any other change.
|
|
195
|
+
// How deep in a chain of automations the change being committed was made.
|
|
196
|
+
let chainDepth = 0
|
|
197
|
+
// The table an automation changed itself: it reports that change.
|
|
198
|
+
let chainWrote: string | undefined
|
|
199
|
+
// This base's own key for its records' comments and activity (`baseScope`).
|
|
200
|
+
const baseScope = {}
|
|
201
|
+
const runner = createAutomationRunner({
|
|
202
|
+
scope: baseScope,
|
|
203
|
+
getTables: () => (tables ? pulled() : undefined),
|
|
204
|
+
apply: (next, depth = 0, wrote) => {
|
|
205
|
+
chainDepth = depth
|
|
206
|
+
chainWrote = wrote
|
|
207
|
+
try {
|
|
208
|
+
commit(next)
|
|
209
|
+
} finally {
|
|
210
|
+
chainDepth = 0
|
|
211
|
+
chainWrote = undefined
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
})
|
|
215
|
+
// Scheduled automations are armed again when any table's automations change.
|
|
216
|
+
$effect(() => {
|
|
217
|
+
void tables?.map((t) => t.automations)
|
|
218
|
+
untrack(() => runner.schedule())
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
// Edits to one record in one go (a paste, a fill) are one change to it.
|
|
222
|
+
const touched = new Map<string, { table: string; record: Row; before: Row; fields: Set<string> }>()
|
|
223
|
+
function noteUpdate(tableId: string, record: Row | undefined, columnId: string, oldValue: unknown) {
|
|
224
|
+
const t = tableOf(tableId)
|
|
225
|
+
if (!t || !record) return
|
|
226
|
+
const key = `${tableId}:${rowIdOf(t, record)}`
|
|
227
|
+
let hit = touched.get(key)
|
|
228
|
+
if (!hit) {
|
|
229
|
+
hit = { table: tableId, record, before: { ...record }, fields: new Set() }
|
|
230
|
+
touched.set(key, hit)
|
|
231
|
+
if (touched.size === 1) queueMicrotask(flushTouched)
|
|
232
|
+
}
|
|
233
|
+
const field = t.columns.find((d) => colId(d) === columnId)?.field
|
|
234
|
+
if (field != null && !hit.fields.has(columnId)) hit.before[String(field)] = oldValue
|
|
235
|
+
hit.fields.add(columnId)
|
|
236
|
+
}
|
|
237
|
+
function flushTouched() {
|
|
238
|
+
const list = [...touched.values()]
|
|
239
|
+
touched.clear()
|
|
240
|
+
for (const u of list) void runner.handle({ type: 'updated', table: u.table, record: u.record, before: u.before, fields: [...u.fields] })
|
|
241
|
+
}
|
|
242
|
+
/** The handler of a button field, when an automation runs on it. */
|
|
243
|
+
function buttonFor(tableId: string, columnId: string): ((row: Row) => void) | null {
|
|
244
|
+
const on = (tableOf(tableId)?.automations ?? []).some((a) => a.enabled && a.trigger.type === 'button' && a.trigger.field === columnId)
|
|
245
|
+
return on ? (row) => void runner.handle({ type: 'button', table: tableId, record: row, field: columnId }) : null
|
|
246
|
+
}
|
|
247
|
+
const syncLine = $derived.by(() => {
|
|
248
|
+
const s = syncState
|
|
249
|
+
if (!tables?.some((t) => t.source)) return null
|
|
250
|
+
if (s.state === 'loading') return { text: 'Loading records…' }
|
|
251
|
+
if (s.state === 'saving') return { text: 'Saving…' }
|
|
252
|
+
if (s.state === 'error') return { text: `Not saved: ${s.message}`, tone: 'error' as const, title: `${s.table}: ${s.message}` }
|
|
253
|
+
if (s.state === 'limited') return { text: `${s.table}: the first ${s.limit.toLocaleString()} records` }
|
|
254
|
+
return savedOnce ? { text: 'All changes saved' } : null
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
/** The rows the shown table's grid holds now (records added, deleted). */
|
|
258
|
+
function liveRows(): Row[] | undefined {
|
|
259
|
+
return api ? (gridOf(api)?.internalData as Row[] | undefined) : undefined
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** The tables with the shown one's rows as its grid holds them. */
|
|
263
|
+
function pulled(change: Partial<BaseTable> = {}): BaseTable[] {
|
|
264
|
+
const list = tables ?? []
|
|
265
|
+
const id = current?.id
|
|
266
|
+
const live = liveRows()
|
|
267
|
+
return list.map((t) => (t.id === id ? { ...t, ...(live ? { data: live } : {}), ...change } : t))
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function switchTo(id: string) {
|
|
271
|
+
if (!tables || id === current?.id) return
|
|
272
|
+
commit(pulled())
|
|
273
|
+
show(id)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/** Show table `id`: a new grid with its rows. */
|
|
277
|
+
function show(id: string) {
|
|
278
|
+
const t = tableOf(id)
|
|
279
|
+
if (!t) return
|
|
280
|
+
closeRecord()
|
|
281
|
+
api = null
|
|
282
|
+
if (viewOf[id] === undefined) viewOf[id] = ''
|
|
283
|
+
shownId = id
|
|
284
|
+
gridData = t.data
|
|
285
|
+
activeTable = id
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// ---- What the shown table's grid reports ----------------------------------
|
|
289
|
+
|
|
290
|
+
const linkFieldOf = (t: BaseTable | undefined, id: string) => t?.columns.find((d) => colId(d) === id && d.fieldType === 'link')
|
|
291
|
+
|
|
292
|
+
function call(name: string, e: unknown) {
|
|
293
|
+
;(current?.props?.[name] as ((e: unknown) => void) | undefined)?.(e)
|
|
294
|
+
;(grid[name] as ((e: unknown) => void) | undefined)?.(e)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const handlers = {
|
|
298
|
+
onColumnAdd: (e: { column: Record<string, any>; columns: any[]; data?: Row[] }) => {
|
|
299
|
+
const id = current!.id
|
|
300
|
+
let next = pulled({ columns: e.columns, ...(e.data ? { data: e.data } : {}) })
|
|
301
|
+
if (e.column?.fieldType === 'link') next = addInverse(next, id, colId(e.column))
|
|
302
|
+
commit(next)
|
|
303
|
+
call('onColumnAdd', e)
|
|
304
|
+
},
|
|
305
|
+
onColumnChange: (e: { column: Record<string, any>; previous?: Record<string, any>; columns: any[]; data?: Row[] }) => {
|
|
306
|
+
const id = current!.id
|
|
307
|
+
let next = pulled({ columns: e.columns, ...(e.data ? { data: e.data } : {}) })
|
|
308
|
+
if (e.previous?.fieldType === 'link' || e.column?.fieldType === 'link') next = fieldChanged(next, id, e.previous, colId(e.column))
|
|
309
|
+
commit(next)
|
|
310
|
+
call('onColumnChange', e)
|
|
311
|
+
},
|
|
312
|
+
onColumnRemove: (e: { columnId: string; columns: any[] }) => {
|
|
313
|
+
const removed = linkFieldOf(current, e.columnId)
|
|
314
|
+
commit(removeLinkField(pulled({ columns: e.columns }), current!.id, removed))
|
|
315
|
+
call('onColumnRemove', e)
|
|
316
|
+
},
|
|
317
|
+
onCellValueChange: (e: { columnId: string; row?: Row; oldValue?: unknown }) => {
|
|
318
|
+
const id = current!.id
|
|
319
|
+
const next = pulled()
|
|
320
|
+
commit(linkFieldOf(current, e.columnId)?.fieldProps?.inverse ? syncInverse(next, id, e.columnId) : next)
|
|
321
|
+
noteUpdate(id, e.row, e.columnId, e.oldValue)
|
|
322
|
+
call('onCellValueChange', e)
|
|
323
|
+
},
|
|
324
|
+
onRowAdd: (e: { row?: Row }) => {
|
|
325
|
+
const id = current!.id
|
|
326
|
+
commit(syncAllInverses(pulled(), id))
|
|
327
|
+
if (e?.row) void runner.handle({ type: 'created', table: id, record: e.row })
|
|
328
|
+
call('onRowAdd', e)
|
|
329
|
+
},
|
|
330
|
+
onRowsDelete: (e: { data: Row[] }) => {
|
|
331
|
+
commit(syncAllInverses(pulled({ data: e.data }), current!.id))
|
|
332
|
+
call('onRowsDelete', e)
|
|
333
|
+
},
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// ---- Every table is a table link fields can point at ----------------------
|
|
337
|
+
|
|
338
|
+
/** A record named `name` in table `id` (the link picker's "+ Create"). */
|
|
339
|
+
function createIn(id: string, name: string): Row {
|
|
340
|
+
const t = tableOf(id)!
|
|
341
|
+
const row: Row = { id: newRecordId(), [primaryOf(t)]: name }
|
|
342
|
+
if (id === current?.id && api) {
|
|
343
|
+
api.addRow(row, 'bottom')
|
|
344
|
+
commit(pulled())
|
|
345
|
+
} else {
|
|
346
|
+
commit(pulled().map((x) => (x.id === id ? { ...x, data: [...x.data, row] } : x)))
|
|
347
|
+
}
|
|
348
|
+
return row
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/** Show record `rowId` in its own table, expanded. */
|
|
352
|
+
function openIn(id: string, rowId: string) {
|
|
353
|
+
if (id === current?.id) {
|
|
354
|
+
const ctrl = api ? gridOf(api) : null
|
|
355
|
+
if (ctrl) openRecord({ ctrl, rowId })
|
|
356
|
+
return
|
|
357
|
+
}
|
|
358
|
+
pendingOpen = rowId
|
|
359
|
+
switchTo(id)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// What was registered for each table: registering again only when its name or fields change.
|
|
363
|
+
const registered = new Map<string, { name: string; columns: unknown; primary: string }>()
|
|
364
|
+
// This base's registrations: unregistering them leaves another base's
|
|
365
|
+
// table, or the app's, with the same id alone.
|
|
366
|
+
const owner = {}
|
|
367
|
+
onMount(() => {
|
|
368
|
+
// Loaded links that will not sync (an inverse naming no field) or that disagree: said once, in the console.
|
|
369
|
+
if (tables) checkLinks(tables)
|
|
370
|
+
return () => {
|
|
371
|
+
for (const id of registered.keys()) unregisterLinkedTable(id, owner)
|
|
372
|
+
}
|
|
373
|
+
})
|
|
374
|
+
$effect(() => {
|
|
375
|
+
const list = tables
|
|
376
|
+
if (!list) return
|
|
377
|
+
for (const t of list) {
|
|
378
|
+
const primary = primaryOf(t)
|
|
379
|
+
const seen = registered.get(t.id)
|
|
380
|
+
if (seen && seen.name === t.name && seen.columns === t.columns && seen.primary === primary) continue
|
|
381
|
+
registered.set(t.id, { name: t.name, columns: t.columns, primary })
|
|
382
|
+
const id = t.id
|
|
383
|
+
registerLinkedTable({
|
|
384
|
+
id,
|
|
385
|
+
name: t.name,
|
|
386
|
+
// Read each time: the shown table from its grid, the others from the list.
|
|
387
|
+
rows: () => (id === current?.id ? (liveRows() ?? tableOf(id)?.data ?? []) : (tableOf(id)?.data ?? [])),
|
|
388
|
+
getRowId: (r) => {
|
|
389
|
+
const own = tableOf(id)
|
|
390
|
+
return own ? rowIdOf(own, r) : String(r.id ?? '')
|
|
391
|
+
},
|
|
392
|
+
primaryField: primary,
|
|
393
|
+
fields: t.columns
|
|
394
|
+
.filter((d) => d.field)
|
|
395
|
+
.map((d) => ({ field: String(d.field), header: String(d.header ?? d.field), fieldType: d.fieldType, fieldProps: d.fieldProps })),
|
|
396
|
+
create: (name) => createIn(id, name),
|
|
397
|
+
open: (rowId) => openIn(id, rowId),
|
|
398
|
+
}, owner)
|
|
399
|
+
}
|
|
400
|
+
for (const id of [...registered.keys()]) {
|
|
401
|
+
if (list.some((t) => t.id === id)) continue
|
|
402
|
+
registered.delete(id)
|
|
403
|
+
unregisterLinkedTable(id, owner)
|
|
404
|
+
}
|
|
405
|
+
})
|
|
406
|
+
|
|
407
|
+
// ---- The tabs ---------------------------------------------------------------
|
|
408
|
+
|
|
409
|
+
function addTable() {
|
|
410
|
+
const list = pulled()
|
|
411
|
+
const t = blankTable(list)
|
|
412
|
+
commit([...list, t])
|
|
413
|
+
switchTo(t.id)
|
|
414
|
+
}
|
|
415
|
+
function renameTable(id: string, name: string) {
|
|
416
|
+
commit(pulled().map((t) => (t.id === id ? { ...t, name } : t)))
|
|
417
|
+
}
|
|
418
|
+
function duplicateTable(id: string) {
|
|
419
|
+
const list = pulled()
|
|
420
|
+
const source = list.find((t) => t.id === id)
|
|
421
|
+
if (!source) return
|
|
422
|
+
const copy = copyTable(list, source)
|
|
423
|
+
let next = [...list, copy]
|
|
424
|
+
for (const d of copy.columns) if (d.fieldType === 'link') next = addInverse(next, copy.id, colId(d))
|
|
425
|
+
commit(next)
|
|
426
|
+
switchTo(copy.id)
|
|
427
|
+
}
|
|
428
|
+
/** The base as Postgres SQL, downloaded: tables, links, records, views and automations. */
|
|
429
|
+
function exportSql() {
|
|
430
|
+
const list = pulled()
|
|
431
|
+
const sql = baseToSql(list, { title: list.map((t) => t.name).join(', ') })
|
|
432
|
+
const url = URL.createObjectURL(new Blob([sql], { type: 'application/sql' }))
|
|
433
|
+
const a = document.createElement('a')
|
|
434
|
+
a.href = url
|
|
435
|
+
a.download = 'base.sql'
|
|
436
|
+
a.click()
|
|
437
|
+
setTimeout(() => URL.revokeObjectURL(url), 1000)
|
|
438
|
+
}
|
|
439
|
+
function deleteTable(id: string) {
|
|
440
|
+
const list = pulled()
|
|
441
|
+
if (list.length < 2) return
|
|
442
|
+
const i = list.findIndex((t) => t.id === id)
|
|
443
|
+
const next = removeTable(list, id)
|
|
444
|
+
const shown = id === current?.id
|
|
445
|
+
commit(next)
|
|
446
|
+
if (shown) show(next[Math.max(0, i - 1)]!.id)
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// One table: rows keyed by their id field, as a table of `tables` is, so
|
|
450
|
+
// comments, activity and an open record stay with the record when a row
|
|
451
|
+
// above it is deleted. A row without an id falls back to its index; a
|
|
452
|
+
// `getRowId` prop wins.
|
|
453
|
+
const singleRowId = (r: Row, i: number): string =>
|
|
454
|
+
grid.getRowId ? grid.getRowId(r, i) : r?.id != null && r.id !== '' ? String(r.id) : String(i)
|
|
455
|
+
|
|
456
|
+
// Per table, not per change: an edit gives the grid no new getRowId or rowAdder.
|
|
457
|
+
const gridProps = $derived.by(() => {
|
|
458
|
+
const id = currentId
|
|
459
|
+
if (!id) return {}
|
|
460
|
+
const t = untrack(() => tableOf(id))
|
|
461
|
+
if (!t) return {}
|
|
462
|
+
const own = (t.props ?? {}) as Record<string, any>
|
|
463
|
+
const adder = own.rowAdder ?? grid.rowAdder ?? true
|
|
464
|
+
// A new record gets an id, as every record of a base has one.
|
|
465
|
+
const rowAdder =
|
|
466
|
+
adder === false
|
|
467
|
+
? false
|
|
468
|
+
: {
|
|
469
|
+
...(typeof adder === 'object' ? adder : {}),
|
|
470
|
+
defaults: () => ({ id: newRecordId(), ...(typeof adder === 'object' && typeof adder.defaults === 'function' ? adder.defaults() : {}) }),
|
|
471
|
+
}
|
|
472
|
+
return {
|
|
473
|
+
...grid,
|
|
474
|
+
...own,
|
|
475
|
+
...handlers,
|
|
476
|
+
rowAdder,
|
|
477
|
+
primaryField: primaryOf(t),
|
|
478
|
+
getRowId: (r: Row) => rowIdOf(tableOf(id) ?? t, r),
|
|
479
|
+
// Comments and activity are kept by base and table id, so they outlive this grid.
|
|
480
|
+
baseTableId: id,
|
|
481
|
+
baseScope,
|
|
482
|
+
// A button field an automation runs on.
|
|
483
|
+
fieldButtons: (columnId: string) => buttonFor(id, columnId),
|
|
484
|
+
}
|
|
485
|
+
})
|
|
486
|
+
</script>
|
|
487
|
+
|
|
488
|
+
{#if tables && current}
|
|
489
|
+
<div class="sv-fbase-tables" style:height>
|
|
490
|
+
<BaseTabs
|
|
491
|
+
{tables}
|
|
492
|
+
activeId={current.id}
|
|
493
|
+
onSwitch={switchTo}
|
|
494
|
+
onAdd={addTable}
|
|
495
|
+
onRename={renameTable}
|
|
496
|
+
onDuplicate={duplicateTable}
|
|
497
|
+
onDelete={deleteTable}
|
|
498
|
+
onExportSql={exportSql}
|
|
499
|
+
status={syncLine}
|
|
500
|
+
/>
|
|
501
|
+
<div class="sv-fbase-slot">
|
|
502
|
+
{#key current.id}
|
|
503
|
+
<BaseTableView
|
|
504
|
+
{...gridProps}
|
|
505
|
+
bare
|
|
506
|
+
data={gridData}
|
|
507
|
+
columns={current.columns}
|
|
508
|
+
views={current.views ?? GRID_ONLY}
|
|
509
|
+
bind:activeView={viewOf[current.id]}
|
|
510
|
+
onViewsChange={(v: FieldView[]) => commit(pulled({ views: v }))}
|
|
511
|
+
table={current}
|
|
512
|
+
tables={() => pulled()}
|
|
513
|
+
runner={automations ? runner : undefined}
|
|
514
|
+
{serverRuns}
|
|
515
|
+
onAutomationsChange={(list: BaseAutomation[]) => commit(pulled({ automations: list }))}
|
|
516
|
+
onFormSubmit={(row: Row, viewId: string) => void runner.handle({ type: 'form', table: current!.id, record: row, view: viewId })}
|
|
517
|
+
newRecord={() => ({ id: newRecordId() })}
|
|
518
|
+
{viewTypes}
|
|
519
|
+
{rowHeights}
|
|
520
|
+
containerHeight="100%"
|
|
521
|
+
onApiReady={(a: any) => {
|
|
522
|
+
api = a
|
|
523
|
+
onApiReady?.(a)
|
|
524
|
+
const rowId = pendingOpen
|
|
525
|
+
pendingOpen = null
|
|
526
|
+
if (rowId) queueMicrotask(() => {
|
|
527
|
+
const ctrl = gridOf(a)
|
|
528
|
+
if (ctrl) openRecord({ ctrl, rowId })
|
|
529
|
+
})
|
|
530
|
+
}}
|
|
531
|
+
/>
|
|
532
|
+
{/key}
|
|
533
|
+
</div>
|
|
534
|
+
</div>
|
|
535
|
+
{:else}
|
|
536
|
+
<BaseTableView {...grid} getRowId={singleRowId} data={data ?? []} columns={columns ?? []} bind:views bind:activeView {onViewsChange} {viewTypes} {rowHeights} {containerHeight} {onApiReady} />
|
|
537
|
+
{/if}
|
|
538
|
+
|
|
539
|
+
<style>
|
|
540
|
+
.sv-fbase-tables {
|
|
541
|
+
display: flex; flex-direction: column; min-height: 0; box-sizing: border-box; overflow: hidden;
|
|
542
|
+
border: 1px solid var(--sg-border, #e2e8f0); border-radius: var(--sg-radius-lg, 10px); background: var(--sg-bg, #fff);
|
|
543
|
+
}
|
|
544
|
+
.sv-fbase-slot { flex: 1 1 auto; min-height: 0; }
|
|
545
|
+
</style>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type BaseTable } from './base-tables.js';
|
|
2
|
+
import type { FieldView, FieldViewType } from './view-model.js';
|
|
3
|
+
import { type AutomationRun } from './automations.svelte.js';
|
|
4
|
+
type $$ComponentProps = {
|
|
5
|
+
/** Several tables, shown as tabs. Without it, `data` and `columns` are the one table. */
|
|
6
|
+
tables?: BaseTable[];
|
|
7
|
+
activeTable?: string;
|
|
8
|
+
onTablesChange?: (tables: BaseTable[]) => void;
|
|
9
|
+
data?: any[];
|
|
10
|
+
columns?: any[];
|
|
11
|
+
views?: FieldView[];
|
|
12
|
+
activeView?: string;
|
|
13
|
+
onViewsChange?: (views: FieldView[]) => void;
|
|
14
|
+
viewTypes?: ReadonlyArray<FieldViewType>;
|
|
15
|
+
/** The row heights the view bar's row height menu offers. */
|
|
16
|
+
rowHeights?: ReadonlyArray<{
|
|
17
|
+
label: string;
|
|
18
|
+
height: number;
|
|
19
|
+
}>;
|
|
20
|
+
containerHeight?: number | string;
|
|
21
|
+
onApiReady?: (api: any) => void;
|
|
22
|
+
/** The server runner's latest runs, shown with this page's under Runs (an endpoint returning `server.runs`). */
|
|
23
|
+
serverRuns?: () => Promise<ReadonlyArray<AutomationRun>>;
|
|
24
|
+
/** The view bar's Automations; false hides it (automations already set still run). */
|
|
25
|
+
automations?: boolean;
|
|
26
|
+
[prop: string]: any;
|
|
27
|
+
};
|
|
28
|
+
declare const SvBase: import("svelte").Component<$$ComponentProps, {}, "tables" | "views" | "activeView" | "activeTable">;
|
|
29
|
+
type SvBase = ReturnType<typeof SvBase>;
|
|
30
|
+
export default SvBase;
|