mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-20 08:01:35 +00:00
feat: Update apps button component with colors (#936)
* feat: Update app component types * fix: Typos * feat: Add select input type to components * fix: Remove width property from component types * fix: Make button full width in editor * fix: Types Co-authored-by: Faton Ramadani <faton.ramadani14@gmail.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import { Button, type ButtonType } from '$lib/components/common'
|
||||
import type { ComponentInputsSpec, InputsSpec } from '../../types'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
import RunnableComponent from '../helpers/RunnableComponent.svelte'
|
||||
@@ -14,10 +14,12 @@
|
||||
export const staticOutputs: string[] = ['loading', 'result']
|
||||
|
||||
let labelValue: string = 'Default label'
|
||||
let color: ButtonType.Color
|
||||
let runnableComponent: RunnableComponent
|
||||
</script>
|
||||
|
||||
<InputValue input={componentInputs.label} bind:value={labelValue} />
|
||||
<InputValue input={componentInputs.color} bind:value={color} />
|
||||
|
||||
<RunnableComponent
|
||||
bind:this={runnableComponent}
|
||||
@@ -32,7 +34,8 @@
|
||||
on:click={() => {
|
||||
runnableComponent?.runComponent()
|
||||
}}
|
||||
btnClasses="h-full w-full"
|
||||
btnClasses="w-full h-full"
|
||||
{color}
|
||||
>
|
||||
{labelValue}
|
||||
</Button>
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
import type { StaticInput, DynamicInput, AppEditorContext, UserInput } from '../../types'
|
||||
import { accessPropertyByPath } from '../../utils'
|
||||
|
||||
type T = $$Generic
|
||||
type T = string | number | boolean | Record<string | number, any> | undefined
|
||||
|
||||
export let input: DynamicInput | StaticInput | UserInput
|
||||
export let value: T | undefined = undefined
|
||||
export let value: T
|
||||
|
||||
const { worldStore } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
@@ -25,12 +26,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
function onValueChange(newValue: T): void {
|
||||
function onValueChange(newValue: any): void {
|
||||
if (input.type === 'output') {
|
||||
if (input.name?.includes('.')) {
|
||||
const path = input.name.split('.').slice(1).join('.')
|
||||
|
||||
value = accessPropertyByPath(newValue, path)
|
||||
value = accessPropertyByPath<T>(newValue, path)
|
||||
} else {
|
||||
value = newValue
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import type { Aligned } from "../../types"
|
||||
|
||||
const defaultProps = {
|
||||
inputs: {},
|
||||
componentInputs: {}
|
||||
}
|
||||
|
||||
const defaultAlignement = {
|
||||
horizontalAlignement: 'center',
|
||||
verticalAlignement: 'center'
|
||||
const defaultAlignement: Aligned = {
|
||||
horizontalAlignment: 'center',
|
||||
verticalAlignment: 'center'
|
||||
}
|
||||
|
||||
export { defaultProps, defaultAlignement }
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { BUTTON_COLORS } from "../../../common";
|
||||
|
||||
const buttonColorOptions = [...BUTTON_COLORS]
|
||||
|
||||
export const staticValues = {
|
||||
buttonColorOptions,
|
||||
} as const
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AppComponent } from '../../types'
|
||||
import type { AppComponent, ComponentSet } from '../../types'
|
||||
import { defaultAlignement, defaultProps } from './componentDefaultProps'
|
||||
|
||||
const windmillComponents = {
|
||||
@@ -20,7 +20,7 @@ const windmillComponents = {
|
||||
] as AppComponent[]
|
||||
}
|
||||
|
||||
const plainComponents = {
|
||||
const plainComponents: ComponentSet = {
|
||||
title: 'Plain Components',
|
||||
components: [
|
||||
{
|
||||
@@ -47,11 +47,18 @@ const plainComponents = {
|
||||
visible: true,
|
||||
value: 'Lorem ipsum',
|
||||
fieldType: 'textarea'
|
||||
},
|
||||
color: {
|
||||
fieldType: 'select',
|
||||
type: 'static',
|
||||
visible: true,
|
||||
value: 'blue',
|
||||
optionValuesKey: 'buttonColorOptions',
|
||||
}
|
||||
},
|
||||
runnable: true
|
||||
}
|
||||
] as AppComponent[]
|
||||
]
|
||||
}
|
||||
|
||||
const chartComponents = {
|
||||
|
||||
@@ -118,11 +118,11 @@
|
||||
</PanelSection>
|
||||
{/if}
|
||||
|
||||
{#if component.verticalAlignement !== undefined}
|
||||
<PanelSection title="Alignement">
|
||||
<div class="w-full text-xs font-bold">Horizontal alignement</div>
|
||||
{#if component.verticalAlignment !== undefined}
|
||||
<PanelSection title="Alignment">
|
||||
<div class="w-full text-xs font-bold">Horizontal alignment</div>
|
||||
|
||||
<ToggleButtonGroup bind:selected={component.horizontalAlignement}>
|
||||
<ToggleButtonGroup bind:selected={component.horizontalAlignment}>
|
||||
<ToggleButton position="left" value="left" size="xs">
|
||||
<Icon data={faAlignLeft} />
|
||||
</ToggleButton>
|
||||
@@ -133,9 +133,9 @@
|
||||
<Icon data={faAlignRight} />
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
<div class="w-full text-xs font-bold">Vertical alignement</div>
|
||||
<div class="w-full text-xs font-bold">Vertical alignment</div>
|
||||
|
||||
<ToggleButtonGroup bind:selected={component.verticalAlignement}>
|
||||
<ToggleButtonGroup bind:selected={component.verticalAlignment}>
|
||||
<ToggleButton position="left" value="top" size="xs">
|
||||
<Icon data={faAlignLeft} />
|
||||
</ToggleButton>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { StaticInput } from '../../types'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import { staticValues } from '../componentsPanel/componentStaticValues'
|
||||
|
||||
export let input: StaticInput
|
||||
export let canHide: boolean
|
||||
@@ -16,6 +17,14 @@
|
||||
<textarea bind:value={input.value} />
|
||||
{:else if input.fieldType === 'boolean'}
|
||||
<Toggle bind:checked={input.value} />
|
||||
{:else if input.fieldType === 'select'}
|
||||
<select bind:value={input.value}>
|
||||
{#each staticValues[input.optionValuesKey] || [] as option}
|
||||
<option value={option}>
|
||||
{option}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
{:else}
|
||||
<input bind:value={input.value} />
|
||||
{/if}
|
||||
|
||||
@@ -12,7 +12,7 @@ export interface Output<T> extends Observable<T> {
|
||||
}
|
||||
|
||||
export interface Input<T> extends Subscriber<T> {
|
||||
peak(): T | undefined
|
||||
peak(): T | any | undefined
|
||||
}
|
||||
|
||||
export type World = {
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Schema, SchemaProperty } from '$lib/common'
|
||||
import type { Preview } from '$lib/gen'
|
||||
import type { FilledItem } from 'svelte-grid'
|
||||
import type { Writable } from 'svelte/store'
|
||||
import type { staticValues } from './editor/componentsPanel/componentStaticValues'
|
||||
import type { World } from './rx'
|
||||
|
||||
export type UserInput = {
|
||||
@@ -20,84 +21,113 @@ export type DynamicInput = {
|
||||
defaultValue: any
|
||||
}
|
||||
|
||||
export type StaticInput = {
|
||||
export type StaticInputType =
|
||||
('text'
|
||||
| 'textarea'
|
||||
| 'number'
|
||||
| 'boolean'
|
||||
| 'select'
|
||||
| 'date'
|
||||
| 'time'
|
||||
| 'datetime'
|
||||
| 'object')
|
||||
|
||||
type BaseStaticInput<T extends StaticInputType, V> = {
|
||||
fieldType: T
|
||||
value: V | undefined
|
||||
type: 'static'
|
||||
value: any
|
||||
visible?: boolean
|
||||
fieldType:
|
||||
| 'text'
|
||||
| 'textarea'
|
||||
| 'number'
|
||||
| 'boolean'
|
||||
| 'select'
|
||||
| 'date'
|
||||
| 'time'
|
||||
| 'datetime'
|
||||
| 'object'
|
||||
}
|
||||
|
||||
export type SelectStaticInput = BaseStaticInput<'select', string> & {
|
||||
/**
|
||||
* One of the keys of `staticValues` from `lib/components/apps/editor/componentsPanel/componentStaticValues`
|
||||
*/
|
||||
optionValuesKey: keyof typeof staticValues
|
||||
}
|
||||
|
||||
export type StaticInput =
|
||||
BaseStaticInput<'text', string>
|
||||
| BaseStaticInput<'textarea', string>
|
||||
| BaseStaticInput<'number', number>
|
||||
| BaseStaticInput<'boolean', boolean>
|
||||
| SelectStaticInput
|
||||
| BaseStaticInput<'date', string>
|
||||
| BaseStaticInput<'time', string>
|
||||
| BaseStaticInput<'datetime', string>
|
||||
| BaseStaticInput<'object', Record<string | number, any>>
|
||||
|
||||
|
||||
export type AppInputTransform = DynamicInput | StaticInput | UserInput
|
||||
|
||||
// Inner inputs, (search, filter, page, inputs of a script or flow)
|
||||
export type InputsSpec = Record<FieldID, AppInputTransform>
|
||||
export type ComponentInputsSpec = Record<FieldID, DynamicInput | StaticInput>
|
||||
|
||||
export type TextComponent = {
|
||||
type: 'textcomponent'
|
||||
}
|
||||
|
||||
export type TextInputComponent = {
|
||||
type: 'textinputcomponent'
|
||||
}
|
||||
|
||||
export type ButtonComponent = {
|
||||
type: 'buttoncomponent'
|
||||
}
|
||||
|
||||
type Runnable = {
|
||||
inlineScriptName?: string
|
||||
path?: string
|
||||
runType?: 'script' | 'flow'
|
||||
}
|
||||
|
||||
export type BarChartComponent = Runnable & {
|
||||
type: 'barchartcomponent'
|
||||
type BaseComponent<T extends string> = {
|
||||
type: T
|
||||
}
|
||||
|
||||
export type PieChartComponent = Runnable & {
|
||||
type: 'piechartcomponent'
|
||||
export type TextComponent = BaseComponent<'textcomponent'>
|
||||
export type TextInputComponent = BaseComponent<'textinputcomponent'>
|
||||
export type ButtonComponent = BaseComponent<'buttoncomponent'>
|
||||
export type RunFormComponent = Runnable & BaseComponent<'runformcomponent'>
|
||||
export type BarChartComponent = BaseComponent<'barchartcomponent'>
|
||||
export type PieChartComponent = Runnable & BaseComponent<'piechartcomponent'>
|
||||
export type TableComponent = Runnable & BaseComponent<'tablecomponent'>
|
||||
export type DisplayComponent = BaseComponent<'displaycomponent'>
|
||||
export type ImageComponent = BaseComponent<'imagecomponent'>
|
||||
export type InputComponent = BaseComponent<'inputcomponent'>
|
||||
export type SelectComponent = BaseComponent<'selectcomponent'>
|
||||
export type CheckboxComponent = BaseComponent<'checkboxcomponent'>
|
||||
export type RadioComponent = BaseComponent<'radiocomponent'>
|
||||
|
||||
export type HorizontalAlignment = 'left' | 'center' | 'right'
|
||||
export type VerticalAlignment = 'top' | 'center' | 'bottom'
|
||||
export type Aligned = {
|
||||
horizontalAlignment: HorizontalAlignment
|
||||
verticalAlignment: VerticalAlignment
|
||||
}
|
||||
|
||||
export type TableComponent = Runnable & {
|
||||
type: 'tablecomponent'
|
||||
}
|
||||
export interface BaseAppComponent extends Partial<Aligned> {
|
||||
id: ComponentID
|
||||
inputs: InputsSpec
|
||||
// Only dynamic inputs (Result of display)
|
||||
componentInputs: ComponentInputsSpec
|
||||
runnable?: boolean | undefined
|
||||
card?: boolean | undefined
|
||||
|
||||
export type DisplayComponent = {
|
||||
type: 'displaycomponent'
|
||||
// TODO: add min/max width/height
|
||||
}
|
||||
|
||||
export type AppComponent =
|
||||
| (
|
||||
| DisplayComponent
|
||||
| TextInputComponent
|
||||
| BarChartComponent
|
||||
| TableComponent
|
||||
| TextComponent
|
||||
| TableComponent
|
||||
| ButtonComponent
|
||||
| PieChartComponent
|
||||
) & {
|
||||
id: ComponentID
|
||||
horizontalAlignement?: 'left' | 'center' | 'right'
|
||||
verticalAlignement?: 'top' | 'center' | 'bottom'
|
||||
BaseAppComponent & (
|
||||
RunFormComponent
|
||||
| DisplayComponent
|
||||
| TextInputComponent
|
||||
| BarChartComponent
|
||||
| TableComponent
|
||||
| TextComponent
|
||||
| TableComponent
|
||||
| ButtonComponent
|
||||
| PieChartComponent
|
||||
| ImageComponent
|
||||
| InputComponent
|
||||
| SelectComponent
|
||||
| CheckboxComponent
|
||||
| RadioComponent
|
||||
)
|
||||
|
||||
inputs: InputsSpec
|
||||
componentInputs: ComponentInputsSpec
|
||||
runnable?: boolean | undefined
|
||||
card?: boolean | undefined
|
||||
|
||||
// TODO: add min/max width/height
|
||||
}
|
||||
export type ComponentSet = {
|
||||
title: string,
|
||||
components: AppComponent[]
|
||||
}
|
||||
|
||||
type SectionID = string
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
export const BUTTON_COLORS = ['blue', 'red', 'dark', 'light', 'green'] as const
|
||||
|
||||
export namespace ButtonType {
|
||||
|
||||
export type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||
export type Color = 'blue' | 'red' | 'dark' | 'light' | 'green'
|
||||
export type Color = typeof BUTTON_COLORS[number]
|
||||
export type Variant = 'contained' | 'border'
|
||||
export type Target = '_self' | '_blank'
|
||||
export type Element = HTMLButtonElement | HTMLAnchorElement
|
||||
|
||||
Reference in New Issue
Block a user