UX improvements

This commit is contained in:
Ruben Fiszel
2022-11-26 23:09:21 +01:00
parent ac6454b383
commit 6c03aad73e
19 changed files with 245 additions and 166 deletions
+96 -15
View File
@@ -24,6 +24,7 @@
"set-interval-async": "^3.0.2",
"svelte-autosize": "^1.0.1",
"svelte-chartjs": "^3.1.0",
"svelte-select": "^5.0.0-beta.40",
"vscode-ws-jsonrpc": "^2.0.0"
},
"devDependencies": {
@@ -255,6 +256,19 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/@floating-ui/core": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.0.2.tgz",
"integrity": "sha512-Skfy0YS3NJ5nV9us0uuPN0HDk1Q4edljaOhRBJGDWs9EBa7ZVMYBHRFlhLvvmwEoaIM9BlH6QJFn9/uZg0bACg=="
},
"node_modules/@floating-ui/dom": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.0.7.tgz",
"integrity": "sha512-6RsqvCYe0AYWtsGvuWqCm7mZytnXAZCjWtsWu1Kg8dI3INvj/DbKlDsZO+mKSaQdPT12uxIW9W2dAWJkPx4Y5g==",
"dependencies": {
"@floating-ui/core": "^1.0.2"
}
},
"node_modules/@fortawesome/fontawesome-common-types": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.2.0.tgz",
@@ -1993,8 +2007,7 @@
"node_modules/dedent-js": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz",
"integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==",
"dev": true
"integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ=="
},
"node_modules/deep-extend": {
"version": "0.6.0",
@@ -3736,7 +3749,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
"dev": true,
"dependencies": {
"tslib": "^2.0.3"
}
@@ -4047,7 +4059,6 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
"dev": true,
"dependencies": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
@@ -4282,7 +4293,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
"dev": true,
"dependencies": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
@@ -5978,6 +5988,29 @@
"integrity": "sha512-uSiaGiSY5KCTx5OtColSk/1qFFUAzGvnoQYDE5xfOmcyvf3lAI1IjPv0p0LRKrTudS9rGZYWPx44qsD09ER6QQ==",
"dev": true
},
"node_modules/svelte-floating-ui": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/svelte-floating-ui/-/svelte-floating-ui-0.3.2.tgz",
"integrity": "sha512-L5YqnVLfCp+JcGNMD6MFdmzsFSgskFR+TJ/2xhKjSQkAXi4dTowImb5HzAAsJpPOPY10e/+Ta/ucyNTZPGr3VQ==",
"dependencies": {
"@floating-ui/core": "^0.7.3",
"@floating-ui/dom": "^0.5.4",
"svelte2tsx": "^0.5.11"
}
},
"node_modules/svelte-floating-ui/node_modules/@floating-ui/core": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-0.7.3.tgz",
"integrity": "sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg=="
},
"node_modules/svelte-floating-ui/node_modules/@floating-ui/dom": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.5.4.tgz",
"integrity": "sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg==",
"dependencies": {
"@floating-ui/core": "^0.7.3"
}
},
"node_modules/svelte-grid": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/svelte-grid/-/svelte-grid-5.1.1.tgz",
@@ -6115,6 +6148,15 @@
"sourcemap-codec": "^1.4.8"
}
},
"node_modules/svelte-select": {
"version": "5.0.0-beta.40",
"resolved": "https://registry.npmjs.org/svelte-select/-/svelte-select-5.0.0-beta.40.tgz",
"integrity": "sha512-qL21CUu/H+sVdIynYMdZTEEEAWgeWYgpGAiDq87wPfc1PK69Osl4p6zZOCEmHhNwW5s9gUqe67ovh9Fx/NbdKA==",
"dependencies": {
"@floating-ui/dom": "^1.0.2",
"svelte-floating-ui": "^0.3.2"
}
},
"node_modules/svelte-splitpanes": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/svelte-splitpanes/-/svelte-splitpanes-0.7.3.tgz",
@@ -6159,7 +6201,6 @@
"version": "0.5.20",
"resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.5.20.tgz",
"integrity": "sha512-yNHmN/uoAnJ7d1XqVohiNA6TMFOxibHyEddUAHVt1PiLXtbwAJF3WaGYlg8QbOdoXzOVsVNCAlqRUIdULUm+OA==",
"dev": true,
"dependencies": {
"dedent-js": "^1.0.1",
"pascal-case": "^3.1.1"
@@ -6442,7 +6483,6 @@
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -7058,6 +7098,19 @@
"strip-json-comments": "^3.1.1"
}
},
"@floating-ui/core": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.0.2.tgz",
"integrity": "sha512-Skfy0YS3NJ5nV9us0uuPN0HDk1Q4edljaOhRBJGDWs9EBa7ZVMYBHRFlhLvvmwEoaIM9BlH6QJFn9/uZg0bACg=="
},
"@floating-ui/dom": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.0.7.tgz",
"integrity": "sha512-6RsqvCYe0AYWtsGvuWqCm7mZytnXAZCjWtsWu1Kg8dI3INvj/DbKlDsZO+mKSaQdPT12uxIW9W2dAWJkPx4Y5g==",
"requires": {
"@floating-ui/core": "^1.0.2"
}
},
"@fortawesome/fontawesome-common-types": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.2.0.tgz",
@@ -8269,8 +8322,7 @@
"dedent-js": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz",
"integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==",
"dev": true
"integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ=="
},
"deep-extend": {
"version": "0.6.0",
@@ -9504,7 +9556,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
"dev": true,
"requires": {
"tslib": "^2.0.3"
}
@@ -9737,7 +9788,6 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
"dev": true,
"requires": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
@@ -9909,7 +9959,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
"dev": true,
"requires": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
@@ -11100,6 +11149,31 @@
"integrity": "sha512-uSiaGiSY5KCTx5OtColSk/1qFFUAzGvnoQYDE5xfOmcyvf3lAI1IjPv0p0LRKrTudS9rGZYWPx44qsD09ER6QQ==",
"dev": true
},
"svelte-floating-ui": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/svelte-floating-ui/-/svelte-floating-ui-0.3.2.tgz",
"integrity": "sha512-L5YqnVLfCp+JcGNMD6MFdmzsFSgskFR+TJ/2xhKjSQkAXi4dTowImb5HzAAsJpPOPY10e/+Ta/ucyNTZPGr3VQ==",
"requires": {
"@floating-ui/core": "^0.7.3",
"@floating-ui/dom": "^0.5.4",
"svelte2tsx": "^0.5.11"
},
"dependencies": {
"@floating-ui/core": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-0.7.3.tgz",
"integrity": "sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg=="
},
"@floating-ui/dom": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.5.4.tgz",
"integrity": "sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg==",
"requires": {
"@floating-ui/core": "^0.7.3"
}
}
}
},
"svelte-grid": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/svelte-grid/-/svelte-grid-5.1.1.tgz",
@@ -11176,6 +11250,15 @@
}
}
},
"svelte-select": {
"version": "5.0.0-beta.40",
"resolved": "https://registry.npmjs.org/svelte-select/-/svelte-select-5.0.0-beta.40.tgz",
"integrity": "sha512-qL21CUu/H+sVdIynYMdZTEEEAWgeWYgpGAiDq87wPfc1PK69Osl4p6zZOCEmHhNwW5s9gUqe67ovh9Fx/NbdKA==",
"requires": {
"@floating-ui/dom": "^1.0.2",
"svelte-floating-ui": "^0.3.2"
}
},
"svelte-splitpanes": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/svelte-splitpanes/-/svelte-splitpanes-0.7.3.tgz",
@@ -11210,7 +11293,6 @@
"version": "0.5.20",
"resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.5.20.tgz",
"integrity": "sha512-yNHmN/uoAnJ7d1XqVohiNA6TMFOxibHyEddUAHVt1PiLXtbwAJF3WaGYlg8QbOdoXzOVsVNCAlqRUIdULUm+OA==",
"dev": true,
"requires": {
"dedent-js": "^1.0.1",
"pascal-case": "^3.1.1"
@@ -11421,8 +11503,7 @@
"typescript": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
"dev": true
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ=="
},
"uglify-js": {
"version": "3.16.3",
+1
View File
@@ -74,6 +74,7 @@
"set-interval-async": "^3.0.2",
"svelte-autosize": "^1.0.1",
"svelte-chartjs": "^3.1.0",
"svelte-select": "^5.0.0-beta.40",
"vscode-ws-jsonrpc": "^2.0.0"
}
}
+13 -42
View File
@@ -201,7 +201,12 @@
You can also contribute to windmill and add it as an API integration if relevant.
</Alert>
{/if}
<div class="mb-1 font-semibold text-gray-700">OAuth APIs</div>
<h2 class="mb-2">OAuth APIs</h2>
{#if Object.keys(connects).length == 0}
<Alert class="mb-4" type="error" title="No OAuth connection setup">
Your instance has no OAuth connection setup. You can still add a resource manually.
</Alert>
{/if}
<div class="grid sm:grid-cols-2 md:grid-cols-3 gap-x-2 gap-y-1 items-center mb-2">
{#each Object.entries(connects).sort((a, b) => a[0].localeCompare(b[0])) as [key, values]}
<Button
@@ -222,7 +227,7 @@
</Button>
{/each}
</div>
<div class="mb-1 font-semibold text-gray-700 mt-6">Scopes</div>
<h3>Scopes</h3>
{#if !manual && resource_type != ''}
{#each scopes as v}
<div class="flex flex-row max-w-md mb-2">
@@ -259,47 +264,13 @@
{:else}
<p class="italic text-sm">Pick an OAuth API and customize the scopes here</p>
{/if}
<div class="mb-1 font-semibold text-gray-700 mt-6">Extra params</div>
{#if !manual && resource_type != ''}
{#each extra_params as [k, v]}
<div class="flex flex-row max-w-md mb-2">
<input type="text" bind:value={k} class="mr-2" />
<input type="text" bind:value={v} />
<Button
variant="border"
color="red"
size="xs"
btnClasses="mx-6"
on:click={() => {
extra_params = extra_params.filter((el) => el[0] != k)
}}
>
<Icon data={faMinus} />
</Button>
</div>
{/each}
<div class="flex items-center mt-1">
<Button
variant="border"
color="blue"
size="sm"
endIcon={{ icon: faPlus }}
on:click={() => {
extra_params.push(['', ''])
extra_params = extra_params
}}
>
Add item
</Button>
<span class="ml-2 text-sm text-gray-500">
({(extra_params ?? []).length} item{(extra_params ?? []).length > 1 ? 's' : ''})
</span>
</div>
{:else}
<p class="italic text-sm">Pick an OAuth API and customize the extra parameters here</p>
<h2 class="mt-8 mb-2">Non OAuth APIs</h2>
{#if Object.keys(connectsManual).length == 0}
<Alert class="mb-4" type="error" title="No resource types synced">
Your instance has no resource types setup. Sync with the hub to get all the latest
resource types.
</Alert>
{/if}
<div class="mb-1 font-semibold text-gray-700 mt-6">Non OAuth APIs</div>
<div class="grid sm:grid-cols-2 md:grid-cols-3 gap-x-2 gap-y-1 items-center mb-2">
{#each connectsManual as [key, instructions]}
<Button
+7 -4
View File
@@ -123,9 +123,12 @@
$: {
if (value == undefined || value == null) {
value = defaultValue
if ((defaultValue === undefined || defaultValue === null) && inputCat === 'string') {
value = ''
}
if (defaultValue === undefined || defaultValue === null)
if (inputCat === 'string') {
value = ''
} else if (inputCat == 'enum') {
value = enum_?.[0]
}
}
}
@@ -268,7 +271,7 @@
</span>
</div>
{:else if inputCat == 'resource-object'}
<ObjectResourceInput {format} bind:value />
<ObjectResourceInput {compact} {format} bind:value />
{:else if inputCat == 'object'}
{#if properties && Object.keys(properties).length > 0}
<div class="p-4 pl-8 border rounded w-full">
+1 -1
View File
@@ -49,7 +49,7 @@
/>
</div>
{#if !disabled}
<div class="flex flex-row text-xs text-blue-500 gap-3 pl-28">
<div class="flex flex-row text-xs text-blue-500 gap-3 pl-28 mb-2">
<button
on:click={() => {
schedule = '0 */15 * * *'
+9 -4
View File
@@ -199,19 +199,24 @@
loadItems={async () =>
await ResourceService.listResource({ workspace: $workspaceStore ?? 'NO_W' })}
>
<div slot="submission" class="flex flex-row gap-x-1">
<Button target="_blank" color="blue" size="sm" href="/resources?connect_app=undefined">
<div slot="submission" class="flex flex-row gap-x-1 mr-2">
<Button
target="_blank"
variant="border"
color="blue"
size="sm"
href="/resources?connect_app=undefined"
>
Connect an API
</Button>
<Button
variant="border"
color="blue"
size="sm"
on:click={() => {
resourceEditor.initNew()
}}
>
New custom resource
Add a resource
</Button>
</div>
</ItemPicker>
@@ -10,7 +10,7 @@
sendUserToast,
setQueryWithoutLoad
} from '$lib/utils'
import { faEye, faPen } from '@fortawesome/free-solid-svg-icons'
import { faEye, faPen, faSave } from '@fortawesome/free-solid-svg-icons'
import { setContext } from 'svelte'
import { writable } from 'svelte/store'
import CenteredPage from './CenteredPage.svelte'
@@ -244,7 +244,12 @@
<div class="flex flex-row space-x-2">
<FlowPreviewButtons />
<div class="center-center">
<Button disabled={pathError != ''} size="sm" on:click={saveFlow}>Save</Button>
<Button
disabled={pathError != ''}
startIcon={{ icon: faSave }}
size="sm"
on:click={saveFlow}>Save</Button
>
</div>
</div>
</div>
@@ -151,12 +151,18 @@
}}
>
{#if isStaticTemplate(inputCat)}
<ToggleButton position="left" value="static" size="xs">Template</ToggleButton>
<ToggleButton light position="left" value="static" size="xs">Template</ToggleButton>
{:else}
<ToggleButton position="left" value="static" size="xs">Static</ToggleButton>
<ToggleButton light position="left" value="static" size="xs">Static</ToggleButton>
{/if}
<ToggleButton position="right" value="javascript" startIcon={{ icon: faCode }} size="xs">
<ToggleButton
light
position="right"
value="javascript"
startIcon={{ icon: faCode }}
size="xs"
>
Dynamic (JS)
</ToggleButton>
</ToggleButtonGroup>
@@ -1,13 +1,15 @@
<script lang="ts">
import { ResourceService } from '$lib/gen'
import { logout } from '$lib/logout'
import { workspaceStore } from '$lib/stores'
import RadioButton from './RadioButton.svelte'
import { ToggleButton, ToggleButtonGroup } from './common'
import ResourcePicker from './ResourcePicker.svelte'
import SchemaForm from './SchemaForm.svelte'
export let format: string
export let value: any
export let compact: boolean
function isString(value: any) {
return typeof value === 'string' || value instanceof String
@@ -58,18 +60,27 @@
$: value && valueToPath()
</script>
<div class="flex flex-row w-full flex-wrap gap-x-2">
<div class="shrink">
<RadioButton
options={[
[`Resource (${resourceTypeName})`, 'resource'],
[`Raw object value`, 'raw']
]}
on:change={argToValue}
bind:value={option}
/>
<div class="flex flex-col w-full flex-wrap gap-x-2 gap-y-0.5">
<div class="shrink flex flex-row justify-center">
<div>
<ToggleButtonGroup
bind:selected={option}
on:selected={(e) => {
if (e.detail === 'resource') {
resourceToValue()
} else {
argToValue()
}
}}
>
<ToggleButton light position="left" value="resource" size="xs"
>Resource ({resourceTypeName})</ToggleButton
>
<ToggleButton light position="right" value="raw" size="xs">Raw</ToggleButton>
</ToggleButtonGroup>
</div>
</div>
<div class="grow">
<div>
{#if option == 'resource'}
<ResourcePicker
on:refresh={() => loadSchema(format)}
@@ -83,13 +94,9 @@
: undefined}
/>
{:else}
<div class="border rounded p-5 w-full">
<h2 class="mb-5">
Object of <a target="_blank" href="/resources">resource type</a>
{resourceTypeName}
</h2>
<div class="border rounded p-2 w-full">
{#if !isString(args)}
<SchemaForm {schema} bind:isValid bind:args />
<SchemaForm {compact} {schema} bind:isValid bind:args />
{/if}
</div>
{/if}
@@ -15,6 +15,7 @@
import DrawerContent from './common/drawer/DrawerContent.svelte'
import autosize from 'svelte-autosize'
import SimpleEditor from './SimpleEditor.svelte'
import AppConnect from './AppConnect.svelte'
let path = ''
let initialPath = ''
@@ -217,8 +218,17 @@
</div>
{/if}
</div>
<span slot="submission" class="flex gap-4">
<span slot="submission" class="flex gap-4 mr-2">
{#if step === 1}
<Button
target="_blank"
color="blue"
variant="border"
size="sm"
href="/resources?connect_app=undefined"
>
Connect an API
</Button>
<Button
on:click={async () => {
await loadResourceType()
@@ -1,8 +1,12 @@
<script lang="ts">
import { ResourceService, type Resource } from '$lib/gen'
import { workspaceStore } from '$lib/stores'
import { faPlus, faRotateRight } from '@fortawesome/free-solid-svg-icons'
import { createEventDispatcher } from 'svelte'
import Icon from 'svelte-awesome'
import { Button } from './common'
import ResourceEditor from './ResourceEditor.svelte'
import Select from 'svelte-select'
const dispatch = createEventDispatcher()
let resources: Resource[] = []
@@ -24,38 +28,33 @@
}
}
$: dispatch('change', value)
$: collection = resources.map((x) => ({
value: x.path,
label: `${x.path}${x.description ? ' | ' + x.description : ''}`
}))
</script>
<ResourceEditor bind:this={resourceEditor} on:refresh={() => loadResources(resourceType)} />
<select bind:value placeholder="Pick a resource {resourceType}">
<option value={undefined} />
{#each resources as r}
<option value={r.path}>{r.path}{r.description ? ' | ' + r.description : ''}</option>
{/each}
</select>
<div class="flex flex-row gap-2">
<a
class="text-xs hover:underline"
rel="noreferrer"
target="_blank"
href="/resources?connect_app={resourceType}">Connect {resourceType} with OAuth</a
>
<button
class="text-xs text-blue-500 font-normal"
type="button"
on:click={() => {
loadResources(resourceType)
}}
>
refresh
</button>
<button
class="text-xs text-blue-500 font-normal"
type="button"
<div class="flex flex-row gap-x-1">
<Select
bind:justValue={value}
items={collection}
class="grow"
placeholder="Pick a {resourceType} resource"
/>
<Button
variant="border"
size="xs"
on:click={() => {
resourceEditor.initNew(resourceType)
}}
}}><Icon scale={0.8} data={faPlus} /></Button
>
<Button
variant="border"
size="xs"
on:click={() => {
loadResources(resourceType)
}}><Icon scale={0.8} data={faRotateRight} /></Button
>
+Create a new {resourceType}
</button>
</div>
@@ -161,6 +161,7 @@
variant={step == 1 ? 'border' : 'contained'}
disabled={step === 1 && pathError !== ''}
btnClasses={step == 1 && initialPath == '' ? 'invisible' : ''}
startIcon={{ icon: faSave }}
on:click={editScript}>Save</Button
>
</div>
@@ -194,7 +194,7 @@
classes: 'animate-none'
}}
>
{testIsLoading ? 'Running' : 'Test (Ctrl+Enter)'}
{#if testIsLoading}Running{:else}Test <Kbd class="ml-4">Ctrl+Enter</Kbd>{/if}
</Button>
{/if}
</div>
+24 -39
View File
@@ -1,10 +1,10 @@
<script lang="ts">
import { ScriptService, FlowService, Script } from '$lib/gen'
import { faSearch } from '@fortawesome/free-solid-svg-icons'
import { hubScripts, workspaceStore } from '$lib/stores'
import { createEventDispatcher } from 'svelte'
import ItemPicker from './ItemPicker.svelte'
import Select from 'svelte-select'
import { getScriptByPath } from '$lib/utils'
import RadioButton from './RadioButton.svelte'
@@ -17,8 +17,7 @@
export let itemKind: 'hub' | 'script' | 'flow' = allowHub ? 'hub' : 'script'
export let kind: Script.kind = Script.kind.SCRIPT
let items: { summary: String; path: String; version?: String }[] = []
let itemPicker: ItemPicker
let items: { value: string; label: string }[] = []
let drawerViewer: Drawer
let code: string = ''
let lang: 'deno' | 'python3' | 'go' | 'bash' | undefined
@@ -30,53 +29,39 @@
async function loadItems(): Promise<void> {
if (itemKind == 'flow') {
items = await FlowService.listFlows({ workspace: $workspaceStore! })
items = (await FlowService.listFlows({ workspace: $workspaceStore! })).map((flow) => ({
value: flow.path,
label: `${flow.path}${flow.summary ? `| ${flow.summary}` : ''}`
}))
} else if (itemKind == 'script') {
items = await ScriptService.listScripts({ workspace: $workspaceStore!, kind })
items = (await ScriptService.listScripts({ workspace: $workspaceStore!, kind })).map(
(script) => ({
value: script.path,
label: `${script.path}${script.summary ? `| ${script.summary}` : ''}`
})
)
} else {
items = $hubScripts ?? []
items =
$hubScripts?.map((x) => ({
value: x.path,
label: `${x.path}${x.summary ? `| ${x.summary}` : ''}`
})) ?? []
}
}
$: {
if ($workspaceStore) {
loadItems()
}
}
$: $workspaceStore && itemKind && loadItems()
$: dispatch('select', { path: scriptPath })
</script>
<ItemPicker
bind:this={itemPicker}
pickCallback={(path, _) => {
scriptPath = path
dispatch('select', { path: scriptPath })
}}
itemName={itemKind == 'flow' ? 'Flow' : 'Script'}
extraField="summary"
loadItems={async () => {
await loadItems()
return items
}}
/>
<div class="flex flex-row flex-wrap 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 -mb-2">
<div class="w-80">
<RadioButton bind:value={itemKind} {options} />
</div>
{/if}
<div class="flex items-center grow gap-4">
<input class="grow w-full" type="text" value={scriptPath ?? 'No path chosen yet'} disabled />
<Button
size="sm"
endIcon={{ icon: faSearch }}
btnClasses="mx-auto whitespace-nowrap"
on:click={() => itemPicker.openDrawer()}
>
Pick a {itemKind} path
</Button>
</div>
<Select class="grow" bind:justValue={scriptPath} {items} placeholder="Pick a {itemKind}" />
{#if scriptPath !== undefined && scriptPath !== ''}
<Button
color="light"
@@ -23,7 +23,6 @@
export let buttonType: 'button' | 'submit' | 'reset' = 'button'
export let loading = false
const dispatch = createEventDispatcher()
// Order of classes: border, border modifier, bg, bg modifier, text, text modifier, everything else
const colorVariants: Record<ButtonType.Color, Record<ButtonType.Variant, string>> = {
@@ -47,6 +46,12 @@
'border-gray-800 hover:border-gray-900 focus:border-gray-900 bg-white hover:bg-gray-200 focus:bg-gray-200 text-gray-800 hover:text-gray-900 focus:text-gray-900 focus:ring-gray-300',
contained: 'bg-gray-700 hover:bg-gray-900 focus:bg-gray-900 text-white focus:ring-gray-300'
},
gray: {
border:
'border-gray-600 hover:border-gray-900 focus:border-gray-900 bg-white hover:bg-gray-200 focus:bg-gray-200 text-gray-800 hover:text-gray-900 focus:text-gray-900 focus:ring-gray-300',
contained:
'bg-gray-700/90 hover:bg-gray-900/90 focus:bg-gray-900/90 text-white focus:ring-gray-300'
},
light: {
border:
'border border-gray-300 bg-white hover:bg-gray-100 focus:bg-gray-100 text-gray-700 hover:text-gray-800 focus:text-gray-800 focus:ring-gray-300',
@@ -1,4 +1,4 @@
export const BUTTON_COLORS = ['blue', 'red', 'dark', 'light', 'green'] as const
export const BUTTON_COLORS = ['blue', 'red', 'dark', 'light', 'green', 'gray'] as const
export namespace ButtonType {
@@ -1,12 +1,12 @@
<script lang="ts">
import { classNames } from '$lib/utils'
import { faRing } from '@fortawesome/free-solid-svg-icons'
import { getContext } from 'svelte'
import Button from '../button/Button.svelte'
import type { ToggleButtonContext } from './ToggleButtonGroup.svelte'
export let value: any
export let position: 'left' | 'center' | 'right'
export let light = false
const { select, selected } = getContext<ToggleButtonContext>('ToggleButtonGroup')
</script>
@@ -20,7 +20,7 @@
position === 'center' ? 'rounded-none border-t border-b' : '',
position === 'right' ? 'rounded-none rounded-r-md !border border-l-0' : ''
)}
color={$selected === value ? 'dark' : 'light'}
color={$selected === value ? (light ? 'gray' : 'dark') : 'light'}
variant="contained"
>
<slot />
@@ -20,7 +20,7 @@
import { userStore, workspaceStore } from '$lib/stores'
import CenteredPage from '$lib/components/CenteredPage.svelte'
import RunForm from '$lib/components/RunForm.svelte'
import { Button, Skeleton } from '$lib/components/common'
import { Button, Kbd, Skeleton } from '$lib/components/common'
import { faPlay, faScroll } from '@fortawesome/free-solid-svg-icons'
import SharedBadge from '$lib/components/SharedBadge.svelte'
import SvelteMarkdown from 'svelte-markdown'
@@ -103,7 +103,7 @@
<Button
startIcon={{ icon: faPlay }}
disabled={runForm == undefined || !isValid}
on:click={() => runForm?.run()}>Run (Ctrl+Enter)</Button
on:click={() => runForm?.run()}>Run <Kbd class="ml-2">Ctrl+Enter</Kbd></Button
>
</div>
</div>
@@ -23,7 +23,7 @@
import { inferArgs } from '$lib/infer'
import CenteredPage from '$lib/components/CenteredPage.svelte'
import RunForm from '$lib/components/RunForm.svelte'
import { Alert, Badge, Button, Skeleton } from '$lib/components/common'
import { Alert, Badge, Button, Kbd, Skeleton } from '$lib/components/common'
import SharedBadge from '$lib/components/SharedBadge.svelte'
import SvelteMarkdown from 'svelte-markdown'
import { faPlay, faScroll } from '@fortawesome/free-solid-svg-icons'
@@ -128,7 +128,7 @@
<Button
startIcon={{ icon: faPlay }}
disabled={runForm == undefined || !isValid}
on:click={() => runForm?.run()}>Run (Ctrl+Enter)</Button
on:click={() => runForm?.run()}>Run <Kbd class="ml-2">Ctrl+Enter</Kbd></Button
>
</div>
</div>