Compare commits

...

17 Commits

Author SHA1 Message Date
Ruben Fiszel
4b1bfed090 push 2023-02-24 19:16:11 +01:00
Faton Ramadani
2125d119ff fix(frontend): Fix findGridItem 2023-02-24 19:04:33 +01:00
Faton Ramadani
d3f1ef92ea Merge branch 'rf/flatten' of https://github.com/windmill-labs/windmill into rf/flatten 2023-02-24 19:01:01 +01:00
Faton Ramadani
26296ee05c fix(frontend): Fix findGridItem 2023-02-24 19:00:41 +01:00
Ruben Fiszel
7e4179a741 flatten 2023-02-24 18:52:05 +01:00
Faton Ramadani
52adaa4cb5 fix(frontend): Fix next id 2023-02-24 18:51:50 +01:00
Faton Ramadani
a94f266743 fix(frontend): wip 2023-02-24 18:49:06 +01:00
Faton Ramadani
9d680e6744 Merge branch 'rf/flatten' of https://github.com/windmill-labs/windmill into rf/flatten 2023-02-24 18:44:19 +01:00
Faton Ramadani
5060c37fed fix(frontend): gridtab 2023-02-24 18:44:16 +01:00
Ruben Fiszel
15c2bdcdae pushed 2023-02-24 18:43:44 +01:00
Faton Ramadani
45ce630a75 fix(frontend): duplicate 2023-02-24 18:04:31 +01:00
Faton Ramadani
d50734cbb3 fix(frontend): delete grid item 2023-02-24 17:56:47 +01:00
Ruben Fiszel
b08b559eec script editor panel 2023-02-24 17:53:26 +01:00
Ruben Fiszel
5742bf2235 settings panel 2023-02-24 17:49:16 +01:00
Ruben Fiszel
c56176ec91 Merge branch 'main' into rf/flatten 2023-02-24 17:38:19 +01:00
Faton Ramadani
640242b713 fix(frontend): rewrote utils 2023-02-24 17:17:11 +01:00
Ruben Fiszel
c696f3b6cf flatten 2023-02-24 15:09:38 +01:00
21 changed files with 325 additions and 320 deletions

View File

@@ -7,12 +7,12 @@
export let id: string
export let configuration: Record<string, AppInput>
export let subGrids: GridItem[][] | undefined = undefined
export let componentContainerHeight: number
let noPadding: boolean | undefined = undefined
export const staticOutputs: string[] = []
const { focusedGrid, selectedComponent } = getContext<AppEditorContext>('AppEditorContext')
const { app, focusedGrid, selectedComponent } = getContext<AppEditorContext>('AppEditorContext')
let gridContent: string[] | undefined = undefined
@@ -27,15 +27,13 @@
</script>
<InputValue {id} input={configuration.noPadding} bind:value={noPadding} />
<InputValue {id} input={configuration.gridContent} bind:value={gridContent} />
{#if subGrids && subGrids[0]}
{#if $app.subgrids?.[`${id}-0`]}
<SubGridEditor
{noPadding}
bind:subGrid={subGrids[0]}
bind:subGrid={$app.subgrids[`${id}-0`]}
containerHeight={componentContainerHeight}
parentId={id}
index={0}
on:focus={() => {
$selectedComponent = id
}}

View File

@@ -8,14 +8,13 @@
import InputValue from '../helpers/InputValue.svelte'
export let id: string
export let configuration: Record<string, AppInput>
export let subGrids: GridItem[][] | undefined = undefined
export let componentContainerHeight: number
export let tabs: string[]
export const staticOutputs: string[] = ['selectedTabIndex']
const { worldStore, focusedGrid, selectedComponent } =
const { app, worldStore, focusedGrid, selectedComponent } =
getContext<AppEditorContext>('AppEditorContext')
let selected: string = ''
@@ -36,6 +35,7 @@
}
$: selectedIndex >= 0 && handleTabSelection()
let tabHeight: number = 0
function onFocus() {
@@ -46,7 +46,6 @@
}
$: $selectedComponent === id && selectedIndex >= 0 && onFocus()
$: console.log(subGrids)
</script>
<InputValue {id} input={configuration.tabs} bind:value={tabs} />
@@ -62,12 +61,10 @@
{/each}
</Tabs>
</div>
{#if subGrids && subGrids[selectedIndex]}
{#if $app.subgrids?.[`${id}-${selectedIndex}`]}
<SubGridEditor
parentId={id}
index={selectedIndex}
bind:subGrid={$app.subgrids[`${id}-${selectedIndex}`]}
{noPadding}
bind:subGrid={subGrids[selectedIndex]}
containerHeight={componentContainerHeight - tabHeight}
on:focus={() => {
$selectedComponent = id

View File

@@ -36,6 +36,7 @@
import UnsavedConfirmationModal from '$lib/components/common/confirmationModal/UnsavedConfirmationModal.svelte'
import { page } from '$app/stores'
import CssSettings from './componentsPanel/CssSettings.svelte'
import { findGridItem } from './appUtils'
export let app: App
export let path: string

View File

@@ -1,14 +1,35 @@
<script lang="ts">
import { getContext } from 'svelte'
import type { AppEditorContext } from '../types'
import { allItems, allItemsWithParent } from '../utils'
import PanelSection from './settingsPanel/common/PanelSection.svelte'
import ComponentPanel from './settingsPanel/ComponentPanel.svelte'
import InputsSpecsEditor from './settingsPanel/InputsSpecsEditor.svelte'
import SettingsPanelRec from './SettingsPanelRec.svelte'
import TablePanel from './TablePanel.svelte'
const { selectedComponent, app } = getContext<AppEditorContext>('AppEditorContext')
$: subgridKeys = Object.keys($app.subgrids ?? {})
</script>
<SettingsPanelRec bind:gridItems={$app.grid} />
{#each $app.grid as gridItem (gridItem.data.id)}
{#if gridItem.data.id === $selectedComponent}
<ComponentPanel parent={undefined} bind:component={gridItem.data} />
{:else if gridItem.data.type === 'tablecomponent'}
<TablePanel bind:component={gridItem.data} />
{/if}
{/each}
{#if $app.subgrids}
{#each subgridKeys as key (key)}
{#each $app.subgrids[key] as gridItem (gridItem.data.id)}
{#if gridItem.data.id === $selectedComponent}
<ComponentPanel parent={key} bind:component={gridItem.data} />
{:else if gridItem.data.type === 'tablecomponent'}
<TablePanel bind:component={gridItem.data} />
{/if}
{/each}
{/each}
{/if}
{#each $app?.hiddenInlineScripts ?? [] as script, index (script.name)}
{#if $selectedComponent === `bg_${index}`}

View File

@@ -1,16 +0,0 @@
<script lang="ts">
import type { GridItem } from '../types'
import SettingsPanelRec from './SettingsPanelRec.svelte'
export let subgrids: GridItem[][]
let elems = subgrids
$: subgrids = elems
</script>
{#if subgrids}
{#each elems as subGrid, i (i)}
<SettingsPanelRec bind:gridItems={subGrid} />
{/each}
{/if}

View File

@@ -1,24 +0,0 @@
<script lang="ts">
import { getContext } from 'svelte'
import type { AppEditorContext, GridItem } from '../types'
import ComponentPanel from './settingsPanel/ComponentPanel.svelte'
import SettingsPanelList from './SettingsPanelList.svelte'
import TablePanel from './TablePanel.svelte'
const { selectedComponent } = getContext<AppEditorContext>('AppEditorContext')
export let gridItems: GridItem[]
</script>
{#if gridItems}
{#each gridItems as gridItem (gridItem.data.id)}
{#if gridItem.data.id === $selectedComponent}
<ComponentPanel {gridItems} bind:component={gridItem.data} />
{:else if gridItem.data.type === 'tablecomponent'}
<TablePanel bind:component={gridItem.data} />
{:else if gridItem.data.subGrids}
<SettingsPanelList bind:subgrids={gridItem.data.subGrids} />
{/if}
{/each}
{/if}

View File

@@ -6,11 +6,10 @@
import type { AppEditorContext, GridItem } from '../types'
import Component from './component/Component.svelte'
export let subGrid: GridItem[]
export let containerHeight: number
export let noPadding = false
export let parentId: string
export let index: number
//export let id: string
export let subGrid: GridItem[] = []
const dispatch = createEventDispatcher()
@@ -38,10 +37,12 @@
onComponent = id
if (!$connectingInput.opened) {
$selectedComponent = id
/*
$focusedGrid = {
parentComponentId: parentId,
subGridIndex: index
}
*/
}
}

View File

@@ -11,7 +11,8 @@
{#each component.actionButtons as actionButton (actionButton.id)}
{#if actionButton.id === $selectedComponent}
<ComponentPanel
gridItems={undefined}
parent={undefined}
noGrid
rowColumns
bind:component={actionButton}
onDelete={() => {

View File

@@ -0,0 +1,182 @@
import { getNextId } from '$lib/components/flows/flowStateUtils'
import type { App, FocusedGrid, GridItem } from '../types'
import { Component, getRecommendedDimensionsByComponent, type AppComponent } from './component'
import gridHelp from '@windmill-labs/svelte-grid/src/utils/helper'
import { gridColumns } from '../gridUtils'
import { allItems } from '../utils'
function findGridItemById(
root: GridItem[],
subGrids: Record<string, GridItem[]> | undefined,
id: string
): GridItem | undefined {
for (const gridItem of root) {
if (gridItem.id === id) {
return gridItem
}
if (subGrids) {
const numberOfSubgrids = gridItem.data.numberOfSubgrids
if (numberOfSubgrids) {
for (let i = 0; i < numberOfSubgrids; i++) {
const subgrid = subGrids[`${gridItem.id}-${i}`] ?? []
const found = findGridItemById(subgrid, subGrids, id)
if (found) {
return found
}
}
}
}
}
return undefined
}
export function findGridItem(app: App, id: string): GridItem | undefined {
return findGridItemById(app.grid, app.subgrids, id)
}
export function getNextGridItemId(app: App): string {
const subgridsKeys = allItems(app.grid, app.subgrids).map((x) => x.id)
const withoutDash = subgridsKeys.map((element) => element.split('-')[0])
const id = getNextId([...new Set(withoutDash)])
return id
}
export function createNewGridItem(grid: GridItem[], id: string, data: AppComponent): GridItem {
const appComponent = data
appComponent.id = id
const newComponent = {
fixed: false,
resizable: true,
draggable: true,
customDragger: false,
customResizer: false,
x: 0,
y: 0
}
let newData: AppComponent = JSON.parse(JSON.stringify(appComponent))
const newItem: GridItem = {
data: newData,
id: id
}
gridColumns.forEach((column) => {
const rec = getRecommendedDimensionsByComponent(appComponent.type, column)
newItem[column] = {
...newComponent,
min: { w: 1, h: 1 },
max: { w: column, h: 100 },
w: rec.w,
h: rec.h
}
const position = gridHelp.findSpace(newItem, grid, column) as { x: number; y: number }
newItem[column] = { ...newItem[column], ...position }
})
return newItem
}
export function insertNewGridItem(
app: App,
data: AppComponent,
focusedGrid: FocusedGrid | undefined
) {
const id = getNextGridItemId(app)
if (!focusedGrid) {
const newItem = createNewGridItem(app.grid, id, data)
app.grid.push(newItem)
} else {
const { parentComponentId, subGridIndex } = focusedGrid
if (!app.subgrids) {
app.subgrids = {}
}
const subGrid = app.subgrids[`${parentComponentId}-${subGridIndex}`] ?? []
const newItem = createNewGridItem(subGrid, id, data)
const key = `${parentComponentId}-${subGridIndex ?? 0}`
if (!app.subgrids[key]) {
app.subgrids[key] = [newItem]
} else {
app.subgrids[key].push(newItem)
}
}
return id
}
export function getAllSubgridsAndComponentIds(
app: App,
component: AppComponent
): [string[], string[]] {
const subgrids: string[] = []
let components: string[] = [component.id]
if (app.subgrids && component.numberOfSubgrids) {
for (let i = 0; i < component.numberOfSubgrids; i++) {
const subgrid = app.subgrids[`${component.id}-${i}`]
if (subgrid) {
for (const item of subgrid) {
let [recSubgrids, recComponents] = getAllSubgridsAndComponentIds(app, item.data)
subgrids.push(...recSubgrids)
components.push(...recComponents)
}
}
}
}
return [subgrids, components]
}
export function deleteGridItem(
app: App,
component: AppComponent,
parent: string | undefined
): string[] {
let [subgrids, components] = getAllSubgridsAndComponentIds(app, component)
if (app.subgrids) {
subgrids.forEach((id) => {
delete app.subgrids![id]
})
}
if (!parent) {
let index = app.grid.findIndex((x) => x.id == component.id)
if (index > -1) {
app.grid.splice(index, 1)
}
} else {
let grid = app.subgrids![parent]
let index = grid.findIndex((x) => x.id == component.id)
if (index > -1) {
grid.splice(index, 1)
}
}
return components
}
export function duplicateGridItem(
app: App,
focusedGrid: FocusedGrid | undefined,
id: string
): string | undefined {
const gridItem = findGridItem(app, id)
if (gridItem) {
const newId = getNextGridItemId(app)
const newItem = JSON.parse(JSON.stringify(gridItem))
newItem.id = newId
newItem.data.id = newId
return insertNewGridItem(app, newItem.data, focusedGrid)
}
return undefined
}

View File

@@ -200,10 +200,7 @@
<AppRangeInput {...component} bind:staticOutputs={$staticOutputs[component.id]} />
{:else if component.type === 'tabscomponent'}
<AppTabs
id={component.id}
configuration={component.configuration}
tabs={component.tabs}
bind:subGrids={component.subGrids}
{...component}
bind:staticOutputs={$staticOutputs[component.id]}
{componentContainerHeight}
/>

View File

@@ -152,7 +152,7 @@ export const components: Record<AppComponent['type'], AppComponentConfig> = {
configuration: {},
customCss: {
header: { class: '', style: '' },
container: { class: '', style: '' },
container: { class: '', style: '' }
} as const,
card: false
}
@@ -175,7 +175,7 @@ export const components: Record<AppComponent['type'], AppComponentConfig> = {
},
componentInput: undefined,
card: false,
subGrids: [[]]
numberOfSubgrids: 1
}
},
textcomponent: {
@@ -1027,7 +1027,7 @@ Hello \${ctx.username}
},
componentInput: undefined,
card: false,
subGrids: [[], []],
numberOfSubgrids: 2,
tabs: ['First tab', 'Second tab']
}
},
@@ -1200,4 +1200,4 @@ Hello \${ctx.username}
card: false
}
}
}
}

View File

@@ -1,34 +1,20 @@
<script lang="ts">
import type { AppEditorContext, GridItem } from '../../types'
import type { AppEditorContext } from '../../types'
import { getContext, onMount } from 'svelte'
import { getNextId } from '$lib/components/flows/flowStateUtils'
import { isOpenStore } from './store'
import { dirtyStore } from '$lib/components/common/confirmationModal/dirtyStore'
import { components as componentsRecord, COMPONENT_SETS, type AppComponent } from '../component'
import ListItem from './ListItem.svelte'
import { insertNewGridItem, createNewGridItem, getNextGridItemId } from '../../utils'
import { insertNewGridItem } from '../appUtils'
const TITLE_PREFIX = 'Component.' as const
const { app, selectedComponent, focusedGrid } = getContext<AppEditorContext>('AppEditorContext')
function addComponent(appComponentType: AppComponent['type']): void {
// When a new component is added, we need to mark the app as dirty,
// so a confirmation modal will appear if the user tries to leave the page
$dirtyStore = true
const grid = $app.grid ?? []
const id = getNextGridItemId(grid)
const data = componentsRecord[appComponentType].data
if ($focusedGrid) {
const { parentComponentId, subGridIndex } = $focusedGrid
$app.grid = insertNewGridItem($app.grid, parentComponentId, subGridIndex, id, data)
} else {
const newItem = createNewGridItem(grid, id, data)
$app.grid = [...grid, newItem]
}
const id = insertNewGridItem($app, data, $focusedGrid)
$selectedComponent = id
}

View File

@@ -2,7 +2,7 @@
import { classNames } from '$lib/utils'
import { getContext } from 'svelte'
import type { AppEditorContext } from '../../types'
import { findParent } from '../../utils'
import { findGridItem } from '../appUtils'
import { components } from '../component'
import PanelSection from '../settingsPanel/common/PanelSection.svelte'
import ComponentOutputViewer from './ComponentOutputViewer.svelte'
@@ -27,7 +27,7 @@
}
function getComponentNameById(componentId: string) {
const component = findParent($app.grid, componentId)
const component = findGridItem($app, componentId)
if (component?.data.type) {
return components[component?.data.type].name

View File

@@ -1,16 +0,0 @@
<script lang="ts">
import type { GridItem } from '../../types'
import InlineScriptEditorRec from './InlineScriptEditorRec.svelte'
export let subgrids: GridItem[][]
export let selectedScriptComponentId: string | undefined = undefined
let elems = subgrids
$: subgrids = elems
</script>
{#if subgrids}
{#each elems as subGrid, i (i)}
<InlineScriptEditorRec {selectedScriptComponentId} bind:gridItems={subGrid} />
{/each}
{/if}

View File

@@ -8,7 +8,7 @@
import { emptySchema, getScriptByPath } from '$lib/utils'
import { faCodeBranch, faExternalLinkAlt, faEye, faPen } from '@fortawesome/free-solid-svg-icons'
import type { AppInput, RunnableByPath } from '../../inputType'
import { clearResultAppInput, schemaToInputsSpec } from '../../utils'
import { clearResultAppInput } from '../../utils'
import EmptyInlineScript from './EmptyInlineScript.svelte'
import InlineScriptEditor from './InlineScriptEditor.svelte'
import { computeFields } from './utils'

View File

@@ -1,40 +0,0 @@
<script lang="ts">
import type { GridItem } from '../../types'
import InlineScriptEditorList from './InlineScriptEditorList.svelte'
import InlineScriptEditorPanel from './InlineScriptEditorPanel.svelte'
export let gridItems: GridItem[]
export let selectedScriptComponentId: string | undefined = undefined
</script>
{gridItems}
{#if gridItems}
{#each gridItems as gridComponent, index (index)}
{#if gridComponent.data}
{#if gridComponent.data.id === selectedScriptComponentId}
<InlineScriptEditorPanel
id={gridComponent.data.id}
bind:componentInput={gridComponent.data.componentInput}
/>
{:else if gridComponent.data.subGrids}
<!-- <InlineScriptEditorList
{selectedScriptComponentId}
bind:subgrids={gridComponent.data.subGrids}
/> -->
{/if}
{#if gridComponent.data.type === 'tablecomponent'}
{#each gridComponent.data.actionButtons as actionButton, index (index)}
{#if actionButton.id === selectedScriptComponentId}
<InlineScriptEditorPanel
id={actionButton.id}
bind:componentInput={actionButton.componentInput}
/>
{/if}
{/each}
{/if}
{/if}
{/each}
{/if}

View File

@@ -6,7 +6,8 @@
import InlineScriptsPanelList from './InlineScriptsPanelList.svelte'
import InlineScriptEditor from './InlineScriptEditor.svelte'
import EmptyInlineScript from './EmptyInlineScript.svelte'
import InlineScriptEditorRec from './InlineScriptEditorRec.svelte'
import { allItems } from '../../utils'
import InlineScriptEditorPanel from './InlineScriptEditorPanel.svelte'
const { app, staticOutputs, runnableComponents } =
getContext<AppEditorContext>('AppEditorContext')
@@ -24,7 +25,25 @@
<span class="p-2 text-sm text-gray-600">Select a script on the left panel</span>
{/if}
<InlineScriptEditorRec {selectedScriptComponentId} bind:gridItems={$app.grid} />
{#each allItems($app.grid, $app.subgrids) as gridItem (gridItem.data.id)}
{#if gridItem.data.id === selectedScriptComponentId}
<InlineScriptEditorPanel
id={gridItem.data.id}
bind:componentInput={gridItem.data.componentInput}
/>
{/if}
{#if gridItem.data.type === 'tablecomponent'}
{#each gridItem.data.actionButtons as actionButton, index (index)}
{#if actionButton.id === selectedScriptComponentId}
<InlineScriptEditorPanel
id={actionButton.id}
bind:componentInput={actionButton.componentInput}
/>
{/if}
{/each}
{/if}
{/each}
{#each $app.unusedInlineScripts as unusedInlineScript, index (index)}
{#if `unused-${index}` === selectedScriptComponentId}
<InlineScriptEditor

View File

@@ -10,15 +10,7 @@
import ConnectedInputEditor from './inputEditor/ConnectedInputEditor.svelte'
import Badge from '$lib/components/common/badge/Badge.svelte'
import { capitalize, classNames } from '$lib/utils'
import {
buildExtraLib,
createNewGridItem,
deleteComponent,
fieldTypeToTsType,
findParent,
getNextGridItemId,
insertNewGridItem
} from '../../utils'
import { buildExtraLib, fieldTypeToTsType } from '../../utils'
import Recompute from './Recompute.svelte'
import Tooltip from '$lib/components/Tooltip.svelte'
import ComponentInputTypeEditor from './ComponentInputTypeEditor.svelte'
@@ -29,46 +21,38 @@
import CssProperty from '../componentsPanel/CssProperty.svelte'
import { dirtyStore } from '$lib/components/common/confirmationModal/dirtyStore'
import GridTab from './GridTab.svelte'
import { duplicateGridItem } from '../appUtils'
import { deleteGridItem } from '../appUtils'
export let component: AppComponent | undefined
export let component: AppComponent
export let rowColumns = false
export let gridItems: GridItem[] | undefined
export let onDelete: (() => void) | undefined = undefined
export let parent: string | undefined
export let noGrid = false
const { app, staticOutputs, runnableComponents, selectedComponent, worldStore, focusedGrid } =
getContext<AppEditorContext>('AppEditorContext')
function duplicateElement(id: string) {
const parent = findParent($app.grid, id)
if (!parent) {
return
}
const data: AppComponent = JSON.parse(JSON.stringify(parent.data))
$dirtyStore = true
const grid = $app.grid ?? []
const newId = getNextGridItemId(grid)
if ($focusedGrid) {
const { parentComponentId, subGridIndex } = $focusedGrid
$app.grid = insertNewGridItem($app.grid, parentComponentId, subGridIndex, newId, data)
} else {
const newItem = createNewGridItem(grid, newId, data)
$app.grid = [...grid, newItem]
}
const newId = duplicateGridItem($app, $focusedGrid, id)
$selectedComponent = newId
}
function removeGridElement() {
$selectedComponent = undefined
$focusedGrid = undefined
if (component) {
deleteComponent(gridItems, component, $app, $staticOutputs, $runnableComponents)
if (component && !noGrid) {
let ids = deleteGridItem($app, component, parent)
for (const key in ids) {
delete $staticOutputs[key]
delete $runnableComponents[key]
}
}
delete $staticOutputs[component.id]
delete $runnableComponents[component.id]
$app = $app
$staticOutputs = $staticOutputs
$runnableComponents = $runnableComponents
@@ -164,8 +148,8 @@
</PanelSection>
{/if}
{#if component.type === 'tabscomponent' && Array.isArray(component.subGrids)}
<GridTab bind:tabs={component.tabs} bind:subGrids={component.subGrids} />
{#if component.type === 'tabscomponent'}
<GridTab bind:tabs={component.tabs} {component} />
{/if}
{#if component.type === 'tablecomponent' && Array.isArray(component.actionButtons)}

View File

@@ -2,33 +2,41 @@
import Button from '$lib/components/common/button/Button.svelte'
import { faPlus, faTrashAlt } from '@fortawesome/free-solid-svg-icons'
import { getContext } from 'svelte'
import type { AppEditorContext, GridItem } from '../../types'
import { deleteComponent } from '../../utils'
import type { AppEditorContext } from '../../types'
import { deleteGridItem } from '../appUtils'
import type { AppComponent } from '../component'
import PanelSection from './common/PanelSection.svelte'
export let tabs: string[]
export let subGrids: GridItem[][]
export let component: AppComponent
const { runnableComponents, staticOutputs, app, focusedGrid } =
const { app, staticOutputs, runnableComponents } =
getContext<AppEditorContext>('AppEditorContext')
function addTab() {
tabs = [...tabs, `Tab ${tabs.length + 1}`]
subGrids = [...subGrids, []]
const numberOfTabs = tabs.length
tabs = [...tabs, `Tab ${numberOfTabs + 1}`]
if (!$app.subgrids) {
$app.subgrids = {}
}
$app.subgrids[`${component.id}-${numberOfTabs}`] = []
component.numberOfSubgrids = tabs.length
}
function deleteSubgrid(index: number) {
$focusedGrid = undefined
subGrids[index].forEach((x) => {
deleteComponent(undefined, x.data, $app, $staticOutputs, $runnableComponents)
})
tabs.splice(index, 1)
subGrids.splice(index, 1)
tabs = tabs
subGrids = subGrids
$app.grid = $app.grid
$staticOutputs = $staticOutputs
$runnableComponents = $runnableComponents
let subgrid = `${component.id}-${index}`
for (const item of $app!.subgrids![subgrid]) {
const components = deleteGridItem($app, item.data, subgrid)
for (const key in components) {
delete $staticOutputs[key]
delete $runnableComponents[key]
}
}
delete $app!.subgrids![subgrid]
}
</script>

View File

@@ -59,7 +59,8 @@ export interface BaseAppComponent extends Partial<Aligned> {
* *For example when the component has a popup like `Select`*
*/
softWrap?: boolean
subGrids?: GridItem[][]
// Number of subgrids
numberOfSubgrids?: number
}
export type ComponentSet = {
@@ -99,6 +100,7 @@ export type App = {
fields: Record<string, StaticAppInput | ConnectedAppInput | RowAppInput | UserAppInput>
}>
css?: Record<'viewer' | 'grid' | AppComponent['type'], ComponentCustomCSS>
subgrids?: Record<string, GridItem[]>
}
export type ConnectingInput = {
@@ -132,7 +134,6 @@ export type AppEditorContext = {
}
export type FocusedGrid = { parentComponentId: string; subGridIndex: number }
export type EditorMode = 'dnd' | 'preview'
export type EditorBreakpoint = 'sm' | 'lg'

View File

@@ -2,30 +2,20 @@ import type { Schema } from '$lib/common'
import { FlowService, ScriptService } from '$lib/gen'
import { inferArgs } from '$lib/infer'
import { emptySchema } from '$lib/utils'
import type { AppComponent, AppComponentConfig } from './editor/component'
import {
components as componentsRecord,
getRecommendedDimensionsByComponent
} from './editor/component'
import { gridColumns } from './gridUtils'
import gridHelp from '@windmill-labs/svelte-grid/src/utils/helper'
import type { AppComponent } from './editor/component'
import type { AppInput, InputType, ResultAppInput, StaticAppInput } from './inputType'
import type { Output } from './rx'
import type { App, GridItem } from './types'
import { getNextId } from '../flows/flowStateUtils'
export function deleteComponent(parentItems: GridItem[] | undefined, component: AppComponent, app: App, staticOutputs: Record<string, any>, runnableComponents: Record<string, any>) {
(component.subGrids ?? []).forEach((subgrid) => {
if (subgrid) {
subgrid.forEach((item) => {
if (item.data) {
deleteComponent(undefined, item.data, app, staticOutputs, runnableComponents)
}
})
}
})
/*
export function deleteComponent(
subgrid: string | undefined,
component: AppComponent,
app: App,
staticOutputs: Record<string, any>,
runnableComponents: Record<string, any>
) {
if (parentItems) {
let index = parentItems.findIndex((item) => item.data?.id === component.id)
if (index != -1) {
@@ -54,6 +44,24 @@ export function deleteComponent(parentItems: GridItem[] | undefined, component:
}
}
}
*/
export function allItems(grid: GridItem[], subgrids: Record<string, GridItem[]> | undefined): GridItem[] {
if (subgrids == undefined) {
return grid
}
return [...grid, ...Object.values(subgrids).flat()]
}
export function allItemsWithParent(grid: GridItem[], subgrids: Record<string, GridItem[]> | undefined): [GridItem, string | undefined][] {
const items: [GridItem, string | undefined][] = grid.map((item) => [item, undefined])
if (subgrids == undefined) {
return items
}
return [...items, ...Object.entries(subgrids).flatMap(([k, v]) => v.map((g) => [g, k] as [GridItem, string]))]
}
export async function loadSchema(
workspace: string,
path: string,
@@ -256,106 +264,3 @@ export function toPascalCase(text: string) {
export function toKebabCase(text: string) {
return text.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
}
export function findParent(root: GridItem[], id: string): GridItem | undefined {
if (!root) {
return undefined
}
for (const a of root) {
if (a.id === id) {
return a
}
if (a.data.subGrids) {
// Recursively search the sub-grids
for (const subGrid of a.data.subGrids) {
const result = findParent(subGrid, id)
if (result) {
return result
}
}
}
}
return undefined
}
export function insertNewGridItem(
root: GridItem[],
id: string,
subGridIndex: number,
newId: string,
data: AppComponent
): GridItem[] {
const parentA = findParent(root, id)
if (!parentA) {
throw new Error(`Parent A object with ID ${id} not found.`)
}
const subGrid = parentA.data.subGrids[subGridIndex]
if (!subGrid) {
throw new Error(`Sub-grid with index ${subGridIndex} not found.`)
}
const newItem = createNewGridItem(subGrid ?? [], newId, data)
subGrid.push(newItem)
return root
}
// The grid is needed to find a space for the new component
export function createNewGridItem(grid: GridItem[], id: string, data: AppComponent): GridItem {
const appComponent = data
appComponent.id = id
const newComponent = {
fixed: false,
resizable: true,
draggable: true,
customDragger: false,
customResizer: false,
x: 0,
y: 0
}
let newData: AppComponent = JSON.parse(JSON.stringify(appComponent))
const newItem: GridItem = {
data: newData,
id: id
}
gridColumns.forEach((column) => {
const rec = getRecommendedDimensionsByComponent(appComponent.type, column)
newItem[column] = {
...newComponent,
min: { w: 1, h: 1 },
max: { w: column, h: 100 },
w: rec.w,
h: rec.h
}
const position = gridHelp.findSpace(newItem, grid, column) as { x: number; y: number }
newItem[column] = { ...newItem[column], ...position }
})
return newItem
}
export function recursiveGetIds(gridItem: GridItem): string[] {
const subGrids = gridItem.data.subGrids ?? []
const subGridIds = subGrids
.map((subGrid: GridItem[]) => subGrid?.map(recursiveGetIds) ?? [])
.flat(Infinity)
return [gridItem.data.id, ...subGridIds]
}
export function getNextGridItemId(grid: GridItem[] = []): string {
const gridItemIds = grid.map(recursiveGetIds).flat()
const id = getNextId(gridItemIds)
return id
}