mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-19 00:02:03 +00:00
fix(frontend): Add missing tooltips + multilpe small fix in the app builder (#1590)
* fix(frontend): revert commit that were removed + delete outdated components + add missing tooltips * fix(frontend): remove outdated select button * fix(frontend): add missing tooltips * fix(frontend): add debug tab * fix(frontend): remove duplicate file * fix(frontend): add missing props
This commit is contained in:
+7
-2
@@ -3,6 +3,8 @@
|
||||
A simple CLI allowing interactions with windmill from the command line.
|
||||

|
||||
|
||||
You can find more information in [Windmill Docs](https://docs.windmill.dev/docs/advanced/cli)
|
||||
|
||||
## Installation
|
||||
|
||||
Install the `wmill` CLI tool using
|
||||
@@ -18,11 +20,14 @@ workspace settings.
|
||||
## Running Flows & Scripts
|
||||
|
||||
Run a script or flow using `wmill flow/script run u/username/path/to/script` and
|
||||
pass any inputs using `--input/-i <name>=<value>` curl-style syntax using
|
||||
`-i @-` for stdin or `-i @<filename>` is also supported
|
||||
pass any inputs using `--data` + Inputs specified as a JSON string or a file using `@ <filename>` or stdin using @-.
|
||||
|
||||
Curl-style syntax using `-d @-` for stdin or `-d @<filename>` is also supported.
|
||||
|
||||
Flow Steps and Logs will be streamed during execution automatically.
|
||||
|
||||

|
||||
|
||||
## Pushing Resources, Scripts & More
|
||||
|
||||
The CLI can push specifications to a windmill instance. See the
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 109 KiB |
@@ -1,67 +0,0 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
faArchive,
|
||||
faEdit,
|
||||
faList,
|
||||
faPlay,
|
||||
faShare,
|
||||
faTrash
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import Icon from 'svelte-awesome'
|
||||
|
||||
export let category: 'delete' | 'list' | 'run' | 'add' | 'edit' | 'archive' | 'share'
|
||||
export let disabled: boolean = false
|
||||
|
||||
const colors = {
|
||||
red: 'bg-transparent hover:bg-red-600 text-red-600 font-normal hover:text-white border-red-600 hover:border-transparent rounded',
|
||||
blue: 'hover:bg-blue-500 hover:text-white'
|
||||
}
|
||||
|
||||
const getCategoryClasses = () => {
|
||||
if (category === 'delete' || category === 'archive') return colors.red
|
||||
else if (category === 'edit' || category === 'list' || category === 'share') return colors.blue
|
||||
return ''
|
||||
}
|
||||
</script>
|
||||
|
||||
<button
|
||||
class="{$$props.class} inline-flex items-center bg-[#5e81ac] hover:bg-blue-700 text-white
|
||||
font-bold py-1 px-2 border rounded border-blue-500 hover:border-blue-700 w-min min-w-max
|
||||
text-sm {getCategoryClasses()}"
|
||||
on:click
|
||||
{disabled}
|
||||
>
|
||||
<div class="inline-flex items-center justify-center">
|
||||
{#if category === 'delete'}
|
||||
<Icon data={faTrash} scale={0.5} />
|
||||
<slot name="text">
|
||||
<span class="pl-1">Delete</span>
|
||||
</slot>
|
||||
{:else if category === 'list'}
|
||||
<Icon data={faList} scale={0.5} />
|
||||
<slot name="text">
|
||||
<span class="pl-1">List</span>
|
||||
</slot>
|
||||
{:else if category === 'run'}
|
||||
<Icon data={faPlay} scale={0.5} />
|
||||
<slot name="text">
|
||||
<span class="pl-1">Run</span>
|
||||
</slot>
|
||||
{:else if category === 'edit'}
|
||||
<Icon data={faEdit} scale={0.5} />
|
||||
<slot name="text-gray-500">
|
||||
<span class="pl-1">Edit</span>
|
||||
</slot>
|
||||
{:else if category === 'archive'}
|
||||
<Icon data={faArchive} scale={0.5} />
|
||||
<slot name="text">
|
||||
<span class="pl-1">Archive</span>
|
||||
</slot>
|
||||
{:else if category === 'share'}
|
||||
<Icon data={faShare} scale={0.5} />
|
||||
<slot name="text">
|
||||
<span class="pl-1">Share</span>
|
||||
</slot>
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="mr-6 text-sm underline text-gray-700 inline-flex items-center"
|
||||
class="mr-6 text-sm underline text-gray-700 inline-flex items-center"
|
||||
on:click={() => {
|
||||
viewOptions = !viewOptions
|
||||
}}
|
||||
|
||||
@@ -23,15 +23,17 @@
|
||||
</span>
|
||||
<Required {required} class="!ml-0" />
|
||||
|
||||
{#if format && format != ''}
|
||||
<span class="text-sm italic ml-1 text-indigo-800">
|
||||
({format})
|
||||
</span>
|
||||
{:else if displayType}
|
||||
<span class="text-sm italic ml-1 text-indigo-800">
|
||||
({type ?? 'any'}{contentEncoding && contentEncoding != ''
|
||||
? `, encoding: ${contentEncoding}`
|
||||
: ''})
|
||||
</span>
|
||||
{#if displayType}
|
||||
{#if format && format != ''}
|
||||
<span class="text-sm italic ml-1 text-indigo-800">
|
||||
({format})
|
||||
</span>
|
||||
{:else}
|
||||
<span class="text-sm italic ml-1 text-indigo-800">
|
||||
({type ?? 'any'}{contentEncoding && contentEncoding != ''
|
||||
? `, encoding: ${contentEncoding}`
|
||||
: ''})
|
||||
</span>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
|
||||
<div class="flex flex-row items-center gap-4 w-full">
|
||||
<div class="flex flex-row items-center gap-4 w-full">
|
||||
{#if options.length > 1}
|
||||
<div class="w-80 mt-1">
|
||||
<RadioButton {disabled} bind:value={itemKind} {options} />
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<DrawerContent overflow_y={false} title="Superadmin Settings" on:close={closeDrawer}>
|
||||
<div class="flex flex-col h-full">
|
||||
<div>
|
||||
<div class="text-xs pt-1 text-gray-500 ">
|
||||
<div class="text-xs pt-1 text-gray-500">
|
||||
Windmill {version}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -125,7 +125,6 @@
|
||||
{outputs}
|
||||
{extraKey}
|
||||
refreshOnStart={resolvedConfig.triggerOnAppLoad}
|
||||
triggerable
|
||||
>
|
||||
<AlignWrapper {noWFull} {horizontalAlignment} {verticalAlignment}>
|
||||
{#if errorsMessage}
|
||||
|
||||
@@ -75,7 +75,6 @@
|
||||
runnableClass={css?.container?.class}
|
||||
runnableStyle={css?.container?.style}
|
||||
{outputs}
|
||||
triggerable
|
||||
>
|
||||
<AlignWrapper {horizontalAlignment}>
|
||||
<div
|
||||
|
||||
@@ -91,7 +91,6 @@
|
||||
doOnSuccess={resolvedConfig.onSuccess}
|
||||
doOnError={resolvedConfig.onError}
|
||||
{errorHandledByComponent}
|
||||
triggerable
|
||||
>
|
||||
<div class="flex flex-col gap-2 px-4 w-full">
|
||||
<div>
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
export let customCss: ComponentCustomCSS<'htmlcomponent'> | undefined = undefined
|
||||
export let render: boolean
|
||||
|
||||
const { app, worldStore, selectedComponent, mode } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
const { app, worldStore, mode } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const outputs = initOutput($worldStore, id, {
|
||||
result: undefined,
|
||||
@@ -35,13 +34,6 @@
|
||||
bind:clientHeight={h}
|
||||
bind:clientWidth={w}
|
||||
>
|
||||
{#if $mode == 'dnd'}
|
||||
<button
|
||||
class="absolute bottom-0 left-0 text-xs border px-2 py-0.5 bg-white/80"
|
||||
on:click={() => ($selectedComponent = [id])}>Select</button
|
||||
>
|
||||
{/if}
|
||||
|
||||
<RunnableWrapper
|
||||
{outputs}
|
||||
{render}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<button
|
||||
on:pointerdown|preventDefault|stopPropagation
|
||||
on:click|preventDefault|stopPropagation={refresh}
|
||||
class="center-center p-1 rounded border bg-white/60 hover:bg-gray-200 z-10"
|
||||
class="center-center p-1 rounded border bg-white/60 hover:bg-gray-200 z-10"
|
||||
>
|
||||
<RefreshCw class={loading ? 'animate-spin' : ''} size={16} />
|
||||
</button>
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
export let outputs: { result: Output<any>; loading: Output<boolean> }
|
||||
export let extraKey: string | undefined = undefined
|
||||
export let refreshOnStart: boolean = false
|
||||
export let triggerable: boolean = false
|
||||
export let errorHandledByComponent: boolean = false
|
||||
|
||||
const { staticExporter, noBackend, componentControl, runnableComponents } =
|
||||
@@ -69,7 +68,7 @@
|
||||
})
|
||||
|
||||
// We need to make sure that old apps have correct values. Triggerable (button, form, etc) have both autoRefresh and recomputeOnInputChanged set to false
|
||||
$: if (triggerable && componentInput?.type === 'runnable' && componentInput.autoRefresh) {
|
||||
$: if (!autoRefresh && componentInput?.type === 'runnable' && componentInput.autoRefresh) {
|
||||
componentInput.autoRefresh = false
|
||||
componentInput.recomputeOnInputChanged = false
|
||||
}
|
||||
|
||||
@@ -124,7 +124,6 @@
|
||||
forceSchemaDisplay={true}
|
||||
runnableClass="!block"
|
||||
{outputs}
|
||||
triggerable
|
||||
bind:result
|
||||
errorHandledByComponent={true}
|
||||
>
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
import type { AppComponent } from './component'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { getErrorFromLatestResult } from './appUtils'
|
||||
import ButtonDropdown from '$lib/components/common/button/ButtonDropdown.svelte'
|
||||
import { MenuItem } from '@rgossiaux/svelte-headlessui'
|
||||
|
||||
import TabsDebug from './TabsDebug.svelte'
|
||||
|
||||
export let component: AppComponent
|
||||
export let selected: boolean
|
||||
@@ -20,11 +20,9 @@
|
||||
export let inlineEditorOpened: boolean = false
|
||||
export let errorHandledByComponent: boolean = false
|
||||
|
||||
let isConditionalWrapperManuallySelected: boolean = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
const { errorByComponent, openDebugRun, jobs, connectingInput, componentControl } =
|
||||
const { errorByComponent, openDebugRun, jobs, connectingInput } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
$: error = getErrorFromLatestResult(component.id, $errorByComponent, $jobs)
|
||||
@@ -74,56 +72,10 @@
|
||||
</button>
|
||||
{/if}
|
||||
{#if component.type === 'conditionalwrapper'}
|
||||
<button
|
||||
title="Conditions"
|
||||
class={classNames(
|
||||
'text-2xs py-0.5 font-bold w-fit border cursor-pointer rounded-sm',
|
||||
isConditionalWrapperManuallySelected
|
||||
? 'bg-red-100 text-red-600 border-red-500 hover:bg-red-200 hover:text-red-800'
|
||||
: 'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800'
|
||||
)}
|
||||
on:click={() => dispatch('triggerInlineEditor')}
|
||||
on:pointerdown|stopPropagation
|
||||
>
|
||||
<ButtonDropdown hasPadding={false}>
|
||||
<svelte:fragment slot="items">
|
||||
{#each component.conditions ?? [] as { }, index}
|
||||
<MenuItem
|
||||
on:click={() => {
|
||||
$componentControl?.[component.id]?.setTab?.(index)
|
||||
isConditionalWrapperManuallySelected = true
|
||||
}}
|
||||
>
|
||||
<div
|
||||
class={classNames(
|
||||
'!text-gray-600 text-left px-4 py-2 gap-2 cursor-pointer hover:bg-gray-100 !text-xs font-semibold'
|
||||
)}
|
||||
>
|
||||
{#if index === component.conditions.length - 1}
|
||||
{`Debug default condition`}
|
||||
{:else}
|
||||
{`Debug condition ${index + 1}`}
|
||||
{/if}
|
||||
</div>
|
||||
</MenuItem>
|
||||
{/each}
|
||||
<MenuItem
|
||||
on:click={() => {
|
||||
$componentControl?.[component.id]?.setTab?.(-1)
|
||||
isConditionalWrapperManuallySelected = false
|
||||
}}
|
||||
>
|
||||
<div
|
||||
class={classNames(
|
||||
'!text-red-600 text-left px-4 py-2 gap-2 cursor-pointer hover:bg-gray-100 !text-xs font-semibold'
|
||||
)}
|
||||
>
|
||||
{`Reset debug mode`}
|
||||
</div>
|
||||
</MenuItem>
|
||||
</svelte:fragment>
|
||||
</ButtonDropdown>
|
||||
</button>
|
||||
<TabsDebug id={component.id} tabs={component.conditions ?? []} isConditionalDebugMode />
|
||||
{/if}
|
||||
{#if component.type === 'tabscomponent' && component.configuration.tabsKind.type === 'static' && component.configuration.tabsKind.value === 'invisibleOnView'}
|
||||
<TabsDebug id={component.id} tabs={component.tabs ?? []} />
|
||||
{/if}
|
||||
<button
|
||||
title="Expand"
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<script lang="ts">
|
||||
import ButtonDropdown from '$lib/components/common/button/ButtonDropdown.svelte'
|
||||
import { classNames } from '$lib/utils'
|
||||
import { MenuItem } from '@rgossiaux/svelte-headlessui'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
import type { AppViewerContext } from '../types'
|
||||
|
||||
export let tabs: any[] = []
|
||||
export let id: string
|
||||
|
||||
export let isConditionalDebugMode: boolean = false
|
||||
|
||||
const { componentControl } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let isManuallySelected: boolean = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
<button
|
||||
title={isConditionalDebugMode ? 'Debug conditions' : 'Debug tabs'}
|
||||
class={classNames(
|
||||
'text-2xs py-0.5 font-bold w-fit border cursor-pointer rounded-sm',
|
||||
isManuallySelected
|
||||
? 'bg-red-100 text-red-600 border-red-500 hover:bg-red-200 hover:text-red-800'
|
||||
: 'bg-indigo-100 text-indigo-600 border-indigo-500 hover:bg-indigo-200 hover:text-indigo-800'
|
||||
)}
|
||||
on:click={() => dispatch('triggerInlineEditor')}
|
||||
on:pointerdown|stopPropagation
|
||||
>
|
||||
<ButtonDropdown hasPadding={false}>
|
||||
<svelte:fragment slot="items">
|
||||
{#each tabs ?? [] as { }, index}
|
||||
<MenuItem
|
||||
on:click={() => {
|
||||
$componentControl?.[id]?.setTab?.(index)
|
||||
isManuallySelected = true
|
||||
}}
|
||||
>
|
||||
<div
|
||||
class={classNames(
|
||||
'!text-gray-600 text-left px-4 py-2 gap-2 cursor-pointer hover:bg-gray-100 !text-xs font-semibold'
|
||||
)}
|
||||
>
|
||||
{#if index === tabs.length - 1}
|
||||
{isConditionalDebugMode ? `Debug default condition` : `Debug tab ${index + 1}`}
|
||||
{:else}
|
||||
{`Debug ${isConditionalDebugMode ? 'condition' : 'tab'} ${index + 1}`}
|
||||
{/if}
|
||||
</div>
|
||||
</MenuItem>
|
||||
{/each}
|
||||
<MenuItem
|
||||
on:click={() => {
|
||||
$componentControl?.[id]?.setTab?.(-1)
|
||||
isManuallySelected = false
|
||||
}}
|
||||
>
|
||||
<div
|
||||
class={classNames(
|
||||
'!text-red-600 text-left px-4 py-2 gap-2 cursor-pointer hover:bg-gray-100 !text-xs font-semibold'
|
||||
)}
|
||||
>
|
||||
{`Reset debug mode`}
|
||||
</div>
|
||||
</MenuItem>
|
||||
</svelte:fragment>
|
||||
</ButtonDropdown>
|
||||
</button>
|
||||
@@ -1484,11 +1484,11 @@ Hello \${ctx.username}
|
||||
type: 'static',
|
||||
onlyStatic: true,
|
||||
selectOptions: selectOptions.tabsKindOptions,
|
||||
value: 'tabs' as string
|
||||
value: 'tabs' as string,
|
||||
tooltip: `Tabs can be configured to be either horizontal (tabs), vertical (sidebar), or invisible.`
|
||||
}
|
||||
},
|
||||
componentInput: undefined,
|
||||
|
||||
numberOfSubgrids: 2,
|
||||
tabs: ['First tab', 'Second tab'] as string[]
|
||||
}
|
||||
@@ -1530,12 +1530,15 @@ Hello \${ctx.username}
|
||||
icon: {
|
||||
type: 'static',
|
||||
value: 'Smile',
|
||||
fieldType: 'icon-select'
|
||||
fieldType: 'icon-select',
|
||||
tooltip: 'The icons can be found at https://lucide.dev/'
|
||||
},
|
||||
color: {
|
||||
type: 'static',
|
||||
value: 'currentColor',
|
||||
fieldType: 'color'
|
||||
fieldType: 'color',
|
||||
tooltip:
|
||||
'The color of the icon can be overridden by the `background-color` property in the styling menu'
|
||||
},
|
||||
size: {
|
||||
type: 'static',
|
||||
@@ -1810,7 +1813,6 @@ Hello \${ctx.username}
|
||||
initialData: {
|
||||
configuration: {},
|
||||
componentInput: undefined,
|
||||
|
||||
panes: [50, 50] as number[],
|
||||
numberOfSubgrids: 2
|
||||
}
|
||||
@@ -1912,7 +1914,6 @@ Hello \${ctx.username}
|
||||
}
|
||||
},
|
||||
componentInput: undefined,
|
||||
|
||||
numberOfSubgrids: 1
|
||||
}
|
||||
},
|
||||
@@ -1945,13 +1946,15 @@ Hello \${ctx.username}
|
||||
fieldType: 'boolean',
|
||||
type: 'static',
|
||||
value: false,
|
||||
onlyStatic: true
|
||||
onlyStatic: true,
|
||||
tooltip: 'This will diplay the type and/or the format on the field next to the label.'
|
||||
},
|
||||
largeGap: {
|
||||
fieldType: 'boolean',
|
||||
type: 'static',
|
||||
value: false,
|
||||
onlyStatic: true
|
||||
onlyStatic: true,
|
||||
tooltip: 'This will add a large gap between the form elements.'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1989,7 +1992,9 @@ Hello \${ctx.username}
|
||||
type: 'static',
|
||||
value: 'sm',
|
||||
fieldType: 'select',
|
||||
selectOptions: selectOptions.buttonSizeOptions
|
||||
selectOptions: selectOptions.buttonSizeOptions,
|
||||
tooltip:
|
||||
'Size of the tabs can be overwritten with custom styles using `font-size` in CSS or using tailwind classes.'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
StylePropertyUnits,
|
||||
STYLE_STORE_KEY,
|
||||
type StyleStore,
|
||||
type StyleStoreValue
|
||||
type StyleStoreValue,
|
||||
type StylePropertyValue
|
||||
} from './quickStyleProperties'
|
||||
|
||||
export let prop: StyleStoreValue['style'][number]['prop']
|
||||
@@ -21,7 +22,19 @@
|
||||
let unit: (typeof StylePropertyUnits)[number] = StylePropertyUnits[0]
|
||||
let internalValue: number | string
|
||||
|
||||
$: internalValue = value ? +value.replace(unit, '') : ''
|
||||
function getInteralValue(value: string | undefined, propValue: StylePropertyValue) {
|
||||
if (!value) {
|
||||
return ''
|
||||
}
|
||||
if (propValue.type === StylePropertyType.number) {
|
||||
return value
|
||||
}
|
||||
if (propValue.type === StylePropertyType.text) {
|
||||
return +value.replace(unit, '')
|
||||
}
|
||||
return ''
|
||||
}
|
||||
$: internalValue = getInteralValue(value, prop.value as StylePropertyValue)
|
||||
$: dispatch('change', value)
|
||||
|
||||
function updateValue(next: number) {
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="py-1" role="none">
|
||||
<a
|
||||
<button
|
||||
on:click={() => {
|
||||
if ($workspaceStore === 'admins') {
|
||||
return
|
||||
@@ -88,13 +88,12 @@
|
||||
switchWorkspace('admins')
|
||||
close()
|
||||
}}
|
||||
href=""
|
||||
class="text-gray-700 block px-4 py-2 text-sm hover:bg-gray-100 hover:text-gray-900"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<Icon class="pr-0.5" data={faCog} /> Superadmin workspace
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="py-1" role="none">
|
||||
|
||||
@@ -316,9 +316,9 @@
|
||||
<div>
|
||||
<div class="mb-1 font-semibold text-gray-700">Schema</div>
|
||||
<div class="mb-2 w-full flex flex-row-reverse">
|
||||
<Button on:click={openInferrer} size="sm" color="dark" variant="border"
|
||||
>Infer schema from a json value</Button
|
||||
>
|
||||
<Button on:click={openInferrer} size="sm" color="dark" variant="border">
|
||||
Infer schema from a json value
|
||||
</Button>
|
||||
</div>
|
||||
<SchemaEditor bind:schema={newResourceType.schema} />
|
||||
</div>
|
||||
@@ -340,9 +340,9 @@
|
||||
documentationLink="https://docs.windmill.dev/docs/core_concepts/resources_and_types"
|
||||
>
|
||||
<div class="flex flex-row justify-end gap-4">
|
||||
<Button variant="border" size="md" startIcon={{ icon: faPlus }} on:click={startNewType}
|
||||
>Add a resource type</Button
|
||||
>
|
||||
<Button variant="border" size="md" startIcon={{ icon: faPlus }} on:click={startNewType}>
|
||||
Add a resource type
|
||||
</Button>
|
||||
<Button size="md" startIcon={{ icon: faChain }} on:click={() => appConnect.open?.()}>
|
||||
Add a resource/API
|
||||
</Button>
|
||||
@@ -357,19 +357,23 @@
|
||||
</Tab>
|
||||
<Tab size="md" value="types">
|
||||
<div class="flex gap-2 items-center my-1">
|
||||
Resource Types <Tooltip documentationLink="https://docs.windmill.dev/docs/core_concepts/resources_and_types"
|
||||
>Every resources have Resource Types attached to them which contains its schema and make
|
||||
it easy in scripts and flows to accept only resources of a specific resource type</Tooltip
|
||||
Resource Types
|
||||
<Tooltip
|
||||
documentationLink="https://docs.windmill.dev/docs/core_concepts/resources_and_types"
|
||||
>
|
||||
Every resources have Resource Types attached to them which contains its schema and make it
|
||||
easy in scripts and flows to accept only resources of a specific resource type
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab size="md" value="states">
|
||||
<div class="flex gap-2 items-center my-1">
|
||||
States <Tooltip
|
||||
>States are actually resources (but excluded from the Workspace tab for clarity). States
|
||||
States
|
||||
<Tooltip>
|
||||
States are actually resources (but excluded from the Workspace tab for clarity). States
|
||||
are used by scripts to keep data persistent between runs of the same script by the same
|
||||
trigger (schedule or user)</Tooltip
|
||||
>
|
||||
trigger (schedule or user)
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@@ -413,8 +417,8 @@
|
||||
>{#if marked}{@html marked}{:else}{path}{/if}</a
|
||||
>
|
||||
</td>
|
||||
<td class="px-2"
|
||||
><a
|
||||
<td class="px-2">
|
||||
<a
|
||||
href="#{name}"
|
||||
on:click={() => {
|
||||
const linkedRt = resourceTypes?.find((rt) => rt.name === resource_type)
|
||||
@@ -431,14 +435,16 @@
|
||||
true
|
||||
)
|
||||
}
|
||||
}}><IconedResourceType name={resource_type} after={true} /></a
|
||||
></td
|
||||
>
|
||||
<td
|
||||
><span class="text-gray-500 text-xs"
|
||||
>{removeMarkdown(truncate(description ?? '', 30))}</span
|
||||
></td
|
||||
>
|
||||
}}
|
||||
>
|
||||
<IconedResourceType name={resource_type} after={true} />
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="text-gray-500 text-xs">
|
||||
{removeMarkdown(truncate(description ?? '', 30))}
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<div class="flex flex-row">
|
||||
<div class="w-10">
|
||||
@@ -595,8 +601,8 @@
|
||||
{#if resourceTypes}
|
||||
{#each resourceTypes as { name, description, schema, canWrite }}
|
||||
<tr>
|
||||
<td
|
||||
><a
|
||||
<td>
|
||||
<a
|
||||
href="#{name}"
|
||||
on:click={() => {
|
||||
resourceTypeViewerObj = {
|
||||
@@ -606,22 +612,25 @@
|
||||
}
|
||||
|
||||
resourceTypeViewer.openDrawer?.()
|
||||
}}><IconedResourceType after={true} {name} /></a
|
||||
></td
|
||||
>
|
||||
<td
|
||||
><span class="text-gray-500 text-xs"
|
||||
>{removeMarkdown(truncate(description ?? '', 200))}</span
|
||||
></td
|
||||
>
|
||||
}}
|
||||
>
|
||||
<IconedResourceType after={true} {name} />
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="text-gray-500 text-xs">
|
||||
{removeMarkdown(truncate(description ?? '', 200))}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
{#if !canWrite}
|
||||
<Badge
|
||||
>Shared globally<Tooltip
|
||||
>This resource type is from the 'admins' workspace shared with all
|
||||
workspaces</Tooltip
|
||||
></Badge
|
||||
>
|
||||
<Badge>
|
||||
Shared globally
|
||||
<Tooltip>
|
||||
This resource type is from the 'admins' workspace shared with all
|
||||
workspaces
|
||||
</Tooltip>
|
||||
</Badge>
|
||||
{:else if $userStore?.is_admin || $userStore?.is_super_admin}
|
||||
<Button
|
||||
size="sm"
|
||||
@@ -633,12 +642,13 @@
|
||||
Delete
|
||||
</Button>
|
||||
{:else}
|
||||
<Badge
|
||||
>Non Editable <Tooltip
|
||||
>Since resource types are shared with the whole workspace, only admins can
|
||||
edit/delete them</Tooltip
|
||||
></Badge
|
||||
>
|
||||
<Badge>
|
||||
Non Editable
|
||||
<Tooltip>
|
||||
Since resource types are shared with the whole workspace, only admins can
|
||||
edit/delete them
|
||||
</Tooltip>
|
||||
</Badge>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user