mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-07 16:03:21 +00:00
new app component: currency + improved select
This commit is contained in:
@@ -1774,6 +1774,8 @@ for k, v in list(args.items()):
|
||||
|
||||
try:
|
||||
res = inner_script.main(**args)
|
||||
if type(res).__name__ == 'DataFrame':
|
||||
res = res.values.tolist()
|
||||
res_json = json.dumps(res, separators=(',', ':'), default=str).replace('\n', '')
|
||||
with open("result.json", 'w') as f:
|
||||
f.write(res_json)
|
||||
|
||||
Generated
+11
@@ -8,6 +8,7 @@
|
||||
"name": "windmill",
|
||||
"version": "1.64.0",
|
||||
"dependencies": {
|
||||
"@canutin/svelte-currency-input": "^0.8.0",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||
"@leeoniya/ufuzzy": "^0.9.1",
|
||||
@@ -205,6 +206,11 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@canutin/svelte-currency-input": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@canutin/svelte-currency-input/-/svelte-currency-input-0.8.0.tgz",
|
||||
"integrity": "sha512-u/ywCjAQzBTU1GvoljNgVzA/xV6UjVXsFbe4KISxk3cZJOA3eN35qaGtNMJhWQ0JI+QbFjxv2I2nHbdzmmn1Nw=="
|
||||
},
|
||||
"node_modules/@csstools/selector-specificity": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz",
|
||||
@@ -7278,6 +7284,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@canutin/svelte-currency-input": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@canutin/svelte-currency-input/-/svelte-currency-input-0.8.0.tgz",
|
||||
"integrity": "sha512-u/ywCjAQzBTU1GvoljNgVzA/xV6UjVXsFbe4KISxk3cZJOA3eN35qaGtNMJhWQ0JI+QbFjxv2I2nHbdzmmn1Nw=="
|
||||
},
|
||||
"@csstools/selector-specificity": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz",
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@canutin/svelte-currency-input": "^0.8.0",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||
"@leeoniya/ufuzzy": "^0.9.1",
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.svelte-select-list {
|
||||
z-index: 1000 !important;
|
||||
}
|
||||
.nowrap pre code.hljs {
|
||||
whitespace: normal !important;
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if resource_type == 'postgresql' || resource_type == 'mysql'}
|
||||
{#if resource_type == 'postgresql' || resource_type == 'mysql' || resource_type == 'mongodb'}
|
||||
<WhitelistIp />
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppInput } from '../../inputType'
|
||||
import type { Output } from '../../rx'
|
||||
import type { AppEditorContext } from '../../types'
|
||||
import AlignWrapper from '../helpers/AlignWrapper.svelte'
|
||||
import InputDefaultValue from '../helpers/InputDefaultValue.svelte'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
import CurrencyInput from '@canutin/svelte-currency-input'
|
||||
|
||||
export let id: string
|
||||
export let configuration: Record<string, AppInput>
|
||||
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
|
||||
export const staticOutputs: string[] = ['result']
|
||||
|
||||
const { worldStore } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
let defaultValue: number | undefined = undefined
|
||||
|
||||
let isNegativeAllowed: boolean | undefined = undefined
|
||||
let currency: string | undefined = undefined
|
||||
let locale: string | undefined = undefined
|
||||
let value: number | undefined = undefined
|
||||
|
||||
$: outputs = $worldStore?.outputsById[id] as {
|
||||
result: Output<number | null>
|
||||
}
|
||||
|
||||
function handleInput() {
|
||||
outputs?.result.set(value ?? null)
|
||||
}
|
||||
|
||||
function handleDefault() {
|
||||
value = defaultValue
|
||||
}
|
||||
|
||||
$: value && handleInput()
|
||||
|
||||
$: defaultValue && handleDefault()
|
||||
</script>
|
||||
|
||||
<InputValue {id} input={configuration.defaultValue} bind:value={defaultValue} />
|
||||
<InputValue {id} input={configuration.isNegativeAllowed} bind:value={isNegativeAllowed} />
|
||||
<InputValue {id} input={configuration.currency} bind:value={currency} />
|
||||
<InputValue {id} input={configuration.locale} bind:value={locale} />
|
||||
|
||||
<AlignWrapper {verticalAlignment}>
|
||||
{#key isNegativeAllowed}
|
||||
{#key locale}
|
||||
{#key currency}
|
||||
<CurrencyInput
|
||||
inputClasses={{ formatted: 'p-0' }}
|
||||
bind:value
|
||||
{currency}
|
||||
{locale}
|
||||
on:focus={(e) => {
|
||||
e?.stopPropagation()
|
||||
}}
|
||||
{isNegativeAllowed}
|
||||
/>
|
||||
{/key}
|
||||
{/key}
|
||||
{/key}
|
||||
</AlignWrapper>
|
||||
@@ -18,6 +18,10 @@
|
||||
let defaultValue: number | undefined = undefined
|
||||
let placeholder: string | undefined = undefined
|
||||
|
||||
let min: number | undefined = undefined
|
||||
let max: number | undefined = undefined
|
||||
let step = 1
|
||||
|
||||
$: outputs = $worldStore?.outputsById[id] as {
|
||||
result: Output<number | null>
|
||||
}
|
||||
@@ -31,6 +35,9 @@
|
||||
$: input && handleInput()
|
||||
</script>
|
||||
|
||||
<InputValue {id} input={configuration.step} bind:value={step} />
|
||||
<InputValue {id} input={configuration.min} bind:value={min} />
|
||||
<InputValue {id} input={configuration.max} bind:value={max} />
|
||||
<InputValue {id} input={configuration.placeholder} bind:value={placeholder} />
|
||||
<InputValue {id} input={configuration.defaultValue} bind:value={defaultValue} />
|
||||
<InputDefaultValue bind:input {defaultValue} />
|
||||
@@ -43,6 +50,9 @@
|
||||
e?.stopPropagation()
|
||||
window.dispatchEvent(new Event('pointerup'))
|
||||
}}
|
||||
{min}
|
||||
{max}
|
||||
{step}
|
||||
type="number"
|
||||
inputmode="numeric"
|
||||
pattern="\d*"
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
let label: string
|
||||
let items: string[]
|
||||
let itemKey: string
|
||||
let multiple: boolean = false
|
||||
let placeholder: string = 'Select an item'
|
||||
|
||||
$: outputs = $worldStore?.outputsById[id] as {
|
||||
result: Output<string | undefined>
|
||||
@@ -35,24 +37,30 @@
|
||||
<InputValue {id} input={configuration.label} bind:value={label} />
|
||||
<InputValue {id} input={configuration.items} bind:value={items} />
|
||||
<InputValue {id} input={configuration.itemKey} bind:value={itemKey} />
|
||||
<InputValue {id} input={configuration.multiple} bind:value={multiple} />
|
||||
<InputValue {id} input={configuration.placeholder} bind:value={placeholder} />
|
||||
|
||||
<AlignWrapper {horizontalAlignment} {verticalAlignment}>
|
||||
<Select
|
||||
--height="34px"
|
||||
class="select"
|
||||
on:clear={onChange}
|
||||
on:change={onChange}
|
||||
on:focus={(e) => {
|
||||
e?.stopPropagation()
|
||||
window.dispatchEvent(new Event('pointerup'))
|
||||
}}
|
||||
items={Array.isArray(items) ? items : []}
|
||||
{value}
|
||||
placeholder="Select an item"
|
||||
on:click={() => {
|
||||
if (!$connectingInput.opened) {
|
||||
$selectedComponent = id
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div class="app-select w-full" style="height: 34px" on:pointerdown|stopPropagation>
|
||||
<Select
|
||||
--height="34px"
|
||||
{multiple}
|
||||
on:clear={onChange}
|
||||
on:change={onChange}
|
||||
items={Array.isArray(items) ? items : []}
|
||||
{value}
|
||||
{placeholder}
|
||||
on:click={() => {
|
||||
if (!$connectingInput.opened) {
|
||||
$selectedComponent = id
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</AlignWrapper>
|
||||
|
||||
<style global>
|
||||
.app-select .value-container {
|
||||
@apply p-0 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
GripHorizontal,
|
||||
Code2,
|
||||
SlidersHorizontal,
|
||||
PlusSquare
|
||||
PlusSquare,
|
||||
DollarSign
|
||||
} from 'lucide-svelte'
|
||||
import type { Size } from 'svelte-grid'
|
||||
|
||||
@@ -38,6 +39,7 @@
|
||||
export type PasswordInputComponent = BaseComponent<'passwordinputcomponent'>
|
||||
export type DateInputComponent = BaseComponent<'dateinputcomponent'>
|
||||
export type NumberInputComponent = BaseComponent<'numberinputcomponent'>
|
||||
export type CurrencyComponent = BaseComponent<'currencycomponent'>
|
||||
export type SliderComponent = BaseComponent<'slidercomponent'>
|
||||
export type RangeComponent = BaseComponent<'rangecomponent'>
|
||||
export type HtmlComponent = BaseComponent<'htmlcomponent'>
|
||||
@@ -74,6 +76,7 @@
|
||||
| PasswordInputComponent
|
||||
| DateInputComponent
|
||||
| NumberInputComponent
|
||||
| CurrencyComponent
|
||||
| SliderComponent
|
||||
| RangeComponent
|
||||
| BarChartComponent
|
||||
@@ -679,6 +682,18 @@
|
||||
type: 'static',
|
||||
fieldType: 'text',
|
||||
value: 'value'
|
||||
},
|
||||
multiple: {
|
||||
type: 'static',
|
||||
fieldType: 'boolean',
|
||||
value: false,
|
||||
onlyStatic: true
|
||||
},
|
||||
placeholder: {
|
||||
type: 'static',
|
||||
fieldType: 'text',
|
||||
value: 'Select an item',
|
||||
onlyStatic: true
|
||||
}
|
||||
},
|
||||
card: false,
|
||||
@@ -706,6 +721,64 @@
|
||||
type: 'static',
|
||||
value: undefined,
|
||||
fieldType: 'number'
|
||||
},
|
||||
min: {
|
||||
type: 'static',
|
||||
value: undefined,
|
||||
fieldType: 'number',
|
||||
onlyStatic: true
|
||||
},
|
||||
max: {
|
||||
type: 'static',
|
||||
value: undefined,
|
||||
fieldType: 'number',
|
||||
onlyStatic: true
|
||||
},
|
||||
step: {
|
||||
type: 'static',
|
||||
value: 1,
|
||||
fieldType: 'number',
|
||||
onlyStatic: true
|
||||
}
|
||||
},
|
||||
card: false
|
||||
}
|
||||
},
|
||||
currencycomponent: {
|
||||
name: 'Currency',
|
||||
icon: DollarSign,
|
||||
dims: '2:1-3:1',
|
||||
data: {
|
||||
softWrap: true,
|
||||
verticalAlignment: 'center',
|
||||
id: '',
|
||||
type: 'currencycomponent',
|
||||
componentInput: undefined,
|
||||
configuration: {
|
||||
defaultValue: {
|
||||
type: 'static',
|
||||
value: undefined,
|
||||
fieldType: 'number'
|
||||
},
|
||||
isNegativeAllowed: {
|
||||
type: 'static',
|
||||
value: false,
|
||||
fieldType: 'boolean',
|
||||
onlyStatic: true
|
||||
},
|
||||
currency: {
|
||||
type: 'static',
|
||||
value: 'USD',
|
||||
fieldType: 'select',
|
||||
onlyStatic: true,
|
||||
optionValuesKey: 'currencyOptions'
|
||||
},
|
||||
locale: {
|
||||
type: 'static',
|
||||
value: 'en-US',
|
||||
fieldType: 'select',
|
||||
onlyStatic: true,
|
||||
optionValuesKey: 'localeOptions'
|
||||
}
|
||||
},
|
||||
card: false
|
||||
@@ -854,6 +927,7 @@
|
||||
'textinputcomponent',
|
||||
'passwordinputcomponent',
|
||||
'numberinputcomponent',
|
||||
'currencycomponent',
|
||||
'slidercomponent',
|
||||
'rangecomponent',
|
||||
'dateinputcomponent',
|
||||
@@ -1241,6 +1315,7 @@
|
||||
import PlotlyHtml from '../components/dataDisplay/PlotlyHtml.svelte'
|
||||
import { defaultAlignement } from './componentsPanel/componentDefaultProps'
|
||||
import AppRangeInput from '../components/numberInputs/AppRangeInput.svelte'
|
||||
import AppCurrencyInput from '../components/numberInputs/AppCurrencyInput.svelte'
|
||||
|
||||
export let component: AppComponent
|
||||
export let selected: boolean
|
||||
@@ -1389,6 +1464,8 @@
|
||||
/>
|
||||
{:else if component.type === 'numberinputcomponent'}
|
||||
<AppNumberInput {...component} bind:staticOutputs={$staticOutputs[component.id]} />
|
||||
{:else if component.type === 'currencycomponent'}
|
||||
<AppCurrencyInput {...component} bind:staticOutputs={$staticOutputs[component.id]} />
|
||||
{:else if component.type === 'slidercomponent'}
|
||||
<AppSliderInputs {...component} bind:staticOutputs={$staticOutputs[component.id]} />
|
||||
{:else if component.type === 'rangecomponent'}
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<div class="pb-2 relative w-full z-20">
|
||||
<div class="pb-2 relative w-full z-20 overflow-visible border">
|
||||
<div
|
||||
class="w-full sticky top-0 flex justify-between border-l border-r border-b {$connectingInput?.opened
|
||||
? ''
|
||||
|
||||
@@ -22,10 +22,7 @@
|
||||
function addComponent(appComponentType: AppComponent['type']) {
|
||||
$dirtyStore = true
|
||||
const grid = $app.grid ?? []
|
||||
const id = getNextId(
|
||||
grid.map((gridItem) => gridItem.data.id),
|
||||
true
|
||||
)
|
||||
const id = getNextId(grid.map((gridItem) => gridItem.data.id))
|
||||
|
||||
const appComponent = componentsRecord[appComponentType].data
|
||||
|
||||
|
||||
@@ -7,5 +7,8 @@ export const staticValues = {
|
||||
buttonSizeOptions: ['xs', 'sm', 'md', 'lg', 'xl'],
|
||||
tableSearchOptions: ['By Component', 'By Runnable', 'Disabled'],
|
||||
chartThemeOptions: ['theme1', 'theme2', 'theme3'],
|
||||
textStyleOptions: ['Title', 'Subtitle', 'Body', 'Label', 'Caption']
|
||||
textStyleOptions: ['Title', 'Subtitle', 'Body', 'Label', 'Caption'],
|
||||
currencyOptions: ['USD', 'EUR', 'GBP', 'CAD', 'AUD', 'JPY', 'CNY', 'INR', 'BRL'],
|
||||
localeOptions: ['en-US', 'en-GB', 'en-IE', 'de-DE', 'fr-FR', 'br-FR', 'ja-JP', 'pt-TL', 'fr-CA', 'en-CA']
|
||||
|
||||
} as const
|
||||
|
||||
@@ -32,7 +32,7 @@ export async function loadFlowModuleState(flowModule: FlowModule): Promise<FlowM
|
||||
|
||||
export const idMutex = new Mutex()
|
||||
|
||||
export function getNextId(currentKeys: string[], skipTilde: boolean = false): string {
|
||||
export function getNextId(currentKeys: string[]): string {
|
||||
const max = currentKeys.reduce((acc, key) => {
|
||||
if (key === 'failure' || key.includes('branch') || key.includes('loop')) {
|
||||
return acc
|
||||
|
||||
@@ -179,9 +179,9 @@ export function emptyFlowModuleState(): FlowModuleState {
|
||||
|
||||
const aCharCode = 'a'.charCodeAt(0)
|
||||
|
||||
export function numberToChars(n: number, skipTilde: boolean = false) {
|
||||
export function numberToChars(n: number) {
|
||||
if (n < 0) {
|
||||
return "-" + numberToChars(-n, skipTilde)
|
||||
return "-" + numberToChars(-n)
|
||||
}
|
||||
var b = [n],
|
||||
sp,
|
||||
@@ -190,12 +190,11 @@ export function numberToChars(n: number, skipTilde: boolean = false) {
|
||||
div
|
||||
|
||||
sp = 0
|
||||
const basisInc = skipTilde ? -1 : 0
|
||||
while (sp < b.length) {
|
||||
if (b[sp] > (25 + basisInc)) {
|
||||
div = Math.floor(b[sp] / (27 + basisInc))
|
||||
if (b[sp] > (25)) {
|
||||
div = Math.floor(b[sp] / (26))
|
||||
b[sp + 1] = div - 1
|
||||
b[sp] %= (27 + basisInc)
|
||||
b[sp] %= (26)
|
||||
}
|
||||
sp += 1
|
||||
}
|
||||
@@ -203,7 +202,7 @@ export function numberToChars(n: number, skipTilde: boolean = false) {
|
||||
out = ''
|
||||
for (i = 0; i < b.length; i += 1) {
|
||||
let charCode = aCharCode + b[i]
|
||||
out = (b[i] == 26 ? "-" : String.fromCharCode(charCode)) + out
|
||||
out = String.fromCharCode(charCode) + out
|
||||
}
|
||||
|
||||
return out
|
||||
|
||||
Reference in New Issue
Block a user