mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-19 08:01:25 +00:00
feat(frontend): add AppDrawer controls (#2339)
* feat(frontend): add AppDrawer controls * feat(frontend): add AppDrawer controls * Update utils.ts * fix app drawer cc * fix app drawer cc --------- Co-authored-by: Ruben Fiszel <ruben@windmill.dev> Co-authored-by: Ruben Fiszel <ruben@rubenfiszel.com>
This commit is contained in:
@@ -29,7 +29,8 @@
|
||||
|
||||
export const staticOutputs: string[] = ['loading', 'result', 'jobId']
|
||||
|
||||
const { app, worldStore, stateId } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { app, worldStore, stateId, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const outputs = initOutput($worldStore, id, {
|
||||
result: undefined,
|
||||
@@ -42,6 +43,12 @@
|
||||
configuration
|
||||
)
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: string) {
|
||||
wrapper?.setArgs(nvalue)
|
||||
}
|
||||
}
|
||||
|
||||
let runnableComponent: RunnableComponent
|
||||
let loading = false
|
||||
|
||||
@@ -50,6 +57,8 @@
|
||||
(componentInput?.type != 'runnable' || Object.keys(componentInput?.fields ?? {}).length == 0)
|
||||
|
||||
let css = initCss($app.css?.formcomponent, customCss)
|
||||
|
||||
let wrapper: RunnableWrapper
|
||||
</script>
|
||||
|
||||
{#each Object.keys(components['formcomponent'].initialData.configuration) as key (key)}
|
||||
@@ -74,6 +83,7 @@
|
||||
<RunnableWrapper
|
||||
{recomputeIds}
|
||||
{render}
|
||||
bind:this={wrapper}
|
||||
bind:runnableComponent
|
||||
bind:loading
|
||||
{componentInput}
|
||||
|
||||
@@ -79,6 +79,10 @@
|
||||
|
||||
$runnableComponents = $runnableComponents
|
||||
|
||||
export function setArgs(value: any) {
|
||||
args = value
|
||||
}
|
||||
|
||||
let args: Record<string, any> | undefined = undefined
|
||||
let runnableInputValues: Record<string, any> = {}
|
||||
let executeTimeout: NodeJS.Timeout | undefined = undefined
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
| 'errorOverlay'
|
||||
| 'openModal'
|
||||
| 'closeModal'
|
||||
| 'open'
|
||||
| 'close'
|
||||
configuration: {
|
||||
gotoUrl: { url: string | undefined; newTab: boolean | undefined }
|
||||
setTab: {
|
||||
@@ -40,6 +42,12 @@
|
||||
closeModal?: {
|
||||
modalId: string | undefined
|
||||
}
|
||||
open?: {
|
||||
id: string | undefined
|
||||
}
|
||||
close?: {
|
||||
id: string | undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
| undefined
|
||||
@@ -69,6 +77,10 @@
|
||||
export let errorHandledByComponent: boolean = false
|
||||
export let hasChildrens: boolean = false
|
||||
|
||||
export function setArgs(value: any) {
|
||||
runnableComponent?.setArgs(value)
|
||||
}
|
||||
|
||||
const { staticExporter, noBackend, componentControl, runnableComponents } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
@@ -168,6 +180,22 @@
|
||||
$componentControl[modalId].closeModal?.()
|
||||
break
|
||||
}
|
||||
case 'open': {
|
||||
const id = sideEffect?.configuration?.open?.id
|
||||
|
||||
if (!id) return
|
||||
|
||||
$componentControl[id].open?.()
|
||||
break
|
||||
}
|
||||
case 'close': {
|
||||
const id = sideEffect?.configuration?.close?.id
|
||||
|
||||
if (!id) return
|
||||
|
||||
$componentControl[id].close?.()
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export function computeGlobalContext(world: World | undefined, extraContext: any
|
||||
|
||||
function create_context_function_template(eval_string: string, context, noReturn: boolean) {
|
||||
return `
|
||||
return async function (context, state, goto, setTab, recompute, getAgGrid, setValue, setSelectedIndex, openModal, closeModal) {
|
||||
return async function (context, state, goto, setTab, recompute, getAgGrid, setValue, setSelectedIndex, openModal, closeModal, open, close) {
|
||||
"use strict";
|
||||
${
|
||||
Object.keys(context).length > 0
|
||||
@@ -50,7 +50,9 @@ function make_context_evaluator(
|
||||
setValue,
|
||||
setSelectedIndex,
|
||||
openModal,
|
||||
closeModal
|
||||
closeModal,
|
||||
open,
|
||||
close
|
||||
) => Promise<any> {
|
||||
let template = create_context_function_template(eval_string, context, noReturn)
|
||||
let functor = Function(template)
|
||||
@@ -104,6 +106,8 @@ export async function eval_like(
|
||||
setSelectedIndex?: (index: number) => void
|
||||
openModal?: () => void
|
||||
closeModal?: () => void
|
||||
open?: () => void
|
||||
close?: () => void
|
||||
}
|
||||
>,
|
||||
worldStore: World | undefined,
|
||||
@@ -160,6 +164,12 @@ export async function eval_like(
|
||||
},
|
||||
(id) => {
|
||||
controlComponents[id]?.closeModal?.()
|
||||
},
|
||||
(id) => {
|
||||
controlComponents[id]?.open?.()
|
||||
},
|
||||
(id) => {
|
||||
controlComponents[id]?.close?.()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,8 +21,15 @@
|
||||
export let noWFull = false
|
||||
export let render: boolean
|
||||
|
||||
const { app, focusedGrid, selectedComponent, worldStore, connectingInput, mode } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
const {
|
||||
app,
|
||||
focusedGrid,
|
||||
selectedComponent,
|
||||
worldStore,
|
||||
connectingInput,
|
||||
mode,
|
||||
componentControl
|
||||
} = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const resolvedConfig = initConfig(
|
||||
components['drawercomponent'].initialData.configuration,
|
||||
@@ -32,6 +39,15 @@
|
||||
|
||||
let appDrawer: Drawer
|
||||
|
||||
$componentControl[id] = {
|
||||
open: () => {
|
||||
appDrawer?.openDrawer()
|
||||
},
|
||||
close: () => {
|
||||
appDrawer?.closeDrawer()
|
||||
}
|
||||
}
|
||||
|
||||
let css = initCss($app.css?.drawercomponent, customCss)
|
||||
</script>
|
||||
|
||||
|
||||
@@ -64,6 +64,12 @@
|
||||
},
|
||||
closeModal: () => {
|
||||
open = false
|
||||
},
|
||||
open: () => {
|
||||
open = true
|
||||
},
|
||||
close: () => {
|
||||
open = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -453,7 +453,7 @@
|
||||
)}
|
||||
style={$appStore.css?.['app']?.['viewer']?.style}
|
||||
>
|
||||
<div class="absolute bottom-4 left-4 z-50">
|
||||
<div class="absolute bottom-2 left-4 z-50">
|
||||
<div class="flex flex-row gap-2 text-xs items-center">
|
||||
<Button
|
||||
color="light"
|
||||
@@ -466,7 +466,7 @@
|
||||
>
|
||||
<Minus size={14} />
|
||||
</Button>
|
||||
{$scale}
|
||||
{$scale}%
|
||||
<Button
|
||||
color="light"
|
||||
variant="border"
|
||||
|
||||
@@ -297,8 +297,8 @@ const labels = {
|
||||
setTab: 'Set the tab of a tabs component',
|
||||
sendToast: 'Display a toast notification',
|
||||
sendErrorToast: 'Display an error toast notification',
|
||||
openModal: 'Open a modal',
|
||||
closeModal: 'Close a modal'
|
||||
open: 'Open a modal or a drawer',
|
||||
close: 'Close a modal or a drawer'
|
||||
}
|
||||
|
||||
const onSuccessClick = {
|
||||
@@ -356,6 +356,22 @@ const onSuccessClick = {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
open: {
|
||||
id: {
|
||||
tooltip: 'The id of the modal or the drawer to open',
|
||||
fieldType: 'text',
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
close: {
|
||||
id: {
|
||||
tooltip: 'The id of the modal or the drawer to close',
|
||||
fieldType: 'text',
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
} as const
|
||||
@@ -406,18 +422,18 @@ const onErrorClick = {
|
||||
value: true
|
||||
}
|
||||
},
|
||||
openModal: {
|
||||
modalId: {
|
||||
tooltip: 'The id of the modal to open',
|
||||
open: {
|
||||
id: {
|
||||
tooltip: 'The id of the modal or the drawer to open',
|
||||
fieldType: 'text',
|
||||
type: 'static',
|
||||
value: '',
|
||||
noVariablePicker: true
|
||||
}
|
||||
},
|
||||
closeModal: {
|
||||
modalId: {
|
||||
tooltip: 'The id of the modal to close',
|
||||
close: {
|
||||
id: {
|
||||
tooltip: 'The id of the modal or the drawer to close',
|
||||
fieldType: 'text',
|
||||
type: 'static',
|
||||
value: '',
|
||||
@@ -457,8 +473,7 @@ const paginationOneOf = {
|
||||
}
|
||||
} as const
|
||||
|
||||
const documentationBaseUrl =
|
||||
'https://www.windmill.dev/docs/apps/app_configuration_settings'
|
||||
const documentationBaseUrl = 'https://www.windmill.dev/docs/apps/app_configuration_settings'
|
||||
|
||||
export const components = {
|
||||
displaycomponent: {
|
||||
|
||||
@@ -14,20 +14,6 @@ const setTab = {
|
||||
documentation: 'https://www.windmill.dev/docs/apps/app-runnable-panel#settab'
|
||||
}
|
||||
|
||||
const openModal = {
|
||||
title: 'openModal',
|
||||
description: 'Use the openModal function to open a modal.',
|
||||
example: 'openModal(id: string)',
|
||||
documentation: 'https://www.windmill.dev/docs/apps/app-runnable-panel#openmodal'
|
||||
}
|
||||
|
||||
const closeModal = {
|
||||
title: 'closeModal',
|
||||
description: 'Use the closeModal function to close a modal.',
|
||||
example: 'closeModal(id: string)',
|
||||
documentation: 'https://www.windmill.dev/docs/apps/app-runnable-panel#closemodal'
|
||||
}
|
||||
|
||||
const recompute = {
|
||||
title: 'recompute',
|
||||
description: 'Use the recompute function to recompute the value of a component.',
|
||||
@@ -57,6 +43,20 @@ const setSelectedIndex = {
|
||||
documentation: 'https://www.windmill.dev/docs/apps/app-runnable-panel#setselectedindex'
|
||||
}
|
||||
|
||||
const open = {
|
||||
title: 'open',
|
||||
description: 'Use the open function to open a modal or a drawer.',
|
||||
example: 'open(id: string)',
|
||||
documentation: 'https://www.windmill.dev/docs/apps/app-runnable-panel#open'
|
||||
}
|
||||
|
||||
const close = {
|
||||
title: 'close',
|
||||
description: 'Use the close function to close a modal or a drawer.',
|
||||
example: 'close(id: string)',
|
||||
documentation: 'https://www.windmill.dev/docs/apps/app-runnable-panel#close'
|
||||
}
|
||||
|
||||
export function getComponentControl(type: keyof typeof components): Array<ComponentFunction> {
|
||||
switch (type) {
|
||||
case 'tabscomponent':
|
||||
@@ -70,7 +70,9 @@ export function getComponentControl(type: keyof typeof components): Array<Compon
|
||||
case 'steppercomponent':
|
||||
return [setTab]
|
||||
case 'modalcomponent':
|
||||
return [openModal, closeModal]
|
||||
return [open, close]
|
||||
case 'drawercomponent':
|
||||
return [open, close]
|
||||
case 'aggridcomponent':
|
||||
return [getAgGrid, setSelectedIndex]
|
||||
case 'displaycomponent':
|
||||
|
||||
@@ -234,6 +234,8 @@ export type AppViewerContext = {
|
||||
setSelectedIndex?: (index: number) => void
|
||||
openModal?: () => void
|
||||
closeModal?: () => void
|
||||
open?: () => void
|
||||
close?: () => void
|
||||
}
|
||||
>
|
||||
>
|
||||
@@ -249,7 +251,7 @@ export type AppEditorContext = {
|
||||
pickVariableCallback: Writable<((path: string) => void) | undefined>
|
||||
selectedComponentInEditor: Writable<string | undefined>
|
||||
movingcomponents: Writable<string[] | undefined>
|
||||
jobsDrawerOpen: Writable<boolean>,
|
||||
jobsDrawerOpen: Writable<boolean>
|
||||
scale: Writable<number>
|
||||
}
|
||||
|
||||
|
||||
@@ -172,20 +172,65 @@ export function buildExtraLib(
|
||||
return `${cs}
|
||||
${
|
||||
goto
|
||||
? `declare async function goto(path: string, newTab?: boolean): Promise<void>;
|
||||
? `
|
||||
/** open a window or tab
|
||||
* @param path path/url to go to
|
||||
* @param open in a tab?
|
||||
*/
|
||||
declare async function goto(path: string, newTab?: boolean): Promise<void>;
|
||||
|
||||
/** set tab
|
||||
* @param id component's id
|
||||
* @param index index of the tab to set
|
||||
*/
|
||||
declare function setTab(id: string, index: string): void;
|
||||
|
||||
/** recompute a component's runnable or background runnable
|
||||
* @param id component's id
|
||||
*/
|
||||
declare function recompute(id: string): void;
|
||||
|
||||
/** get the ag grid api from an AgGridTable
|
||||
* @param id component's id
|
||||
*/
|
||||
declare function getAgGrid(id: string): {api: any, columnApi: any} | undefined;
|
||||
|
||||
|
||||
/** set value of a component
|
||||
* @param id component's id
|
||||
* @param value value to set
|
||||
*/
|
||||
declare function setValue(id: string, value: any): void;
|
||||
|
||||
/** set selected index of a table
|
||||
* @param id component's id
|
||||
* @param index index to set
|
||||
*/
|
||||
declare function setSelectedIndex(id: string, index: number): void;
|
||||
declare function openModal(id: string): void;
|
||||
declare function closeModal(id: string): void;
|
||||
|
||||
/** close a drawer or modal
|
||||
* @param id component's id
|
||||
*/
|
||||
declare function open(id: string): void;
|
||||
|
||||
/** close a drawer or modal
|
||||
* @param id component's id
|
||||
*/
|
||||
declare function close(id: string): void;
|
||||
`
|
||||
: ''
|
||||
}
|
||||
|
||||
/** The current's app state */
|
||||
declare const state: ${JSON.stringify(state)};
|
||||
|
||||
/** The iterator within the context of a list */
|
||||
declare const iter: {index: number, value: any};
|
||||
|
||||
/** The row within the context of a table */
|
||||
declare const row: Record<string, any>;
|
||||
|
||||
/** The group fields within the context of a container's group */
|
||||
declare const group: Record<string, any>;
|
||||
|
||||
`
|
||||
|
||||
@@ -162,6 +162,18 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
open: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
close: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -207,6 +219,18 @@ export function createAppFromScript(path: string, schema: Record<string, any> |
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
open: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
close: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -547,6 +571,18 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
open: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
close: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -592,6 +628,18 @@ export function createAppFromFlow(path: string, schema: Record<string, any> | un
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
open: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
close: {
|
||||
id: {
|
||||
type: 'static',
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user