diff --git a/frontend/src/lib/components/ResourcePicker.svelte b/frontend/src/lib/components/ResourcePicker.svelte
index 67ec0185e3..6e3033f72d 100644
--- a/frontend/src/lib/components/ResourcePicker.svelte
+++ b/frontend/src/lib/components/ResourcePicker.svelte
@@ -88,7 +88,7 @@
}}
items={collection}
class="text-clip grow min-w-0"
- placeholder="{resourceType} resource"
+ placeholder="{resourceType ?? 'any'} resource"
inputStyles={SELECT_INPUT_DEFAULT_STYLE.inputStyles}
containerStyles={SELECT_INPUT_DEFAULT_STYLE.containerStyles}
/>
diff --git a/frontend/src/lib/components/apps/components/inputs/AppSelect.svelte b/frontend/src/lib/components/apps/components/inputs/AppSelect.svelte
index 86e8e2ba22..b8a9ffe9d8 100644
--- a/frontend/src/lib/components/apps/components/inputs/AppSelect.svelte
+++ b/frontend/src/lib/components/apps/components/inputs/AppSelect.svelte
@@ -43,6 +43,8 @@
: []
if (defaultValue) {
value = JSON.stringify(defaultValue)
+ } else if (listItems.length > 0) {
+ value = listItems[0]?.value
}
}
diff --git a/frontend/src/lib/components/apps/editor/AppEditor.svelte b/frontend/src/lib/components/apps/editor/AppEditor.svelte
index 0bf0e68936..93374a8826 100644
--- a/frontend/src/lib/components/apps/editor/AppEditor.svelte
+++ b/frontend/src/lib/components/apps/editor/AppEditor.svelte
@@ -212,7 +212,7 @@
-
+
diff --git a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte
index 754b2ad88d..ca6279d0ca 100644
--- a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte
+++ b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte
@@ -471,8 +471,8 @@
{
$app = undo(history, $app)
}}
diff --git a/frontend/src/lib/components/apps/editor/ComponentHeader.svelte b/frontend/src/lib/components/apps/editor/ComponentHeader.svelte
index 4a13c27ed8..1a280e5ed4 100644
--- a/frontend/src/lib/components/apps/editor/ComponentHeader.svelte
+++ b/frontend/src/lib/components/apps/editor/ComponentHeader.svelte
@@ -56,15 +56,15 @@
{/if}
{/if}
@@ -73,7 +73,7 @@
title="Move"
on:mousedown|stopPropagation|capture
class={classNames(
- 'text-gray-600 px-1 text-2xs py-0.5 font-bold rounded-t-sm w-fit absolute border border-gray-300 -top-1 shadow right-[4.5rem] z-50 cursor-move',
+ 'text-gray-600 px-1 text-2xs py-0.5 font-bold rounded-t-sm w-fit absolute border border-gray-300 -top-1 shadow right-[0.5rem] z-50 cursor-move',
'bg-gray-200/80'
)}
>
diff --git a/frontend/src/lib/components/apps/editor/GridEditor.svelte b/frontend/src/lib/components/apps/editor/GridEditor.svelte
index e0041c44cb..818c9779dd 100644
--- a/frontend/src/lib/components/apps/editor/GridEditor.svelte
+++ b/frontend/src/lib/components/apps/editor/GridEditor.svelte
@@ -11,10 +11,11 @@
import HiddenComponent from '../components/helpers/HiddenComponent.svelte'
import Component from './component/Component.svelte'
import { deepEqual } from 'fast-equals'
- import { push } from '$lib/history'
+ import { push, type History } from '$lib/history'
import { expandGriditem, findGridItem } from './appUtils'
export let policy: Policy
+ export let history: History | undefined = undefined
const {
selectedComponent,
@@ -29,8 +30,6 @@
breakpoint
} = getContext('AppViewerContext')
- const { history } = getContext('AppEditorContext')
-
// The drag is disabled when the user is connecting an input
// or when the user is previewing the app
// or when the focused grid is a subgrid
@@ -108,13 +107,17 @@
let pointerdown = false
let lastapp: App | undefined = undefined
const onpointerdown = () => {
- lastapp = JSON.parse(JSON.stringify($app))
- pointerdown = true
+ if (history) {
+ lastapp = JSON.parse(JSON.stringify($app))
+ pointerdown = true
+ }
}
const onpointerup = () => {
- pointerdown = false
- if (!deepEqual(lastapp, $app)) {
- push(history, lastapp, false, true)
+ if (history) {
+ pointerdown = false
+ if (!deepEqual(lastapp, $app)) {
+ push(history, lastapp, false, true)
+ }
}
}
diff --git a/frontend/src/lib/components/apps/editor/component/Component.svelte b/frontend/src/lib/components/apps/editor/component/Component.svelte
index 375814ac31..18b3e2b664 100644
--- a/frontend/src/lib/components/apps/editor/component/Component.svelte
+++ b/frontend/src/lib/components/apps/editor/component/Component.svelte
@@ -222,7 +222,7 @@
recomputeIds={component.recomputeIds}
{render}
/>
- {:else if component.type === 'selectcomponent'}
+ {:else if component.type === 'selectcomponent' || component.type === 'resourceselectcomponent'}
export type DisplayComponent = BaseComponent<'displaycomponent'>
export type ImageComponent = BaseComponent<'imagecomponent'>
export type InputComponent = BaseComponent<'inputcomponent'>
-export type SelectComponent = BaseComponent<'selectcomponent'>
+export type SelectComponent = BaseComponent<'resourceselectcomponent'>
+export type ResourceSelectComponent = BaseComponent<'selectcomponent'>
export type MultiSelectComponent = BaseComponent<'multiselectcomponent'>
export type CheckboxComponent = BaseComponent<'checkboxcomponent'>
export type RadioComponent = BaseComponent<'radiocomponent'>
@@ -116,6 +117,7 @@ export type AppComponent = BaseAppComponent &
| PieChartComponent
| ScatterChartComponent
| SelectComponent
+ | ResourceSelectComponent
| MultiSelectComponent
| CheckboxComponent
| FormComponent
@@ -911,7 +913,7 @@ Hello \${ctx.username}
}
},
multiselectcomponent: {
- name: 'MultiSelect',
+ name: 'Multi Select',
icon: List,
dims: '2:1-3:1',
data: {
@@ -940,6 +942,36 @@ Hello \${ctx.username}
softWrap: true
}
},
+ resourceselectcomponent: {
+ name: 'Resource Select',
+ icon: List,
+ dims: '2:1-3:1',
+ data: {
+ verticalAlignment: 'center',
+ id: '',
+ type: 'resourceselectcomponent',
+ componentInput: undefined,
+ configuration: {
+ items: {
+ type: 'static',
+ fieldType: 'array',
+ subFieldType: 'labeledresource',
+ value: []
+ },
+ placeholder: {
+ type: 'static',
+ fieldType: 'text',
+ value: 'Select an item',
+ onlyStatic: true
+ }
+ },
+ customCss: {
+ input: { style: '' }
+ } as const,
+ card: false,
+ softWrap: true
+ }
+ },
numberinputcomponent: {
name: 'Number',
icon: Binary,
diff --git a/frontend/src/lib/components/apps/editor/component/sets.ts b/frontend/src/lib/components/apps/editor/component/sets.ts
index 7677acfb10..59662af0dc 100644
--- a/frontend/src/lib/components/apps/editor/component/sets.ts
+++ b/frontend/src/lib/components/apps/editor/component/sets.ts
@@ -32,6 +32,7 @@ const inputs: ComponentSet = {
'fileinputcomponent',
'checkboxcomponent',
'selectcomponent',
+ 'resourceselectcomponent',
'multiselectcomponent',
]
} as const
diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte
index 7a458bd810..7b5f43c340 100644
--- a/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte
+++ b/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte
@@ -22,6 +22,8 @@
componentInput.value.push(0)
} else if (componentInput.subFieldType === 'object') {
componentInput.value.push({})
+ } else if (componentInput.subFieldType === 'labeledresource') {
+ componentInput.value.push({ value: '', label: '' })
} else if (
componentInput.subFieldType === 'text' ||
componentInput.subFieldType === 'textarea' ||
diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte
index 79371146f2..73065d1970 100644
--- a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte
+++ b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte
@@ -39,6 +39,24 @@
{:else if componentInput.fieldType === 'icon-select'}
+ {:else if componentInput.fieldType === 'labeledresource'}
+ {#if componentInput?.value && typeof componentInput?.value == 'object' && 'label' in componentInput?.value}
+
+
+ {
+ let path = e.detail
+
+ if (componentInput && path) {
+ componentInput.value['value'] = `$res:${path}`
+ }
+ }}
+ />
+
+ {:else}
+ Inconsistent labeled resource object
+ {/if}
{:else if componentInput.fieldType === 'color'}
{:else if componentInput.fieldType === 'object'}
diff --git a/frontend/src/lib/components/apps/inputType.ts b/frontend/src/lib/components/apps/inputType.ts
index e6334fa136..8e6d43c168 100644
--- a/frontend/src/lib/components/apps/inputType.ts
+++ b/frontend/src/lib/components/apps/inputType.ts
@@ -17,6 +17,7 @@ export type InputType =
| 'object'
| 'array'
| 'any'
+ | 'labeledresource'
// Connection to an output of another component
// defined by the id of the component and the path of the output
@@ -139,11 +140,11 @@ export type AppInput =
| AppInputSpec<'object', Record>
| AppInputSpec<'object', string>
| (AppInputSpec<'select', string> & {
- /**
- * One of the keys of `staticValues` from `lib/components/apps/editor/componentsPanel/componentStaticValues`
- */
- optionValuesKey: keyof typeof staticValues
- })
+ /**
+ * One of the keys of `staticValues` from `lib/components/apps/editor/componentsPanel/componentStaticValues`
+ */
+ optionValuesKey: keyof typeof staticValues
+ })
| (AppInputSpec<'select', string> & StaticOptions)
| AppInputSpec<'icon-select', string>
| AppInputSpec<'color', string>
@@ -156,9 +157,12 @@ export type AppInput =
| AppInputSpec<'array', string[], 'datetime'>
| AppInputSpec<'array', object[], 'object'>
| (AppInputSpec<'array', string[], 'select'> & {
- optionValuesKey: keyof typeof staticValues
- })
+ optionValuesKey: keyof typeof staticValues
+ })
| (AppInputSpec<'array', string[], 'select'> & StaticOptions)
+ | AppInputSpec<'array', object[], 'labeledresource'>
+ | AppInputSpec<'labeledresource', object>
+
export type RowAppInput = Extract
export type StaticAppInput = Extract
diff --git a/frontend/src/lib/components/apps/types.ts b/frontend/src/lib/components/apps/types.ts
index 17d9396a59..c65386ed43 100644
--- a/frontend/src/lib/components/apps/types.ts
+++ b/frontend/src/lib/components/apps/types.ts
@@ -137,7 +137,7 @@ export type AppViewerContext = {
}
export type AppEditorContext = {
- history: History
+ history: History | undefined
componentControl: Writable boolean; right?: () => boolean }>>
pickVariableCallback: Writable<((path: string) => void) | undefined>
}
diff --git a/frontend/src/lib/history.ts b/frontend/src/lib/history.ts
index 7f3633142a..983228d32c 100644
--- a/frontend/src/lib/history.ts
+++ b/frontend/src/lib/history.ts
@@ -7,34 +7,43 @@ export function initHistory(initial: T): History {
return writable({ history: [initial], index: 0 })
}
-export function undo(history: History, now: T): T {
- let chistory = get(history)
- if (chistory.index == 0) return now
- if (!deepEqual(chistory.history[chistory.index], now)) {
- push(history, now, true)
+export function undo(history: History | undefined, now: T): T {
+ if (history) {
+
+ let chistory = get(history)
+ if (chistory.index == 0) return now
+ if (!deepEqual(chistory.history[chistory.index], now)) {
+ push(history, now, true)
+ } else {
+ history.update((history) => {
+ history.index--
+ return history
+ })
+ }
+ let nhistory = get(history)
+ return nhistory.history[nhistory.index]
} else {
- history.update((history) => {
- history.index--
+ return now
+ }
+}
+
+export function redo(history: History | undefined): T {
+ if (history) {
+ history?.update((history) => {
+ if (history.index < history.history.length - 1) {
+ history.index++
+ }
return history
})
+ let nhistory = get(history)
+ return nhistory.history[nhistory.index]
+ } else {
+ return undefined as T
}
- let nhistory = get(history)
- return nhistory.history[nhistory.index]
}
-export function redo(history: History): T {
- history.update((history) => {
- if (history.index < history.history.length - 1) {
- history.index++
- }
- return history
- })
- let nhistory = get(history)
- return nhistory.history[nhistory.index]
-}
-
-export function push(history: History, value: T, noSetIndex: boolean = false, skipCopy: boolean = false) {
- history.update((history) => {
+export function push(history: History | undefined, value: T, noSetIndex: boolean = false, skipCopy: boolean = false) {
+ history?.update((history) => {
history.history = JSON.parse(JSON.stringify(history.history.slice(0, history.index + 1)))
const toPush = skipCopy ? value : JSON.parse(JSON.stringify(value))
history.history.push(toPush)