mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-23 00:00:33 +00:00
fix(frontend): rewrote utils
This commit is contained in:
committed by
Ruben Fiszel
parent
4ad6fbefd3
commit
ea1b2c29b9
@@ -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
|
||||
}}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
|
||||
export let containerHeight: number
|
||||
export let noPadding = false
|
||||
export let id: string
|
||||
//export let id: string
|
||||
export let subGrid: GridItem[] = []
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -36,10 +37,12 @@
|
||||
onComponent = id
|
||||
if (!$connectingInput.opened) {
|
||||
$selectedComponent = id
|
||||
/*
|
||||
$focusedGrid = {
|
||||
parentComponentId: parentId,
|
||||
subGridIndex: index
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
import { getNextId } from '$lib/components/flows/flowStateUtils'
|
||||
import type { App, FocusedGrid, GridItem } from '../types'
|
||||
import { getRecommendedDimensionsByComponent, type AppComponent } from './component'
|
||||
import gridHelp from '@windmill-labs/svelte-grid/src/utils/helper'
|
||||
import { gridColumns } from '../gridUtils'
|
||||
|
||||
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
|
||||
const subgrids = subGrids[gridItem.id]
|
||||
if (numberOfSubgrids && subgrids) {
|
||||
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 = app.subgrids ? Object.keys(app.subgrids) : []
|
||||
|
||||
const newArr = subgridsKeys.map((element) => {
|
||||
const matches = element.match(/^([a-z]+)-\d+$/i)
|
||||
if (matches) {
|
||||
return matches[1]
|
||||
}
|
||||
return element
|
||||
})
|
||||
|
||||
const uniqueArr = [...new Set(newArr)]
|
||||
const mainGridItemsIds = app.grid.map((item) => item.id)
|
||||
const id = getNextId([...mainGridItemsIds, ...uniqueArr])
|
||||
|
||||
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
|
||||
}
|
||||
@@ -203,7 +203,6 @@
|
||||
id={component.id}
|
||||
configuration={component.configuration}
|
||||
tabs={component.tabs}
|
||||
bind:subGrids={component.subGrids}
|
||||
bind:staticOutputs={$staticOutputs[component.id]}
|
||||
{componentContainerHeight}
|
||||
/>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
@@ -39,7 +31,8 @@
|
||||
getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
function duplicateElement(id: string) {
|
||||
const parent = findParent($app.grid, id)
|
||||
/*
|
||||
const parent = findGridItem($app.grid, id)
|
||||
|
||||
if (!parent) {
|
||||
return
|
||||
@@ -61,9 +54,11 @@
|
||||
}
|
||||
|
||||
$selectedComponent = newId
|
||||
*/
|
||||
}
|
||||
|
||||
function removeGridElement() {
|
||||
/*
|
||||
$selectedComponent = undefined
|
||||
$focusedGrid = undefined
|
||||
if (component) {
|
||||
@@ -73,12 +68,23 @@
|
||||
$runnableComponents = $runnableComponents
|
||||
|
||||
onDelete?.()
|
||||
*/
|
||||
}
|
||||
|
||||
$: extraLib =
|
||||
component?.componentInput?.type === 'template' && $worldStore
|
||||
? buildExtraLib($worldStore?.outputsById ?? {}, component?.id, false)
|
||||
: undefined
|
||||
|
||||
/*
|
||||
|
||||
|
||||
|
||||
{#if component.type === 'tabscomponent' && Array.isArray(component.subGrids)}
|
||||
<GridTab bind:tabs={component.tabs} bind:subGrids={component.subGrids} />
|
||||
{/if}
|
||||
|
||||
*/
|
||||
</script>
|
||||
|
||||
{#if component}
|
||||
@@ -164,10 +170,6 @@
|
||||
</PanelSection>
|
||||
{/if}
|
||||
|
||||
{#if component.type === 'tabscomponent' && Array.isArray(component.subGrids)}
|
||||
<GridTab bind:tabs={component.tabs} bind:subGrids={component.subGrids} />
|
||||
{/if}
|
||||
|
||||
{#if component.type === 'tablecomponent' && Array.isArray(component.actionButtons)}
|
||||
<TableActions id={component.id} bind:components={component.actionButtons} />
|
||||
{/if}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { faPlus, faTrashAlt } from '@fortawesome/free-solid-svg-icons'
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppEditorContext, GridItem } from '../../types'
|
||||
import { deleteComponent } from '../../utils'
|
||||
//import { deleteComponent } from '../../utils'
|
||||
import PanelSection from './common/PanelSection.svelte'
|
||||
|
||||
export let tabs: string[]
|
||||
@@ -20,7 +20,7 @@
|
||||
function deleteSubgrid(index: number) {
|
||||
$focusedGrid = undefined
|
||||
subGrids[index].forEach((x) => {
|
||||
deleteComponent(undefined, x.data, $app, $staticOutputs, $runnableComponents)
|
||||
//deleteComponent(undefined, x.data, $app, $staticOutputs, $runnableComponents)
|
||||
})
|
||||
tabs.splice(index, 1)
|
||||
subGrids.splice(index, 1)
|
||||
|
||||
@@ -42,14 +42,14 @@ export interface BaseAppComponent extends Partial<Aligned> {
|
||||
configuration: Record<
|
||||
string,
|
||||
GeneralAppInput &
|
||||
(
|
||||
| StaticAppInput
|
||||
| ConnectedAppInput
|
||||
| UserAppInput
|
||||
| RowAppInput
|
||||
| EvalAppInput
|
||||
| UploadAppInput
|
||||
)
|
||||
(
|
||||
| StaticAppInput
|
||||
| ConnectedAppInput
|
||||
| UserAppInput
|
||||
| RowAppInput
|
||||
| EvalAppInput
|
||||
| UploadAppInput
|
||||
)
|
||||
>
|
||||
card: boolean | undefined
|
||||
customCss?: ComponentCustomCSS
|
||||
@@ -59,7 +59,8 @@ export interface BaseAppComponent extends Partial<Aligned> {
|
||||
* *For example when the component has a popup like `Select`*
|
||||
*/
|
||||
softWrap?: boolean
|
||||
subgrids?: number
|
||||
// Number of subgrids
|
||||
numberOfSubgrids?: number
|
||||
}
|
||||
|
||||
export type ComponentSet = {
|
||||
@@ -133,7 +134,6 @@ export type AppEditorContext = {
|
||||
}
|
||||
|
||||
export type FocusedGrid = { parentComponentId: string; subGridIndex: number }
|
||||
|
||||
export type EditorMode = 'dnd' | 'preview'
|
||||
export type EditorBreakpoint = 'sm' | 'lg'
|
||||
|
||||
|
||||
@@ -2,21 +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(subgrid: string | undefined, component: AppComponent, app: App, staticOutputs: Record<string, any>, runnableComponents: Record<string, any>) {
|
||||
/*
|
||||
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) {
|
||||
@@ -45,6 +44,9 @@ export function deleteComponent(subgrid: string | undefined, component: AppCompo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
export async function loadSchema(
|
||||
workspace: string,
|
||||
path: string,
|
||||
@@ -247,106 +249,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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user