mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-12 08:05:44 +00:00
feat: expose a react sdk to integrate windmill into react apps (#1605)
* expose react sdk * expose react sdk * iterate * iterate * iterate * nit * update example * update example * small fixes * update all
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
|
||||
Source code in this repository is variously licensed under the Apache License
|
||||
Version 2.0 (see file ./LICENSE-APACHE),or the AGPLv3 License (see file ./LICENSE-AGPL)
|
||||
Version 2.0 (see file ./LICENSE-APACHE), or the AGPLv3 License (see file ./LICENSE-AGPL)
|
||||
|
||||
Every file is under copyright (c) Windmill Labs, Inc 2022 unless otherwise specified.
|
||||
Every file is under License AGPL unless otherwise specified
|
||||
or belonging to one of the below cases:
|
||||
|
||||
The files under backend/ are AGPL Licensed.
|
||||
The files under frontend/ are AGPL Licensed.
|
||||
The files under backend/ are AGPLv3 Licensed.
|
||||
The files under frontend/ are AGPLv3 Licensed.
|
||||
The files under python-client/ deno-client/ go-client/ are Apache 2.0 Licensed.
|
||||
|
||||
The openapi files, including the OpenFlow spec is Apache 2.0 Licensed.
|
||||
|
||||
@@ -74,7 +74,23 @@ pub async fn pip_compile(
|
||||
) -> error::Result<String> {
|
||||
logs.push_str(&format!("\nresolving dependencies..."));
|
||||
set_logs(logs, job_id, db).await;
|
||||
logs.push_str(&format!("\ncontent of requirements:\n{}", requirements));
|
||||
logs.push_str(&format!("\ncontent of requirements:\n{}\n", requirements));
|
||||
let requirements = if let Some(pip_local_dependencies) = PIP_LOCAL_DEPENDENCIES.as_ref() {
|
||||
let deps = pip_local_dependencies.clone();
|
||||
requirements
|
||||
.lines()
|
||||
.filter(|s| {
|
||||
if !deps.contains(&s.to_string()) {
|
||||
return true;
|
||||
} else {
|
||||
logs.push_str(&format!("\nignoring local dependency: {}", s));
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.join("\n")
|
||||
} else {
|
||||
requirements.to_string()
|
||||
};
|
||||
let req_hash = calculate_hash(&requirements);
|
||||
if let Some(cached) = sqlx::query_scalar!(
|
||||
"SELECT lockfile FROM pip_resolution_cache WHERE hash = $1",
|
||||
@@ -87,15 +103,7 @@ pub async fn pip_compile(
|
||||
return Ok(cached);
|
||||
}
|
||||
let file = "requirements.in";
|
||||
let requirements = if let Some(pip_local_dependencies) = PIP_LOCAL_DEPENDENCIES.as_ref() {
|
||||
let deps = pip_local_dependencies.clone();
|
||||
requirements
|
||||
.lines()
|
||||
.filter(|s| !deps.contains(&s.to_string()))
|
||||
.join("\n")
|
||||
} else {
|
||||
requirements.to_string()
|
||||
};
|
||||
|
||||
write_file(job_dir, file, &requirements).await?;
|
||||
|
||||
let mut args = vec!["-q", "--no-header", file, "--resolver=backtracking"];
|
||||
|
||||
@@ -90,7 +90,7 @@ FROM python:3.10.8-slim-buster
|
||||
ARG APP=/usr/src/app
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y ca-certificates wget curl git jq libprotobuf-dev libnl-route-3-dev unzip build-essential pkg-config libcairo2-dev \
|
||||
&& apt-get install -y ca-certificates wget curl git jq libprotobuf-dev libnl-route-3-dev unzip build-essential pkg-config libcairo2-dev libwebkit2gtk-4.0-37 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN arch="$(dpkg --print-architecture)"; arch="${arch##*-}"; \
|
||||
|
||||
Generated
+3
-4
@@ -22,6 +22,7 @@
|
||||
"chartjs-plugin-zoom": "^2.0.0",
|
||||
"d3-zoom": "^3.0.0",
|
||||
"date-fns": "^2.29.3",
|
||||
"esm-env": "^1.0.0",
|
||||
"fast-equals": "^5.0.1",
|
||||
"highlight.js": "^11.8.0",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -2940,8 +2941,7 @@
|
||||
"node_modules/esm-env": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz",
|
||||
"integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA=="
|
||||
},
|
||||
"node_modules/esm-env-robust": {
|
||||
"version": "0.0.3",
|
||||
@@ -9452,8 +9452,7 @@
|
||||
"esm-env": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz",
|
||||
"integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA=="
|
||||
},
|
||||
"esm-env-robust": {
|
||||
"version": "0.0.3",
|
||||
|
||||
+25
-1
@@ -82,6 +82,7 @@
|
||||
"chartjs-plugin-zoom": "^2.0.0",
|
||||
"d3-zoom": "^3.0.0",
|
||||
"date-fns": "^2.29.3",
|
||||
"esm-env": "^1.0.0",
|
||||
"fast-equals": "^5.0.1",
|
||||
"highlight.js": "^11.8.0",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -157,6 +158,16 @@
|
||||
"svelte": "./package/components/FlowViewer.svelte",
|
||||
"default": "./package/components/FlowViewer.svelte"
|
||||
},
|
||||
"./components/FlowBuilder.svelte": {
|
||||
"types": "./package/components/FlowBuilder.svelte.d.ts",
|
||||
"svelte": "./package/components/FlowBuilder.svelte",
|
||||
"default": "./package/components/FlowBuilder.svelte"
|
||||
},
|
||||
"./components/FlowEditor.svelte": {
|
||||
"types": "./package/components/flows/FlowEditor.svelte.d.ts",
|
||||
"svelte": "./package/components/flows/FlowEditor.svelte",
|
||||
"default": "./package/components/flows/FlowEditor.svelte"
|
||||
},
|
||||
"./components/SchemaViewer.svelte": {
|
||||
"types": "./package/components/SchemaViewer.svelte.d.ts",
|
||||
"svelte": "./package/components/SchemaViewer.svelte",
|
||||
@@ -171,6 +182,10 @@
|
||||
"types": "./package/common.d.ts",
|
||||
"default": "./package/common.js"
|
||||
},
|
||||
"./stores": {
|
||||
"types": "./package/stores.d.ts",
|
||||
"default": "./package/stores.js"
|
||||
},
|
||||
"./components/icons": {
|
||||
"types": "./package/components/icons/index.d.ts",
|
||||
"svelte": "./package/components/icons/index.js",
|
||||
@@ -193,7 +208,7 @@
|
||||
"dist",
|
||||
"package"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"license": "AGPL-3.0",
|
||||
"svelte": "./dist/index.js",
|
||||
"typesVersions": {
|
||||
">4.0": {
|
||||
@@ -227,6 +242,12 @@
|
||||
"components/FlowViewer.svelte": [
|
||||
"./package/components/FlowViewer.svelte.d.ts"
|
||||
],
|
||||
"components/FlowBuilder.svelte": [
|
||||
"./package/components/FlowBuilder.svelte.d.ts"
|
||||
],
|
||||
"components/FlowEditor.svelte": [
|
||||
"./package/components/flows/FlowEditor.svelte.d.ts"
|
||||
],
|
||||
"components/SchemaViewer.svelte": [
|
||||
"./package/components/SchemaViewer.svelte.d.ts"
|
||||
],
|
||||
@@ -236,6 +257,9 @@
|
||||
"common": [
|
||||
"./package/common.d.ts"
|
||||
],
|
||||
"stores": [
|
||||
"./package/stores.d.ts"
|
||||
],
|
||||
"components/icons": [
|
||||
"./package/components/icons/index.d.ts"
|
||||
],
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { BROWSER } from 'esm-env'
|
||||
import { page } from '$app/stores'
|
||||
import { get } from 'svelte/store'
|
||||
import { premiumStore, userStore, workspaceStore } from './stores'
|
||||
import { getUserExt } from './user'
|
||||
import { WorkspaceService } from './gen'
|
||||
|
||||
export function isCloudHosted(): boolean {
|
||||
return get(page)?.url?.hostname == 'app.windmill.dev'
|
||||
}
|
||||
|
||||
if (BROWSER) {
|
||||
workspaceStore.subscribe(async (workspace) => {
|
||||
if (workspace) {
|
||||
try {
|
||||
localStorage.setItem('workspace', String(workspace))
|
||||
} catch (e) {
|
||||
console.error('Could not persist workspace to local storage', e)
|
||||
}
|
||||
const user = await getUserExt(workspace)
|
||||
userStore.set(user)
|
||||
if (isCloudHosted() && user?.is_admin) {
|
||||
premiumStore.set(await WorkspaceService.getPremiumInfo({ workspace }))
|
||||
}
|
||||
} else {
|
||||
userStore.set(undefined)
|
||||
}
|
||||
})
|
||||
|
||||
setInterval(async () => {
|
||||
try {
|
||||
const workspace = get(workspaceStore)
|
||||
const user = get(userStore)
|
||||
|
||||
if (workspace && user && !user.is_super_admin && !user.is_admin) {
|
||||
userStore.set(await getUserExt(workspace))
|
||||
console.log('refreshed user')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Could not refresh user', e)
|
||||
}
|
||||
}, 30000)
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { WorkspaceService } from '$lib/gen'
|
||||
import { Button, ToggleButton, ToggleButtonGroup } from './common'
|
||||
import Tooltip from './Tooltip.svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { JobService, Preview, ResourceService } from '$lib/gen'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { emptySchema, emptyString, sendUserToast } from '$lib/utils'
|
||||
import { emptySchema, emptyString } from '$lib/utils'
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
import Button from './common/button/Button.svelte'
|
||||
import SchemaForm from './SchemaForm.svelte'
|
||||
import SimpleEditor from './SimpleEditor.svelte'
|
||||
import Toggle from './Toggle.svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
export let resource_type: string
|
||||
export let args: Record<string, any> | any = {}
|
||||
|
||||
@@ -57,8 +57,7 @@
|
||||
import { faMinus, faPlus } from '@fortawesome/free-solid-svg-icons'
|
||||
import IconedResourceType from './IconedResourceType.svelte'
|
||||
import { OauthService, ResourceService, VariableService, type TokenResponse } from '$lib/gen'
|
||||
import { page } from '$app/stores'
|
||||
import { emptyString, sendUserToast, truncateRev } from '$lib/utils'
|
||||
import { emptyString, truncateRev } from '$lib/utils'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import Icon from 'svelte-awesome'
|
||||
import Path from './Path.svelte'
|
||||
@@ -68,6 +67,7 @@
|
||||
import SearchItems from './SearchItems.svelte'
|
||||
import autosize from 'svelte-autosize'
|
||||
import WhitelistIp from './WhitelistIp.svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
export let newPageOAuth = false
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
step += 1
|
||||
args = {}
|
||||
} else if (step == 1 && !manual) {
|
||||
const url = new URL(`/api/oauth/connect/${resource_type}`, $page.url.origin)
|
||||
const url = new URL(`/api/oauth/connect/${resource_type}`, window.location.origin)
|
||||
url.searchParams.append('scopes', scopes.join('+'))
|
||||
if (extra_params.length > 0) {
|
||||
extra_params.forEach(([key, value]) => url.searchParams.append(key, value))
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
import Icon from 'svelte-awesome'
|
||||
import { MoreVertical } from 'lucide-svelte'
|
||||
import { Button, Menu } from './common'
|
||||
import { goto } from '$app/navigation'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
type Alignment = 'start' | 'end'
|
||||
@@ -79,7 +78,6 @@
|
||||
{:else if item.href && !item.disabled}
|
||||
<a
|
||||
href={item.href}
|
||||
on:click|stopPropagation|preventDefault={() => goto(item.href ?? '')}
|
||||
class="block w-full px-4 font-semibold text-left py-2 text-sm text-gray-700 hover:drop-shadow-sm hover:bg-gray-50 hover:bg-opacity-30
|
||||
{item.disabled ? 'bg-gray-200' : ''}"
|
||||
role="menuitem"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { browser } from '$app/environment'
|
||||
import { page } from '$app/stores'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { BROWSER } from 'esm-env'
|
||||
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
import { createEventDispatcher, onDestroy, onMount } from 'svelte'
|
||||
|
||||
@@ -339,7 +339,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
const wsProtocol = $page.url.protocol == 'https:' ? 'wss' : 'ws'
|
||||
const wsProtocol = BROWSER && window.location.protocol == 'https:' ? 'wss' : 'ws'
|
||||
const hostname = BROWSER ? window.location.protocol + '//' + window.location.host : 'SSR'
|
||||
|
||||
let encodedImportMap = ''
|
||||
if (lang == 'typescript') {
|
||||
@@ -349,14 +350,7 @@
|
||||
const token = await UserService.createToken({
|
||||
requestBody: { label: 'Ephemeral lsp token', expiration: expiration.toISOString() }
|
||||
})
|
||||
let root =
|
||||
$page.url.protocol +
|
||||
'//' +
|
||||
$page.url.host +
|
||||
'/api/scripts_u/tokened_raw/' +
|
||||
$workspaceStore +
|
||||
'/' +
|
||||
token
|
||||
let root = hostname + '/api/scripts_u/tokened_raw/' + $workspaceStore + '/' + token
|
||||
const importMap = {
|
||||
imports: {
|
||||
'file:///': root + '/'
|
||||
@@ -375,7 +369,7 @@
|
||||
encodedImportMap = 'data:text/plain;base64,' + btoa(JSON.stringify(importMap))
|
||||
}
|
||||
await connectToLanguageServer(
|
||||
`${wsProtocol}://${$page.url.host}/ws/deno`,
|
||||
`${wsProtocol}://${window.location.host}/ws/deno`,
|
||||
'deno',
|
||||
{
|
||||
certificateStores: null,
|
||||
@@ -417,7 +411,7 @@
|
||||
)
|
||||
} else if (lang === 'python') {
|
||||
await connectToLanguageServer(
|
||||
`${wsProtocol}://${$page.url.host}/ws/pyright`,
|
||||
`${wsProtocol}://${window.location.host}/ws/pyright`,
|
||||
'pyright',
|
||||
{},
|
||||
(params, token, next) => {
|
||||
@@ -447,9 +441,14 @@
|
||||
}
|
||||
)
|
||||
|
||||
connectToLanguageServer(`${wsProtocol}://${$page.url.host}/ws/ruff`, 'ruff', {}, undefined)
|
||||
connectToLanguageServer(
|
||||
`${wsProtocol}://${$page.url.host}/ws/diagnostic`,
|
||||
`${wsProtocol}://${window.location.host}/ws/ruff`,
|
||||
'ruff',
|
||||
{},
|
||||
undefined
|
||||
)
|
||||
connectToLanguageServer(
|
||||
`${wsProtocol}://${window.location.host}/ws/diagnostic`,
|
||||
'black',
|
||||
{
|
||||
formatters: {
|
||||
@@ -466,7 +465,7 @@
|
||||
)
|
||||
} else if (lang === 'go') {
|
||||
connectToLanguageServer(
|
||||
`${wsProtocol}://${$page.url.host}/ws/go`,
|
||||
`${wsProtocol}://${window.location.host}/ws/go`,
|
||||
'go',
|
||||
{
|
||||
'build.allowImplicitNetworkAccess': true
|
||||
@@ -475,7 +474,7 @@
|
||||
)
|
||||
} else if (lang === 'shell') {
|
||||
connectToLanguageServer(
|
||||
`${wsProtocol}://${$page.url.host}/ws/diagnostic`,
|
||||
`${wsProtocol}://${window.location.host}/ws/diagnostic`,
|
||||
'shellcheck',
|
||||
{
|
||||
linters: {
|
||||
@@ -658,7 +657,7 @@
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
if (browser) {
|
||||
if (BROWSER) {
|
||||
loadMonaco().then((x) => (disposeMethod = x))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { ResourceService, VariableService } from '$lib/gen'
|
||||
import { getScriptByPath, sendUserToast } from '$lib/utils'
|
||||
|
||||
import {
|
||||
faCube,
|
||||
@@ -30,6 +29,8 @@
|
||||
import Skeleton from './common/skeleton/Skeleton.svelte'
|
||||
import Popover from './Popover.svelte'
|
||||
import { SCRIPT_EDITOR_SHOW_EXPLORE_OTHER_SCRIPTS } from '$lib/consts'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { getScriptByPath } from '$lib/scripts'
|
||||
|
||||
export let lang: 'python3' | 'deno' | 'go' | 'bash'
|
||||
export let editor: Editor | undefined
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation'
|
||||
import { FlowService, ScheduleService, type Flow, type FlowModule, DraftService } from '$lib/gen'
|
||||
import { initHistory, redo, undo } from '$lib/history'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { encodeState, formatCron, loadHubScripts, sendUserToast } from '$lib/utils'
|
||||
import { encodeState, formatCron } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
import { faCalendarAlt, faSave } from '@fortawesome/free-solid-svg-icons'
|
||||
import { setContext } from 'svelte'
|
||||
import { writable, type Writable } from 'svelte/store'
|
||||
@@ -20,7 +21,8 @@
|
||||
import type { FlowEditorContext } from './flows/types'
|
||||
import { cleanInputs } from './flows/utils'
|
||||
import { Pen } from 'lucide-svelte'
|
||||
import UnsavedConfirmationModal from './common/confirmationModal/UnsavedConfirmationModal.svelte'
|
||||
import { loadHubScripts } from '$lib/scripts'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export let initialPath: string = ''
|
||||
export let selectedId: string | undefined
|
||||
@@ -29,6 +31,8 @@
|
||||
export let flowStore: Writable<Flow>
|
||||
export let flowStateStore: Writable<FlowState>
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
async function createSchedule(path: string) {
|
||||
const { cron, timezone, args, enabled } = $scheduleStore
|
||||
|
||||
@@ -79,7 +83,7 @@
|
||||
})
|
||||
if (initialPath == '') {
|
||||
$dirtyStore = false
|
||||
goto(`/flows/edit/${flow.path}`)
|
||||
dispatch('saveInitial')
|
||||
}
|
||||
sendUserToast('Saved as draft')
|
||||
} catch (error) {
|
||||
@@ -155,8 +159,7 @@
|
||||
}
|
||||
loadingSave = false
|
||||
$dirtyStore = false
|
||||
window.history.replaceState(window.history.state, '', `/flows/edit/${flow.path}`)
|
||||
goto(`/flows/get/${$flowStore.path}?workspace=${$workspaceStore}`)
|
||||
dispatch('deploy')
|
||||
} catch (err) {
|
||||
sendUserToast(`The flow could not be saved: ${err.body}`, true)
|
||||
loadingSave = false
|
||||
@@ -190,6 +193,10 @@
|
||||
|
||||
const selectedIdStore = writable<string>(selectedId ?? 'settings-metadata')
|
||||
|
||||
export function getSelectedId() {
|
||||
return $selectedIdStore
|
||||
}
|
||||
|
||||
const scheduleStore = writable<Schedule>({
|
||||
args: {},
|
||||
cron: '',
|
||||
@@ -306,7 +313,7 @@
|
||||
}> = [
|
||||
{
|
||||
label: 'Exit & see details',
|
||||
onClick: () => goto(`/flows/get/${$flowStore.path}?workspace=${$workspaceStore}`)
|
||||
onClick: () => dispatch('details')
|
||||
}
|
||||
]
|
||||
|
||||
@@ -320,8 +327,6 @@
|
||||
|
||||
<svelte:window on:keydown={onKeyDown} />
|
||||
|
||||
<UnsavedConfirmationModal />
|
||||
|
||||
{#if !$userStore?.operator}
|
||||
<ScriptEditorDrawer bind:this={$scriptEditorDrawer} />
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import HighlightCode from './HighlightCode.svelte'
|
||||
import InputTransformsViewer from './InputTransformsViewer.svelte'
|
||||
import IconedPath from './IconedPath.svelte'
|
||||
import { scriptPathToHref } from '../utils'
|
||||
import type { FlowModule, FlowValue } from '$lib/gen'
|
||||
import { Badge, Button, Drawer, DrawerContent } from './common'
|
||||
import { Highlight } from 'svelte-highlight'
|
||||
@@ -12,6 +11,7 @@
|
||||
import { cleanExpr } from './flows/utils'
|
||||
import FlowPathViewer from './flows/content/FlowPathViewer.svelte'
|
||||
import SchemaViewer from './SchemaViewer.svelte'
|
||||
import { scriptPathToHref } from '$lib/scripts'
|
||||
export let flow: {
|
||||
summary: string
|
||||
description?: string
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { GranularAclService, GroupService, UserService, type Group } from '$lib/gen'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { canWrite, sendUserToast } from '$lib/utils'
|
||||
import AutoComplete from 'simple-svelte-autocomplete'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import autosize from 'svelte-autosize'
|
||||
@@ -9,6 +8,8 @@
|
||||
import Skeleton from './common/skeleton/Skeleton.svelte'
|
||||
import TableCustom from './TableCustom.svelte'
|
||||
import Tooltip from './Tooltip.svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { canWrite } from '$lib/utils'
|
||||
|
||||
export let name: string
|
||||
let can_write = false
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { UserService } from '$lib/gen'
|
||||
import { Button } from './common'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { WorkspaceService } from '$lib/gen'
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
import type { Schema } from '$lib/common'
|
||||
import { ScriptService, type FlowModule, type Job } from '$lib/gen'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { getModifierKey, getScriptByPath } from '$lib/utils'
|
||||
import { getModifierKey } from '$lib/utils'
|
||||
import { getScriptByPath } from '$lib/scripts'
|
||||
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
import { getContext } from 'svelte'
|
||||
import { Pane, Splitpanes } from 'svelte-splitpanes'
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { isOwner } from '$lib/utils'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { Alert, Button, Drawer } from './common'
|
||||
import DrawerContent from './common/drawer/DrawerContent.svelte'
|
||||
import Path from './Path.svelte'
|
||||
import { AppService, FlowService, RawAppService, ScriptService } from '$lib/gen'
|
||||
import { isOwner } from '$lib/utils'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { Schema } from '$lib/common'
|
||||
import { ResourceService, type Resource } from '$lib/gen'
|
||||
import { canWrite, emptyString, isOwner, sendUserToast } from '$lib/utils'
|
||||
import { canWrite, emptyString, isOwner } from '$lib/utils'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { Alert, Button, Drawer, Skeleton } from './common'
|
||||
import Path from './Path.svelte'
|
||||
@@ -14,6 +14,7 @@
|
||||
import SchemaForm from './SchemaForm.svelte'
|
||||
import SimpleEditor from './SimpleEditor.svelte'
|
||||
import Toggle from './Toggle.svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
let path = ''
|
||||
let initialPath = ''
|
||||
|
||||
@@ -5,13 +5,7 @@
|
||||
import { inferArgs } from '$lib/infer'
|
||||
import { initialCode } from '$lib/script_helpers'
|
||||
import { userStore, workerTags, workspaceStore } from '$lib/stores'
|
||||
import {
|
||||
emptySchema,
|
||||
encodeState,
|
||||
getModifierKey,
|
||||
sendUserToast,
|
||||
setQueryWithoutLoad
|
||||
} from '$lib/utils'
|
||||
import { emptySchema, encodeState, getModifierKey, setQueryWithoutLoad } from '$lib/utils'
|
||||
import Path from './Path.svelte'
|
||||
import ScriptEditor from './ScriptEditor.svelte'
|
||||
import ScriptSchema from './ScriptSchema.svelte'
|
||||
@@ -32,6 +26,7 @@
|
||||
SCRIPT_CUSTOMISE_SHOW_KIND
|
||||
} from '$lib/consts'
|
||||
import UnsavedConfirmationModal from './common/confirmationModal/UnsavedConfirmationModal.svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
export let script: NewScript
|
||||
export let initialPath: string = ''
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import type { Schema } from '$lib/common'
|
||||
import { CompletedJob, Job, JobService } from '$lib/gen'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { emptySchema, getModifierKey, scriptLangToEditorLang } from '$lib/utils'
|
||||
import { emptySchema, getModifierKey } from '$lib/utils'
|
||||
import { faPlay } from '@fortawesome/free-solid-svg-icons'
|
||||
import Editor from './Editor.svelte'
|
||||
import { inferArgs } from '$lib/infer'
|
||||
@@ -17,6 +17,7 @@
|
||||
import { Button, Kbd } from './common'
|
||||
import SplitPanesWrapper from './splitPanes/SplitPanesWrapper.svelte'
|
||||
import WindmillIcon from './icons/WindmillIcon.svelte'
|
||||
import { scriptLangToEditorLang } from '$lib/scripts'
|
||||
|
||||
// Exported
|
||||
export let schema: Schema = emptySchema()
|
||||
@@ -51,11 +52,8 @@
|
||||
let testIsLoading = false
|
||||
let testJob: Job | undefined
|
||||
let pastPreviews: CompletedJob[] = []
|
||||
let lastSave: string | null
|
||||
let validCode = true
|
||||
|
||||
$: lastSave = localStorage.getItem(path ?? 'last_save')
|
||||
|
||||
function onKeyDown(event: KeyboardEvent) {
|
||||
if ((event.ctrlKey || event.metaKey) && event.key == 'Enter') {
|
||||
event.preventDefault()
|
||||
@@ -177,7 +175,6 @@
|
||||
} catch (e) {
|
||||
console.error('Could not save last_save to local storage', e)
|
||||
}
|
||||
lastSave = code
|
||||
dispatch('format')
|
||||
}}
|
||||
class="flex flex-1 h-full !overflow-visible"
|
||||
@@ -231,14 +228,7 @@
|
||||
</div>
|
||||
</Pane>
|
||||
<Pane size={67}>
|
||||
<LogPanel
|
||||
{path}
|
||||
{lang}
|
||||
previewJob={testJob}
|
||||
{pastPreviews}
|
||||
previewIsLoading={testIsLoading}
|
||||
bind:lastSave
|
||||
/>
|
||||
<LogPanel {lang} previewJob={testJob} {pastPreviews} previewIsLoading={testIsLoading} />
|
||||
</Pane>
|
||||
</Splitpanes>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import Select from 'svelte-select'
|
||||
|
||||
import { getScriptByPath } from '$lib/utils'
|
||||
import { getScriptByPath } from '$lib/scripts'
|
||||
import RadioButton from './RadioButton.svelte'
|
||||
import { Button, Drawer, DrawerContent } from './common'
|
||||
import HighlightCode from './HighlightCode.svelte'
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import TableCustom from './TableCustom.svelte'
|
||||
|
||||
import { GranularAclService } from '$lib/gen/services/GranularAclService'
|
||||
import { isOwner, sendUserToast } from '$lib/utils'
|
||||
import { GroupService, UserService } from '$lib/gen'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import AutoComplete from 'simple-svelte-autocomplete'
|
||||
@@ -10,6 +9,8 @@
|
||||
import { Alert, Button, Drawer, ToggleButton, ToggleButtonGroup } from './common'
|
||||
import DrawerContent from './common/drawer/DrawerContent.svelte'
|
||||
import Tooltip from './Tooltip.svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { isOwner } from '$lib/utils'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { browser } from '$app/environment'
|
||||
import { BROWSER } from 'esm-env'
|
||||
|
||||
import { createHash, editorConfig, langToExt, updateOptions } from '$lib/editorUtils'
|
||||
import 'monaco-editor/esm/vs/editor/edcore.main'
|
||||
@@ -181,7 +181,7 @@
|
||||
|
||||
let mounted = false
|
||||
onMount(async () => {
|
||||
if (browser) {
|
||||
if (BROWSER) {
|
||||
mounted = true
|
||||
await loadMonaco()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { FavoriteService } from '$lib/gen'
|
||||
import { starStore } from '$lib/stores'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { Star, StarOff } from 'lucide-svelte'
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import PageHeader from '$lib/components/PageHeader.svelte'
|
||||
import InviteGlobalUser from '$lib/components/InviteGlobalUser.svelte'
|
||||
import { Badge, Drawer, DrawerContent } from '$lib/components/common'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import SearchItems from './SearchItems.svelte'
|
||||
import { page } from '$app/stores'
|
||||
import { goto } from '$app/navigation'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { browser } from '$app/environment'
|
||||
import { BROWSER } from 'esm-env'
|
||||
import {
|
||||
convertKind,
|
||||
createDocumentationString,
|
||||
@@ -578,7 +578,7 @@
|
||||
|
||||
let mounted = false
|
||||
onMount(async () => {
|
||||
if (browser) {
|
||||
if (BROWSER) {
|
||||
await loadMonaco()
|
||||
mounted = true
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import type { ToastAction } from '$lib/utils'
|
||||
import { toast } from '@zerodevx/svelte-toast'
|
||||
import { CheckCircle2, XCircleIcon } from 'lucide-svelte'
|
||||
import { onMount } from 'svelte'
|
||||
import Button from './common/button/Button.svelte'
|
||||
import type { ToastAction } from '$lib/toast'
|
||||
|
||||
export let message: string
|
||||
export let toastId: string
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { usersWorkspaceStore } from '$lib/stores'
|
||||
import type { TruncatedToken, NewToken } from '$lib/gen'
|
||||
import { UserService, SettingsService } from '$lib/gen'
|
||||
import { displayDate, sendUserToast, copyToClipboard } from '$lib/utils'
|
||||
import { displayDate, copyToClipboard } from '$lib/utils'
|
||||
import { faClipboard, faPlus } from '@fortawesome/free-solid-svg-icons'
|
||||
import TableCustom from '$lib/components/TableCustom.svelte'
|
||||
import { Button } from '$lib/components/common'
|
||||
@@ -22,6 +22,7 @@
|
||||
import DrawerContent from '$lib/components/common/drawer/DrawerContent.svelte'
|
||||
import { page } from '$app/stores'
|
||||
import { goto } from '$app/navigation'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
let drawer: Drawer
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
import { canWrite, isOwner, sendUserToast } from '$lib/utils'
|
||||
import { VariableService } from '$lib/gen'
|
||||
import Path from './Path.svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
@@ -14,6 +13,8 @@
|
||||
import Toggle from './Toggle.svelte'
|
||||
import { faSave } from '@fortawesome/free-solid-svg-icons'
|
||||
import SimpleEditor from './SimpleEditor.svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { canWrite, isOwner } from '$lib/utils'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
color={resolvedConfig.color}
|
||||
download={resolvedConfig.filename}
|
||||
href={transformBareBase64IfNecessary(resolvedConfig.source)}
|
||||
target="_self"
|
||||
nonCaptureEvent
|
||||
>
|
||||
<span class="truncate inline-flex gap-2 items-center">
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
import { isScriptByNameDefined, isScriptByPathDefined } from '../../utils'
|
||||
import NonRunnableComponent from './NonRunnableComponent.svelte'
|
||||
import RunnableComponent from './RunnableComponent.svelte'
|
||||
import { goto } from '$app/navigation'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import InitializeComponent from './InitializeComponent.svelte'
|
||||
|
||||
export let componentInput: AppInput | undefined
|
||||
@@ -108,7 +107,7 @@
|
||||
if (sideEffect.configuration.gotoUrl.newTab) {
|
||||
window.open(sideEffect.configuration.gotoUrl.url, '_blank')
|
||||
} else {
|
||||
goto(sideEffect.configuration.gotoUrl.url)
|
||||
window.location.href = sideEffect.configuration.gotoUrl.url
|
||||
}
|
||||
} else if (
|
||||
sideEffect.selected == 'sendToast' &&
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { isPlainObject } from 'lodash'
|
||||
import type { World } from '../../rx'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
export function computeGlobalContext(world: World | undefined, extraContext: any = {}) {
|
||||
return {
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
import { getContext } from 'svelte'
|
||||
import { Icon } from 'svelte-awesome'
|
||||
import { Pane, Splitpanes } from 'svelte-splitpanes'
|
||||
import { classNames, copyToClipboard, sendUserToast } from '../../../utils'
|
||||
import { classNames, copyToClipboard } from '../../../utils'
|
||||
import type {
|
||||
AppInput,
|
||||
ConnectedAppInput,
|
||||
@@ -51,6 +51,7 @@
|
||||
import UnsavedConfirmationModal from '$lib/components/common/confirmationModal/UnsavedConfirmationModal.svelte'
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import { Sha256 } from '@aws-crypto/sha256-js'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
async function hash(message) {
|
||||
try {
|
||||
|
||||
@@ -21,7 +21,8 @@ import gridHelp from '../svelte-grid/utils/helper'
|
||||
import type { FilledItem } from '../svelte-grid/types'
|
||||
import type { EvalAppInput, StaticAppInput } from '../inputType'
|
||||
import { get, type Writable } from 'svelte/store'
|
||||
import { deepMergeWithPriority, sendUserToast } from '$lib/utils'
|
||||
import { deepMergeWithPriority } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { getNextId } from '$lib/components/flows/idUtils'
|
||||
|
||||
export function dfs(
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
} from '../appUtils'
|
||||
import type { AppEditorContext, AppViewerContext, FocusedGrid, GridItem } from '../../types'
|
||||
import { push } from '$lib/history'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { gridColumns } from '../../gridUtils'
|
||||
|
||||
const { app, selectedComponent, focusedGrid, componentControl } =
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
import { Script, type Preview } from '$lib/gen'
|
||||
import { inferArgs } from '$lib/infer'
|
||||
import { initialCode } from '$lib/script_helpers'
|
||||
import { capitalize, emptySchema, getScriptByPath } from '$lib/utils'
|
||||
import { capitalize, emptySchema } from '$lib/utils'
|
||||
import { getScriptByPath } from '$lib/scripts'
|
||||
|
||||
import { faCodeBranch } from '@fortawesome/free-solid-svg-icons'
|
||||
import { Building, Globe2 } from 'lucide-svelte'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
|
||||
+2
-1
@@ -9,7 +9,7 @@
|
||||
import type { Schema } from '$lib/common'
|
||||
import Badge from '$lib/components/common/badge/Badge.svelte'
|
||||
import Editor from '$lib/components/Editor.svelte'
|
||||
import { emptySchema, getModifierKey, scriptLangToEditorLang } from '$lib/utils'
|
||||
import { emptySchema, getModifierKey } from '$lib/utils'
|
||||
import { computeFields } from './utils'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import type { AppInput } from '../../inputType'
|
||||
@@ -17,6 +17,7 @@
|
||||
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
|
||||
import { buildExtraLib } from '../../utils'
|
||||
import RunButton from './RunButton.svelte'
|
||||
import { scriptLangToEditorLang } from '$lib/scripts'
|
||||
|
||||
let inlineScriptEditorDrawer: InlineScriptEditorDrawer
|
||||
|
||||
|
||||
+3
-1
@@ -2,7 +2,7 @@
|
||||
import { Button, Drawer, DrawerContent } from '$lib/components/common'
|
||||
import FlowModuleScript from '$lib/components/flows/content/FlowModuleScript.svelte'
|
||||
import FlowPathViewer from '$lib/components/flows/content/FlowPathViewer.svelte'
|
||||
import { emptySchema, getScriptByPath, sendUserToast } from '$lib/utils'
|
||||
import { emptySchema } from '$lib/utils'
|
||||
import { getContext } from 'svelte'
|
||||
import type {
|
||||
ConnectedAppInput,
|
||||
@@ -27,6 +27,8 @@
|
||||
import { loadSchema } from '../../utils'
|
||||
import { inferArgs } from '$lib/infer'
|
||||
import RunButton from './RunButton.svelte'
|
||||
import { getScriptByPath } from '$lib/scripts'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
export let runnable: RunnableByPath
|
||||
export let fields: Record<string, StaticAppInput | ConnectedAppInput | RowAppInput | UserAppInput>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/common'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { Copy } from 'lucide-svelte'
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppViewerContext } from '../../types'
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import Icon from 'svelte-awesome'
|
||||
import { ButtonType } from './model'
|
||||
import { goto } from '$app/navigation'
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import ButtonDropdown from './ButtonDropdown.svelte'
|
||||
@@ -18,14 +17,13 @@
|
||||
export let wrapperStyle: string = ''
|
||||
export let disabled: boolean = false
|
||||
export let href: string | undefined = undefined
|
||||
export let target: ButtonType.Target = '_self'
|
||||
export let target: '_self' | '_blank' | undefined = undefined
|
||||
export let iconOnly: boolean = false
|
||||
export let startIcon: ButtonType.Icon | undefined = undefined
|
||||
export let endIcon: ButtonType.Icon | undefined = undefined
|
||||
export let element: ButtonType.Element | undefined = undefined
|
||||
export let id: string = ''
|
||||
export let nonCaptureEvent: boolean = false
|
||||
export let buttonType: 'button' | 'submit' | 'reset' = 'button'
|
||||
export let loading = false
|
||||
export let title: string | undefined = undefined
|
||||
export let style: string = ''
|
||||
@@ -97,33 +95,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: buttonProps = {
|
||||
id,
|
||||
href,
|
||||
target,
|
||||
tabindex: disabled ? -1 : 0,
|
||||
type: buttonType,
|
||||
title,
|
||||
...$$restProps
|
||||
}
|
||||
|
||||
async function onClick(event: MouseEvent) {
|
||||
if (!nonCaptureEvent) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
dispatch('click', event)
|
||||
if (href) {
|
||||
if (href.startsWith('data')) {
|
||||
return
|
||||
}
|
||||
if (href.startsWith('http') || target == '_blank') {
|
||||
window.open(href, target)
|
||||
} else {
|
||||
loading = true
|
||||
await goto(href)
|
||||
loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,33 +125,75 @@
|
||||
class="{dropdownItems ? colorVariants[color].divider : ''} {wrapperClasses} flex flex-row"
|
||||
style={wrapperStyle}
|
||||
>
|
||||
<svelte:element
|
||||
this={href ? 'a' : 'button'}
|
||||
bind:this={element}
|
||||
on:pointerdown
|
||||
on:click={onClick}
|
||||
on:focus
|
||||
on:blur
|
||||
{download}
|
||||
class={twMerge(buttonClass, disabled ? '!bg-gray-300 !text-gray-600 !cursor-not-allowed' : '')}
|
||||
{...buttonProps}
|
||||
disabled={disabled || loading}
|
||||
type="submit"
|
||||
{style}
|
||||
>
|
||||
{#if loading}
|
||||
<Loader2 class="animate-spin mr-1" size={14} />
|
||||
{:else if startIcon}
|
||||
<Icon data={startIcon.icon} class={startIconClass} scale={ButtonType.IconScale[size]} />
|
||||
{/if}
|
||||
{#if href}
|
||||
<a
|
||||
data-sveltekit-preload-code="hover"
|
||||
bind:this={element}
|
||||
on:pointerdown
|
||||
on:focus
|
||||
on:blur
|
||||
on:click={() => {
|
||||
loading = true
|
||||
dispatch('click', event)
|
||||
loading = false
|
||||
}}
|
||||
{href}
|
||||
{download}
|
||||
class={twMerge(
|
||||
buttonClass,
|
||||
disabled ? '!bg-gray-300 !text-gray-600 !cursor-not-allowed' : ''
|
||||
)}
|
||||
{id}
|
||||
{target}
|
||||
tabindex={disabled ? -1 : 0}
|
||||
{...$$restProps}
|
||||
{style}
|
||||
>
|
||||
{#if loading}
|
||||
<Loader2 class="animate-spin mr-1" size={14} />
|
||||
{:else if startIcon}
|
||||
<Icon data={startIcon.icon} class={startIconClass} scale={ButtonType.IconScale[size]} />
|
||||
{/if}
|
||||
|
||||
{#if !iconOnly}
|
||||
<slot />
|
||||
{/if}
|
||||
{#if endIcon}
|
||||
<Icon data={endIcon.icon} class={endIconClass} scale={ButtonType.IconScale[size]} />
|
||||
{/if}
|
||||
</svelte:element>
|
||||
{#if !iconOnly}
|
||||
<slot />
|
||||
{/if}
|
||||
{#if endIcon}
|
||||
<Icon data={endIcon.icon} class={endIconClass} scale={ButtonType.IconScale[size]} />
|
||||
{/if}
|
||||
</a>
|
||||
{:else}
|
||||
<button
|
||||
bind:this={element}
|
||||
on:pointerdown
|
||||
on:click={onClick}
|
||||
on:focus
|
||||
on:blur
|
||||
class={twMerge(
|
||||
buttonClass,
|
||||
disabled ? '!bg-gray-300 !text-gray-600 !cursor-not-allowed' : ''
|
||||
)}
|
||||
{id}
|
||||
tabindex={disabled ? -1 : 0}
|
||||
{title}
|
||||
{...$$restProps}
|
||||
disabled={disabled || loading}
|
||||
{style}
|
||||
>
|
||||
{#if loading}
|
||||
<Loader2 class="animate-spin mr-1" size={14} />
|
||||
{:else if startIcon}
|
||||
<Icon data={startIcon.icon} class={startIconClass} scale={ButtonType.IconScale[size]} />
|
||||
{/if}
|
||||
|
||||
{#if !iconOnly}
|
||||
<slot />
|
||||
{/if}
|
||||
{#if endIcon}
|
||||
<Icon data={endIcon.icon} class={endIconClass} scale={ButtonType.IconScale[size]} />
|
||||
{/if}
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
{#if dropdownItems}
|
||||
<div class={twMerge(buttonClass, 'rounded-r-md rounded-l-none m-0 p-0 h-auto')}>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { browser } from '$app/environment'
|
||||
import { BROWSER } from 'esm-env'
|
||||
|
||||
export let open = false
|
||||
export let duration = 0.3
|
||||
@@ -35,7 +35,7 @@
|
||||
$: style = `--duration: ${duration}s; --size: ${size};`
|
||||
|
||||
function scrollLock(open: boolean) {
|
||||
if (browser) {
|
||||
if (BROWSER) {
|
||||
const body = document.querySelector('body')
|
||||
|
||||
if (mounted && body) {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import type ShareModal from '$lib/components/ShareModal.svelte'
|
||||
import { FlowService, type Flow } from '$lib/gen'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { isOwner, sendUserToast } from '$lib/utils'
|
||||
import {
|
||||
faArchive,
|
||||
faCalendarAlt,
|
||||
@@ -25,6 +24,8 @@
|
||||
import Button from '../button/Button.svelte'
|
||||
import Row from './Row.svelte'
|
||||
import DraftBadge from '$lib/components/DraftBadge.svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { isOwner } from '$lib/utils'
|
||||
|
||||
export let flow: Flow & { has_draft?: boolean; draft_only?: boolean; canWrite: boolean }
|
||||
export let marked: string | undefined
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
import { ScriptService, type Script } from '$lib/gen'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { isOwner, sendUserToast } from '$lib/utils'
|
||||
import {
|
||||
faArchive,
|
||||
faCalendarAlt,
|
||||
@@ -27,6 +26,8 @@
|
||||
import LanguageBadge from './LanguageBadge.svelte'
|
||||
import Row from './Row.svelte'
|
||||
import DraftBadge from '$lib/components/DraftBadge.svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { isOwner } from '$lib/utils'
|
||||
|
||||
export let script: Script & { canWrite: boolean }
|
||||
export let marked: string | undefined
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores'
|
||||
import { BROWSER } from 'esm-env'
|
||||
import { Button } from '$lib/components/common'
|
||||
import Drawer from '$lib/components/common/drawer/Drawer.svelte'
|
||||
import DrawerContent from '$lib/components/common/drawer/DrawerContent.svelte'
|
||||
@@ -44,6 +44,8 @@
|
||||
captureInput = capture
|
||||
jsonSchema = { required: [], properties: {}, ...convert(capture) }
|
||||
}
|
||||
|
||||
let hostname = BROWSER ? window.location.protocol + '//' + window.location.host : 'SSR'
|
||||
</script>
|
||||
|
||||
<Drawer
|
||||
@@ -63,14 +65,10 @@
|
||||
class="text-2xl"
|
||||
on:click={(e) => {
|
||||
e.preventDefault()
|
||||
copyToClipboard(
|
||||
`${$page.url.protocol}//${$page.url.hostname}/api/w/${$workspaceStore}/capture_u/${$flowStore.path}`
|
||||
)
|
||||
copyToClipboard(`${hostname}/api/w/${$workspaceStore}/capture_u/${$flowStore.path}`)
|
||||
}}
|
||||
href="{$page.url.protocol}//{$page.url
|
||||
.hostname}/api/w/{$workspaceStore}/capture_u/{$flowStore.path}"
|
||||
>{$page.url.protocol}//{$page.url
|
||||
.hostname}/api/w/{$workspaceStore}/capture_u/{$flowStore.path}
|
||||
href="{hostname}/api/w/{$workspaceStore}/capture_u/{$flowStore.path}"
|
||||
>{hostname}/api/w/{$workspaceStore}/capture_u/{$flowStore.path}
|
||||
<Icon data={faClipboard} /></a
|
||||
>
|
||||
</div>
|
||||
@@ -78,7 +76,7 @@
|
||||
|
||||
<div class="text-xs box mb-4 b">
|
||||
<pre class="overflow-auto"
|
||||
>{`curl -X POST ${$page.url.protocol}//${$page.url.hostname}/api/w/${$workspaceStore}/capture_u/${$flowStore.path} \\
|
||||
>{`curl -X POST ${hostname}/api/w/${$workspaceStore}/capture_u/${$flowStore.path} \\
|
||||
-H 'Content-Type: application/json' \\
|
||||
-d '{"foo": 42}'`}</pre
|
||||
>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import { RawScript, type FlowModule, type PathFlow, type PathScript } from '$lib/gen'
|
||||
import FlowCard from '../common/FlowCard.svelte'
|
||||
import FlowModuleHeader from './FlowModuleHeader.svelte'
|
||||
import { getLatestHashForScript, schemaToObject, scriptLangToEditorLang } from '$lib/utils'
|
||||
import { getLatestHashForScript, scriptLangToEditorLang } from '$lib/scripts'
|
||||
import PropPickerWrapper from '../propPicker/PropPickerWrapper.svelte'
|
||||
import { afterUpdate, getContext } from 'svelte'
|
||||
import type { FlowEditorContext } from '../types'
|
||||
@@ -27,6 +27,7 @@
|
||||
import FlowModuleSleep from './FlowModuleSleep.svelte'
|
||||
import FlowPathViewer from './FlowPathViewer.svelte'
|
||||
import InputTransformSchemaForm from '$lib/components/InputTransformSchemaForm.svelte'
|
||||
import { schemaToObject } from '$lib/schema'
|
||||
|
||||
const { selectedId, previewArgs, flowStateStore, flowStore, saveDraft } =
|
||||
getContext<FlowEditorContext>('FlowEditorContext')
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
import { Bed, PhoneIncoming, Repeat, Square } from 'lucide-svelte'
|
||||
import Popover from '../../Popover.svelte'
|
||||
import type { FlowEditorContext } from '../types'
|
||||
import { getLatestHashForScript, sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { workerTags } from '$lib/stores'
|
||||
import { getLatestHashForScript } from '$lib/scripts'
|
||||
|
||||
export let module: FlowModule
|
||||
const { scriptEditorDrawer } = getContext<FlowEditorContext>('FlowEditorContext')
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import HighlightCode from '$lib/components/HighlightCode.svelte'
|
||||
import { ScriptService } from '$lib/gen'
|
||||
import { getScriptByPath } from '$lib/scripts'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { getScriptByPath } from '$lib/utils'
|
||||
|
||||
export let path: string
|
||||
export let hash: string | undefined = undefined
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import Tab from '$lib/components/common/tabs/Tab.svelte'
|
||||
import TabContent from '$lib/components/common/tabs/TabContent.svelte'
|
||||
|
||||
import { BROWSER } from 'esm-env'
|
||||
import Path from '$lib/components/Path.svelte'
|
||||
import Required from '$lib/components/Required.svelte'
|
||||
import FlowCard from '../common/FlowCard.svelte'
|
||||
@@ -13,7 +14,6 @@
|
||||
import type { FlowEditorContext } from '../types'
|
||||
import autosize from 'svelte-autosize'
|
||||
import Slider from '$lib/components/Slider.svelte'
|
||||
import { page } from '$app/stores'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { copyToClipboard } from '$lib/utils'
|
||||
import { Icon } from 'svelte-awesome'
|
||||
@@ -22,8 +22,9 @@
|
||||
|
||||
const { selectedId, flowStore, initialPath } = getContext<FlowEditorContext>('FlowEditorContext')
|
||||
|
||||
$: url = `${$page.url.hostname}/api/w/${$workspaceStore}/jobs/run/f/${$flowStore?.path}`
|
||||
$: syncedUrl = `${$page.url.hostname}/api/w/${$workspaceStore}/jobs/run_wait_result/f/${$flowStore?.path}`
|
||||
let hostname = BROWSER ? window.location.protocol + '//' + window.location.host : 'SSR'
|
||||
$: url = `${hostname}/api/w/${$workspaceStore}/jobs/run/f/${$flowStore?.path}`
|
||||
$: syncedUrl = `${hostname}/api/w/${$workspaceStore}/jobs/run_wait_result/f/${$flowStore?.path}`
|
||||
</script>
|
||||
|
||||
<div class="h-full overflow-hidden">
|
||||
@@ -107,7 +108,7 @@
|
||||
e.preventDefault()
|
||||
copyToClipboard(url)
|
||||
}}
|
||||
href={$page.url.protocol + '//' + url}
|
||||
href={url}
|
||||
class="whitespace-nowrap text-ellipsis overflow-hidden mr-1"
|
||||
>
|
||||
{url}
|
||||
@@ -123,7 +124,7 @@
|
||||
e.preventDefault()
|
||||
copyToClipboard(syncedUrl)
|
||||
}}
|
||||
href={$page.url.protocol + '//' + syncedUrl}
|
||||
href={syncedUrl}
|
||||
class="whitespace-nowrap text-ellipsis overflow-hidden mr-1"
|
||||
>
|
||||
{syncedUrl}
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from '$lib/gen'
|
||||
import { initialCode } from '$lib/script_helpers'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { getScriptByPath } from '$lib/utils'
|
||||
import { getScriptByPath } from '$lib/scripts'
|
||||
import { get, type Writable } from 'svelte/store'
|
||||
import type { FlowModuleState, FlowState } from './flowState'
|
||||
import { charsToNumber, numberToChars } from './idUtils'
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import { Badge, Skeleton } from '$lib/components/common'
|
||||
import SearchItems from '$lib/components/SearchItems.svelte'
|
||||
import { loadHubApps } from '$lib/utils'
|
||||
import ListFilters from '$lib/components/home/ListFilters.svelte'
|
||||
import NoItemFound from '$lib/components/home/NoItemFound.svelte'
|
||||
import RowIcon from '$lib/components/common/table/RowIcon.svelte'
|
||||
import { loadHubApps } from '$lib/hub'
|
||||
|
||||
export let filter = ''
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<div class="flex items-center gap-4">
|
||||
<RowIcon kind="app" />
|
||||
|
||||
<div class="w-full text-left font-normal ">
|
||||
<div class="w-full text-left font-normal">
|
||||
<div class="text-gray-900 flex-wrap text-md font-semibold mb-1">
|
||||
{#if item.marked}
|
||||
{@html item.marked ?? ''}
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import { Badge, Skeleton } from '$lib/components/common'
|
||||
import SearchItems from '$lib/components/SearchItems.svelte'
|
||||
import { loadHubFlows } from '$lib/utils'
|
||||
import ListFilters from '$lib/components/home/ListFilters.svelte'
|
||||
import NoItemFound from '$lib/components/home/NoItemFound.svelte'
|
||||
import RowIcon from '$lib/components/common/table/RowIcon.svelte'
|
||||
import { loadHubFlows } from '$lib/hub'
|
||||
|
||||
export let filter = ''
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<div class="flex items-center gap-4">
|
||||
<RowIcon kind="flow" />
|
||||
|
||||
<div class="w-full text-left font-normal ">
|
||||
<div class="w-full text-left font-normal">
|
||||
<div class="text-gray-900 flex-wrap text-md font-semibold mb-1">
|
||||
{#if item.marked}
|
||||
{@html item.marked ?? ''}
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
import type { HubItem } from './model'
|
||||
import { Badge, Skeleton } from '$lib/components/common'
|
||||
import SearchItems from '$lib/components/SearchItems.svelte'
|
||||
import { capitalize, classNames, loadHubScripts } from '$lib/utils'
|
||||
import { capitalize, classNames } from '$lib/utils'
|
||||
import NoItemFound from '$lib/components/home/NoItemFound.svelte'
|
||||
import { APP_TO_ICON_COMPONENT } from '$lib/components/icons'
|
||||
import ListFilters from '$lib/components/home/ListFilters.svelte'
|
||||
import { loadHubScripts } from '$lib/scripts'
|
||||
|
||||
export let kind: 'script' | 'trigger' | 'approval' | 'failure' = 'script'
|
||||
export let filter = ''
|
||||
@@ -61,7 +62,7 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="w-full text-left font-normal ">
|
||||
<div class="w-full text-left font-normal">
|
||||
<div class="text-gray-900 flex-wrap text-md font-semibold mb-1">
|
||||
{#if item.marked}
|
||||
{@html item.marked ?? ''}
|
||||
@@ -69,7 +70,7 @@
|
||||
{item.summary ?? ''}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="text-gray-600 text-xs ">
|
||||
<div class="text-gray-600 text-xs">
|
||||
{item.path}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { Schema } from '$lib/common'
|
||||
import type { Flow, FlowModule } from '$lib/gen'
|
||||
import { schemaToObject } from '$lib/utils'
|
||||
import { schemaToObject } from '$lib/schema'
|
||||
import type { FlowState } from './flowState'
|
||||
|
||||
export type PickableProperties = {
|
||||
flow_input: Object
|
||||
priorIds: Record<string, any>
|
||||
previousId: string | undefined,
|
||||
previousId: string | undefined
|
||||
hasResume: boolean
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ type StepPropPicker = {
|
||||
extraLib: string
|
||||
}
|
||||
|
||||
|
||||
type ModuleBranches = FlowModule[][]
|
||||
|
||||
function getSubModules(flowModule: FlowModule): ModuleBranches {
|
||||
@@ -24,19 +23,18 @@ function getSubModules(flowModule: FlowModule): ModuleBranches {
|
||||
} else if (flowModule.value.type === 'branchall') {
|
||||
return flowModule.value.branches.map((branch) => branch.modules)
|
||||
} else if (flowModule.value.type == 'branchone') {
|
||||
return [
|
||||
...flowModule.value.branches.map((branch) => branch.modules),
|
||||
flowModule.value.default
|
||||
]
|
||||
return [...flowModule.value.branches.map((branch) => branch.modules), flowModule.value.default]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
function getAllSubmodules(flowModule: FlowModule): ModuleBranches {
|
||||
return getSubModules(flowModule).map((modules) => {
|
||||
return modules.map((module) => {
|
||||
return [module, ...getAllSubmodules(module).flat()]
|
||||
}).flat()
|
||||
return modules
|
||||
.map((module) => {
|
||||
return [module, ...getAllSubmodules(module).flat()]
|
||||
})
|
||||
.flat()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -47,8 +45,6 @@ function dfs(id: string | undefined, flow: Flow, getParents: boolean = true): Fl
|
||||
|
||||
function rec(id: string, moduleBranches: ModuleBranches): FlowModule[] | undefined {
|
||||
for (let modules of moduleBranches) {
|
||||
|
||||
|
||||
for (const [i, module] of modules.entries()) {
|
||||
if (module.id === id) {
|
||||
return getParents ? [module] : modules.slice(0, i + 1).reverse()
|
||||
@@ -93,7 +89,7 @@ function getFlowInput(
|
||||
value: "Iteration's value",
|
||||
index: "Iteration's index"
|
||||
},
|
||||
...parentFlowInput,
|
||||
...parentFlowInput
|
||||
}
|
||||
} else {
|
||||
return parentFlowInput
|
||||
@@ -111,38 +107,40 @@ export function getStepPropPicker(
|
||||
id: string,
|
||||
flow: Flow,
|
||||
args: any,
|
||||
include_node: boolean,
|
||||
include_node: boolean
|
||||
): StepPropPicker {
|
||||
const flowInput = getFlowInput(dfs(parentModule?.id, flow), flowState, args, flow.schema)
|
||||
|
||||
const previousIds = dfs(id, flow, false).map((x) => {
|
||||
let submodules = getAllSubmodules(x).flat().map((x) => x.id)
|
||||
const previousIds = dfs(id, flow, false)
|
||||
.map((x) => {
|
||||
let submodules = getAllSubmodules(x)
|
||||
.flat()
|
||||
.map((x) => x.id)
|
||||
|
||||
if (submodules.includes(id)) {
|
||||
return [x.id]
|
||||
} else {
|
||||
return [x.id, ...submodules]
|
||||
}
|
||||
}).flat()
|
||||
if (submodules.includes(id)) {
|
||||
return [x.id]
|
||||
} else {
|
||||
return [x.id, ...submodules]
|
||||
}
|
||||
})
|
||||
.flat()
|
||||
if (!include_node) {
|
||||
previousIds.shift()
|
||||
}
|
||||
|
||||
|
||||
let priorIds = Object.fromEntries(previousIds.map((id) => [id, flowState[id]?.previewResult ?? {}]).reverse())
|
||||
|
||||
let priorIds = Object.fromEntries(
|
||||
previousIds.map((id) => [id, flowState[id]?.previewResult ?? {}]).reverse()
|
||||
)
|
||||
|
||||
const pickableProperties = {
|
||||
flow_input: flowInput,
|
||||
priorIds: priorIds,
|
||||
previousId: previousIds[0],
|
||||
hasResume: previousModule?.suspend != undefined,
|
||||
hasResume: previousModule?.suspend != undefined
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (pickableProperties.hasResume) {
|
||||
pickableProperties["approvers"] = "The list of approvers"
|
||||
pickableProperties['approvers'] = 'The list of approvers'
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -151,7 +149,11 @@ export function getStepPropPicker(
|
||||
}
|
||||
}
|
||||
|
||||
export function buildExtraLib(flowInput: Record<string, any>, results: Record<string, any>, resume: boolean): string {
|
||||
export function buildExtraLib(
|
||||
flowInput: Record<string, any>,
|
||||
results: Record<string, any>,
|
||||
resume: boolean
|
||||
): string {
|
||||
return `
|
||||
/**
|
||||
* get variable (including secret) at path
|
||||
@@ -180,7 +182,9 @@ declare const params: any;
|
||||
*/
|
||||
declare const results = ${JSON.stringify(results)};
|
||||
|
||||
${resume ? `
|
||||
${
|
||||
resume
|
||||
? `
|
||||
/**
|
||||
* resume payload
|
||||
*/
|
||||
@@ -190,7 +194,8 @@ declare const resume: any
|
||||
* The list of approvers separated by ,
|
||||
*/
|
||||
declare const approvers: string
|
||||
` : ''}
|
||||
`
|
||||
|
||||
: ''
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
@@ -10,11 +10,12 @@ import {
|
||||
import { inferArgs } from '$lib/infer'
|
||||
import { loadSchema, loadSchemaFlow } from '$lib/scripts'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { emptySchema, sendUserToast } from '$lib/utils'
|
||||
import { emptySchema } from '$lib/utils'
|
||||
import { get } from 'svelte/store'
|
||||
import type { FlowModuleState } from './flowState'
|
||||
import type { PickableProperties } from './previousResults'
|
||||
import { NEVER_TESTED_THIS_FAR } from './models'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
function create_context_function_template(eval_string: string, context: Record<string, any>) {
|
||||
return `
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
RawAppService
|
||||
} from '$lib/gen'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { canWrite } from '$lib/utils'
|
||||
import type uFuzzy from '@leeoniya/ufuzzy'
|
||||
import { Code2, LayoutDashboard } from 'lucide-svelte'
|
||||
|
||||
@@ -35,6 +34,7 @@
|
||||
import ToggleButton from '../common/toggleButton-v2/ToggleButton.svelte'
|
||||
import FlowIcon from './FlowIcon.svelte'
|
||||
import RawAppRow from '../common/table/RawAppRow.svelte'
|
||||
import { canWrite } from '$lib/utils'
|
||||
|
||||
type TableItem<T, U extends 'script' | 'flow' | 'app' | 'raw_app'> = T & {
|
||||
canWrite: boolean
|
||||
|
||||
@@ -20,12 +20,10 @@
|
||||
import SplitPanesWrapper from '../splitPanes/SplitPanesWrapper.svelte'
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
|
||||
export let path: string | undefined
|
||||
export let lang: Preview.language
|
||||
export let previewIsLoading = false
|
||||
export let previewJob: Job | undefined
|
||||
export let pastPreviews: CompletedJob[] = []
|
||||
export let lastSave: string | null
|
||||
|
||||
type DrawerContent = {
|
||||
mode: 'json' | Preview.language | 'plain'
|
||||
@@ -67,9 +65,8 @@
|
||||
</Drawer>
|
||||
|
||||
<Tabs bind:selected={selectedTab} class="mt-1">
|
||||
<Tab value="logs" size="xs">Logs/Result</Tab>
|
||||
<Tab value="logs" size="xs">Logs & Result</Tab>
|
||||
<Tab value="history" size="xs">History</Tab>
|
||||
<Tab value="last_save" size="xs">Last save</Tab>
|
||||
|
||||
<svelte:fragment slot="content">
|
||||
<!--
|
||||
@@ -180,16 +177,5 @@
|
||||
</tbody>
|
||||
</TableCustom>
|
||||
</TabContent>
|
||||
<TabContent value="last_save" class="p-2">
|
||||
{#if lastSave}
|
||||
<div class="text-sm font-bold text-gray-600">
|
||||
Last local save for path
|
||||
<span class="italic">{path}</span>
|
||||
</div>
|
||||
<HighlightCode language={lang} code={lastSave} />
|
||||
{:else}
|
||||
No local save
|
||||
{/if}
|
||||
</TabContent>
|
||||
</svelte:fragment>
|
||||
</Tabs>
|
||||
|
||||
@@ -10,11 +10,12 @@
|
||||
switchWorkspace,
|
||||
workspaceStore
|
||||
} from '$lib/stores'
|
||||
import { classNames, isCloudHosted } from '$lib/utils'
|
||||
import { classNames } from '$lib/utils'
|
||||
import { faCog, faCrown, faHardHat, faSignOut, faUser } from '@fortawesome/free-solid-svg-icons'
|
||||
import Icon from 'svelte-awesome'
|
||||
import Menu from '../common/menu/Menu.svelte'
|
||||
import { SUPERADMIN_SETTINGS_HASH, USER_SETTINGS_HASH } from './settings'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
|
||||
export let isCollapsed: boolean = false
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import type { Schema } from './common'
|
||||
import { AppService, FlowService, type Flow, type Script } from './gen'
|
||||
import { encodeState } from './utils'
|
||||
|
||||
export function scriptToHubUrl(
|
||||
content: string,
|
||||
summary: string,
|
||||
description: string,
|
||||
kind: Script.kind,
|
||||
language: Script.language,
|
||||
schema: Schema | undefined,
|
||||
lock: string | undefined
|
||||
): URL {
|
||||
const url = new URL('https://hub.windmill.dev/scripts/add')
|
||||
|
||||
url.searchParams.append('content', content)
|
||||
url.searchParams.append('summary', summary)
|
||||
url.searchParams.append('description', description)
|
||||
url.searchParams.append('kind', kind)
|
||||
url.searchParams.append('language', language)
|
||||
url.searchParams.append('schema', JSON.stringify(schema, null, 2))
|
||||
lock && url.searchParams.append('lockfile', lock)
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
export async function loadHubFlows() {
|
||||
try {
|
||||
const flows = (await FlowService.listHubFlows()).flows ?? []
|
||||
const processed = flows.sort((a, b) => b.votes - a.votes)
|
||||
return processed
|
||||
} catch {
|
||||
console.error('Hub is not available')
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadHubApps() {
|
||||
try {
|
||||
const apps = (await AppService.listHubApps()).apps ?? []
|
||||
const processed = apps.sort((a, b) => b.votes - a.votes)
|
||||
return processed
|
||||
} catch {
|
||||
console.error('Hub is not available')
|
||||
}
|
||||
}
|
||||
|
||||
export function flowToHubUrl(flow: Flow): URL {
|
||||
const url = new URL('https://hub.windmill.dev/flows/add')
|
||||
const openFlow = {
|
||||
value: flow.value,
|
||||
summary: flow.summary,
|
||||
description: flow.description,
|
||||
schema: flow.schema
|
||||
}
|
||||
url.searchParams.append('flow', encodeState(openFlow))
|
||||
return url
|
||||
}
|
||||
|
||||
export function appToHubUrl(staticApp: any): URL {
|
||||
const url = new URL('https://hub.windmill.dev/apps/add')
|
||||
url.searchParams.append('app', encodeState(staticApp))
|
||||
return url
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
import { goto } from '$app/navigation'
|
||||
import { UserService } from '$lib/gen'
|
||||
import { clearStores } from './stores.js'
|
||||
import { sendUserToast } from './utils.js'
|
||||
import { sendUserToast } from './toast'
|
||||
|
||||
export async function logoutWithRedirect(rd?: string): Promise<void> {
|
||||
|
||||
await clearUser()
|
||||
if (rd && rd != "/" && rd?.split('?')[0] != '/user/login') {
|
||||
if (rd && rd != '/' && rd?.split('?')[0] != '/user/login') {
|
||||
const error = document.cookie.includes('token')
|
||||
? `error=${encodeURIComponent('You have been logged out because your session has expired.')}&`
|
||||
: ''
|
||||
console.log({rd});
|
||||
console.log({ rd })
|
||||
goto(`/user/login?${error}${rd ? 'rd=' + encodeURIComponent(rd) : ''}`, { replaceState: true })
|
||||
} else {
|
||||
goto('/user/login', { replaceState: true })
|
||||
@@ -27,6 +26,5 @@ export async function clearUser() {
|
||||
try {
|
||||
clearStores()
|
||||
await UserService.logout()
|
||||
} catch (error) {
|
||||
}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { goto } from '$app/navigation'
|
||||
|
||||
export async function setQuery(url: URL, key: string, value: string): Promise<void> {
|
||||
url.searchParams.set(key, value)
|
||||
await goto(`?${url.searchParams.toString()}`)
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import type { Schema } from './common'
|
||||
|
||||
export function schemaToTsType(schema: Schema): string {
|
||||
if (!schema || !schema.properties) {
|
||||
return 'any'
|
||||
}
|
||||
const propKeys = Object.keys(schema.properties)
|
||||
|
||||
const types = propKeys
|
||||
.map((key: string) => {
|
||||
const prop = schema.properties[key]
|
||||
const isOptional = !schema.required.includes(key)
|
||||
const prefix = `${key}${isOptional ? '?' : ''}`
|
||||
let type: string = 'any'
|
||||
if (prop.type === 'string') {
|
||||
type = 'string'
|
||||
} else if (prop.type === 'number' || prop.type === 'integer') {
|
||||
type = 'number'
|
||||
} else if (prop.type === 'boolean') {
|
||||
type = 'boolean'
|
||||
} else if (prop.type === 'array') {
|
||||
let type = prop.items?.type ?? 'any'
|
||||
if (type === 'integer') {
|
||||
type = 'number'
|
||||
}
|
||||
type = `${type}[]`
|
||||
}
|
||||
|
||||
return `${prefix}: ${type}`
|
||||
})
|
||||
.join(';')
|
||||
|
||||
return `{ ${types} }`
|
||||
}
|
||||
|
||||
export function schemaToObject(schema: Schema, args: Record<string, any>): Object {
|
||||
const object = {}
|
||||
if (!schema || !schema.properties) {
|
||||
return object
|
||||
}
|
||||
const propKeys = Object.keys(schema.properties)
|
||||
|
||||
propKeys.forEach((key: string) => {
|
||||
object[key] = args[key] ?? null
|
||||
})
|
||||
return object
|
||||
}
|
||||
@@ -1,10 +1,22 @@
|
||||
import { get } from 'svelte/store'
|
||||
import type { Schema } from './common'
|
||||
import { FlowService, ScriptService } from './gen'
|
||||
import type { Schema, SupportedLanguage } from './common'
|
||||
import { FlowService, Script, ScriptService } from './gen'
|
||||
import { inferArgs } from './infer'
|
||||
import { workspaceStore } from './stores'
|
||||
import { workspaceStore, hubScripts } from './stores'
|
||||
import { emptySchema } from './utils'
|
||||
|
||||
export function scriptLangToEditorLang(lang: Script.language) {
|
||||
if (lang == 'deno') {
|
||||
return 'typescript'
|
||||
} else if (lang == 'python3') {
|
||||
return 'python'
|
||||
} else if (lang == 'bash') {
|
||||
return 'shell'
|
||||
} else {
|
||||
return lang
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadSchema(path: string, hash?: string): Promise<Schema> {
|
||||
if (path.startsWith('hub/')) {
|
||||
const { content, language, schema } = await ScriptService.getHubScriptByPath({ path })
|
||||
@@ -37,3 +49,72 @@ export async function loadSchemaFlow(path: string): Promise<Schema> {
|
||||
})
|
||||
return flow.schema
|
||||
}
|
||||
|
||||
export function scriptPathToHref(path: string): string {
|
||||
if (path.startsWith('hub/')) {
|
||||
return 'https://hub.windmill.dev/from_version/' + path.substring(4)
|
||||
} else {
|
||||
return `/scripts/get/${path}?workspace=${get(workspaceStore)}`
|
||||
}
|
||||
}
|
||||
|
||||
export async function getScriptByPath(path: string): Promise<{
|
||||
content: string
|
||||
language: SupportedLanguage
|
||||
schema: any
|
||||
description: string
|
||||
tag: string | undefined
|
||||
}> {
|
||||
if (path.startsWith('hub/')) {
|
||||
const { content, language, schema } = await ScriptService.getHubScriptByPath({ path })
|
||||
|
||||
return {
|
||||
content,
|
||||
language: language as SupportedLanguage,
|
||||
schema,
|
||||
description: '',
|
||||
tag: undefined
|
||||
}
|
||||
} else {
|
||||
const script = await ScriptService.getScriptByPath({
|
||||
workspace: get(workspaceStore)!,
|
||||
path: path ?? ''
|
||||
})
|
||||
return {
|
||||
content: script.content,
|
||||
language: script.language,
|
||||
schema: script.schema,
|
||||
description: script.description,
|
||||
tag: script.tag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function getLatestHashForScript(path: string): Promise<string> {
|
||||
const script = await ScriptService.getScriptByPath({
|
||||
workspace: get(workspaceStore)!,
|
||||
path: path ?? ''
|
||||
})
|
||||
return script.hash
|
||||
}
|
||||
|
||||
export async function loadHubScripts() {
|
||||
try {
|
||||
const scripts = (await ScriptService.listHubScripts()).asks ?? []
|
||||
const processed = scripts
|
||||
.map((x) => ({
|
||||
path: `hub/${x.id}/${x.app}/${x.summary.toLowerCase().replaceAll(/\s+/g, '_')}`,
|
||||
summary: `${x.summary} (${x.app})`,
|
||||
approved: x.approved,
|
||||
kind: x.kind,
|
||||
app: x.app,
|
||||
views: x.views,
|
||||
votes: x.votes,
|
||||
ask_id: x.ask_id
|
||||
}))
|
||||
.sort((a, b) => b.views - a.views)
|
||||
hubScripts.set(processed)
|
||||
} catch {
|
||||
console.error('Hub is not available')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { browser } from '$app/environment'
|
||||
import { derived, type Readable, writable, get } from 'svelte/store'
|
||||
import { BROWSER } from 'esm-env'
|
||||
import { derived, type Readable, writable } from 'svelte/store'
|
||||
import type { UserWorkspaceList } from '$lib/gen/models/UserWorkspaceList.js'
|
||||
import { getUserExt } from './user'
|
||||
import { WorkspaceService, type TokenResponse } from './gen'
|
||||
import { isCloudHosted } from './utils'
|
||||
import type { TokenResponse } from './gen'
|
||||
|
||||
export interface UserExt {
|
||||
email: string
|
||||
@@ -18,7 +16,7 @@ export interface UserExt {
|
||||
folders_owners: string[]
|
||||
}
|
||||
|
||||
let persistedWorkspace = browser && localStorage.getItem('workspace')
|
||||
let persistedWorkspace = BROWSER && localStorage.getItem('workspace')
|
||||
|
||||
export const workerTags = writable<string[] | undefined>(undefined)
|
||||
export const usageStore = writable<number>(0)
|
||||
@@ -65,39 +63,6 @@ export const hubScripts = writable<
|
||||
| undefined
|
||||
>(undefined)
|
||||
|
||||
if (browser) {
|
||||
workspaceStore.subscribe(async (workspace) => {
|
||||
if (workspace) {
|
||||
try {
|
||||
localStorage.setItem('workspace', String(workspace))
|
||||
} catch (e) {
|
||||
console.error('Could not persist workspace to local storage', e)
|
||||
}
|
||||
const user = await getUserExt(workspace)
|
||||
userStore.set(user)
|
||||
if (isCloudHosted() && user?.is_admin) {
|
||||
premiumStore.set(await WorkspaceService.getPremiumInfo({ workspace }))
|
||||
}
|
||||
} else {
|
||||
userStore.set(undefined)
|
||||
}
|
||||
})
|
||||
|
||||
setInterval(async () => {
|
||||
try {
|
||||
const workspace = get(workspaceStore)
|
||||
const user = get(userStore)
|
||||
|
||||
if (workspace && user && !user.is_super_admin && !user.is_admin) {
|
||||
userStore.set(await getUserExt(workspace))
|
||||
console.log('refreshed user')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Could not refresh user', e)
|
||||
}
|
||||
}, 30000)
|
||||
}
|
||||
|
||||
export function switchWorkspace(workspace: string | undefined) {
|
||||
localStorage.removeItem('flow')
|
||||
localStorage.removeItem('app')
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import Toast from '$lib/components/Toast.svelte'
|
||||
import { toast } from '@zerodevx/svelte-toast'
|
||||
|
||||
export type ToastAction = {
|
||||
label: string
|
||||
callback: () => void
|
||||
}
|
||||
|
||||
export function sendUserToast(
|
||||
message: string,
|
||||
error: boolean = false,
|
||||
actions: ToastAction[] = [],
|
||||
errorMessage: string | undefined = undefined
|
||||
): void {
|
||||
toast.push({
|
||||
component: {
|
||||
src: Toast,
|
||||
props: {
|
||||
message,
|
||||
error,
|
||||
actions,
|
||||
errorMessage
|
||||
},
|
||||
sendIdTo: 'toastId'
|
||||
},
|
||||
dismissable: false,
|
||||
initial: 0,
|
||||
theme: {
|
||||
'--toastPadding': '0',
|
||||
'--toastMsgPadding': '0'
|
||||
}
|
||||
})
|
||||
}
|
||||
+85
-317
@@ -1,12 +1,15 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { goto } from '$app/navigation'
|
||||
import { AppService, type Flow, FlowService, Script, ScriptService, type User } from '$lib/gen'
|
||||
import { toast } from '@zerodevx/svelte-toast'
|
||||
import type { Schema, SupportedLanguage } from './common'
|
||||
import { hubScripts, type UserExt, workspaceStore } from './stores'
|
||||
import { page } from '$app/stores'
|
||||
import { get } from 'svelte/store'
|
||||
import Toast from '$lib/components/Toast.svelte'
|
||||
// /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
// import { goto } from '$app/navigation'
|
||||
// import { AppService, type Flow, FlowService, Script, ScriptService, type User } from '$lib/gen'
|
||||
// import { toast } from '@zerodevx/svelte-toast'
|
||||
// import type { Schema, SupportedLanguage } from './common'
|
||||
// import { hubScripts, type UserExt, workspaceStore } from './stores'
|
||||
// import { page } from '$app/stores'
|
||||
// import { get } from 'svelte/store'
|
||||
|
||||
import type { UserExt } from './stores'
|
||||
import { sendUserToast } from './toast'
|
||||
export { sendUserToast }
|
||||
|
||||
export function validateUsername(username: string): string {
|
||||
if (username != '' && !/^\w+$/.test(username)) {
|
||||
@@ -79,37 +82,6 @@ export function getToday() {
|
||||
return today
|
||||
}
|
||||
|
||||
export type ToastAction = {
|
||||
label: string
|
||||
callback: () => void
|
||||
}
|
||||
|
||||
export function sendUserToast(
|
||||
message: string,
|
||||
error: boolean = false,
|
||||
actions: ToastAction[] = [],
|
||||
errorMessage: string | undefined = undefined
|
||||
): void {
|
||||
toast.push({
|
||||
component: {
|
||||
src: Toast,
|
||||
props: {
|
||||
message,
|
||||
error,
|
||||
actions,
|
||||
errorMessage
|
||||
},
|
||||
sendIdTo: 'toastId'
|
||||
},
|
||||
dismissable: false,
|
||||
initial: 0,
|
||||
theme: {
|
||||
'--toastPadding': '0',
|
||||
'--toastMsgPadding': '0'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function truncateHash(hash: string): string {
|
||||
if (hash.length >= 6) {
|
||||
return hash.substr(hash.length - 6)
|
||||
@@ -193,79 +165,6 @@ export function removeItemAll<T>(arr: T[], value: T) {
|
||||
return arr
|
||||
}
|
||||
|
||||
export function isOwner(
|
||||
path: string,
|
||||
user: UserExt | undefined,
|
||||
workspace: string | undefined
|
||||
): boolean {
|
||||
if (!user || !workspace) {
|
||||
return false
|
||||
}
|
||||
if (user.is_super_admin) {
|
||||
return true
|
||||
}
|
||||
if (workspace == 'admin') {
|
||||
return false
|
||||
} else if (user.is_admin) {
|
||||
return true
|
||||
} else if (path.startsWith('u/' + user.username + '/')) {
|
||||
return true
|
||||
} else if (path.startsWith('f/')) {
|
||||
return user.folders_owners.some((x) => path.startsWith('f/' + x + '/'))
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export function isObviousOwner(path: string, user?: UserExt): boolean {
|
||||
if (!user) {
|
||||
return false
|
||||
}
|
||||
if (user.is_admin || user.is_super_admin) {
|
||||
return true
|
||||
}
|
||||
let userOwner = `u/${user.username}`
|
||||
if (path.startsWith(userOwner)) {
|
||||
return true
|
||||
}
|
||||
if (user.pgroups.findIndex((x) => path.startsWith(x)) != -1) {
|
||||
return true
|
||||
}
|
||||
if (user.folders.findIndex((x) => path.startsWith('f/' + x)) != -1) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export function canWrite(
|
||||
path: string,
|
||||
extra_perms: Record<string, boolean>,
|
||||
user?: UserExt
|
||||
): boolean {
|
||||
if (user?.is_admin || user?.is_super_admin) {
|
||||
return true
|
||||
}
|
||||
let keys = Object.keys(extra_perms)
|
||||
if (!user) {
|
||||
return false
|
||||
}
|
||||
if (isObviousOwner(path, user)) {
|
||||
return true
|
||||
}
|
||||
let userOwner = `u/${user.username}`
|
||||
if (keys.includes(userOwner) && extra_perms[userOwner]) {
|
||||
return true
|
||||
}
|
||||
if (user.pgroups.findIndex((x) => keys.includes(x) && extra_perms[x]) != -1) {
|
||||
return true
|
||||
}
|
||||
if (user.folders.findIndex((x) => path.startsWith('f/' + x)) != -1) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export function emptyString(str: string | undefined | null): boolean {
|
||||
return str === undefined || str === null || str === ''
|
||||
}
|
||||
@@ -320,11 +219,6 @@ export function decodeArgs(queryArgs: string | undefined): any {
|
||||
return {}
|
||||
}
|
||||
|
||||
export async function setQuery(url: URL, key: string, value: string): Promise<void> {
|
||||
url.searchParams.set(key, value)
|
||||
await goto(`?${url.searchParams.toString()}`)
|
||||
}
|
||||
|
||||
let debounced: NodeJS.Timeout | undefined = undefined
|
||||
export function setQueryWithoutLoad(
|
||||
url: URL,
|
||||
@@ -412,60 +306,6 @@ export function isString(value: any) {
|
||||
return typeof value === 'string' || value instanceof String
|
||||
}
|
||||
|
||||
export function mapUserToUserExt(user: User): UserExt {
|
||||
return {
|
||||
...user,
|
||||
groups: user.groups!,
|
||||
pgroups: user.groups!.map((x) => `g/${x}`)
|
||||
}
|
||||
}
|
||||
|
||||
export function schemaToTsType(schema: Schema): string {
|
||||
if (!schema || !schema.properties) {
|
||||
return 'any'
|
||||
}
|
||||
const propKeys = Object.keys(schema.properties)
|
||||
|
||||
const types = propKeys
|
||||
.map((key: string) => {
|
||||
const prop = schema.properties[key]
|
||||
const isOptional = !schema.required.includes(key)
|
||||
const prefix = `${key}${isOptional ? '?' : ''}`
|
||||
let type: string = 'any'
|
||||
if (prop.type === 'string') {
|
||||
type = 'string'
|
||||
} else if (prop.type === 'number' || prop.type === 'integer') {
|
||||
type = 'number'
|
||||
} else if (prop.type === 'boolean') {
|
||||
type = 'boolean'
|
||||
} else if (prop.type === 'array') {
|
||||
let type = prop.items?.type ?? 'any'
|
||||
if (type === 'integer') {
|
||||
type = 'number'
|
||||
}
|
||||
type = `${type}[]`
|
||||
}
|
||||
|
||||
return `${prefix}: ${type}`
|
||||
})
|
||||
.join(';')
|
||||
|
||||
return `{ ${types} }`
|
||||
}
|
||||
|
||||
export function schemaToObject(schema: Schema, args: Record<string, any>): Object {
|
||||
const object = {}
|
||||
if (!schema || !schema.properties) {
|
||||
return object
|
||||
}
|
||||
const propKeys = Object.keys(schema.properties)
|
||||
|
||||
propKeys.forEach((key: string) => {
|
||||
object[key] = args[key] ?? null
|
||||
})
|
||||
return object
|
||||
}
|
||||
|
||||
export type InputCat =
|
||||
| 'string'
|
||||
| 'number'
|
||||
@@ -512,95 +352,6 @@ export function setInputCat(
|
||||
}
|
||||
}
|
||||
|
||||
export function scriptPathToHref(path: string): string {
|
||||
if (path.startsWith('hub/')) {
|
||||
return 'https://hub.windmill.dev/from_version/' + path.substring(4)
|
||||
} else {
|
||||
return `/scripts/get/${path}?workspace=${get(workspaceStore)}`
|
||||
}
|
||||
}
|
||||
|
||||
export async function getScriptByPath(path: string): Promise<{
|
||||
content: string
|
||||
language: SupportedLanguage
|
||||
schema: any
|
||||
description: string
|
||||
tag: string | undefined
|
||||
}> {
|
||||
if (path.startsWith('hub/')) {
|
||||
const { content, language, schema } = await ScriptService.getHubScriptByPath({ path })
|
||||
|
||||
return {
|
||||
content,
|
||||
language: language as SupportedLanguage,
|
||||
schema,
|
||||
description: '',
|
||||
tag: undefined
|
||||
}
|
||||
} else {
|
||||
const script = await ScriptService.getScriptByPath({
|
||||
workspace: get(workspaceStore)!,
|
||||
path: path ?? ''
|
||||
})
|
||||
return {
|
||||
content: script.content,
|
||||
language: script.language,
|
||||
schema: script.schema,
|
||||
description: script.description,
|
||||
tag: script.tag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function getLatestHashForScript(path: string): Promise<string> {
|
||||
const script = await ScriptService.getScriptByPath({
|
||||
workspace: get(workspaceStore)!,
|
||||
path: path ?? ''
|
||||
})
|
||||
return script.hash
|
||||
}
|
||||
|
||||
export async function loadHubScripts() {
|
||||
try {
|
||||
const scripts = (await ScriptService.listHubScripts()).asks ?? []
|
||||
const processed = scripts
|
||||
.map((x) => ({
|
||||
path: `hub/${x.id}/${x.app}/${x.summary.toLowerCase().replaceAll(/\s+/g, '_')}`,
|
||||
summary: `${x.summary} (${x.app})`,
|
||||
approved: x.approved,
|
||||
kind: x.kind,
|
||||
app: x.app,
|
||||
views: x.views,
|
||||
votes: x.votes,
|
||||
ask_id: x.ask_id
|
||||
}))
|
||||
.sort((a, b) => b.views - a.views)
|
||||
hubScripts.set(processed)
|
||||
} catch {
|
||||
console.error('Hub is not available')
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadHubFlows() {
|
||||
try {
|
||||
const flows = (await FlowService.listHubFlows()).flows ?? []
|
||||
const processed = flows.sort((a, b) => b.votes - a.votes)
|
||||
return processed
|
||||
} catch {
|
||||
console.error('Hub is not available')
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadHubApps() {
|
||||
try {
|
||||
const apps = (await AppService.listHubApps()).apps ?? []
|
||||
const processed = apps.sort((a, b) => b.votes - a.votes)
|
||||
return processed
|
||||
} catch {
|
||||
console.error('Hub is not available')
|
||||
}
|
||||
}
|
||||
|
||||
export function formatCron(inp: string): string {
|
||||
// Allow for cron expressions inputted by the user to omit month and year
|
||||
let splitted = inp.split(' ')
|
||||
@@ -612,62 +363,10 @@ export function formatCron(inp: string): string {
|
||||
}
|
||||
}
|
||||
|
||||
export function flowToHubUrl(flow: Flow): URL {
|
||||
const url = new URL('https://hub.windmill.dev/flows/add')
|
||||
const openFlow = {
|
||||
value: flow.value,
|
||||
summary: flow.summary,
|
||||
description: flow.description,
|
||||
schema: flow.schema
|
||||
}
|
||||
url.searchParams.append('flow', encodeState(openFlow))
|
||||
return url
|
||||
}
|
||||
|
||||
export function appToHubUrl(staticApp: any): URL {
|
||||
const url = new URL('https://hub.windmill.dev/apps/add')
|
||||
url.searchParams.append('app', encodeState(staticApp))
|
||||
return url
|
||||
}
|
||||
|
||||
export function scriptToHubUrl(
|
||||
content: string,
|
||||
summary: string,
|
||||
description: string,
|
||||
kind: Script.kind,
|
||||
language: Script.language,
|
||||
schema: Schema | undefined,
|
||||
lock: string | undefined
|
||||
): URL {
|
||||
const url = new URL('https://hub.windmill.dev/scripts/add')
|
||||
|
||||
url.searchParams.append('content', content)
|
||||
url.searchParams.append('summary', summary)
|
||||
url.searchParams.append('description', description)
|
||||
url.searchParams.append('kind', kind)
|
||||
url.searchParams.append('language', language)
|
||||
url.searchParams.append('schema', JSON.stringify(schema, null, 2))
|
||||
lock && url.searchParams.append('lockfile', lock)
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
export function classNames(...classes: Array<string | undefined>): string {
|
||||
return classes.filter(Boolean).join(' ')
|
||||
}
|
||||
|
||||
export function scriptLangToEditorLang(lang: Script.language) {
|
||||
if (lang == 'deno') {
|
||||
return 'typescript'
|
||||
} else if (lang == 'python3') {
|
||||
return 'python'
|
||||
} else if (lang == 'bash') {
|
||||
return 'shell'
|
||||
} else {
|
||||
return lang
|
||||
}
|
||||
}
|
||||
|
||||
export async function copyToClipboard(value?: string, sendToast = true): Promise<boolean> {
|
||||
if (!value) {
|
||||
return false
|
||||
@@ -706,10 +405,6 @@ export function addWhitespaceBeforeCapitals(word?: string): string {
|
||||
return word.replace(/([A-Z])/g, ' $1').trim()
|
||||
}
|
||||
|
||||
export function isCloudHosted(): boolean {
|
||||
return get(page)?.url?.hostname == 'app.windmill.dev'
|
||||
}
|
||||
|
||||
export function isObject(obj: any) {
|
||||
return typeof obj === 'object'
|
||||
}
|
||||
@@ -788,3 +483,76 @@ export function deepMergeWithPriority<T>(target: T, source: T): T {
|
||||
|
||||
return merged
|
||||
}
|
||||
|
||||
export function canWrite(
|
||||
path: string,
|
||||
extra_perms: Record<string, boolean>,
|
||||
user?: UserExt
|
||||
): boolean {
|
||||
if (user?.is_admin || user?.is_super_admin) {
|
||||
return true
|
||||
}
|
||||
let keys = Object.keys(extra_perms)
|
||||
if (!user) {
|
||||
return false
|
||||
}
|
||||
if (isObviousOwner(path, user)) {
|
||||
return true
|
||||
}
|
||||
let userOwner = `u/${user.username}`
|
||||
if (keys.includes(userOwner) && extra_perms[userOwner]) {
|
||||
return true
|
||||
}
|
||||
if (user.pgroups.findIndex((x) => keys.includes(x) && extra_perms[x]) != -1) {
|
||||
return true
|
||||
}
|
||||
if (user.folders.findIndex((x) => path.startsWith('f/' + x)) != -1) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export function isOwner(
|
||||
path: string,
|
||||
user: UserExt | undefined,
|
||||
workspace: string | undefined
|
||||
): boolean {
|
||||
if (!user || !workspace) {
|
||||
return false
|
||||
}
|
||||
if (user.is_super_admin) {
|
||||
return true
|
||||
}
|
||||
if (workspace == 'admin') {
|
||||
return false
|
||||
} else if (user.is_admin) {
|
||||
return true
|
||||
} else if (path.startsWith('u/' + user.username + '/')) {
|
||||
return true
|
||||
} else if (path.startsWith('f/')) {
|
||||
return user.folders_owners.some((x) => path.startsWith('f/' + x + '/'))
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export function isObviousOwner(path: string, user?: UserExt): boolean {
|
||||
if (!user) {
|
||||
return false
|
||||
}
|
||||
if (user.is_admin || user.is_super_admin) {
|
||||
return true
|
||||
}
|
||||
let userOwner = `u/${user.username}`
|
||||
if (path.startsWith(userOwner)) {
|
||||
return true
|
||||
}
|
||||
if (user.pgroups.findIndex((x) => path.startsWith(x)) != -1) {
|
||||
return true
|
||||
}
|
||||
if (user.folders.findIndex((x) => path.startsWith('f/' + x)) != -1) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { BROWSER } from 'esm-env'
|
||||
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons'
|
||||
import Icon from 'svelte-awesome'
|
||||
|
||||
@@ -11,8 +12,7 @@
|
||||
ScriptService,
|
||||
UserService
|
||||
} from '$lib/gen'
|
||||
import { classNames, isCloudHosted } from '$lib/utils'
|
||||
import { browser } from '$app/environment'
|
||||
import { classNames } from '$lib/utils'
|
||||
|
||||
import WorkspaceMenu from '$lib/components/sidebar/WorkspaceMenu.svelte'
|
||||
import SidebarContent from '$lib/components/sidebar/SidebarContent.svelte'
|
||||
@@ -25,6 +25,7 @@
|
||||
import { page } from '$app/stores'
|
||||
import FavoriteMenu from '$lib/components/sidebar/FavoriteMenu.svelte'
|
||||
import { SUPERADMIN_SETTINGS_HASH, USER_SETTINGS_HASH } from '$lib/components/sidebar/settings'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
|
||||
OpenAPI.WITH_CREDENTIALS = true
|
||||
let menuOpen = false
|
||||
@@ -53,7 +54,7 @@
|
||||
menuOpen = false
|
||||
})
|
||||
|
||||
let innerWidth = browser ? window.innerWidth : 2000
|
||||
let innerWidth = BROWSER ? window.innerWidth : 2000
|
||||
|
||||
let favoriteLinks = [] as {
|
||||
label: string
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import PageHeader from '$lib/components/PageHeader.svelte'
|
||||
import CreateActionsFlow from '$lib/components/flows/CreateActionsFlow.svelte'
|
||||
import CreateActionsScript from '$lib/components/scripts/CreateActionsScript.svelte'
|
||||
import { getScriptByPath } from '$lib/utils'
|
||||
import { getScriptByPath } from '$lib/scripts'
|
||||
import type { HubItem } from '$lib/components/flows/pickers/model'
|
||||
import { faCodeFork } from '@fortawesome/free-solid-svg-icons'
|
||||
import PickHubScript from '$lib/components/flows/pickers/PickHubScript.svelte'
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
import AppEditor from '$lib/components/apps/editor/AppEditor.svelte'
|
||||
import { AppService, Policy } from '$lib/gen'
|
||||
import { page } from '$app/stores'
|
||||
import { decodeState, sendUserToast } from '$lib/utils'
|
||||
import { decodeState } from '$lib/utils'
|
||||
import { dirtyStore } from '$lib/components/common/confirmationModal/dirtyStore'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import type { App } from '$lib/components/apps/types'
|
||||
import { goto } from '$app/navigation'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
let nodraft = $page.url.searchParams.get('nodraft')
|
||||
const hubId = $page.url.searchParams.get('hub')
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
import { AppService, AppWithLastVersion } from '$lib/gen'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { page } from '$app/stores'
|
||||
import { decodeState, sendUserToast, type ToastAction } from '$lib/utils'
|
||||
import { decodeState } from '$lib/utils'
|
||||
import { goto } from '$app/navigation'
|
||||
import { dirtyStore } from '$lib/components/common/confirmationModal/dirtyStore'
|
||||
import { sendUserToast, type ToastAction } from '$lib/toast'
|
||||
|
||||
let app = undefined as (AppWithLastVersion & { draft_only?: boolean }) | undefined
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { page } from '$app/stores'
|
||||
import { Skeleton } from '$lib/components/common'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
let loaded = false
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
import { goto } from '$app/navigation'
|
||||
import { page } from '$app/stores'
|
||||
import { dirtyStore } from '$lib/components/common/confirmationModal/dirtyStore'
|
||||
import UnsavedConfirmationModal from '$lib/components/common/confirmationModal/UnsavedConfirmationModal.svelte'
|
||||
|
||||
import FlowBuilder from '$lib/components/FlowBuilder.svelte'
|
||||
import type { FlowState } from '$lib/components/flows/flowState'
|
||||
import { importFlowStore, initFlow } from '$lib/components/flows/flowStore'
|
||||
import { FlowService, type Flow } from '$lib/gen'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { decodeState, emptySchema, sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { decodeState, emptySchema } from '$lib/utils'
|
||||
import { writable } from 'svelte/store'
|
||||
|
||||
let nodraft = $page.url.searchParams.get('nodraft')
|
||||
@@ -104,8 +106,26 @@
|
||||
loadFlow()
|
||||
|
||||
$dirtyStore = true
|
||||
|
||||
let getSelectedId: (() => string) | undefined = undefined
|
||||
</script>
|
||||
|
||||
<div id="monaco-widgets-root" class="monaco-editor" style="z-index: 1200;" />
|
||||
<UnsavedConfirmationModal />
|
||||
|
||||
<FlowBuilder {flowStore} {flowStateStore} {selectedId} {loading} />
|
||||
<FlowBuilder
|
||||
on:saveInitial={() => {
|
||||
goto(`/flows/edit/${$flowStore.path}?selected=${getSelectedId?.()}`)
|
||||
}}
|
||||
on:deploy={() => {
|
||||
goto(`/flows/get/${$flowStore.path}?workspace=${$workspaceStore}`)
|
||||
}}
|
||||
on:details={() => {
|
||||
goto(`/flows/get/${$flowStore.path}?workspace=${$workspaceStore}`)
|
||||
}}
|
||||
bind:getSelectedId
|
||||
{flowStore}
|
||||
{flowStateStore}
|
||||
{selectedId}
|
||||
{loading}
|
||||
/>
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
import { page } from '$app/stores'
|
||||
import FlowBuilder from '$lib/components/FlowBuilder.svelte'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { decodeArgs, decodeState, emptySchema, sendUserToast } from '$lib/utils'
|
||||
import { decodeArgs, decodeState, emptySchema } from '$lib/utils'
|
||||
import { initFlow } from '$lib/components/flows/flowStore'
|
||||
import { dirtyStore } from '$lib/components/common/confirmationModal/dirtyStore'
|
||||
import { goto } from '$app/navigation'
|
||||
import { writable } from 'svelte/store'
|
||||
import type { FlowState } from '$lib/components/flows/flowState'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import UnsavedConfirmationModal from '$lib/components/common/confirmationModal/UnsavedConfirmationModal.svelte'
|
||||
|
||||
let nodraft = $page.url.searchParams.get('nodraft')
|
||||
const initialState = nodraft ? undefined : localStorage.getItem(`flow-${$page.params.path}`)
|
||||
@@ -78,7 +80,7 @@
|
||||
|
||||
await initFlow(flow, flowStore, flowStateStore)
|
||||
loading = false
|
||||
selectedId = stateLoadedFromUrl?.selectedId
|
||||
selectedId = stateLoadedFromUrl?.selectedId ?? $page.url.searchParams.get('selected')
|
||||
$dirtyStore = false
|
||||
}
|
||||
|
||||
@@ -91,7 +93,15 @@
|
||||
|
||||
<div id="monaco-widgets-root" class="monaco-editor" style="z-index: 1200;" />
|
||||
|
||||
<UnsavedConfirmationModal />
|
||||
|
||||
<FlowBuilder
|
||||
on:deploy={() => {
|
||||
goto(`/flows/get/${$flowStore.path}?workspace=${$workspaceStore}`)
|
||||
}}
|
||||
on:details={() => {
|
||||
goto(`/flows/get/${$flowStore.path}?workspace=${$workspaceStore}`)
|
||||
}}
|
||||
{flowStore}
|
||||
{flowStateStore}
|
||||
initialPath={$page.params.path}
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
import { page } from '$app/stores'
|
||||
import { FlowService, JobService, ScheduleService, type Flow, type Schedule } from '$lib/gen'
|
||||
import {
|
||||
canWrite,
|
||||
canWrite,
|
||||
copyToClipboard,
|
||||
defaultIfEmptyString,
|
||||
displayDaysAgo,
|
||||
emptyString,
|
||||
encodeState,
|
||||
sendUserToast
|
||||
encodeState
|
||||
} from '$lib/utils'
|
||||
import {
|
||||
faArchive,
|
||||
@@ -40,6 +39,7 @@
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import Icon from 'svelte-awesome'
|
||||
import { slide } from 'svelte/transition'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
let userSettings: UserSettings
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
defaultIfEmptyString,
|
||||
displayDaysAgo,
|
||||
emptyString,
|
||||
getModifierKey,
|
||||
sendUserToast
|
||||
getModifierKey
|
||||
} from '$lib/utils'
|
||||
import { faEye, faPen, faPlay } from '@fortawesome/free-solid-svg-icons'
|
||||
import SplitPanesWrapper from '$lib/components/splitPanes/SplitPanesWrapper.svelte'
|
||||
@@ -21,6 +20,7 @@
|
||||
import { tweened } from 'svelte/motion'
|
||||
import { cubicOut } from 'svelte/easing'
|
||||
import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
const path = $page.params.path
|
||||
let flow: Flow | undefined
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { Folder } from '$lib/gen'
|
||||
import { FolderService } from '$lib/gen'
|
||||
import { canWrite } from '$lib/utils'
|
||||
|
||||
import CenteredPage from '$lib/components/CenteredPage.svelte'
|
||||
import Dropdown from '$lib/components/Dropdown.svelte'
|
||||
@@ -14,6 +13,7 @@
|
||||
import { Button, Drawer, DrawerContent, Skeleton } from '$lib/components/common'
|
||||
import FolderInfo from '$lib/components/FolderInfo.svelte'
|
||||
import FolderUsageInfo from '$lib/components/FolderUsageInfo.svelte'
|
||||
import { canWrite } from '$lib/utils'
|
||||
|
||||
type FolderW = Folder & { canWrite: boolean }
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { Group } from '$lib/gen'
|
||||
import { GroupService } from '$lib/gen'
|
||||
import { canWrite } from '$lib/utils'
|
||||
|
||||
import CenteredPage from '$lib/components/CenteredPage.svelte'
|
||||
import { Button, Drawer, DrawerContent, Skeleton } from '$lib/components/common'
|
||||
@@ -13,6 +12,7 @@
|
||||
import TableCustom from '$lib/components/TableCustom.svelte'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { faEdit, faPlus, faTrash } from '@fortawesome/free-solid-svg-icons'
|
||||
import { canWrite } from '$lib/utils'
|
||||
|
||||
type GroupW = Group & { canWrite: boolean }
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation'
|
||||
import { page } from '$app/stores'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { onMount } from 'svelte'
|
||||
import { OauthService } from '$lib/gen'
|
||||
import { oauthStore } from '$lib/stores'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation'
|
||||
import { page } from '$app/stores'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { onMount } from 'svelte'
|
||||
import { OauthService } from '$lib/gen'
|
||||
import { workspaceStore, oauthStore } from '$lib/stores'
|
||||
|
||||
@@ -26,14 +26,8 @@
|
||||
import type { ResourceType } from '$lib/gen'
|
||||
import { OauthService, ResourceService, type ListableResource } from '$lib/gen'
|
||||
import { oauthStore, userStore, workspaceStore } from '$lib/stores'
|
||||
import {
|
||||
canWrite,
|
||||
classNames,
|
||||
emptySchema,
|
||||
removeMarkdown,
|
||||
sendUserToast,
|
||||
truncate
|
||||
} from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { canWrite, classNames, emptySchema, removeMarkdown, truncate } from '$lib/utils'
|
||||
import {
|
||||
faChain,
|
||||
faCircle,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores'
|
||||
import { JobService, Job } from '$lib/gen'
|
||||
import { canWrite, displayDate, forLater, sendUserToast, truncateHash } from '$lib/utils'
|
||||
import { canWrite, displayDate, forLater, truncateHash } from '$lib/utils'
|
||||
import Icon from 'svelte-awesome'
|
||||
import { check } from 'svelte-awesome/icons'
|
||||
import {
|
||||
@@ -33,6 +33,7 @@
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import Dropdown from '$lib/components/Dropdown.svelte'
|
||||
import { goto } from '$app/navigation'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
let job: Job | undefined
|
||||
const iconScale = 1
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
import { JobService, Job, CompletedJob, ScriptService, FlowService } from '$lib/gen'
|
||||
import { setQuery, setQueryWithoutLoad } from '$lib/utils'
|
||||
import { setQueryWithoutLoad } from '$lib/utils'
|
||||
|
||||
import { page } from '$app/stores'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import CenteredPage from '$lib/components/CenteredPage.svelte'
|
||||
import Tabs from '$lib/components/common/tabs/Tabs.svelte'
|
||||
@@ -21,6 +21,7 @@
|
||||
import Slider from '$lib/components/Slider.svelte'
|
||||
import JsonEditor from '$lib/components/apps/editor/settingsPanel/inputEditor/JsonEditor.svelte'
|
||||
import { openStore } from '$lib/components/jobs/JobPreview.svelte'
|
||||
import { setQuery } from '$lib/navigation'
|
||||
|
||||
let jobs: Job[] | undefined
|
||||
let error: Error | undefined
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { ScheduleService, type Schedule, JobService, type ScriptArgs } from '$lib/gen'
|
||||
import { canWrite, displayDate, sendUserToast } from '$lib/utils'
|
||||
import { canWrite, displayDate } from '$lib/utils'
|
||||
|
||||
import CenteredPage from '$lib/components/CenteredPage.svelte'
|
||||
import { Badge, Button, Skeleton } from '$lib/components/common'
|
||||
@@ -26,6 +26,7 @@
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { Icon } from 'svelte-awesome'
|
||||
import { goto } from '$app/navigation'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
type ScheduleW = Schedule & { canWrite: boolean }
|
||||
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
import { page } from '$app/stores'
|
||||
import { runFormStore, workspaceStore } from '$lib/stores'
|
||||
import ScriptBuilder from '$lib/components/ScriptBuilder.svelte'
|
||||
import { decodeState, sendUserToast } from '$lib/utils'
|
||||
import { decodeState } from '$lib/utils'
|
||||
import { goto } from '$app/navigation'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
const initialState = $page.url.searchParams.get('state')
|
||||
let initialArgs = {}
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
import { JobService, ScriptService, type Script } from '$lib/gen'
|
||||
import {
|
||||
truncateHash,
|
||||
sendUserToast,
|
||||
displayDaysAgo,
|
||||
canWrite,
|
||||
defaultIfEmptyString,
|
||||
scriptToHubUrl,
|
||||
copyToClipboard,
|
||||
emptyString,
|
||||
encodeState
|
||||
encodeState,
|
||||
|
||||
canWrite
|
||||
|
||||
} from '$lib/utils'
|
||||
import {
|
||||
faPlay,
|
||||
@@ -55,6 +55,8 @@
|
||||
SCRIPT_VIEW_WEBHOOK_INFO_LINK,
|
||||
SCRIPT_VIEW_WEBHOOK_INFO_TIP
|
||||
} from '$lib/consts'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { scriptToHubUrl } from '$lib/hub'
|
||||
|
||||
let userSettings: UserSettings
|
||||
let script: Script | undefined
|
||||
|
||||
@@ -10,19 +10,19 @@
|
||||
import { inferArgs } from '$lib/infer'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import {
|
||||
canWrite,
|
||||
canWrite,
|
||||
defaultIfEmptyString,
|
||||
displayDaysAgo,
|
||||
emptySchema,
|
||||
emptyString,
|
||||
getModifierKey,
|
||||
sendUserToast
|
||||
} from '$lib/utils'
|
||||
import { faEye, faPen, faPlay } from '@fortawesome/free-solid-svg-icons'
|
||||
import { Pane, Splitpanes } from 'svelte-splitpanes'
|
||||
import { tweened } from 'svelte/motion'
|
||||
import { cubicOut } from 'svelte/easing'
|
||||
import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
$: hash = $page.params.hash
|
||||
let script: Script | undefined
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation'
|
||||
import { UserService, WorkspaceService } from '$lib/gen'
|
||||
import { sendUserToast, validateUsername } from '$lib/utils'
|
||||
import { validateUsername } from '$lib/utils'
|
||||
import { logoutWithRedirect } from '$lib/logout'
|
||||
import { page } from '$app/stores'
|
||||
import { switchWorkspace, usersWorkspaceStore } from '$lib/stores'
|
||||
@@ -10,6 +10,7 @@
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import { onMount } from 'svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
const rd = $page.url.searchParams.get('rd')
|
||||
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
import { onMount } from 'svelte'
|
||||
import { OauthService, SettingsService, UserService, WorkspaceService } from '$lib/gen'
|
||||
import { clearStores, usersWorkspaceStore, workspaceStore, userStore } from '$lib/stores'
|
||||
import { classNames, isCloudHosted, sendUserToast } from '$lib/utils'
|
||||
import { classNames } from '$lib/utils'
|
||||
import { getUserExt, refreshSuperadmin } from '$lib/user'
|
||||
import { Button, Skeleton } from '$lib/components/common'
|
||||
import { WindmillIcon } from '$lib/components/icons'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
|
||||
let email = $page.url.searchParams.get('email') ?? ''
|
||||
let password = $page.url.searchParams.get('password') ?? ''
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation'
|
||||
import { page } from '$app/stores'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { logout, logoutWithRedirect } from '$lib/logout'
|
||||
import { UserService, type WorkspaceInvite, WorkspaceService } from '$lib/gen'
|
||||
import {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import CenteredModal from '$lib/components/CenteredModal.svelte'
|
||||
import WindmillIcon from '$lib/components/icons/WindmillIcon.svelte'
|
||||
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
sendUserToast('Sucess. You can return to your terminal now.')
|
||||
goto('/')
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
import type { ContextualVariable, ListableVariable } from '$lib/gen'
|
||||
import { OauthService, VariableService } from '$lib/gen'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { canWrite, isOwner, sendUserToast, truncate } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { canWrite, isOwner, truncate } from '$lib/utils'
|
||||
import {
|
||||
faChain,
|
||||
faCircle,
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
import PageHeader from '$lib/components/PageHeader.svelte'
|
||||
import TableCustom from '$lib/components/TableCustom.svelte'
|
||||
import { WorkerService, type WorkerPing } from '$lib/gen'
|
||||
import { displayDate, groupBy, sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { displayDate, groupBy } from '$lib/utils'
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
|
||||
let workers: WorkerPing[] | undefined = undefined
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation'
|
||||
import { page } from '$app/stores'
|
||||
import { isCloudHosted } from '$lib/cloud'
|
||||
import AddUser from '$lib/components/AddUser.svelte'
|
||||
import CenteredPage from '$lib/components/CenteredPage.svelte'
|
||||
import { Alert, Badge, Button, Skeleton, Tab, Tabs } from '$lib/components/common'
|
||||
@@ -24,7 +25,8 @@
|
||||
type WorkspaceInvite
|
||||
} from '$lib/gen'
|
||||
import { superadmin, userStore, usersWorkspaceStore, workspaceStore } from '$lib/stores'
|
||||
import { capitalize, isCloudHosted, sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { capitalize } from '$lib/utils'
|
||||
import { faSlack } from '@fortawesome/free-brands-svg-icons'
|
||||
import { faBarsStaggered, faExternalLink, faScroll } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
@@ -208,9 +210,9 @@
|
||||
<div class="flex gap-2 items-center my-1"> Users & Invites </div>
|
||||
</Tab>
|
||||
{#if WORKSPACE_SHOW_SLACK_CMD}
|
||||
<Tab size="md" value="slack">
|
||||
<div class="flex gap-2 items-center my-1"> Slack Command </div>
|
||||
</Tab>
|
||||
<Tab size="md" value="slack">
|
||||
<div class="flex gap-2 items-center my-1"> Slack Command </div>
|
||||
</Tab>
|
||||
{/if}
|
||||
{#if isCloudHosted()}
|
||||
<Tab size="md" value="premium">
|
||||
@@ -221,9 +223,9 @@
|
||||
<div class="flex gap-2 items-center my-1"> Export & Delete Workspace </div>
|
||||
</Tab>
|
||||
{#if WORKSPACE_SHOW_WEBHOOK_CLI_SYNC}
|
||||
<Tab size="md" value="webhook">
|
||||
<div class="flex gap-2 items-center my-1">Webhook for CLI Sync</div>
|
||||
</Tab>
|
||||
<Tab size="md" value="webhook">
|
||||
<div class="flex gap-2 items-center my-1">Webhook for CLI Sync</div>
|
||||
</Tab>
|
||||
{/if}
|
||||
</Tabs>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { WindmillIcon } from '$lib/components/icons'
|
||||
import { WorkspaceService } from '$lib/gen'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
|
||||
let success = $page.url.searchParams.get('success') === 'true'
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { logoutWithRedirect } from '$lib/logout'
|
||||
import { superadmin, userStore, usersWorkspaceStore, workspaceStore } from '$lib/stores'
|
||||
import { getUserExt, refreshSuperadmin } from '$lib/user'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { onMount } from 'svelte'
|
||||
import github from 'svelte-highlight/styles/github'
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { page } from '$app/stores'
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import CenteredModal from '$lib/components/CenteredModal.svelte'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import FlowMetadata from '$lib/components/FlowMetadata.svelte'
|
||||
import JobArgs from '$lib/components/JobArgs.svelte'
|
||||
import { onDestroy, onMount } from 'svelte'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { browser } from '$app/environment'
|
||||
import { BROWSER } from 'esm-env'
|
||||
import { page } from '$app/stores'
|
||||
import AppPreview from '$lib/components/apps/editor/AppPreview.svelte'
|
||||
import { IS_APP_PUBLIC_CONTEXT_KEY, type EditorBreakpoint } from '$lib/components/apps/types'
|
||||
@@ -30,7 +30,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (browser) {
|
||||
if (BROWSER) {
|
||||
loadApp()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation'
|
||||
import { page } from '$app/stores'
|
||||
import { sendUserToast } from '$lib/utils'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { onMount } from 'svelte'
|
||||
import { UserService, WorkspaceService } from '$lib/gen'
|
||||
import CenteredModal from '$lib/components/CenteredModal.svelte'
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user