From d4c1e1ab782884efc7b80c288ff22abcffe639f5 Mon Sep 17 00:00:00 2001 From: Faton Ramadani Date: Fri, 2 Dec 2022 19:39:23 +0100 Subject: [PATCH] UI refactor (#973) * fix(frontend): ui refactor * fix(frontend): WIP * fix(frontend): WIP * fix(frontend): WIP * fix(frontend): remove virtual table * fix(frontend): Add virtual list * fix(frontend): fix number of items * fix(frontend): revert changes * fix(frontend): fix build --- backend/windmill-api/openapi.yaml | 10 +- frontend/package-lock.json | 11 + frontend/package.json | 1 + frontend/src/app.css | 12 + frontend/src/lib/components/Dropdown.svelte | 18 +- frontend/src/lib/components/FlowBox.svelte | 153 -------- frontend/src/lib/components/JobArgs.svelte | 10 +- frontend/src/lib/components/PageHeader.svelte | 4 +- frontend/src/lib/components/ScriptBox.svelte | 173 -------- .../src/lib/components/ScriptEditor.svelte | 2 +- .../src/lib/components/SharedBadge.svelte | 2 +- frontend/src/lib/components/Star.svelte | 2 +- .../src/lib/components/apps/CreateApp.svelte | 73 ++++ .../components/helpers/DebouncedInput.svelte | 5 +- .../lib/components/common/badge/Badge.svelte | 7 +- .../common/button/ButtonPopup.svelte | 4 +- .../lib/components/common/table/AppRow.svelte | 65 +++ .../components/common/table/FlowRow.svelte | 152 ++++++++ .../lib/components/common/table/Row.svelte | 53 +++ .../components/common/table/RowIcon.svelte | 28 ++ .../components/common/table/ScriptRow.svelte | 167 ++++++++ .../lib/components/common/table/Table.svelte | 9 + .../common/toggleButton/ToggleButton.svelte | 6 +- .../toggleButton/ToggleButtonGroup.svelte | 2 +- .../components/flows/CreateActionsFlow.svelte | 11 +- .../components/scriptEditor/LogPanel.svelte | 2 +- .../scripts/CreateActionsScript.svelte | 6 +- .../components/sidebar/SidebarContent.svelte | 2 +- frontend/src/lib/utils.ts | 7 +- frontend/src/routes/apps.svelte | 224 ----------- .../src/routes/apps/edit/[...path].svelte | 2 - frontend/src/routes/apps/get/[...path].svelte | 10 +- frontend/src/routes/audit_logs.svelte | 6 +- .../src/routes/flows/get/[...path].svelte | 2 - frontend/src/routes/index.svelte | 369 +++++++++++------- frontend/src/routes/run/[...run].svelte | 12 +- frontend/src/routes/runs/[...path].svelte | 12 +- .../src/routes/scripts/get/[...hash].svelte | 11 +- .../src/routes/user/workspaces@user.svelte | 10 +- frontend/src/routes/variables.svelte | 6 +- frontend/src/routes/workers.svelte | 6 - frontend/tailwind.config.cjs | 3 +- 42 files changed, 886 insertions(+), 784 deletions(-) delete mode 100644 frontend/src/lib/components/FlowBox.svelte delete mode 100644 frontend/src/lib/components/ScriptBox.svelte create mode 100644 frontend/src/lib/components/apps/CreateApp.svelte create mode 100644 frontend/src/lib/components/common/table/AppRow.svelte create mode 100644 frontend/src/lib/components/common/table/FlowRow.svelte create mode 100644 frontend/src/lib/components/common/table/Row.svelte create mode 100644 frontend/src/lib/components/common/table/RowIcon.svelte create mode 100644 frontend/src/lib/components/common/table/ScriptRow.svelte create mode 100644 frontend/src/lib/components/common/table/Table.svelte delete mode 100644 frontend/src/routes/apps.svelte diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index c93f92af66..e1d18fe18f 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -4831,7 +4831,15 @@ components: execution_mode: type: string enum: [viewer, publisher, anonymous] - + required: + - id + - workspace_id + - path + - summary + - version + - extra_perms + - edited_at + - execution_mode AppWithLastVersion: type: object properties: diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 8aec21926a..913b1e26fb 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,6 +12,7 @@ "@fortawesome/free-solid-svg-icons": "^6.2.0", "@leeoniya/ufuzzy": "^0.8.0", "@redocly/json-to-json-schema": "^0.0.1", + "@sveltejs/svelte-virtual-list": "^3.0.1", "@types/node": "^18.11.9", "async-mutex": "^0.4.0", "chartjs-adapter-date-fns": "^2.0.0", @@ -483,6 +484,11 @@ "vite": "^3.0.0" } }, + "node_modules/@sveltejs/svelte-virtual-list": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sveltejs/svelte-virtual-list/-/svelte-virtual-list-3.0.1.tgz", + "integrity": "sha512-aF9TptS7NKKS7/TqpsxQBSDJ9Q0XBYzBehCeIC5DzdMEgrJZpIYao9LRLnyyo6SVodpapm2B7FE/Lj+FSA5/SQ==" + }, "node_modules/@sveltejs/vite-plugin-svelte": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.1.tgz", @@ -7341,6 +7347,11 @@ "tiny-glob": "^0.2.9" } }, + "@sveltejs/svelte-virtual-list": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sveltejs/svelte-virtual-list/-/svelte-virtual-list-3.0.1.tgz", + "integrity": "sha512-aF9TptS7NKKS7/TqpsxQBSDJ9Q0XBYzBehCeIC5DzdMEgrJZpIYao9LRLnyyo6SVodpapm2B7FE/Lj+FSA5/SQ==" + }, "@sveltejs/vite-plugin-svelte": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 5f9657ecac..7e6b45c8e8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -63,6 +63,7 @@ "@fortawesome/free-solid-svg-icons": "^6.2.0", "@leeoniya/ufuzzy": "^0.8.0", "@redocly/json-to-json-schema": "^0.0.1", + "@sveltejs/svelte-virtual-list": "^3.0.1", "@types/node": "^18.11.9", "async-mutex": "^0.4.0", "chartjs-adapter-date-fns": "^2.0.0", diff --git a/frontend/src/app.css b/frontend/src/app.css index 11f2cd00b9..8534d5befd 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -22,6 +22,17 @@ .monaco-workbench > .notifications-toasts.visible { display: none !important; } + + svelte-virtual-list-row { + overflow: visible !important; + } + + svelte-virtual-list-contents > * + * { + border-top-width: 1px !important; + border-bottom-width: 0px !important + } + + } @layer components { @@ -31,3 +42,4 @@ cursor: pointer !important; } } + diff --git a/frontend/src/lib/components/Dropdown.svelte b/frontend/src/lib/components/Dropdown.svelte index b0282b1ece..1d605c06a5 100644 --- a/frontend/src/lib/components/Dropdown.svelte +++ b/frontend/src/lib/components/Dropdown.svelte @@ -78,7 +78,8 @@ scale={0.6} class="inline mr-2 {item.type == 'delete' ? 'text-red-500' : 'text-gray-700'}" /> - {/if}{item.displayName} + {/if} + {item.displayName} {:else if item.href} {#if item.icon} + > + {#if item.icon} - {/if}{item.displayName} + {/if} + {item.displayName} + {:else} {item.displayName}{/if} + id="user-menu-item-{name}-{i}}" + > + {item.displayName} + + {/if} {/each} {/if} diff --git a/frontend/src/lib/components/FlowBox.svelte b/frontend/src/lib/components/FlowBox.svelte deleted file mode 100644 index bbcbbc09df..0000000000 --- a/frontend/src/lib/components/FlowBox.svelte +++ /dev/null @@ -1,153 +0,0 @@ - - - -
-
- - - {#if marked} - {@html marked} - {:else} - {!summary || summary.length == 0 ? path : summary} - {/if} -
-
-
{path} - dispatch('change')} - /> - -
-
-
- { - shareModal.openDrawer(path) - }, - disabled: !canWrite - }, - { - displayName: 'Archive', - icon: faArchive, - action: () => { - path ? archiveFlow(path) : null - }, - type: 'delete', - disabled: !canWrite - } - ]} - /> -
-
- -
- {#if canWrite} -
- -
- {:else} -
- -
- {/if} -
-
diff --git a/frontend/src/lib/components/JobArgs.svelte b/frontend/src/lib/components/JobArgs.svelte index 770f743887..bc42a0b850 100644 --- a/frontend/src/lib/components/JobArgs.svelte +++ b/frontend/src/lib/components/JobArgs.svelte @@ -6,11 +6,11 @@ export let args: any - - Argument - Value + + + Argument + Value + {#if args && Object.keys(args).length > 0} {#each Object.entries(args) as [arg, value]} diff --git a/frontend/src/lib/components/PageHeader.svelte b/frontend/src/lib/components/PageHeader.svelte index af5e22d780..d09c1daf51 100644 --- a/frontend/src/lib/components/PageHeader.svelte +++ b/frontend/src/lib/components/PageHeader.svelte @@ -9,14 +9,14 @@
{#if primary} -

{title}

+

{title}

{#if tooltip} {tooltip} {/if}
{:else} -

{title}

+

{title}

{#if tooltip} {tooltip} {/if} diff --git a/frontend/src/lib/components/ScriptBox.svelte b/frontend/src/lib/components/ScriptBox.svelte deleted file mode 100644 index f7bd5e3d8e..0000000000 --- a/frontend/src/lib/components/ScriptBox.svelte +++ /dev/null @@ -1,173 +0,0 @@ - - - -
-
- - - {#if marked} - {@html marked} - {:else} - {!summary || summary.length == 0 ? path : summary} - {/if} -
-
-
- {path} - dispatch('change')} - /> - -
- {#if kind != 'script'} - {kind} - {/if} - {#if lock_error_logs} - Deployment error - {/if} -
-
-
-
- { - shareModal.openDrawer(path) - }, - disabled: !canWrite - }, - { - displayName: 'Archive', - icon: faArchive, - action: () => { - path ? archiveScript(path) : null - }, - type: 'delete', - disabled: !canWrite - } - ]} - /> -
-
- -
- {#if canWrite} -
- -
- {:else} -
- -
- {/if} -
-
-
diff --git a/frontend/src/lib/components/ScriptEditor.svelte b/frontend/src/lib/components/ScriptEditor.svelte index baeafa0398..7f3285621c 100644 --- a/frontend/src/lib/components/ScriptEditor.svelte +++ b/frontend/src/lib/components/ScriptEditor.svelte @@ -167,7 +167,7 @@ -
Preview
+
Preview
diff --git a/frontend/src/lib/components/SharedBadge.svelte b/frontend/src/lib/components/SharedBadge.svelte index e8951d9014..0616d3b41c 100644 --- a/frontend/src/lib/components/SharedBadge.svelte +++ b/frontend/src/lib/components/SharedBadge.svelte @@ -49,7 +49,7 @@ {#if kind === 'read' || kind === 'write'} - + {kind} {#if reason} {reason} diff --git a/frontend/src/lib/components/Star.svelte b/frontend/src/lib/components/Star.svelte index 4416dfd4c3..9009650c56 100644 --- a/frontend/src/lib/components/Star.svelte +++ b/frontend/src/lib/components/Star.svelte @@ -1,6 +1,6 @@ + + + closeDrawer()}> + +
+ App permissions depend on their path. Select the group all + to share it, and user to keep it private. + docs +
+
+ + +
+
+ + diff --git a/frontend/src/lib/components/apps/components/helpers/DebouncedInput.svelte b/frontend/src/lib/components/apps/components/helpers/DebouncedInput.svelte index 9b22e16286..520d9c68f2 100644 --- a/frontend/src/lib/components/apps/components/helpers/DebouncedInput.svelte +++ b/frontend/src/lib/components/apps/components/helpers/DebouncedInput.svelte @@ -3,6 +3,9 @@ export let value: string export let debounceDelay: number = 500 + let parentClass: string | undefined = undefined + export { parentClass as class } + let timer: NodeJS.Timeout function debounce(event: KeyboardEvent): void { @@ -15,4 +18,4 @@ } - + diff --git a/frontend/src/lib/components/common/badge/Badge.svelte b/frontend/src/lib/components/common/badge/Badge.svelte index da1faab536..a30e785f96 100644 --- a/frontend/src/lib/components/common/badge/Badge.svelte +++ b/frontend/src/lib/components/common/badge/Badge.svelte @@ -8,9 +8,8 @@ export let large = false export let href = '' export let rounded = false - export let index = false export let dismissable = false - export let baseClass = 'text-center -mb-0.5' + export let baseClass = 'text-center' export let capitalize = false export let icon: BadgeIconProps | undefined = undefined @@ -51,10 +50,6 @@ href && (color.startsWith(ColorModifier) ? hovers[color.replace(ColorModifier, '')] : hovers[color]), rounded ? 'rounded-full px-2 py-1' : 'rounded px-2.5 py-0.5', - index - ? 'absolute flex justify-center items-center font-bold overflow-hidden border-2 border-white dark:border-gray-900' + - (large ? 'w-7 h-7 -top-3.5 -right-3.5' : 'w-6 h-6 -top-3 -right-3') - : '', $$props.class ) $: iconProps = icon ? { ...defaulIconProps, ...icon } : { data: undefined } diff --git a/frontend/src/lib/components/common/button/ButtonPopup.svelte b/frontend/src/lib/components/common/button/ButtonPopup.svelte index cb052f64ce..02b4699b6b 100644 --- a/frontend/src/lib/components/common/button/ButtonPopup.svelte +++ b/frontend/src/lib/components/common/button/ButtonPopup.svelte @@ -14,6 +14,7 @@ export let target: ButtonType.Target = '_self' export let startIcon: ButtonType.Icon | undefined = undefined export let endIcon: ButtonType.Icon | undefined = undefined + export let spacingSize: ButtonType.Size = size let ref: ButtonType.Element @@ -24,7 +25,8 @@ size, color, variant, - disabled + disabled, + spacingSize } diff --git a/frontend/src/lib/components/common/table/AppRow.svelte b/frontend/src/lib/components/common/table/AppRow.svelte new file mode 100644 index 0000000000..6677ccfb50 --- /dev/null +++ b/frontend/src/lib/components/common/table/AppRow.svelte @@ -0,0 +1,65 @@ + + + + + + + + + + {#if canWrite} +
+ +
+ {/if} + + +
+
diff --git a/frontend/src/lib/components/common/table/FlowRow.svelte b/frontend/src/lib/components/common/table/FlowRow.svelte new file mode 100644 index 0000000000..329c0ac682 --- /dev/null +++ b/frontend/src/lib/components/common/table/FlowRow.svelte @@ -0,0 +1,152 @@ + + + + + + + + { + shareModal.openDrawer && shareModal.openDrawer(path) + }, + disabled: !canWrite + }, + { + displayName: 'Archive', + icon: faArchive, + action: () => { + path ? archiveFlow(path) : null + }, + type: 'delete', + disabled: !canWrite + } + ]} + /> + + {#if canWrite} +
+ +
+ {:else} +
+ +
+ {/if} + + + +
+
diff --git a/frontend/src/lib/components/common/table/Row.svelte b/frontend/src/lib/components/common/table/Row.svelte new file mode 100644 index 0000000000..3836206d6c --- /dev/null +++ b/frontend/src/lib/components/common/table/Row.svelte @@ -0,0 +1,53 @@ + + + + + +
+
+ {#if marked} + {@html marked} + {:else} + {!summary || summary.length == 0 ? path : summary} + {/if} +
+
+ {path} +
+
+
+ +
+ +
+ +
+
+ { + dispatch('change') + }} + /> +
+
diff --git a/frontend/src/lib/components/common/table/RowIcon.svelte b/frontend/src/lib/components/common/table/RowIcon.svelte new file mode 100644 index 0000000000..6c73e8b717 --- /dev/null +++ b/frontend/src/lib/components/common/table/RowIcon.svelte @@ -0,0 +1,28 @@ + + +
+ +
diff --git a/frontend/src/lib/components/common/table/ScriptRow.svelte b/frontend/src/lib/components/common/table/ScriptRow.svelte new file mode 100644 index 0000000000..a60d58133c --- /dev/null +++ b/frontend/src/lib/components/common/table/ScriptRow.svelte @@ -0,0 +1,167 @@ + + + + + + {#if lock_error_logs} + Deployment failed + {/if} + {capitalize(kind)} + + + { + shareModal.openDrawer && shareModal.openDrawer(path) + }, + disabled: !canWrite + }, + { + displayName: 'Archive', + icon: faArchive, + action: () => { + path ? archiveScript(path) : null + }, + type: 'delete', + disabled: !canWrite + } + ]} + /> + + {#if canWrite} +
+ +
+ {:else} +
+ +
+ {/if} + + + +
+
diff --git a/frontend/src/lib/components/common/table/Table.svelte b/frontend/src/lib/components/common/table/Table.svelte new file mode 100644 index 0000000000..1bd4aca0ba --- /dev/null +++ b/frontend/src/lib/components/common/table/Table.svelte @@ -0,0 +1,9 @@ +
+
+ + + + +
+
+
diff --git a/frontend/src/lib/components/common/toggleButton/ToggleButton.svelte b/frontend/src/lib/components/common/toggleButton/ToggleButton.svelte index efec285935..4f180634d2 100644 --- a/frontend/src/lib/components/common/toggleButton/ToggleButton.svelte +++ b/frontend/src/lib/components/common/toggleButton/ToggleButton.svelte @@ -17,10 +17,10 @@ btnClasses={classNames( 'border-gray-200 focus:ring-0 w-full', position === 'left' ? 'rounded-none rounded-l-lg border' : '', - position === 'center' ? 'rounded-none border-t border-b' : '', - position === 'right' ? 'rounded-none rounded-r-md !border border-l-0' : '' + position === 'center' ? 'rounded-none border-t border-b border-r' : '', + position === 'right' ? 'rounded-none rounded-r-md border-r border-y' : '' )} - color={$selected === value ? (light ? 'gray' : 'dark') : 'light'} + color={$selected === value ? (light ? 'dark' : 'dark') : 'light'} variant="contained" > diff --git a/frontend/src/lib/components/common/toggleButton/ToggleButtonGroup.svelte b/frontend/src/lib/components/common/toggleButton/ToggleButtonGroup.svelte index 83c912cd37..e3e7344810 100644 --- a/frontend/src/lib/components/common/toggleButton/ToggleButtonGroup.svelte +++ b/frontend/src/lib/components/common/toggleButton/ToggleButtonGroup.svelte @@ -31,6 +31,6 @@ }) -
+
diff --git a/frontend/src/lib/components/flows/CreateActionsFlow.svelte b/frontend/src/lib/components/flows/CreateActionsFlow.svelte index 50985a5920..ced575b8e9 100644 --- a/frontend/src/lib/components/flows/CreateActionsFlow.svelte +++ b/frontend/src/lib/components/flows/CreateActionsFlow.svelte @@ -1,16 +1,15 @@ - - - - - closeDrawer()}> - -
- App permissions depend on their path. Select the group all - to share it, and user to keep it private. - docs -
-
- - -
-
- - x.summary + ' (' + x.path + ')'} -/> - - - - - - -
- - - -
- {#each owners as owner} - { - ownerFilter = ownerFilter == owner ? undefined : owner - }} - color={owner === ownerFilter ? 'blue' : 'gray'} - > - {owner} - {#if owner === ownerFilter}✗{/if} - - {/each} -
- - diff --git a/frontend/src/routes/apps/edit/[...path].svelte b/frontend/src/routes/apps/edit/[...path].svelte index 31374a5751..46f9497680 100644 --- a/frontend/src/routes/apps/edit/[...path].svelte +++ b/frontend/src/routes/apps/edit/[...path].svelte @@ -4,8 +4,6 @@ import { workspaceStore } from '$lib/stores' import { page } from '$app/stores' - import gridHelp from 'svelte-grid/build/helper/index.mjs' - let app: AppWithLastVersion | undefined = undefined let path = $page.params.path diff --git a/frontend/src/routes/apps/get/[...path].svelte b/frontend/src/routes/apps/get/[...path].svelte index 36e6e0c1b5..ee560618ec 100644 --- a/frontend/src/routes/apps/get/[...path].svelte +++ b/frontend/src/routes/apps/get/[...path].svelte @@ -15,7 +15,7 @@ import Button from '$lib/components/common/button/Button.svelte' import { AppService, AppWithLastVersion } from '$lib/gen' import { workspaceStore } from '$lib/stores' - import { faArrowLeft, faPen } from '@fortawesome/free-solid-svg-icons' + import { faPen } from '@fortawesome/free-solid-svg-icons' let app: AppWithLastVersion | undefined = undefined @@ -33,12 +33,8 @@ {#if app}
-
- -
{app.value.title}
-
+
{app.value.title}
+ diff --git a/frontend/src/routes/audit_logs.svelte b/frontend/src/routes/audit_logs.svelte index 0526f17095..05de498b22 100644 --- a/frontend/src/routes/audit_logs.svelte +++ b/frontend/src/routes/audit_logs.svelte @@ -141,7 +141,7 @@ {#if logs} {#each logs as { id, timestamp, username, operation, action_kind, resource, parameters }} - {id} + {id}
{displayDate(timestamp)} @@ -153,8 +153,8 @@
{username} -
+
+
{operation}
{resource} diff --git a/frontend/src/routes/flows/get/[...path].svelte b/frontend/src/routes/flows/get/[...path].svelte index 478834d59c..72349832eb 100644 --- a/frontend/src/routes/flows/get/[...path].svelte +++ b/frontend/src/routes/flows/get/[...path].svelte @@ -34,9 +34,7 @@ import ShareModal from '$lib/components/ShareModal.svelte' import Toggle from '$lib/components/Toggle.svelte' import { userStore, workspaceStore } from '$lib/stores' - import SharedBadge from '$lib/components/SharedBadge.svelte' import SvelteMarkdown from 'svelte-markdown' - import Dropdown from '$lib/components/Dropdown.svelte' import CenteredPage from '$lib/components/CenteredPage.svelte' import FlowViewer from '$lib/components/FlowViewer.svelte' import { Button, ActionRow, Skeleton, Badge } from '$lib/components/common' diff --git a/frontend/src/routes/index.svelte b/frontend/src/routes/index.svelte index 0be0e11a15..294c1b9a60 100644 --- a/frontend/src/routes/index.svelte +++ b/frontend/src/routes/index.svelte @@ -2,15 +2,18 @@ import CenteredPage from '$lib/components/CenteredPage.svelte' import JobDetail from '$lib/components/jobs/JobDetail.svelte' import { + AppService, FlowService, Job, JobService, + ListableApp, Script, ScriptService, type Flow, type OpenFlow } from '$lib/gen' import { superadmin, userStore, workspaceStore } from '$lib/stores' + import VirtualList from '@sveltejs/svelte-virtual-list' import { Alert, Button, @@ -25,16 +28,15 @@ import PageHeader from '$lib/components/PageHeader.svelte' import CreateActionsFlow from '$lib/components/flows/CreateActionsFlow.svelte' import CreateActionsScript from '$lib/components/scripts/CreateActionsScript.svelte' - import { canWrite, getScriptByPath, sendUserToast } from '$lib/utils' + import { canWrite, classNames, getScriptByPath, pluralize } from '$lib/utils' import type { HubItem } from '$lib/components/flows/pickers/model' import ShareModal from '$lib/components/ShareModal.svelte' - import Icon from 'svelte-awesome' import { - faBuilding, faCodeFork, + faDashboard, faGlobe, - faScroll, - faWind + faLayerGroup, + faPlus } from '@fortawesome/free-solid-svg-icons' import PickHubScript from '$lib/components/flows/pickers/PickHubScript.svelte' import PickHubFlow from './PickHubFlow.svelte' @@ -42,20 +44,40 @@ import HighlightCode from '$lib/components/HighlightCode.svelte' import SearchItems from '$lib/components/SearchItems.svelte' import Badge from '$lib/components/common/badge/Badge.svelte' - import ScriptBox from '$lib/components/ScriptBox.svelte' - import FlowBox from '$lib/components/FlowBox.svelte' import type uFuzzy from '@leeoniya/ufuzzy' + import { Building, Code2, Globe2, LayoutDashboard, Wind } from 'svelte-lucide' + import Table from '$lib/components/common/table/Table.svelte' + import ScriptRow from '$lib/components/common/table/ScriptRow.svelte' + import FlowRow from '$lib/components/common/table/FlowRow.svelte' + import AppRow from '$lib/components/common/table/AppRow.svelte' + + import { fade } from 'svelte/transition' + import { flip } from 'svelte/animate' + import CreateApp from '$lib/components/apps/CreateApp.svelte' let jobs: Job[] = [] type Tab = 'hubscripts' | 'hubflows' | 'workspace' - type ScriptW = Script & { canWrite: boolean; marked?: string } - type FlowW = Flow & { canWrite: boolean; marked?: string } - let scripts: ScriptW[] = [] - let flows: FlowW[] = [] - let filteredItems: ((ScriptW & { type: 'script' }) | (FlowW & { type: 'flow' }))[] = [] - let itemKind: 'script' | 'flow' | 'all' = 'all' + type TableItem = T & { + canWrite: boolean + marked?: string + type?: U + time?: number + starred?: boolean + } + + type TableScript = TableItem + type TableFlow = TableItem + type TableApp = TableItem + + let scripts: TableScript[] = [] + let flows: TableFlow[] = [] + let apps: TableApp[] = [] + + let filteredItems: (TableScript | TableFlow | TableApp)[] = [] + + let itemKind: 'script' | 'flow' | 'app' | 'all' = 'all' let tab: Tab = 'workspace' let filter: string = '' @@ -72,15 +94,20 @@ let codeViewerObj: HubItem | undefined = undefined async function loadScripts(): Promise { - scripts = (await ScriptService.listScripts({ workspace: $workspaceStore!, perPage: 300 })).map( - (x: Script) => { - return { - canWrite: - canWrite(x.path, x.extra_perms, $userStore) && x.workspace_id == $workspaceStore, - ...x - } + const loadedScripts = await ScriptService.listScripts({ + workspace: $workspaceStore!, + perPage: 300 + }) + + scripts = loadedScripts.map((script: Script) => { + return { + canWrite: + canWrite(script.path, script.extra_perms, $userStore) && + script.workspace_id == $workspaceStore, + ...script } - ) + }) + loading = false } @@ -102,14 +129,16 @@ loading = false } - async function archiveFlow(path: string): Promise { - try { - await FlowService.archiveFlowByPath({ workspace: $workspaceStore!, path }) - loadFlows() - sendUserToast(`Successfully archived flow ${path}`) - } catch (err) { - sendUserToast(`Could not archive this flow ${err.body}`, true) - } + async function loadApps(): Promise { + apps = (await AppService.listApps({ workspace: $workspaceStore! })).map((app: ListableApp) => { + return { + canWrite: + canWrite(app.path!, app.extra_perms!, $userStore) && app.workspace_id == $workspaceStore, + ...app + } + }) + + loading = false } async function viewFlow(obj: { flow_id: number }): Promise { @@ -122,10 +151,7 @@ new Set(filteredItems?.map((x) => x.path.split('/').slice(0, 2).join('/')) ?? []) ).sort() - let combinedItems: ( - | (ScriptW & { type: 'script'; time: number }) - | (FlowW & { type: 'flow'; time: number }) - )[] = [] + let combinedItems: (TableScript | TableFlow | TableApp)[] = [] $: combinedItems = [ ...flows.map((x) => ({ ...x, type: 'flow' as 'flow', time: new Date(x.edited_at).getTime() })), @@ -133,7 +159,8 @@ ...x, type: 'script' as 'script', time: new Date(x.created_at).getTime() - })) + })), + ...apps.map((x) => ({ ...x, type: 'app' as 'app', time: new Date(x.edited_at).getTime() })) ].sort((a, b) => (a.starred != b.starred ? (a.starred ? -1 : 1) : a.time - b.time > 0 ? -1 : 1)) $: preFilteredItems = @@ -159,6 +186,7 @@ if (($userStore || $superadmin) && $workspaceStore) { loadScripts() loadFlows() + loadApps() loadJobs() } } @@ -178,7 +206,7 @@ interIns } = info - return idx + const sortResult = idx .map((v, i) => i) .sort( (ia, ib) => @@ -202,8 +230,13 @@ (preFilteredItems[idx[ib]].starred ? 100 : 0) - (preFilteredItems[idx[ia]].starred ? 100 : 0) ) + return sortResult } } + + $: items = filter !== '' ? filteredItems : preFilteredItems + + $: containerHeight = items.length < 5 ? items.length * 80 : 800 -
+
+ startIcon={{ icon: faCodeFork }} + > + Fork + +
@@ -250,15 +288,18 @@ -
+ variant="border" + > + View on the Hub + + +
{#if flowViewerFlow?.flow} @@ -273,14 +314,15 @@ {:else if $workspaceStore == 'starter'}
- The starter workspace has all its elements (variables, resources, scripts, flows) shared + + The starter workspace has all its elements (variables, resources, scripts, flows) shared across all other workspaces. Useful to seed workspace with common elements within your - organization. + organization. + {/if} -
+
+
@@ -288,75 +330,141 @@
- Workspace - Hub Scripts - Hub Flows + +
+ + Workspace +
+
+ +
+ + Hub Scripts +
+
+ +
+ + Hub Flows +
+
-
+
{#if tab == 'workspace'} -
- -
+
+
+ + All + +
+ + Scripts +
+
+ +
+ + Flows +
+
+ +
+ + Apps +
+
+
+
-
- - All - Scripts - Flows - -
-
- {#each owners as owner} - { - ownerFilter = ownerFilter == owner ? undefined : owner - }} - color={owner === ownerFilter ? 'blue' : 'gray'} - > - {owner} - {#if owner === ownerFilter}✗{/if} - - {/each} -
- -
- {#if !loading} - {#each filter != '' ? filteredItems : preFilteredItems as item (item.type + item.path)} - {#if item.type == 'script'} - + + + +
+
+ {#if owners.length > 0} +
+ {#each owners as owner (owner)} +
+ { + ownerFilter = ownerFilter == owner ? undefined : owner + }} + color={owner === ownerFilter ? 'blue' : 'gray'} + baseClass={owner === ownerFilter ? 'border border-blue-500' : 'border'} + > + {owner} + {#if owner === ownerFilter}✗{/if} + +
{/each} +
+ {/if} +
+ {#if filteredItems.length === 0} +
+
+
No items found
+
Try changing your search or filters
+
+
{:else} - {#each Array(10).fill(0) as sk} - - {/each} +
+ + {#if item.type == 'script'} + + {:else if item.type == 'flow'} + + {:else if item.type == 'app'} + + {/if} + +
+ {pluralize(items.length, 'item')} {/if}
{:else if tab == 'hubscripts'} @@ -365,36 +473,5 @@ viewFlow(e.detail)} /> {/if}
-
-

- Runs -

- -
- - {#each jobs.splice(0, 3) as job} - - {/each} - - All runs - - - -
-
diff --git a/frontend/src/routes/run/[...run].svelte b/frontend/src/routes/run/[...run].svelte index bfa4b4f63a..ca67335f0f 100644 --- a/frontend/src/routes/run/[...run].svelte +++ b/frontend/src/routes/run/[...run].svelte @@ -106,11 +106,11 @@

Are you in the right workspace?

{#each $usersWorkspaceStore?.workspaces ?? [] as workspace} -
+
+ +
{/each}
@@ -307,7 +307,7 @@ {#if job} -
+
{#if viewTab == 'logs'}
diff --git a/frontend/src/routes/runs/[...path].svelte b/frontend/src/routes/runs/[...path].svelte index 5be75c0c3d..6d8bbf23ab 100644 --- a/frontend/src/routes/runs/[...path].svelte +++ b/frontend/src/routes/runs/[...path].svelte @@ -176,15 +176,19 @@ on:click={() => { goto('/runs?' + $page.url.searchParams.toString()) }} - size="xs"> + + + +
@@ -248,8 +252,10 @@ maxTs = undefined jobs = await fetchJobs(maxTs, minTs) }} - size="xs"> + +
{#if jobs} diff --git a/frontend/src/routes/scripts/get/[...hash].svelte b/frontend/src/routes/scripts/get/[...hash].svelte index fb0598fb90..c8ac3199d0 100644 --- a/frontend/src/routes/scripts/get/[...hash].svelte +++ b/frontend/src/routes/scripts/get/[...hash].svelte @@ -16,8 +16,7 @@ canWrite, defaultIfEmptyString, scriptToHubUrl, - copyToClipboard, - emptyString + copyToClipboard } from '$lib/utils' import { faPlay, @@ -269,9 +268,9 @@ startIcon={{ icon: faArrowLeft }} href="/scripts/get/{script.parent_hashes[0]}" > - Previous version ({script.parent_hashes.length}) + + Previous version ({script.parent_hashes.length}) + {#each script.parent_hashes as hash} @@ -283,7 +282,7 @@
{#if script.lock_error_logs || topHash || script.archived || script.deleted} -
+
{#if script.lock_error_logs}