mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-20 08:01:35 +00:00
feat(frontend): full height component (#3676)
* feat(frontend): wip * feat(frontend): Full Height component * feat(frontend): wip * feat(frontend): add fullHeight indicator * feat(frontend): add indicator for component that won't render * feat(frontend): update collision algo * fix(frontend): Full height component done * fix(frontend): Remove the hidden check from preview * feat(frontend): code cleanup * feat(frontend): code cleanup * feat(frontend): code cleanup * feat(frontend): code cleanup * feat(frontend): Fix height issue + fix toggle display * feat(frontend): Fix insertNewGridITem * feat(frontend): code cleanup * feat(frontend): mobile fullHeigt * feat(frontend): fix wording * feat(frontend): add missing constants * feat(frontend): fix typo * feat(frontend): remove dead code * feat(frontend): improve the structure * feat(frontend): done --------- Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
import { columnConfiguration } from '../gridUtils'
|
||||
import { HiddenComponent } from '../components'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import { dfs } from './appUtils'
|
||||
import { dfs, maxHeight } from './appUtils'
|
||||
import { BG_PREFIX, migrateApp } from '../utils'
|
||||
import { workspaceStore, enterpriseLicense } from '$lib/stores'
|
||||
import DarkModeObserver from '$lib/components/DarkModeObserver.svelte'
|
||||
@@ -161,13 +161,17 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let appHeight: number = 0
|
||||
|
||||
$: maxRow = maxHeight($appStore.grid, appHeight, $breakpoint)
|
||||
</script>
|
||||
|
||||
<DarkModeObserver on:change={onThemeChange} />
|
||||
|
||||
<svelte:window on:hashchange={hashchange} on:resize={resizeWindow} />
|
||||
|
||||
<div class="relative h-full">
|
||||
<div class="relative h-full" bind:clientHeight={appHeight}>
|
||||
<div id="app-editor-top-level-drawer" />
|
||||
<div id="app-editor-select" />
|
||||
|
||||
@@ -201,7 +205,7 @@
|
||||
class={twMerge(
|
||||
'p-2 overflow-visible',
|
||||
app.css?.['app']?.['grid']?.class ?? '',
|
||||
'wm-app-grid subgrid'
|
||||
'wm-app-grid subgrid'
|
||||
)}
|
||||
bind:clientWidth={$parentWidth}
|
||||
>
|
||||
@@ -210,16 +214,24 @@
|
||||
allIdsInPath={$allIdsInPath}
|
||||
items={app.grid}
|
||||
let:dataItem
|
||||
rowHeight={36}
|
||||
let:hidden
|
||||
cols={columnConfiguration}
|
||||
gap={[4, 2]}
|
||||
{maxRow}
|
||||
breakpoint={$breakpoint}
|
||||
>
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class={'h-full w-full center-center'}
|
||||
on:pointerdown={() => ($selectedComponent = [dataItem.id])}
|
||||
>
|
||||
<Component render={true} component={dataItem.data} selected={false} locked={true} />
|
||||
<Component
|
||||
render={true}
|
||||
component={dataItem.data}
|
||||
selected={false}
|
||||
locked={true}
|
||||
fullHeight={dataItem?.[$breakpoint === 'sm' ? 3 : 12]?.fullHeight}
|
||||
{hidden}
|
||||
/>
|
||||
</div>
|
||||
</GridViewer>
|
||||
</div>
|
||||
@@ -228,6 +240,7 @@
|
||||
|
||||
{#if isLocked}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
on:click={() => (isLocked = false)}
|
||||
class="absolute inset-0 center-center bg-black/20 z-50 backdrop-blur-[1px] cursor-pointer"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils'
|
||||
import type { AppViewerContext } from '../types'
|
||||
import { Anchor, Bug, Expand, Move, Network, Pen, Plug2 } from 'lucide-svelte'
|
||||
import { Anchor, ArrowDownFromLine, Bug, Expand, Move, Network, Pen, Plug2 } from 'lucide-svelte'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
import Popover from '$lib/components/Popover.svelte'
|
||||
import { Button, Popup } from '$lib/components/common'
|
||||
@@ -21,6 +21,8 @@
|
||||
export let hasInlineEditor: boolean = false
|
||||
export let inlineEditorOpened: boolean = false
|
||||
export let errorHandledByComponent: boolean = false
|
||||
export let fullHeight: boolean = false
|
||||
//export let willNotDisplay: boolean = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -115,6 +117,40 @@
|
||||
<DecisionTreeDebug id={component.id} nodes={component.nodes ?? []} />
|
||||
{/if}
|
||||
|
||||
<!-- {#if willNotDisplay}
|
||||
<Popover>
|
||||
<svelte:fragment slot="text">
|
||||
This component won't render, because an other component above it is set to fill the
|
||||
height.
|
||||
</svelte:fragment>
|
||||
<div
|
||||
title="Fill height"
|
||||
class={classNames(
|
||||
'px-1 text-2xs py-0.5 font-bold w-fit border cursor-pointer rounded-sm',
|
||||
'bg-red-100 text-red-600 border-red-500 hover:bg-red-200 hover:text-red-800'
|
||||
)}
|
||||
>
|
||||
<EyeOff aria-label="Expand position" size={14} />
|
||||
</div>
|
||||
</Popover>
|
||||
{/if} -->
|
||||
|
||||
<button
|
||||
title="Fill height"
|
||||
class={classNames(
|
||||
'px-1 text-2xs py-0.5 font-bold w-fit border cursor-pointer rounded-sm',
|
||||
'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800'
|
||||
)}
|
||||
on:click={() => dispatch('fillHeight')}
|
||||
on:pointerdown|stopPropagation
|
||||
>
|
||||
<ArrowDownFromLine
|
||||
aria-label="Expand position"
|
||||
size={14}
|
||||
class={fullHeight ? 'text-orange-500' : ''}
|
||||
/>
|
||||
</button>
|
||||
|
||||
<button
|
||||
title="Expand"
|
||||
class={classNames(
|
||||
|
||||
@@ -86,10 +86,10 @@
|
||||
</div>
|
||||
<div>
|
||||
{policy.on_behalf_of ? `Author ${policy.on_behalf_of_email}` : ''}
|
||||
<Tooltip
|
||||
>The scripts will be run on behalf of the author and a tight policy ensure security about
|
||||
the possible inputs of the runnables.</Tooltip
|
||||
>
|
||||
<Tooltip>
|
||||
The scripts will be run on behalf of the author and a tight policy ensure security about
|
||||
the possible inputs of the runnables.
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -125,9 +125,8 @@
|
||||
$app.grid = e.detail
|
||||
}}
|
||||
let:dataItem
|
||||
rowHeight={36}
|
||||
let:hidden
|
||||
cols={columnConfiguration}
|
||||
gap={[4, 2]}
|
||||
>
|
||||
<ComponentWrapper
|
||||
id={dataItem.id}
|
||||
@@ -139,10 +138,12 @@
|
||||
>
|
||||
<GridEditorMenu id={dataItem.id}>
|
||||
<Component
|
||||
{hidden}
|
||||
render={true}
|
||||
component={dataItem.data}
|
||||
selected={Boolean($selectedComponent?.includes(dataItem.id))}
|
||||
locked={isFixed(dataItem)}
|
||||
fullHeight={dataItem?.[$breakpoint === 'sm' ? 3 : 12]?.fullHeight}
|
||||
on:lock={() => {
|
||||
const gridItem = findGridItem($app, dataItem.id)
|
||||
if (gridItem) {
|
||||
@@ -156,6 +157,14 @@
|
||||
expandGriditem($app.grid, dataItem.id, $breakpoint)
|
||||
$app = $app
|
||||
}}
|
||||
on:fillHeight={() => {
|
||||
const gridItem = findGridItem($app, dataItem.id)
|
||||
const b = $breakpoint === 'sm' ? 3 : 12
|
||||
if (gridItem?.[b]) {
|
||||
gridItem[b].fullHeight = !gridItem[b].fullHeight
|
||||
}
|
||||
$app = $app
|
||||
}}
|
||||
/>
|
||||
</GridEditorMenu>
|
||||
</ComponentWrapper>
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { ROW_GAP_X, ROW_GAP_Y, ROW_HEIGHT } from './appUtils'
|
||||
|
||||
import type { EditorBreakpoint } from '../types'
|
||||
|
||||
import { onMount, createEventDispatcher } from 'svelte'
|
||||
|
||||
import type { FilledItem } from '../svelte-grid/types'
|
||||
@@ -11,10 +15,12 @@
|
||||
type T = $$Generic
|
||||
|
||||
export let items: FilledItem<T>[]
|
||||
export let rowHeight: number
|
||||
export let rowHeight: number = ROW_HEIGHT
|
||||
export let cols: [number, number][]
|
||||
export let gap = [10, 10]
|
||||
export let gap = [ROW_GAP_X, ROW_GAP_Y]
|
||||
export let throttleUpdate = 100
|
||||
export let maxRow: number
|
||||
export let breakpoint: EditorBreakpoint
|
||||
|
||||
export let allIdsInPath: string[] | undefined = undefined
|
||||
export let containerWidth: number | undefined = undefined
|
||||
@@ -81,9 +87,15 @@
|
||||
{@const width =
|
||||
Math.min(getComputedCols, item[getComputedCols] && item[getComputedCols].w) * xPerPx -
|
||||
gapX * 2}
|
||||
{@const height = (item[getComputedCols] && item[getComputedCols].h) * yPerPx - gapY * 2}
|
||||
{@const height =
|
||||
(item?.[breakpoint === 'sm' ? 3 : 12]?.fullHeight
|
||||
? maxRow - item[getComputedCols].y
|
||||
: item[getComputedCols] && item[getComputedCols].h) *
|
||||
yPerPx -
|
||||
gapY * 2}
|
||||
{@const top = (item[getComputedCols] && item[getComputedCols].y) * yPerPx + gapY}
|
||||
{@const left = (item[getComputedCols] && item[getComputedCols].x) * xPerPx + gapX}
|
||||
|
||||
<div
|
||||
class="svlt-grid-item"
|
||||
style="width: {width}px; height:{height}px; {onTop
|
||||
@@ -91,7 +103,7 @@
|
||||
: ''} top: {top}px; left: {left}px;"
|
||||
>
|
||||
{#if item[getComputedCols]}
|
||||
<slot dataItem={item} item={item[getComputedCols]} />
|
||||
<slot dataItem={item} item={item[getComputedCols]} hidden={false} />
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { columnConfiguration, isFixed, toggleFixed } from '../gridUtils'
|
||||
import Grid from '../svelte-grid/Grid.svelte'
|
||||
import type { AppEditorContext, AppViewerContext, GridItem } from '../types'
|
||||
import { expandGriditem, findGridItem, selectId } from './appUtils'
|
||||
import { expandGriditem, findGridItem, maxHeight, selectId } from './appUtils'
|
||||
import Component from './component/Component.svelte'
|
||||
import ComponentWrapper from './component/ComponentWrapper.svelte'
|
||||
import GridViewer from './GridViewer.svelte'
|
||||
@@ -66,6 +66,8 @@
|
||||
}
|
||||
|
||||
let container: HTMLElement | undefined = undefined
|
||||
|
||||
$: maxRow = maxHeight($app.subgrids?.[subGridId] ?? [], containerHeight ?? 0, $breakpoint)
|
||||
</script>
|
||||
|
||||
<div
|
||||
@@ -105,9 +107,8 @@
|
||||
}}
|
||||
selectedIds={$selectedComponent}
|
||||
let:dataItem
|
||||
rowHeight={36}
|
||||
let:hidden
|
||||
cols={columnConfiguration}
|
||||
gap={[4, 2]}
|
||||
scroller={container}
|
||||
parentWidth={$parentWidth - 17}
|
||||
{containerWidth}
|
||||
@@ -123,6 +124,8 @@
|
||||
>
|
||||
<GridEditorMenu id={dataItem.id}>
|
||||
<Component
|
||||
{hidden}
|
||||
fullHeight={dataItem?.[$breakpoint === 'sm' ? 3 : 12]?.fullHeight}
|
||||
render={visible}
|
||||
component={dataItem.data}
|
||||
selected={Boolean($selectedComponent?.includes(dataItem.id))}
|
||||
@@ -146,6 +149,15 @@
|
||||
)
|
||||
$app = $app
|
||||
}}
|
||||
on:fillHeight={() => {
|
||||
const gridItem = findGridItem($app, dataItem.id)
|
||||
const b = $breakpoint === 'sm' ? 3 : 12
|
||||
|
||||
if (gridItem?.[b]) {
|
||||
gridItem[b].fullHeight = !gridItem[b].fullHeight
|
||||
}
|
||||
$app = $app
|
||||
}}
|
||||
/>
|
||||
</GridEditorMenu>
|
||||
</ComponentWrapper>
|
||||
@@ -156,11 +168,12 @@
|
||||
allIdsInPath={$allIdsInPath}
|
||||
items={$app.subgrids?.[subGridId] ?? []}
|
||||
let:dataItem
|
||||
rowHeight={36}
|
||||
let:hidden
|
||||
cols={columnConfiguration}
|
||||
gap={[4, 2]}
|
||||
breakpoint={$breakpoint}
|
||||
parentWidth={$parentWidth - 17}
|
||||
{containerWidth}
|
||||
{maxRow}
|
||||
>
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
@@ -168,10 +181,12 @@
|
||||
class={classNames('h-full w-full center-center', 'top-0')}
|
||||
>
|
||||
<Component
|
||||
fullHeight={dataItem?.[$breakpoint === 'sm' ? 3 : 12]?.fullHeight}
|
||||
render={visible}
|
||||
component={dataItem.data}
|
||||
selected={Boolean($selectedComponent?.includes(dataItem.id))}
|
||||
locked={isFixed(dataItem)}
|
||||
{hidden}
|
||||
/>
|
||||
</div>
|
||||
</GridViewer>
|
||||
|
||||
@@ -246,7 +246,8 @@ export function createNewGridItem(
|
||||
const newComponent = {
|
||||
fixed: false,
|
||||
x: 0,
|
||||
y: 0
|
||||
y: 0,
|
||||
fullHeight: false
|
||||
}
|
||||
|
||||
let newData: AppComponent = JSON.parse(JSON.stringify(data))
|
||||
@@ -378,6 +379,7 @@ export function insertNewGridItem(
|
||||
const id = keepId ?? getNextGridItemId(app)
|
||||
|
||||
const data = builddata(id)
|
||||
|
||||
if (data.type == 'aggridcomponentee' && !get(enterpriseLicense)) {
|
||||
sendUserToast('AgGrid Enterprise Edition require Windmill Enterprise Edition', true)
|
||||
throw Error('AgGrid Enterprise Edition require Windmill Enterprise Edition')
|
||||
@@ -972,3 +974,29 @@ export function collectOneOfFields(fields: AppInputs, app: App) {
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export const ROW_HEIGHT = 36
|
||||
export const ROW_GAP_Y = 2
|
||||
export const ROW_GAP_X = 4
|
||||
|
||||
export function maxHeight(
|
||||
grid: GridItem[],
|
||||
windowHeight: number,
|
||||
breakpoint: EditorBreakpoint = 'lg'
|
||||
) {
|
||||
const totalRowHeight = ROW_HEIGHT + ROW_GAP_Y
|
||||
let maxRows = Math.floor((windowHeight - ROW_GAP_Y) / totalRowHeight)
|
||||
|
||||
if (!grid.length) {
|
||||
return maxRows
|
||||
}
|
||||
|
||||
const breakpointKey = breakpoint === 'sm' ? 3 : 12
|
||||
const maxRowPerGrid = grid.reduce((max, item) => {
|
||||
const y = item[breakpointKey].y
|
||||
const h = item[breakpointKey].h
|
||||
return Math.max(max, y + h)
|
||||
}, 0)
|
||||
|
||||
return Math.max(maxRowPerGrid, maxRows)
|
||||
}
|
||||
|
||||
@@ -80,6 +80,8 @@
|
||||
export let selected: boolean
|
||||
export let locked: boolean = false
|
||||
export let render: boolean
|
||||
export let hidden: boolean
|
||||
export let fullHeight: boolean
|
||||
|
||||
const { mode, app, hoverStore, connectingInput } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
@@ -115,7 +117,9 @@
|
||||
}
|
||||
}}
|
||||
on:mouseout|stopPropagation={mouseOut}
|
||||
class="h-full flex flex-col w-full component {initializing ? 'overflow-hidden h-0' : ''}"
|
||||
class="h-full flex flex-col w-full component {initializing
|
||||
? 'overflow-hidden h-0'
|
||||
: ''} {hidden && $mode === 'preview' ? 'hidden' : ''} "
|
||||
>
|
||||
{#if $mode !== 'preview'}
|
||||
<ComponentHeader
|
||||
@@ -129,9 +133,11 @@
|
||||
hover={$hoverStore === component.id}
|
||||
{component}
|
||||
{selected}
|
||||
{fullHeight}
|
||||
connecting={$connectingInput.opened}
|
||||
on:lock
|
||||
on:expand
|
||||
on:fillHeight
|
||||
{locked}
|
||||
{inlineEditorOpened}
|
||||
hasInlineEditor={component.type === 'textcomponent' &&
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import TableActions from './TableActions.svelte'
|
||||
import StaticInputEditor from './inputEditor/StaticInputEditor.svelte'
|
||||
import ConnectedInputEditor from './inputEditor/ConnectedInputEditor.svelte'
|
||||
import { classNames, getModifierKey } from '$lib/utils'
|
||||
import { classNames, getModifierKey, isMac } from '$lib/utils'
|
||||
import { buildExtraLib } from '../../utils'
|
||||
import Recompute from './Recompute.svelte'
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
@@ -38,6 +38,7 @@
|
||||
import MenuItems from './MenuItems.svelte'
|
||||
import DecisionTreeGraphEditor from './DecisionTreeGraphEditor.svelte'
|
||||
import GridAgChartsLicenseKe from './GridAgChartsLicenseKe.svelte'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
|
||||
export let componentSettings: { item: GridItem; parent: string | undefined } | undefined =
|
||||
undefined
|
||||
@@ -167,10 +168,6 @@
|
||||
componentSettings.item.data.componentInput = appInput
|
||||
}
|
||||
}
|
||||
|
||||
function isMac() {
|
||||
return navigator.platform.toUpperCase().indexOf('MAC') >= 0
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={keydown} />
|
||||
@@ -442,6 +439,30 @@
|
||||
Show
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{#if componentSettings?.item?.[12]?.fullHeight !== undefined}
|
||||
<Toggle
|
||||
bind:checked={componentSettings.item[12].fullHeight}
|
||||
size="xs"
|
||||
options={{
|
||||
right: 'Desktop full height',
|
||||
rightTooltip:
|
||||
'When enabled, the component will take the full height of the parent container.'
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
{#if componentSettings?.item?.[3]?.fullHeight !== undefined}
|
||||
<Toggle
|
||||
bind:checked={componentSettings.item[3].fullHeight}
|
||||
size="xs"
|
||||
options={{
|
||||
right: 'Mobile full height',
|
||||
rightTooltip:
|
||||
'When enabled, the component will take the full height of the parent container.'
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<AlignmentEditor bind:component={componentSettings.item.data} />
|
||||
{#if viewCssOptions}
|
||||
<div transition:slide|local class="w-full">
|
||||
|
||||
@@ -5,22 +5,21 @@
|
||||
import { getColumn, throttle } from './utils/other'
|
||||
import MoveResize from './MoveResize.svelte'
|
||||
import type { FilledItem } from './types'
|
||||
import { sortGridItemsPosition } from '../editor/appUtils'
|
||||
import { ROW_GAP_X, ROW_GAP_Y, ROW_HEIGHT, sortGridItemsPosition } from '../editor/appUtils'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
type T = $$Generic
|
||||
|
||||
export let items: FilledItem<T>[]
|
||||
export let rowHeight: number
|
||||
export let rowHeight: number = ROW_HEIGHT
|
||||
export let cols: [number, number][]
|
||||
export let gap = [10, 10]
|
||||
export let gap = [ROW_GAP_X, ROW_GAP_Y]
|
||||
export let throttleUpdate = 100
|
||||
export let throttleResize = 100
|
||||
export let selectedIds: string[] | undefined
|
||||
export let allIdsInPath: string[] | undefined
|
||||
export let containerWidth: number | undefined = undefined
|
||||
|
||||
export let scroller: HTMLElement | undefined = undefined
|
||||
export let sensor = 20
|
||||
|
||||
@@ -136,13 +135,25 @@
|
||||
|
||||
const throttleMatrix = throttle(updateMatrix, throttleResize)
|
||||
|
||||
//let hiddenComponents = writable({})
|
||||
|
||||
const handleRepaint = ({ detail }) => {
|
||||
if (!detail.isPointerUp) {
|
||||
throttleMatrix({ detail })
|
||||
} else {
|
||||
updateMatrix({ detail })
|
||||
}
|
||||
|
||||
/**
|
||||
setTimeout(() => {
|
||||
$hiddenComponents = {
|
||||
...$hiddenComponents,
|
||||
[detail.id]: updateComponentVisibility(detail, sortedItems, getComputedCols)
|
||||
}
|
||||
}, 0)
|
||||
*/
|
||||
}
|
||||
|
||||
let moveResizes: Record<string, MoveResize> = {}
|
||||
let shadows: Record<string, { x: number; y: number; w: number; h: number } | undefined> = {}
|
||||
|
||||
@@ -193,7 +204,7 @@
|
||||
nativeContainer={container}
|
||||
>
|
||||
{#if item[getComputedCols]}
|
||||
<slot dataItem={item} />
|
||||
<slot dataItem={item} hidden={false} />
|
||||
{/if}
|
||||
</MoveResize>
|
||||
{/if}
|
||||
|
||||
@@ -330,7 +330,6 @@
|
||||
shadow.w = Math.round(Math.max((newSize.width + gapX * 2) / xPerPx, 1))
|
||||
shadow.h = Math.round(Math.max((newSize.height + gapY * 2) / yPerPx, 1))
|
||||
}
|
||||
|
||||
repaint(false, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ export interface Positon {
|
||||
|
||||
interface ItemLayout extends Size, Positon {
|
||||
fixed: boolean
|
||||
fullHeight: boolean
|
||||
}
|
||||
|
||||
export type FilledItem<T> = { [width: number]: Required<ItemLayout>; data: T; id: string }
|
||||
|
||||
@@ -6,6 +6,7 @@ function makeItem(item) {
|
||||
const { min = { w: 1, h: 1 }, max } = item
|
||||
return {
|
||||
fixed: false,
|
||||
fullHeight: false,
|
||||
min: {
|
||||
w: Math.max(1, min.w),
|
||||
h: Math.max(1, min.h)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import type { FilledItem } from '../types'
|
||||
|
||||
export function segmentsOverlap(x1: number, length1: number, x2: number, length2: number): boolean {
|
||||
const end1: number = x1 + length1
|
||||
const end2: number = x2 + length2
|
||||
|
||||
return Math.max(x1, x2) < Math.min(end1, end2)
|
||||
}
|
||||
|
||||
export function updateComponentVisibility<T>(
|
||||
detail: FilledItem<T>,
|
||||
items: FilledItem<T>[],
|
||||
getComputedCols: number
|
||||
): boolean {
|
||||
const c = items.find((x) => x.id === detail.id)
|
||||
|
||||
if (!c) return false
|
||||
|
||||
return items.some((item) => {
|
||||
if (item?.data?.['fullHeight'] !== true || item.id === detail.id) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (item[getComputedCols]) {
|
||||
let { x, y, w } = item[getComputedCols]
|
||||
let { x: x1, y: y1, w: w1 } = c[getComputedCols]
|
||||
|
||||
return y < y1 && segmentsOverlap(x, w, x1, w1)
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import type {
|
||||
HorizontalAlignment,
|
||||
VerticalAlignment
|
||||
} from './types'
|
||||
import { gridColumns } from './gridUtils'
|
||||
|
||||
export const BG_PREFIX = 'bg_'
|
||||
|
||||
@@ -26,7 +27,16 @@ export function migrateApp(app: App) {
|
||||
x.doNotRecomputeOnInputChanged = undefined
|
||||
}
|
||||
})
|
||||
|
||||
allItems(app.grid, app.subgrids).forEach((x) => {
|
||||
gridColumns.forEach((column: number) => {
|
||||
if (x?.[column]?.fullHeight === undefined) {
|
||||
x[column].fullHeight = false
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function allItems(
|
||||
grid: GridItem[],
|
||||
subgrids: Record<string, GridItem[]> | undefined
|
||||
|
||||
@@ -7,14 +7,16 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 2,
|
||||
h: 8
|
||||
h: 8,
|
||||
fullHeight: false
|
||||
},
|
||||
'12': {
|
||||
fixed: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 12,
|
||||
h: 21
|
||||
h: 21,
|
||||
fullHeight: false
|
||||
},
|
||||
data: {
|
||||
type: 'verticalsplitpanescomponent',
|
||||
@@ -40,14 +42,16 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
x: 0,
|
||||
y: 1,
|
||||
w: 3,
|
||||
h: 8
|
||||
h: 8,
|
||||
fullHeight: false
|
||||
},
|
||||
'12': {
|
||||
fixed: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 12,
|
||||
h: 19
|
||||
h: 19,
|
||||
fullHeight: false
|
||||
},
|
||||
data: {
|
||||
type: 'schemaformcomponent',
|
||||
@@ -77,14 +81,16 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 1,
|
||||
h: 1
|
||||
h: 1,
|
||||
fullHeight: false
|
||||
},
|
||||
'12': {
|
||||
fixed: false,
|
||||
x: 0,
|
||||
y: 19,
|
||||
w: 12,
|
||||
h: 1
|
||||
h: 1,
|
||||
fullHeight: false
|
||||
},
|
||||
data: {
|
||||
type: 'buttoncomponent',
|
||||
@@ -262,14 +268,16 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 2,
|
||||
h: 8
|
||||
h: 8,
|
||||
fullHeight: false
|
||||
},
|
||||
'12': {
|
||||
fixed: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 12,
|
||||
h: 20
|
||||
h: 20,
|
||||
fullHeight: false
|
||||
},
|
||||
data: {
|
||||
type: 'tabscomponent',
|
||||
@@ -306,14 +314,16 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 2,
|
||||
h: 8
|
||||
h: 8,
|
||||
fullHeight: false
|
||||
},
|
||||
'12': {
|
||||
fixed: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 12,
|
||||
h: 18
|
||||
h: 18,
|
||||
fullHeight: false
|
||||
},
|
||||
data: {
|
||||
type: 'displaycomponent',
|
||||
@@ -339,14 +349,16 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 2,
|
||||
h: 8
|
||||
h: 8,
|
||||
fullHeight: false
|
||||
},
|
||||
'12': {
|
||||
fixed: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 12,
|
||||
h: 18
|
||||
h: 18,
|
||||
fullHeight: false
|
||||
},
|
||||
data: {
|
||||
type: 'jobidlogcomponent',
|
||||
@@ -410,14 +422,16 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 2,
|
||||
h: 8
|
||||
h: 8,
|
||||
fullHeight: false
|
||||
},
|
||||
'12': {
|
||||
fixed: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 12,
|
||||
h: 21
|
||||
h: 21,
|
||||
fullHeight: false
|
||||
},
|
||||
data: {
|
||||
type: 'verticalsplitpanescomponent',
|
||||
@@ -443,14 +457,16 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
x: 0,
|
||||
y: 1,
|
||||
w: 3,
|
||||
h: 8
|
||||
h: 8,
|
||||
fullHeight: false
|
||||
},
|
||||
'12': {
|
||||
fixed: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 12,
|
||||
h: 19
|
||||
h: 19,
|
||||
fullHeight: false
|
||||
},
|
||||
data: {
|
||||
type: 'schemaformcomponent',
|
||||
@@ -480,14 +496,16 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 1,
|
||||
h: 1
|
||||
h: 1,
|
||||
fullHeight: false
|
||||
},
|
||||
'12': {
|
||||
fixed: false,
|
||||
x: 0,
|
||||
y: 19,
|
||||
w: 12,
|
||||
h: 1
|
||||
h: 1,
|
||||
fullHeight: false
|
||||
},
|
||||
data: {
|
||||
type: 'buttoncomponent',
|
||||
@@ -665,14 +683,16 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 2,
|
||||
h: 8
|
||||
h: 8,
|
||||
fullHeight: false
|
||||
},
|
||||
'12': {
|
||||
fixed: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 12,
|
||||
h: 20
|
||||
h: 20,
|
||||
fullHeight: false
|
||||
},
|
||||
data: {
|
||||
type: 'tabscomponent',
|
||||
@@ -709,14 +729,16 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 2,
|
||||
h: 8
|
||||
h: 8,
|
||||
fullHeight: false
|
||||
},
|
||||
'12': {
|
||||
fixed: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 12,
|
||||
h: 18
|
||||
h: 18,
|
||||
fullHeight: false
|
||||
},
|
||||
data: {
|
||||
type: 'jobidflowstatuscomponent',
|
||||
@@ -743,14 +765,16 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 2,
|
||||
h: 8
|
||||
h: 8,
|
||||
fullHeight: false
|
||||
},
|
||||
'12': {
|
||||
fixed: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 12,
|
||||
h: 18
|
||||
h: 18,
|
||||
fullHeight: false
|
||||
},
|
||||
data: {
|
||||
type: 'jobidlogcomponent',
|
||||
|
||||
Reference in New Issue
Block a user