Files
windmill/frontend/src/lib/components/SimpleAgTable.svelte
T
Diego Imbert 4d2753e307 Small UI fixes (#6294)
* fix step history not refreshing with staticInputs

* fix array of obj not showing up in json editor in test this step

* datatable scales correctly in DisplayResult and scrolling is much more usable

* avoid next button disapearing and changing layout / hurting ux

* nits

* fix bug when renaming module A to B then module C to A, C takes the schema of A

* fix bug with comments in sql repl

* fix aggrid theme randomly not loading

* bindable script

* better delete button in db manager

* property select doesnt exist

* fix all warnings

* delete $flowStateStore[id] on delete
2025-07-29 19:28:54 +00:00

98 lines
2.4 KiB
Svelte

<script lang="ts">
import { sendUserToast } from '$lib/toast'
import 'ag-grid-community/styles/ag-grid.css'
import 'ag-grid-community/styles/ag-theme-alpine.css'
import { createGrid, type GridApi } from 'ag-grid-community'
import DarkModeObserver from './DarkModeObserver.svelte'
import { untrack } from 'svelte'
type Props = {
data: Record<string, any>[]
class?: string
}
let { data, class: className }: Props = $props()
let api: GridApi<any> | undefined = $state()
let eGui: HTMLDivElement | undefined = $state()
$effect(() => eGui && untrack(() => mountGrid()))
function mountGrid() {
if (eGui) {
createGrid(eGui, {
onGridReady: (e) => {
api = e.api
},
autoSizeStrategy: { type: 'fitCellContents' },
...updateGridOptions
})
}
}
let columnDefs = $derived.by(() => {
if (!data.length) return []
const defs: { field: string }[] = []
for (const row of data) {
for (const key in row) {
if (!defs.some((def) => def.field === key)) {
defs.push({ field: key })
}
}
}
return defs
})
let updateGridOptions = $derived({
rowData: data.map((row) => {
const newRow: Record<string, any> = {}
for (const key in row) {
newRow[key] = typeof row[key] === 'string' ? row[key].trim() : JSON.stringify(row[key])
}
return newRow
}),
columnDefs
})
$effect(() => {
api?.updateGridOptions(updateGridOptions)
})
let darkMode = $state(false)
let [clientHeight, clientWidth] = $state([0, 0])
</script>
<DarkModeObserver bind:darkMode />
<div
class={'flex flex-col h-full component-wrapper divide-y wm-aggrid-container ' +
(api ? '' : 'opacity-0 ') +
className}
bind:clientHeight
bind:clientWidth
>
<div
style:height="{clientHeight}px"
style:width="{clientWidth}px"
class="ag-theme-alpine"
class:ag-theme-alpine-dark={darkMode}
>
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
bind:this={eGui}
style:height="100%"
onkeydown={(e) => {
if ((e.ctrlKey || e.metaKey) && e.key === 'c') {
const selectedCell = api?.getFocusedCell()
if (selectedCell) {
const rowIndex = selectedCell.rowIndex
const colId = selectedCell.column?.getId()
const rowNode = api?.getDisplayedRowAtIndex(rowIndex)
const selectedValue = rowNode?.data?.[colId]
navigator.clipboard.writeText(selectedValue)
sendUserToast('Copied cell value to clipboard', false)
}
}
}}
>
</div>
</div>
</div>