mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-19 08:01:25 +00:00
feat: add resource and resource type from json
This commit is contained in:
@@ -19,7 +19,7 @@ export interface SchemaProperty {
|
||||
}
|
||||
|
||||
export type Schema = {
|
||||
$schema: string
|
||||
$schema: string | undefined
|
||||
type: string
|
||||
properties: { [name: string]: SchemaProperty }
|
||||
required: string[]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import { emptySchema, emptyString } from '$lib/utils'
|
||||
import SchemaForm from './SchemaForm.svelte'
|
||||
import SimpleEditor from './SimpleEditor.svelte'
|
||||
import Toggle from './Toggle.svelte'
|
||||
|
||||
export let resource_type: string
|
||||
export let args: Record<string, any> | any = {}
|
||||
@@ -12,7 +13,10 @@
|
||||
|
||||
let schema = emptySchema()
|
||||
let notFound = false
|
||||
|
||||
async function loadSchema() {
|
||||
rawCode = '{}'
|
||||
viewJsonSchema = false
|
||||
try {
|
||||
const rt = await ResourceService.getResourceType({
|
||||
workspace: $workspaceStore!,
|
||||
@@ -21,8 +25,6 @@
|
||||
schema = rt.schema
|
||||
notFound = false
|
||||
} catch (e) {
|
||||
rawCode = '{}'
|
||||
|
||||
notFound = true
|
||||
}
|
||||
}
|
||||
@@ -43,17 +45,38 @@
|
||||
}
|
||||
let error = ''
|
||||
let rawCode = ''
|
||||
let viewJsonSchema = false
|
||||
|
||||
function switchTab(asJson: boolean) {
|
||||
viewJsonSchema = asJson
|
||||
if (asJson) {
|
||||
rawCode = JSON.stringify(args, null, 2)
|
||||
} else {
|
||||
parseJson()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if notFound}
|
||||
{#if !notFound}
|
||||
<div class="w-full flex flex-row-reverse">
|
||||
<Toggle
|
||||
on:change={(e) => switchTab(e.detail)}
|
||||
options={{
|
||||
right: 'As JSON'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<p class="italic text-gray-500 text-xs mb-4"
|
||||
>No corresponding resource type found in your workspace for {resource_type}. Define the value in
|
||||
JSON directly</p
|
||||
>
|
||||
{/if}
|
||||
{#if notFound || viewJsonSchema}
|
||||
{#if !emptyString(error)}<span class="text-red-400 text-xs mb-1 flex flex-row-reverse"
|
||||
>{error}</span
|
||||
>{:else}<div class="py-2" />{/if}
|
||||
<SimpleEditor autoHeight lang="json" bind:code={rawCode} fixedOverflowWidgets={false} />
|
||||
{:else}
|
||||
<SchemaForm {password} isValid {schema} bind:args />
|
||||
<SchemaForm noDelete {password} isValid {schema} bind:args />
|
||||
{/if}
|
||||
|
||||
@@ -155,6 +155,7 @@
|
||||
async function next() {
|
||||
if (step == 1 && manual) {
|
||||
step += 1
|
||||
args = {}
|
||||
} else if (step == 1 && !manual) {
|
||||
const url = new URL(`/api/oauth/connect/${resource_type}`, $page.url.origin)
|
||||
url.searchParams.append('scopes', scopes.join('+'))
|
||||
@@ -410,15 +411,17 @@
|
||||
</ol>
|
||||
</div>
|
||||
{#if apiTokenApps[resource_type].img}
|
||||
<div class="mt-4 w-full">
|
||||
<img class="max-h-96 m-auto" alt="connect" src={apiTokenApps[resource_type].img} />
|
||||
<div class="mt-4 w-full overflow-hidden">
|
||||
<img class="m-auto max-h-60" alt="connect" src={apiTokenApps[resource_type].img} />
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<h2 class="mt-4">Value</h2>
|
||||
<div class="mt-4">
|
||||
<ApiConnectForm password={key ?? ''} {resource_type} bind:args bind:isValid />
|
||||
{#key resource_type}
|
||||
<ApiConnectForm password={key ?? ''} {resource_type} bind:args bind:isValid />
|
||||
{/key}
|
||||
</div>
|
||||
|
||||
<h2 class="mt-4 mb-2">Description</h2>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
import SimpleEditor from './SimpleEditor.svelte'
|
||||
import { faSave } from '@fortawesome/free-solid-svg-icons'
|
||||
import SchemaForm from './SchemaForm.svelte'
|
||||
import Toggle from './Toggle.svelte'
|
||||
|
||||
let path = ''
|
||||
let initialPath = ''
|
||||
@@ -38,6 +39,7 @@
|
||||
path = p
|
||||
resourceToEdit = undefined
|
||||
resourceSchema = undefined
|
||||
viewJsonSchema = false
|
||||
loadingSchema = true
|
||||
drawer.openDrawer?.()
|
||||
resourceToEdit = await ResourceService.getResource({ workspace: $workspaceStore!, path: p })
|
||||
@@ -111,6 +113,16 @@
|
||||
args[k] = `$var:${path}`
|
||||
})
|
||||
}
|
||||
let viewJsonSchema = false
|
||||
|
||||
function switchTab(asJson: boolean) {
|
||||
viewJsonSchema = asJson
|
||||
if (asJson) {
|
||||
rawCode = JSON.stringify(args, null, 2)
|
||||
} else {
|
||||
parseJson()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Drawer bind:this={drawer} size="800px">
|
||||
@@ -136,12 +148,21 @@
|
||||
kind="resource"
|
||||
/>
|
||||
</div>
|
||||
<h3 class="mt-4">Value</h3>
|
||||
<div class="flex w-full justify-between max-w-lg items-center mt-4">
|
||||
<h3>Value</h3>
|
||||
<Toggle
|
||||
on:change={(e) => switchTab(e.detail)}
|
||||
options={{
|
||||
right: 'As JSON'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="text-sm">
|
||||
{#if loadingSchema}
|
||||
<Skeleton layout={[[4]]} />
|
||||
{:else if resourceSchema && resourceSchema?.properties}
|
||||
{:else if !viewJsonSchema && resourceSchema && resourceSchema?.properties}
|
||||
<SchemaForm
|
||||
noDelete
|
||||
disabled={!can_write}
|
||||
compact
|
||||
schema={resourceSchema}
|
||||
@@ -151,10 +172,13 @@
|
||||
{:else if !can_write}
|
||||
<input type="text" disabled value={rawCode} />
|
||||
{:else}
|
||||
<p class="italic text-gray-500 text-xs mb-4"
|
||||
>No corresponding resource type found in your workspace for {selectedResourceType}.
|
||||
Define the value in JSON directly</p
|
||||
>
|
||||
{#if !viewJsonSchema}
|
||||
<p class="italic text-gray-500 text-xs mb-4"
|
||||
>No corresponding resource type found in your workspace for {selectedResourceType}.
|
||||
Define the value in JSON directly</p
|
||||
>
|
||||
{/if}
|
||||
|
||||
{#if !emptyString(jsonError)}<span
|
||||
class="text-red-400 text-xs mb-1 flex flex-row-reverse">{jsonError}</span
|
||||
>{:else}<div class="py-2" />{/if}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
export let filter: string[] | undefined = undefined
|
||||
export let noDynamicToggle = false
|
||||
export let flexWrap = false
|
||||
export let noDelete = false
|
||||
|
||||
let clazz: string = ''
|
||||
export { clazz as class }
|
||||
@@ -59,7 +60,9 @@
|
||||
let lkeys = Object.keys(schema?.properties ?? {})
|
||||
if (schema?.properties && JSON.stringify(lkeys) != JSON.stringify(keys)) {
|
||||
keys = lkeys
|
||||
removeExtraKey()
|
||||
if (!noDelete) {
|
||||
removeExtraKey()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -55,8 +55,10 @@
|
||||
if (open) {
|
||||
switch (event.key) {
|
||||
case 'Escape':
|
||||
open = false
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
event.stopImmediatePropagation()
|
||||
open = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ export interface DropdownItem {
|
||||
|
||||
export function emptySchema() {
|
||||
return {
|
||||
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
||||
$schema: 'https://json-schema.org/draft/2020-12/schema' as string | undefined,
|
||||
properties: {},
|
||||
required: [],
|
||||
type: 'object'
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
import ListFilters from '$lib/components/home/ListFilters.svelte'
|
||||
import SearchItems from '$lib/components/SearchItems.svelte'
|
||||
import autosize from 'svelte-autosize'
|
||||
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
|
||||
import { convert } from '@redocly/json-to-json-schema'
|
||||
import Portal from 'svelte-portal'
|
||||
|
||||
type ResourceW = ListableResource & { canWrite: boolean }
|
||||
type ResourceTypeW = ResourceType & { canWrite: boolean }
|
||||
@@ -200,10 +203,47 @@
|
||||
}
|
||||
})
|
||||
|
||||
function openInferrer(): void {
|
||||
inferrer?.openDrawer?.()
|
||||
}
|
||||
|
||||
let disableCustomPrefix = false
|
||||
let tab: 'workspace' | 'types' | 'states' = 'workspace'
|
||||
|
||||
let inferrer: Drawer | undefined = undefined
|
||||
let inferrerJson = ''
|
||||
|
||||
function inferJson(): void {
|
||||
try {
|
||||
newResourceType.schema = {
|
||||
$schema: undefined,
|
||||
required: [],
|
||||
properties: {},
|
||||
...convert(JSON.parse(inferrerJson))
|
||||
}
|
||||
} catch (e) {
|
||||
sendUserToast(`Invalid JSON: ${e}`, true)
|
||||
}
|
||||
inferrer?.closeDrawer?.()
|
||||
}
|
||||
</script>
|
||||
|
||||
<Portal>
|
||||
<Drawer bind:this={inferrer} size="800px">
|
||||
<DrawerContent title="Import app from JSON" on:close={() => inferrer?.toggleDrawer?.()}>
|
||||
<SimpleEditor
|
||||
bind:code={inferrerJson}
|
||||
lang="json"
|
||||
class="h-full"
|
||||
fixedOverflowWidgets={false}
|
||||
/>
|
||||
<svelte:fragment slot="actions">
|
||||
<Button size="sm" on:click={inferJson}>Infer</Button>
|
||||
</svelte:fragment>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
</Portal>
|
||||
|
||||
<Drawer bind:this={resourceTypeViewer} size="800px">
|
||||
<DrawerContent title={resourceTypeViewerObj.rt} on:close={resourceTypeViewer.closeDrawer}>
|
||||
<div>
|
||||
@@ -259,6 +299,11 @@
|
||||
>
|
||||
<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
|
||||
>
|
||||
</div>
|
||||
<SchemaEditor bind:schema={newResourceType.schema} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user