mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 00:02:23 +00:00
fix(frontend): sync columnDefs + improve columnDefs management (#3632)
* fix(frontend): sync columnDefs + improve columnDefs management * fix(frontend): sync columnDefs + improve columnDefs management * fix(frontend): improve code quality * fix(frontend): improve code quality * fix(frontend): remove useless warning while the config is loading * fix(frontend): Disable actions for database studio, since columnDefs are managed by the component * feat(frontend): Fix Database studio * feat(frontend): revert changes from Database Studio * feat(frontend): fix DB Studio refresh * fix(frontend): improve code quality * fix(frontend): improve code quality * fix(frontend): fix build * fix(frontend): fix wording * fix(frontend): fix aggrid
This commit is contained in:
@@ -201,7 +201,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
function handleSyncRegion() {
|
||||
async function handleSyncRegion() {
|
||||
const gridItem = findGridItem($app, id)
|
||||
if (!map || !gridItem) {
|
||||
return
|
||||
@@ -225,6 +225,8 @@
|
||||
gridItem.data.configuration.longitude.value = center[0]
|
||||
//@ts-ignore
|
||||
gridItem.data.configuration.latitude.value = center[1]
|
||||
|
||||
$app = $app
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
const { app, worldStore, mode, selectedComponent, runnableComponents } =
|
||||
const { app, worldStore, mode, selectedComponent } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
const editorContext = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
@@ -205,24 +205,6 @@
|
||||
})
|
||||
}
|
||||
|
||||
let isCallbackAdded = false
|
||||
|
||||
function addOnRecomputeCallback() {
|
||||
$runnableComponents[id].cb = [
|
||||
...$runnableComponents[id].cb,
|
||||
() =>
|
||||
new CancelablePromise(async (resolve) => {
|
||||
await dbExplorerCount?.computeCount(true)
|
||||
|
||||
aggrid?.clearRows()
|
||||
resolve()
|
||||
})
|
||||
]
|
||||
isCallbackAdded = true
|
||||
}
|
||||
|
||||
$: $runnableComponents[id]?.cb && !isCallbackAdded && addOnRecomputeCallback()
|
||||
|
||||
async function listTables() {
|
||||
let resource = resolvedConfig.type.configuration?.[resolvedConfig.type.selected]?.resource
|
||||
|
||||
@@ -626,11 +608,19 @@
|
||||
noInitialize
|
||||
bind:runnableComponent
|
||||
componentInput={input}
|
||||
autoRefresh={true}
|
||||
autoRefresh={false}
|
||||
bind:loading
|
||||
{render}
|
||||
{id}
|
||||
{outputs}
|
||||
overrideCallback={() =>
|
||||
new CancelablePromise(async (resolve) => {
|
||||
await dbExplorerCount?.computeCount(true)
|
||||
|
||||
aggrid?.clearRows()
|
||||
resolve()
|
||||
})}
|
||||
overrideAutoRefresh={true}
|
||||
>
|
||||
<div class="h-full" bind:clientHeight={componentContainerHeight}>
|
||||
{#if !(hideSearch === true && hideInsert === true)}
|
||||
@@ -678,6 +668,7 @@
|
||||
containerHeight={componentContainerHeight - (buttonContainerHeight ?? 0)}
|
||||
on:update={onUpdate}
|
||||
on:delete={onDelete}
|
||||
allowColumnDefsActions={false}
|
||||
{actions}
|
||||
/>
|
||||
{/key}
|
||||
|
||||
+19
-43
@@ -1,13 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { GridApi, createGrid, type IDatasource } from 'ag-grid-community'
|
||||
import { isObject, sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
import type { AppViewerContext, ComponentCustomCSS } from '../../../types'
|
||||
|
||||
import type { TableAction, components } from '$lib/components/apps/editor/component'
|
||||
import Alert from '$lib/components/common/alert/Alert.svelte'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
|
||||
import SyncColumnDefs from './SyncColumnDefs.svelte'
|
||||
import 'ag-grid-community/styles/ag-grid.css'
|
||||
import 'ag-grid-community/styles/ag-theme-alpine.css'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
@@ -21,7 +20,6 @@
|
||||
import type { ColumnDef } from '../dbtable/utils'
|
||||
import AppAggridTableActions from './AppAggridTableActions.svelte'
|
||||
import Popover from '$lib/components/Popover.svelte'
|
||||
// import 'ag-grid-community/dist/styles/ag-theme-alpine-dark.css'
|
||||
|
||||
export let id: string
|
||||
export let customCss: ComponentCustomCSS<'aggridcomponent'> | undefined = undefined
|
||||
@@ -36,6 +34,8 @@
|
||||
export let outputs: Record<string, Output<any>>
|
||||
export let allowDelete: boolean
|
||||
export let actions: TableAction[] = []
|
||||
export let result: any[] | undefined = undefined
|
||||
export let allowColumnDefsActions: boolean = true
|
||||
let inputs = {}
|
||||
|
||||
const context = getContext<AppViewerContext>('AppViewerContext')
|
||||
@@ -43,32 +43,6 @@
|
||||
|
||||
let css = initCss($app.css?.aggridcomponent, customCss)
|
||||
|
||||
// let result: any[] | undefined = undefined
|
||||
|
||||
// $: result && setValues()
|
||||
|
||||
// let value: any[] = Array.isArray(result)
|
||||
// ? (result as any[]).map((x, i) => ({ ...x, __index: i.toString() }))
|
||||
// : [{ error: 'input was not an array' }]
|
||||
|
||||
// let loaded = false
|
||||
// async function setValues() {
|
||||
// value = Array.isArray(result)
|
||||
// ? (result as any[]).map((x, i) => ({ ...x, __index: i.toString() }))
|
||||
// : [{ error: 'input was not an array' }]
|
||||
// if (api && loaded) {
|
||||
// let selected = api.getSelectedNodes()
|
||||
// if (selected && selected.length > 0 && resolvedConfig?.selectFirstRowByDefault != false) {
|
||||
// let data = { ...selected[0].data }
|
||||
// delete data['__index']
|
||||
// outputs?.selectedRow?.set(data)
|
||||
// }
|
||||
// }
|
||||
// if (!loaded) {
|
||||
// loaded = true
|
||||
// }
|
||||
// }
|
||||
|
||||
let selectedRowIndex = -1
|
||||
|
||||
function toggleRow(row: any) {
|
||||
@@ -182,7 +156,11 @@
|
||||
})
|
||||
})
|
||||
|
||||
function transformColumnDefs(columnDefs: any[]) {
|
||||
function transformColumnDefs(columnDefs: any[] | undefined) {
|
||||
if (!columnDefs) {
|
||||
return []
|
||||
}
|
||||
|
||||
const { isValid, errors } = validateColumnDefs(columnDefs)
|
||||
|
||||
if (!isValid) {
|
||||
@@ -248,10 +226,17 @@
|
||||
let firstRow: number = 0
|
||||
let lastRow: number = 0
|
||||
|
||||
function validateColumnDefs(columnDefs: ColumnDef[]): { isValid: boolean; errors: string[] } {
|
||||
function validateColumnDefs(columnDefs: ColumnDef[]): {
|
||||
isValid: boolean
|
||||
errors: string[]
|
||||
} {
|
||||
let isValid = true
|
||||
const errors: string[] = []
|
||||
|
||||
if (!Array.isArray(columnDefs)) {
|
||||
return { isValid: false, errors: ['Column definitions must be an array.'] }
|
||||
}
|
||||
|
||||
// Validate each column definition
|
||||
columnDefs.forEach((colDef, index) => {
|
||||
// Check if 'field' property exists and is a non-empty string
|
||||
@@ -405,7 +390,7 @@
|
||||
/>
|
||||
{/each}
|
||||
|
||||
{#if Array.isArray(resolvedConfig.columnDefs) && resolvedConfig.columnDefs.every(isObject)}
|
||||
<SyncColumnDefs {id} columnDefs={resolvedConfig.columnDefs} {result} {allowColumnDefsActions}>
|
||||
<div
|
||||
class={twMerge(
|
||||
'flex flex-col h-full component-wrapper divide-y',
|
||||
@@ -451,16 +436,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else if resolvedConfig.columnDefs != undefined}
|
||||
<Alert title="Parsing issues" type="error" size="xs">
|
||||
The columnDefs should be an array of objects, received:
|
||||
<pre class="overflow-auto">
|
||||
{JSON.stringify(resolvedConfig.columnDefs)}
|
||||
</pre>
|
||||
</Alert>
|
||||
{:else}
|
||||
<Alert title="Parsing issues" type="error" size="xs">The columnDefs are undefined</Alert>
|
||||
{/if}
|
||||
</SyncColumnDefs>
|
||||
|
||||
<style>
|
||||
.ag-theme-alpine {
|
||||
|
||||
+5
-3
@@ -27,6 +27,7 @@
|
||||
export let render: boolean
|
||||
export let customCss: ComponentCustomCSS<'aggridinfinitecomponent'> | undefined = undefined
|
||||
export let actions: TableAction[] | undefined = undefined
|
||||
|
||||
let runnableComponent: RunnableComponent | undefined = undefined
|
||||
|
||||
function clear() {
|
||||
@@ -196,9 +197,10 @@
|
||||
{resolvedConfig}
|
||||
{customCss}
|
||||
{outputs}
|
||||
allowDelete={false}
|
||||
{result}
|
||||
{actions}
|
||||
allowDelete={false}
|
||||
bind:this={aggrid}
|
||||
/></div
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
</RunnableWrapper>
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
|
||||
import { initConfig, initOutput } from '$lib/components/apps/editor/appUtils'
|
||||
import { components, type TableAction } from '$lib/components/apps/editor/component'
|
||||
import Alert from '$lib/components/common/alert/Alert.svelte'
|
||||
import ResolveConfig from '../../helpers/ResolveConfig.svelte'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import RefreshButton from '$lib/components/apps/components/helpers/RefreshButton.svelte'
|
||||
import SyncColumnDefs from './SyncColumnDefs.svelte'
|
||||
|
||||
import 'ag-grid-community/styles/ag-grid.css'
|
||||
import './theme/windmill-theme.css'
|
||||
@@ -449,145 +449,126 @@
|
||||
bind:loading
|
||||
hideRefreshButton={true}
|
||||
>
|
||||
{#if Array.isArray(value) && value.every(isObject)}
|
||||
{#if Array.isArray(resolvedConfig.columnDefs) && resolvedConfig.columnDefs.every(isObject)}
|
||||
<div
|
||||
class={twMerge(
|
||||
'flex flex-col h-full component-wrapper divide-y',
|
||||
css?.container?.class,
|
||||
'wm-aggrid-container'
|
||||
)}
|
||||
style={css?.container?.style}
|
||||
bind:clientHeight
|
||||
bind:clientWidth
|
||||
>
|
||||
{#if componentInput?.type === 'runnable' && componentInput.autoRefresh}
|
||||
<div class="absolute top-2 right-2 z-50">
|
||||
<RefreshButton {id} {loading} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div
|
||||
on:pointerdown|stopPropagation={() => {
|
||||
$selectedComponent = [id]
|
||||
}}
|
||||
style:height="{clientHeight}px"
|
||||
style:width="{clientWidth}px"
|
||||
class="ag-theme-alpine relative"
|
||||
class:ag-theme-alpine-dark={$darkMode}
|
||||
>
|
||||
{#key resolvedConfig?.pagination}
|
||||
{#if loaded}
|
||||
<div bind:this={eGui} style:height="100%" />
|
||||
{:else}
|
||||
<Loader2 class="animate-spin" />
|
||||
{/if}
|
||||
{/key}
|
||||
<SyncColumnDefs {id} columnDefs={resolvedConfig.columnDefs} {result}>
|
||||
<div
|
||||
class={twMerge(
|
||||
'flex flex-col h-full component-wrapper divide-y',
|
||||
css?.container?.class,
|
||||
'wm-aggrid-container'
|
||||
)}
|
||||
style={css?.container?.style}
|
||||
bind:clientHeight
|
||||
bind:clientWidth
|
||||
>
|
||||
{#if componentInput?.type === 'runnable' && componentInput.autoRefresh}
|
||||
<div class="absolute top-2 right-2 z-50">
|
||||
<RefreshButton {id} {loading} />
|
||||
</div>
|
||||
{#if resolvedConfig.footer}
|
||||
<div class="flex gap-1 w-full justify-between items-center text-sm text-secondary/80 p-2">
|
||||
<div>
|
||||
<Popover>
|
||||
<svelte:fragment slot="text">Download</svelte:fragment>
|
||||
{/if}
|
||||
|
||||
<div
|
||||
on:pointerdown|stopPropagation={() => {
|
||||
$selectedComponent = [id]
|
||||
}}
|
||||
style:height="{clientHeight}px"
|
||||
style:width="{clientWidth}px"
|
||||
class="ag-theme-alpine relative"
|
||||
class:ag-theme-alpine-dark={$darkMode}
|
||||
>
|
||||
{#key resolvedConfig?.pagination}
|
||||
{#if loaded}
|
||||
<div bind:this={eGui} style:height="100%" />
|
||||
{:else}
|
||||
<Loader2 class="animate-spin" />
|
||||
{/if}
|
||||
{/key}
|
||||
</div>
|
||||
{#if resolvedConfig.footer}
|
||||
<div class="flex gap-1 w-full justify-between items-center text-sm text-secondary/80 p-2">
|
||||
<div>
|
||||
<Popover>
|
||||
<svelte:fragment slot="text">Download</svelte:fragment>
|
||||
<Button
|
||||
startIcon={{ icon: Download }}
|
||||
color="light"
|
||||
size="xs2"
|
||||
on:click={() => {
|
||||
api?.exportDataAsCsv()
|
||||
}}
|
||||
iconOnly
|
||||
/>
|
||||
</Popover>
|
||||
</div>
|
||||
<div class="flex flex-row gap-1 items-center">
|
||||
{#if resolvedConfig?.pagination}
|
||||
{#key refreshCount}
|
||||
<div class="text-xs mx-2 text-primary">
|
||||
{(api?.paginationGetPageSize() ?? 0) * (api?.paginationGetCurrentPage() ?? 0) + 1}
|
||||
to {Math.min(
|
||||
api?.paginationGetRowCount() ?? 0,
|
||||
((api?.paginationGetCurrentPage() ?? 0) + 1) *
|
||||
(api?.paginationGetPageSize() ?? 0)
|
||||
)}
|
||||
of {api?.paginationGetRowCount()}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
startIcon={{ icon: Download }}
|
||||
iconOnly
|
||||
startIcon={{ icon: SkipBack }}
|
||||
color="light"
|
||||
size="xs2"
|
||||
disabled={api?.paginationGetCurrentPage() == 0}
|
||||
on:click={() => {
|
||||
api?.exportDataAsCsv()
|
||||
api?.paginationGoToFirstPage()
|
||||
refreshCount++
|
||||
}}
|
||||
iconOnly
|
||||
/>
|
||||
</Popover>
|
||||
</div>
|
||||
<div class="flex flex-row gap-1 items-center">
|
||||
{#if resolvedConfig?.pagination}
|
||||
{#key refreshCount}
|
||||
<div class="text-xs mx-2 text-primary">
|
||||
{(api?.paginationGetPageSize() ?? 0) * (api?.paginationGetCurrentPage() ?? 0) +
|
||||
1}
|
||||
to {Math.min(
|
||||
api?.paginationGetRowCount() ?? 0,
|
||||
((api?.paginationGetCurrentPage() ?? 0) + 1) *
|
||||
(api?.paginationGetPageSize() ?? 0)
|
||||
)}
|
||||
of {api?.paginationGetRowCount()}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
iconOnly
|
||||
startIcon={{ icon: SkipBack }}
|
||||
color="light"
|
||||
size="xs2"
|
||||
disabled={api?.paginationGetCurrentPage() == 0}
|
||||
on:click={() => {
|
||||
api?.paginationGoToFirstPage()
|
||||
refreshCount++
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
iconOnly
|
||||
startIcon={{ icon: ChevronLeft }}
|
||||
color="light"
|
||||
size="xs2"
|
||||
disabled={api?.paginationGetCurrentPage() == 0}
|
||||
on:click={() => {
|
||||
api?.paginationGoToPreviousPage()
|
||||
refreshCount++
|
||||
}}
|
||||
/>
|
||||
<div class="text-xs mx-2 text-primary">
|
||||
Page {(api?.paginationGetCurrentPage() ?? 0) + 1} of {api?.paginationGetTotalPages() ??
|
||||
0}
|
||||
</div>
|
||||
<Button
|
||||
iconOnly
|
||||
startIcon={{ icon: ChevronRight }}
|
||||
color="light"
|
||||
size="xs2"
|
||||
disabled={(api?.paginationGetCurrentPage() ?? 0) + 1 ==
|
||||
api?.paginationGetTotalPages()}
|
||||
on:click={() => {
|
||||
api?.paginationGoToNextPage()
|
||||
refreshCount++
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
iconOnly
|
||||
startIcon={{ icon: SkipForward }}
|
||||
color="light"
|
||||
size="xs2"
|
||||
disabled={(api?.paginationGetCurrentPage() ?? 0) + 1 ==
|
||||
api?.paginationGetTotalPages()}
|
||||
on:click={() => {
|
||||
api?.paginationGoToLastPage()
|
||||
refreshCount++
|
||||
}}
|
||||
/>
|
||||
{/key}
|
||||
{/if}
|
||||
</div>
|
||||
<Button
|
||||
iconOnly
|
||||
startIcon={{ icon: ChevronLeft }}
|
||||
color="light"
|
||||
size="xs2"
|
||||
disabled={api?.paginationGetCurrentPage() == 0}
|
||||
on:click={() => {
|
||||
api?.paginationGoToPreviousPage()
|
||||
refreshCount++
|
||||
}}
|
||||
/>
|
||||
<div class="text-xs mx-2 text-primary">
|
||||
Page {(api?.paginationGetCurrentPage() ?? 0) + 1} of {api?.paginationGetTotalPages() ??
|
||||
0}
|
||||
</div>
|
||||
<Button
|
||||
iconOnly
|
||||
startIcon={{ icon: ChevronRight }}
|
||||
color="light"
|
||||
size="xs2"
|
||||
disabled={(api?.paginationGetCurrentPage() ?? 0) + 1 ==
|
||||
api?.paginationGetTotalPages()}
|
||||
on:click={() => {
|
||||
api?.paginationGoToNextPage()
|
||||
refreshCount++
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
iconOnly
|
||||
startIcon={{ icon: SkipForward }}
|
||||
color="light"
|
||||
size="xs2"
|
||||
disabled={(api?.paginationGetCurrentPage() ?? 0) + 1 ==
|
||||
api?.paginationGetTotalPages()}
|
||||
on:click={() => {
|
||||
api?.paginationGoToLastPage()
|
||||
refreshCount++
|
||||
}}
|
||||
/>
|
||||
{/key}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else if resolvedConfig.columnDefs != undefined}
|
||||
<Alert title="Parsing issues" type="error" size="xs">
|
||||
The columnDefs should be an array of objects, received:
|
||||
<pre class="overflow-auto">
|
||||
{JSON.stringify(resolvedConfig.columnDefs)}
|
||||
</pre>
|
||||
</Alert>
|
||||
{:else}
|
||||
<Alert title="Parsing issues" type="error" size="xs">The columnDefs are undefined</Alert>
|
||||
{/if}
|
||||
{:else if result != undefined}
|
||||
<Alert title="Parsing issues" type="error" size="xs">
|
||||
The result should be an array of objects, received:
|
||||
<pre class="overflow-auto mt-2">
|
||||
{JSON.stringify(result)}
|
||||
</pre>
|
||||
</Alert>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</SyncColumnDefs>
|
||||
</RunnableWrapper>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
<script lang="ts">
|
||||
import { getContext, tick } from 'svelte'
|
||||
import type { AppViewerContext } from '../../../types'
|
||||
import { findGridItem } from '$lib/components/apps/editor/appUtils'
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import { RefreshCw } from 'lucide-svelte'
|
||||
import Badge from '$lib/components/common/badge/Badge.svelte'
|
||||
import Alert from '$lib/components/common/alert/Alert.svelte'
|
||||
import { isObject } from '$lib/utils'
|
||||
|
||||
export let id: string
|
||||
export let columnDefs: Array<any> = []
|
||||
export let result: Array<any> | undefined = []
|
||||
export let allowColumnDefsActions: boolean = true
|
||||
|
||||
const { app, mode, selectedComponent } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
async function syncColumns() {
|
||||
let gridItem = findGridItem($app, id)
|
||||
|
||||
if (gridItem && result) {
|
||||
const keys = Object.keys(result[0] ?? {}) ?? []
|
||||
|
||||
if (gridItem.data.configuration.columnDefs.type === 'static') {
|
||||
gridItem.data.configuration.columnDefs.value = keys.map((key) => ({
|
||||
field: key,
|
||||
headerName: key,
|
||||
flex: 1
|
||||
}))
|
||||
} else if (gridItem.data.configuration.columnDefs.type === 'evalv2') {
|
||||
gridItem.data.configuration.columnDefs.expr = JSON.stringify(
|
||||
keys.map((key, index) => ({
|
||||
field: key,
|
||||
headerName: key,
|
||||
flex: 1
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
await updateConfiguration()
|
||||
}
|
||||
}
|
||||
|
||||
async function setEmptyColumns() {
|
||||
let gridItem = findGridItem($app, id)
|
||||
if (gridItem && gridItem.data.configuration.columnDefs.type === 'static') {
|
||||
gridItem.data.configuration.columnDefs.value = []
|
||||
await updateConfiguration()
|
||||
} else if (gridItem && gridItem.data.configuration.columnDefs.type === 'evalv2') {
|
||||
gridItem.data.configuration.columnDefs.expr = '[]'
|
||||
await updateConfiguration()
|
||||
}
|
||||
}
|
||||
|
||||
async function updateConfiguration() {
|
||||
$selectedComponent = undefined
|
||||
await tick()
|
||||
$selectedComponent = [id]
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if Array.isArray(result) && result.every(isObject)}
|
||||
{#if Array.isArray(columnDefs) && columnDefs.every(isObject)}
|
||||
{#if $mode === 'dnd' && columnDefs?.length === 0 && result?.length > 0 && allowColumnDefsActions}
|
||||
<div class="m-16">
|
||||
<Alert title="Missing column definitions">
|
||||
<div class="flex flex-col items-start gap-2">
|
||||
<div class="text-xs"> No columns definition found. Columns found in data: </div>
|
||||
<div class="text-sm flex flex-row gap-2">
|
||||
{#each Object.keys(result[0] ?? []) as key}
|
||||
<Badge small color="dark-gray">{key}</Badge>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="w-full flex fles-row justify-end">
|
||||
<Button startIcon={{ icon: RefreshCw }} size="xs" color="dark" on:click={syncColumns}>
|
||||
Sync columns definition
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Alert>
|
||||
</div>
|
||||
{:else}
|
||||
<slot />
|
||||
{/if}
|
||||
{:else if columnDefs !== undefined}
|
||||
<div class="m-16">
|
||||
<Alert title="Parsing issues" type="error" size="xs">
|
||||
<div class="flex flex-col items-start gap-2">
|
||||
The columnDefs should be an array of objects, received:
|
||||
<pre class="overflow-auto">
|
||||
{JSON.stringify(columnDefs)}
|
||||
</pre>
|
||||
{#if allowColumnDefsActions}
|
||||
<div class="w-full flex fles-row justify-end">
|
||||
<Button
|
||||
startIcon={{ icon: RefreshCw }}
|
||||
size="xs"
|
||||
color="red"
|
||||
on:click={setEmptyColumns}
|
||||
>
|
||||
Fix columns definitions
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</Alert>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="m-16">
|
||||
<Alert title="Parsing issues" type="error" size="xs">
|
||||
<div class="flex flex-col items-start gap-2">
|
||||
The columnDefs are undefined.
|
||||
{#if allowColumnDefsActions}
|
||||
<div class="w-full flex fles-row justify-end">
|
||||
<Button
|
||||
startIcon={{ icon: RefreshCw }}
|
||||
size="xs"
|
||||
color="red"
|
||||
on:click={setEmptyColumns}
|
||||
>
|
||||
Fix columns definitions
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</Alert>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -54,6 +54,8 @@
|
||||
export let hasChildrens: boolean
|
||||
export let allowConcurentRequests = false
|
||||
export let noInitialize = false
|
||||
export let overrideCallback: (() => CancelablePromise<void>) | undefined = undefined
|
||||
export let overrideAutoRefresh: boolean = false
|
||||
|
||||
const {
|
||||
worldStore,
|
||||
@@ -538,24 +540,28 @@
|
||||
undefined
|
||||
|
||||
onMount(() => {
|
||||
cancellableRun = (inlineScript?: InlineScript, setRunnableJobEditorPanel?: boolean) => {
|
||||
let rejectCb: (err: Error) => void
|
||||
let p: Partial<CancelablePromise<any>> = new Promise<any>((resolve, reject) => {
|
||||
rejectCb = reject
|
||||
donePromise = resolve
|
||||
executeComponent(true, inlineScript, setRunnableJobEditorPanel).catch(reject)
|
||||
})
|
||||
p.cancel = () => {
|
||||
resultJobLoader?.cancelJob()
|
||||
loading = false
|
||||
rejectCb(new Error('Canceled'))
|
||||
}
|
||||
if (overrideCallback) {
|
||||
cancellableRun = overrideCallback
|
||||
} else {
|
||||
cancellableRun = (inlineScript?: InlineScript, setRunnableJobEditorPanel?: boolean) => {
|
||||
let rejectCb: (err: Error) => void
|
||||
let p: Partial<CancelablePromise<any>> = new Promise<any>((resolve, reject) => {
|
||||
rejectCb = reject
|
||||
donePromise = resolve
|
||||
executeComponent(true, inlineScript, setRunnableJobEditorPanel).catch(reject)
|
||||
})
|
||||
p.cancel = () => {
|
||||
resultJobLoader?.cancelJob()
|
||||
loading = false
|
||||
rejectCb(new Error('Canceled'))
|
||||
}
|
||||
|
||||
return p as CancelablePromise<void>
|
||||
return p as CancelablePromise<void>
|
||||
}
|
||||
}
|
||||
|
||||
$runnableComponents[id] = {
|
||||
autoRefresh: autoRefresh && recomputableByRefreshButton,
|
||||
autoRefresh: (autoRefresh && recomputableByRefreshButton) || overrideAutoRefresh,
|
||||
refreshOnStart: refreshOnStart,
|
||||
cb: [...($runnableComponents[id]?.cb ?? []), cancellableRun]
|
||||
}
|
||||
|
||||
@@ -8,10 +8,13 @@
|
||||
import RunnableComponent from './RunnableComponent.svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import InitializeComponent from './InitializeComponent.svelte'
|
||||
import type { CancelablePromise } from '$lib/gen'
|
||||
|
||||
export let componentInput: AppInput | undefined
|
||||
export let noInitialize = false
|
||||
export let hideRefreshButton: boolean | undefined = undefined
|
||||
export let overrideCallback: (() => CancelablePromise<void>) | undefined = undefined
|
||||
export let overrideAutoRefresh: boolean = false
|
||||
|
||||
type SideEffectAction =
|
||||
| {
|
||||
@@ -255,6 +258,8 @@
|
||||
hideRefreshButton={componentInput.hideRefreshButton ?? hideRefreshButton}
|
||||
transformer={componentInput.transformer}
|
||||
{autoRefresh}
|
||||
{overrideCallback}
|
||||
{overrideAutoRefresh}
|
||||
recomputableByRefreshButton={componentInput.autoRefresh ?? true}
|
||||
bind:recomputeOnInputChanged={componentInput.recomputeOnInputChanged}
|
||||
{id}
|
||||
|
||||
@@ -266,8 +266,6 @@
|
||||
)
|
||||
)) as ([string, Record<string, any>] | undefined)[]
|
||||
|
||||
console.log('allTriggers', allTriggers)
|
||||
|
||||
delete policy.triggerables
|
||||
policy.triggerables_v2 = Object.fromEntries(
|
||||
allTriggers.filter(Boolean) as [string, Record<string, any>][]
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
{
|
||||
label: 'Show style panel',
|
||||
onClick: () => {
|
||||
secondaryMenuLeft?.toggle(StylePanel, {})
|
||||
secondaryMenuLeft?.toggle(StylePanel, { type: 'style' })
|
||||
},
|
||||
icon: Paintbrush2,
|
||||
disabled: $secondaryMenuLeft.isOpen
|
||||
|
||||
@@ -744,11 +744,7 @@ const aggridinfinitecomponentconst = {
|
||||
type: 'static',
|
||||
fieldType: 'array',
|
||||
subFieldType: 'ag-grid',
|
||||
value: [
|
||||
{ field: 'id', flex: 1 },
|
||||
{ field: 'name', editable: true, flex: 1 },
|
||||
{ field: 'age', flex: 1 }
|
||||
]
|
||||
value: []
|
||||
} as StaticAppInput,
|
||||
flex: {
|
||||
type: 'static',
|
||||
@@ -818,22 +814,11 @@ const aggridinfinitecomponentconst = {
|
||||
}
|
||||
},
|
||||
componentInput: {
|
||||
type: 'static',
|
||||
fieldType: 'array',
|
||||
subFieldType: 'object',
|
||||
value: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'A cell with a long name',
|
||||
age: 42
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'A briefer cell',
|
||||
age: 84
|
||||
}
|
||||
]
|
||||
} as StaticAppInput
|
||||
type: 'runnable',
|
||||
fieldType: 'any',
|
||||
fields: {},
|
||||
runnable: undefined
|
||||
}
|
||||
}
|
||||
} as const
|
||||
|
||||
@@ -3670,6 +3655,12 @@ See date-fns format for more information. By default, it is 'dd.MM.yyyy HH:mm'
|
||||
value: false,
|
||||
tooltip:
|
||||
'When true, actions will wrap to the next line. Otherwise, the column will grow to fit the actions.'
|
||||
},
|
||||
footer: {
|
||||
type: 'static',
|
||||
fieldType: 'boolean',
|
||||
value: true,
|
||||
tooltip: 'Allow visible footer for pagination and download'
|
||||
}
|
||||
},
|
||||
componentInput: undefined
|
||||
|
||||
+3
-1
@@ -34,7 +34,9 @@
|
||||
class="flex justify-between {right ? '' : 'flex-row-reverse'} items-center gap-1 px-3 py-2"
|
||||
>
|
||||
<CloseButton on:close={() => secondaryMenu?.close()} />
|
||||
<div class="text-xs font-bold"> Style Panel</div>
|
||||
{#if $secondaryMenu?.props?.type === 'style'}
|
||||
<div class="text-xs font-bold"> Style Panel</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="relative h-full overflow-y-auto">
|
||||
{#if typeof $secondaryMenu.component === 'string'}
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
{#if value}
|
||||
<div class="flex flex-col w-96 p-2 gap-4">
|
||||
<span class="text-sm mb-2 leading-6 font-semibold">
|
||||
Column definition
|
||||
Column definitions
|
||||
<Tooltip
|
||||
documentationLink="https://www.ag-grid.com/javascript-data-grid/column-definitions/"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user