mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-07 08:02:40 +00:00
fix: improve style panel reactivity and CSS defaults (#7935)
This commit is contained in:
@@ -50,7 +50,7 @@ type GridItemLocation =
|
||||
subgridItemIndex: number
|
||||
subgridKey: string
|
||||
}
|
||||
interface GridItemWithLocation {
|
||||
export interface GridItemWithLocation {
|
||||
location: GridItemLocation
|
||||
item: GridItem
|
||||
parent: string | undefined
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
let {
|
||||
name,
|
||||
value = $bindable({}),
|
||||
value = $bindable(),
|
||||
forceStyle = false,
|
||||
forceClass = false,
|
||||
quickStyleProperties = undefined,
|
||||
@@ -61,6 +61,7 @@
|
||||
})
|
||||
|
||||
function toggleQuickMenu() {
|
||||
if (!value) return
|
||||
try {
|
||||
if (!value.style) {
|
||||
value.style = ''
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { Tab, TabContent } from '$lib/components/common'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { getContext } from 'svelte'
|
||||
import { getContext, untrack } from 'svelte'
|
||||
import type { AppViewerContext, ComponentCssProperty } from '../../types'
|
||||
import { ccomponents, components, type AppComponent } from '../component'
|
||||
import { ccomponents, components } from '../component'
|
||||
import CssProperty from '../componentsPanel/CssProperty.svelte'
|
||||
import { quickStyleProperties } from '../componentsPanel/quickStyleProperties'
|
||||
import Tabs from '$lib/components/common/tabs/Tabs.svelte'
|
||||
@@ -16,25 +16,59 @@
|
||||
import CssMigrationModal from './CSSMigrationModal.svelte'
|
||||
import CssPropertyWrapper from './CssPropertyWrapper.svelte'
|
||||
import { onMount } from 'svelte'
|
||||
import { findComponentSettings } from '../appUtils'
|
||||
import { findGridItemWithLocation, type GridItemWithLocation } from '../appUtils'
|
||||
|
||||
const { app, cssEditorOpen, selectedComponent } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let component: AppComponent | undefined
|
||||
$: {
|
||||
const newComponent = findComponentSettings($app, $selectedComponent?.[0])?.item?.data
|
||||
if (component != newComponent) {
|
||||
component = newComponent
|
||||
let tab: 'local' | 'global' = $state('local')
|
||||
let overrideGlobalCSS: (() => void) | undefined = $state(undefined)
|
||||
let overrideLocalCSS: (() => void) | undefined = $state(undefined)
|
||||
|
||||
let componentWithLocation: GridItemWithLocation | undefined = $derived(
|
||||
findGridItemWithLocation($app, $selectedComponent?.[0] ?? '')
|
||||
)
|
||||
let component = $derived(componentWithLocation?.item.data)
|
||||
let type = $derived(component?.type)
|
||||
|
||||
function updateComponentData(
|
||||
loc: GridItemWithLocation,
|
||||
updater: (data: typeof loc.item.data) => typeof loc.item.data
|
||||
) {
|
||||
const { location } = loc
|
||||
if (location.type === 'subgrid') {
|
||||
const item = $app.subgrids?.[location.subgridKey]?.[location.subgridItemIndex]
|
||||
if (item) {
|
||||
item.data = updater(item.data)
|
||||
}
|
||||
} else {
|
||||
const item = $app.grid[location.gridItemIndex]
|
||||
if (item) {
|
||||
item.data = updater(item.data)
|
||||
}
|
||||
}
|
||||
app.set($app)
|
||||
}
|
||||
|
||||
let tab: 'local' | 'global' = 'local'
|
||||
let overrideGlobalCSS: (() => void) | undefined = undefined
|
||||
let overrideLocalCSS: (() => void) | undefined = undefined
|
||||
$: type = component?.type
|
||||
let migrationModal: CssMigrationModal | undefined = undefined
|
||||
$effect.pre(() => {
|
||||
if (
|
||||
(componentWithLocation && component?.customCss === undefined) ||
|
||||
(Object.keys(component?.customCss ?? {}).length === 0 &&
|
||||
Object.keys(ccomponents[component?.type ?? '']?.customCss ?? {}).length > 0)
|
||||
) {
|
||||
untrack(() => {
|
||||
if (componentWithLocation) {
|
||||
updateComponentData(componentWithLocation, (data) => ({
|
||||
...data,
|
||||
customCss: structuredClone(ccomponents[component?.type ?? '']?.customCss ?? {})
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
$: customCssByComponentType =
|
||||
let migrationModal: CssMigrationModal | undefined = $state(undefined)
|
||||
|
||||
let customCssByComponentType = $derived(
|
||||
component?.type && $app.css
|
||||
? Object.entries($app.css[component.type] || {}).map(([id, v]) => ({
|
||||
id,
|
||||
@@ -42,6 +76,7 @@
|
||||
forceClass: v?.['class'] != undefined
|
||||
}))
|
||||
: undefined
|
||||
)
|
||||
|
||||
function copyLocalToGlobal(name: string, value: ComponentCssProperty | undefined) {
|
||||
if (!value) {
|
||||
@@ -53,7 +88,7 @@
|
||||
|
||||
if (hasStyleValue($app.css?.[type]?.[name])) {
|
||||
overrideGlobalCSS = () => {
|
||||
$app.css![type]![name] = JSON.parse(JSON.stringify(value))
|
||||
$app.css![type]![name] = structuredClone(value)
|
||||
app.set($app)
|
||||
}
|
||||
} else {
|
||||
@@ -61,7 +96,7 @@
|
||||
initGlobalCss()
|
||||
}
|
||||
|
||||
$app.css![type]![name] = JSON.parse(JSON.stringify(value))
|
||||
$app.css![type]![name] = structuredClone(value)
|
||||
app.set($app)
|
||||
sendUserToast('Global CSS copied')
|
||||
}
|
||||
@@ -74,12 +109,10 @@
|
||||
} else {
|
||||
if (hasStyleValue(value)) {
|
||||
overrideLocalCSS = () => {
|
||||
component!.customCss![id] = JSON.parse(JSON.stringify(value))
|
||||
app.set($app)
|
||||
updateCssProperty(id, structuredClone(value))
|
||||
}
|
||||
} else {
|
||||
component!.customCss![id] = JSON.parse(JSON.stringify(value))
|
||||
app.set($app)
|
||||
updateCssProperty(id, structuredClone(value))
|
||||
sendUserToast('Local CSS copied')
|
||||
}
|
||||
}
|
||||
@@ -101,11 +134,22 @@
|
||||
components[component.type] &&
|
||||
$app.css[component.type] === undefined
|
||||
) {
|
||||
$app.css[component.type] = JSON.parse(JSON.stringify(components[component.type].customCss))
|
||||
$app.css[component.type] = structuredClone(components[component.type].customCss)
|
||||
app.set($app)
|
||||
}
|
||||
}
|
||||
|
||||
function updateCssProperty(name: string, cssValue: ComponentCssProperty | undefined) {
|
||||
if (!componentWithLocation || !cssValue) return
|
||||
updateComponentData(componentWithLocation, (data) => ({
|
||||
...data,
|
||||
customCss: {
|
||||
...(data?.customCss ?? {}),
|
||||
[name]: cssValue
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
function getSelector(key: string) {
|
||||
return customisationByComponent
|
||||
.find((c) => c.components.includes(component?.type ?? ''))
|
||||
@@ -197,8 +241,10 @@
|
||||
{name}
|
||||
wmClass={getSelector(name)}
|
||||
componentType={component.type}
|
||||
bind:value={component.customCss[name]}
|
||||
on:change={() => app.set($app)}
|
||||
value={component.customCss[name]}
|
||||
on:change={(e) => {
|
||||
updateCssProperty(name, e.detail)
|
||||
}}
|
||||
shouldDisplayRight={hasStyleValue(component.customCss[name])}
|
||||
on:right={() => {
|
||||
copyLocalToGlobal(name, component?.customCss?.[name])
|
||||
@@ -210,6 +256,8 @@
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="text-sm text-secondary mx-2">No local CSS to display</div>
|
||||
{/if}
|
||||
</TabContent>
|
||||
<TabContent value="global">
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ccomponents } from '../apps/editor/component'
|
||||
|
||||
export function createAppFromScript(path: string, schema: Record<string, any> | undefined) {
|
||||
return {
|
||||
grid: [
|
||||
@@ -22,7 +24,7 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
type: 'verticalsplitpanescomponent',
|
||||
configuration: {},
|
||||
panes: [50, 50],
|
||||
customCss: {},
|
||||
customCss: structuredClone(ccomponents['verticalsplitpanescomponent'].customCss),
|
||||
numberOfSubgrids: 2,
|
||||
id: 'a'
|
||||
},
|
||||
@@ -103,7 +105,7 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
fieldType: 'schema',
|
||||
value: schema
|
||||
},
|
||||
customCss: {},
|
||||
customCss: structuredClone(ccomponents['schemaformcomponent'].customCss),
|
||||
id: 'c'
|
||||
},
|
||||
id: 'c'
|
||||
@@ -291,7 +293,7 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
autoRefresh: true,
|
||||
recomputeOnInputChanged: true
|
||||
},
|
||||
customCss: {},
|
||||
customCss: structuredClone(ccomponents['buttoncomponent'].customCss),
|
||||
recomputeIds: [],
|
||||
horizontalAlignment: 'right',
|
||||
verticalAlignment: 'center',
|
||||
@@ -327,7 +329,7 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
}
|
||||
},
|
||||
tabs: ['Result', 'Logs'],
|
||||
customCss: {},
|
||||
customCss: structuredClone(ccomponents['tabscomponent'].customCss),
|
||||
numberOfSubgrids: 2,
|
||||
id: 'b',
|
||||
disabledTabs: [
|
||||
@@ -375,7 +377,7 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
path: 'result'
|
||||
}
|
||||
},
|
||||
customCss: {},
|
||||
customCss: structuredClone(ccomponents['displaycomponent'].customCss),
|
||||
id: 'e'
|
||||
},
|
||||
id: 'e'
|
||||
@@ -410,7 +412,7 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
}
|
||||
}
|
||||
},
|
||||
customCss: {},
|
||||
customCss: structuredClone(ccomponents['jobidlogcomponent'].customCss),
|
||||
id: 'f'
|
||||
},
|
||||
id: 'f'
|
||||
@@ -589,7 +591,7 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
type: 'verticalsplitpanescomponent',
|
||||
configuration: {},
|
||||
panes: [50, 50],
|
||||
customCss: {},
|
||||
customCss: structuredClone(ccomponents['verticalsplitpanescomponent'].customCss),
|
||||
numberOfSubgrids: 2,
|
||||
id: 'a'
|
||||
},
|
||||
@@ -669,7 +671,7 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
fieldType: 'schema',
|
||||
value: schema
|
||||
},
|
||||
customCss: {},
|
||||
customCss: structuredClone(ccomponents['schemaformcomponent'].customCss),
|
||||
id: 'c'
|
||||
},
|
||||
id: 'c'
|
||||
@@ -857,7 +859,7 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
autoRefresh: false,
|
||||
recomputeOnInputChanged: false
|
||||
},
|
||||
customCss: {},
|
||||
customCss: structuredClone(ccomponents['buttoncomponent'].customCss),
|
||||
recomputeIds: [],
|
||||
horizontalAlignment: 'right',
|
||||
verticalAlignment: 'center',
|
||||
@@ -893,7 +895,7 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
}
|
||||
},
|
||||
tabs: ['Result', 'Logs'],
|
||||
customCss: {},
|
||||
customCss: structuredClone(ccomponents['tabscomponent'].customCss),
|
||||
numberOfSubgrids: 2,
|
||||
id: 'b',
|
||||
disabledTabs: [
|
||||
@@ -942,7 +944,7 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
}
|
||||
}
|
||||
},
|
||||
customCss: {},
|
||||
customCss: structuredClone(ccomponents['jobidflowstatuscomponent'].customCss),
|
||||
id: 'e'
|
||||
},
|
||||
id: 'e'
|
||||
@@ -977,7 +979,7 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
}
|
||||
}
|
||||
},
|
||||
customCss: {},
|
||||
customCss: structuredClone(ccomponents['jobidlogcomponent'].customCss),
|
||||
id: 'f'
|
||||
},
|
||||
id: 'f'
|
||||
|
||||
Reference in New Issue
Block a user