Compare commits

...

5 Commits

Author SHA1 Message Date
Ruben Fiszel
46ddbcc254 reformat package.json 2023-02-08 00:39:34 +01:00
Ruben Fiszel
fcab562bf2 update goto 2023-02-08 00:38:47 +01:00
Ruben Fiszel
56616d5c6d remove dist 2023-02-08 00:37:18 +01:00
Ruben Fiszel
471ec6b334 cleanup everything 2023-02-08 00:36:30 +01:00
Ruben Fiszel
56dd32b2f0 iife 2023-02-07 19:13:56 +01:00
25 changed files with 2020 additions and 131 deletions

1
frontend/.gitignore vendored
View File

@@ -1,6 +1,7 @@
.DS_Store
node_modules
/build
/dist
/.svelte-kit
/package
/src/lib/gen

5
frontend/embed/README.md Normal file
View File

@@ -0,0 +1,5 @@
# Build the app preview embed code
./embed/build.sh
serve dist

6
frontend/embed/build.sh Executable file
View File

@@ -0,0 +1,6 @@
mkdir -p dist
npm run build-embed
cp static/Inter-Variable.ttf dist
cp static/tailwind.js dist
npx tailwindcss -o src/lib/assets/app.css --minify -o dist/tailwind.css
cp embed/index.html dist

840
frontend/embed/index.html Normal file
View File

@@ -0,0 +1,840 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Embed demo</title>
<link href="/style.css" rel="stylesheet">
<link href="/tailwind.css" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<script src="/appviewer.iife.js">
</script>
</script>
<script>
loadApp(document.getElementById("app"), {
"grid": [
{
"3": {
"h": 2,
"w": 1,
"x": 0,
"y": 0,
"max": {
"h": 100,
"w": 3
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"12": {
"h": 5,
"w": 3,
"x": 0,
"y": 0,
"id": "a",
"max": {
"h": 100,
"w": 12
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"id": "a",
"data": {
"id": "a",
"card": false,
"type": "htmlcomponent",
"softWrap": false,
"configuration": {},
"componentInput": {
"eval": "<img\n\tsrc=\"https://images.unsplash.com/photo-1554629947-334ff61d85dc?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;ixlib=rb-1.2.1&amp;auto=format&amp;fit=crop&amp;w=1024&amp;h=1280&amp;q=80\"\n>\n<div class=\"absolute top-4 left-2 text-white\">\n\tHello ${ctx.username}\n</div>\t\t\t\n",
"type": "template",
"value": "<img\n\tsrc=\"https://images.unsplash.com/photo-1554629947-334ff61d85dc?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;ixlib=rb-1.2.1&amp;auto=format&amp;fit=crop&amp;w=1024&amp;h=1280&amp;q=80\"\n>\n<div class=\"absolute top-4 left-2 text-white\">\n\tHello ${ctx.username}\n</div>\t\t\t\n",
"fieldType": "template"
}
}
},
{
"3": {
"h": 10,
"w": 3,
"x": 0,
"y": 2,
"max": {
"h": 100,
"w": 3
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"12": {
"h": 10,
"w": 6,
"x": 3,
"y": 0,
"id": "b",
"max": {
"h": 100,
"w": 12
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"id": "b",
"data": {
"id": "b",
"card": true,
"type": "tablecomponent",
"actionButtons": [],
"configuration": {
"search": {
"type": "static",
"value": "Disabled",
"fieldType": "select",
"onlyStatic": true,
"optionValuesKey": "tableSearchOptions"
}
},
"componentInput": {
"type": "static",
"value": [
{
"id": 1,
"age": 42,
"name": "A cell with a long name"
},
{
"id": 2,
"age": 84,
"name": "A briefer cell"
}
],
"fieldType": "array",
"subFieldType": "object"
}
}
},
{
"3": {
"h": 8,
"w": 2,
"x": 0,
"y": 12,
"max": {
"h": 100,
"w": 3
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"12": {
"h": 8,
"w": 6,
"x": 0,
"y": 10,
"max": {
"h": 100,
"w": 12
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"id": "c",
"data": {
"id": "c",
"card": true,
"type": "scatterchartcomponent",
"configuration": {
"pannable": {
"type": "static",
"value": false,
"fieldType": "boolean",
"onlyStatic": true
},
"zoomable": {
"type": "static",
"value": false,
"fieldType": "boolean",
"onlyStatic": true
}
},
"componentInput": {
"type": "static",
"value": [
{
"data": [
{
"x": 25,
"y": 50
},
{
"x": 23,
"y": 23
},
{
"x": 12,
"y": 37
}
],
"label": "foo",
"backgroundColor": "rgb(255, 12, 137)"
},
{
"data": [
{
"x": 32,
"y": 32
},
{
"x": 25,
"y": 42
},
{
"x": 3,
"y": 27
}
],
"label": "foobar",
"backgroundColor": "orange"
}
],
"fieldType": "array",
"subFieldType": "object"
}
}
},
{
"3": {
"h": 8,
"w": 2,
"x": 0,
"y": 20,
"max": {
"h": 100,
"w": 3
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"12": {
"h": 8,
"w": 6,
"x": 6,
"y": 10,
"id": "d",
"max": {
"h": 100,
"w": 12
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"id": "d",
"data": {
"id": "d",
"card": false,
"type": "displaycomponent",
"configuration": {},
"componentInput": {
"type": "connected",
"value": {
"foo": 42
},
"fields": {
"x": {
"type": "connected",
"value": "gooo",
"visible": true,
"fieldType": "string",
"connection": {
"path": "result",
"componentId": "e"
}
}
},
"runnable": {
"name": "Inline Script 1",
"type": "runnableByName",
"inlineScript": {
"path": "/inline-script/Inline Script 1",
"schema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"x"
],
"properties": {
"x": {
"type": "string",
"default": null,
"description": ""
}
}
},
"content": "// import * as wmill from \"https://deno.land/x/windmill@v1.57.1/mod.ts\"\n\nexport async function main(x: string) {\n return x\n}\n",
"language": "deno"
}
},
"fieldType": "object",
"connection": {
"path": "result",
"componentId": "e"
}
}
}
},
{
"3": {
"h": 1,
"w": 2,
"x": 1,
"y": 0,
"max": {
"h": 100,
"w": 3
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"12": {
"h": 1,
"w": 3,
"x": 9,
"y": 0,
"id": "e",
"max": {
"h": 100,
"w": 12
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"id": "e",
"data": {
"id": "e",
"card": false,
"type": "textinputcomponent",
"softWrap": true,
"configuration": {
"placeholder": {
"type": "static",
"value": "Type...",
"fieldType": "text",
"onlyStatic": true
}
},
"verticalAlignment": "center"
}
},
{
"3": {
"h": 1,
"w": 2,
"x": 1,
"y": 1,
"max": {
"h": 100,
"w": 3
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"12": {
"h": 1,
"w": 3,
"x": 9,
"y": 1,
"max": {
"h": 100,
"w": 12
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"id": "f",
"data": {
"id": "f",
"card": false,
"type": "passwordinputcomponent",
"softWrap": true,
"configuration": {
"placeholder": {
"type": "static",
"value": "Password",
"fieldType": "text",
"onlyStatic": true
}
},
"verticalAlignment": "center"
}
},
{
"3": {
"h": 1,
"w": 2,
"x": 0,
"y": 28,
"max": {
"h": 100,
"w": 3
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"12": {
"h": 1,
"w": 3,
"x": 9,
"y": 2,
"max": {
"h": 100,
"w": 12
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"id": "g",
"data": {
"id": "g",
"card": false,
"type": "dateinputcomponent",
"softWrap": true,
"configuration": {
"maxDate": {
"type": "static",
"value": "",
"fieldType": "date"
},
"minDate": {
"type": "static",
"value": "",
"fieldType": "date"
}
},
"verticalAlignment": "center"
}
},
{
"3": {
"h": 1,
"w": 1,
"x": 2,
"y": 12,
"max": {
"h": 100,
"w": 3
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"12": {
"h": 1,
"w": 2,
"x": 9,
"y": 3,
"max": {
"h": 100,
"w": 12
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"id": "h",
"data": {
"id": "h",
"card": false,
"type": "checkboxcomponent",
"softWrap": true,
"configuration": {
"label": {
"type": "static",
"value": "Label",
"fieldType": "text"
}
},
"verticalAlignment": "center",
"horizontalAlignment": "center"
}
},
{
"3": {
"h": 1,
"w": 2,
"x": 0,
"y": 29,
"max": {
"h": 100,
"w": 3
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"12": {
"h": 1,
"w": 3,
"x": 9,
"y": 4,
"max": {
"h": 100,
"w": 12
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"id": "i",
"data": {
"id": "i",
"card": false,
"type": "selectcomponent",
"softWrap": true,
"configuration": {
"items": {
"type": "static",
"value": [
{
"label": "Foo",
"value": "foo"
},
{
"label": "Bar",
"value": "bar"
}
],
"fieldType": "array",
"subFieldType": "object"
},
"itemKey": {
"type": "static",
"value": "value",
"fieldType": "text"
}
},
"verticalAlignment": "center"
}
},
{
"3": {
"h": 1,
"w": 1,
"x": 2,
"y": 13,
"max": {
"h": 100,
"w": 3
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"12": {
"h": 1,
"w": 2,
"x": 0,
"y": 5,
"max": {
"h": 100,
"w": 12
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"id": "j",
"data": {
"id": "j",
"card": false,
"type": "buttoncomponent",
"softWrap": true,
"configuration": {
"size": {
"type": "static",
"value": "xs",
"fieldType": "select",
"onlyStatic": true,
"optionValuesKey": "buttonSizeOptions"
},
"color": {
"type": "static",
"value": "blue",
"fieldType": "select",
"onlyStatic": true,
"optionValuesKey": "buttonColorOptions"
},
"label": {
"type": "static",
"value": "Press me",
"fieldType": "text"
}
},
"componentInput": {
"type": "runnable",
"fields": {},
"fieldType": "any"
},
"verticalAlignment": "center",
"horizontalAlignment": "center"
}
},
{
"3": {
"h": 5,
"w": 3,
"x": 0,
"y": 30,
"max": {
"h": 100,
"w": 3
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"12": {
"h": 5,
"w": 6,
"x": 0,
"y": 18,
"id": "k",
"max": {
"h": 100,
"w": 12
},
"min": {
"h": 1,
"w": 1
},
"fixed": false,
"draggable": true,
"resizable": true,
"customDragger": false,
"customResizer": false
},
"id": "k",
"data": {
"id": "k",
"card": true,
"type": "formcomponent",
"configuration": {
"size": {
"type": "static",
"value": "xs",
"fieldType": "select",
"onlyStatic": true,
"optionValuesKey": "buttonSizeOptions"
},
"color": {
"type": "static",
"value": "dark",
"fieldType": "select",
"onlyStatic": true,
"optionValuesKey": "buttonColorOptions"
},
"label": {
"type": "static",
"value": "Submit",
"fieldType": "text"
}
},
"componentInput": {
"type": "runnable",
"fields": {
"x": {
"type": "user",
"value": null,
"visible": true,
"fieldType": "string"
},
"y": {
"type": "user",
"value": null,
"visible": true,
"fieldType": "string"
}
},
"runnable": {
"name": "Inline Script 0",
"type": "runnableByName",
"inlineScript": {
"path": "/inline-script/Inline Script 0",
"schema": {
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"x",
"y"
],
"properties": {
"x": {
"type": "string",
"default": null,
"description": ""
},
"y": {
"type": "string",
"default": null,
"description": ""
}
}
},
"content": "// import * as wmill from \"https://deno.land/x/windmill@v1.57.1/mod.ts\"\n\nexport async function main(x: string, y: string) {\n return x\n}\n",
"language": "deno"
}
},
"fieldType": "any"
},
"horizontalAlignment": "center"
}
}
],
"fullscreen": false,
"unusedInlineScripts": []
})
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,7 @@
"scripts": {
"dev": "vite dev",
"build": "vite build",
"build-embed": "vite build -c vite.embed.config.js",
"preview": "vite preview",
"check": "svelte-check --tsconfig ./tsconfig.json --threshold warning",
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
@@ -16,6 +17,11 @@
},
"devDependencies": {
"@playwright/test": "^1.29.2",
"@rollup/plugin-commonjs": "^24.0.1",
"@rollup/plugin-html": "^1.0.2",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-terser": "^0.4.0",
"@rollup/plugin-typescript": "^11.0.0",
"@sveltejs/adapter-static": "^1.0.0",
"@sveltejs/kit": "^1.0.0-next.589",
"@sveltejs/package": "^1.0.2",
@@ -34,15 +40,17 @@
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-svelte3": "^4.0.0",
"lucide-svelte": "^0.104.0",
"monaco-editor-workers": "0.33.0",
"openapi-typescript-codegen": "^0.23.0",
"path-browserify": "^1.0.1",
"postcss": "^8.4.18",
"postcss-load-config": "^4.0.1",
"prettier": "^2.8.3",
"prettier-plugin-svelte": "^2.9.0",
"rollup-plugin-svelte": "^7.1.0",
"simple-svelte-autocomplete": "^2.5.1",
"stylelint-config-recommended": "^9.0.0",
"svelte": "^3.53.1",
"svelte": "^3.55.1",
"svelte-awesome": "^3.0.0",
"svelte-check": "^3.0.2",
"svelte-dnd-action": "^0.9.22",
@@ -67,6 +75,7 @@
"@redocly/json-to-json-schema": "^0.0.1",
"@tanstack/svelte-table": "^8.7.6",
"async-mutex": "^0.4.0",
"chart.js": "3.8.2",
"chartjs-adapter-date-fns": "^3.0.0",
"chartjs-plugin-zoom": "^2.0.0",
"date-fns": "^2.29.3",
@@ -83,5 +92,6 @@
},
"peerDependencies": {
"svelte": "^3.53.1"
}
},
"main": "index.js"
}

9
frontend/src/embed.js Normal file
View File

@@ -0,0 +1,9 @@
import AppPreview from './lib/components/apps/editor/AppPreview.svelte'
globalThis.process = { env: { NODE_ENV: 'production' } }
globalThis.loadApp = (target, value) => {
new AppPreview({
target: target,
props: { app: value }
})
}

View File

@@ -1,8 +1,6 @@
<script lang="ts">
import { truncate } from '$lib/utils'
import Tooltip from './Tooltip.svelte'
import json from 'svelte-highlight/languages/json'
import { Highlight } from 'svelte-highlight'
import { ResourceService } from '$lib/gen'
import { workspaceStore } from '$lib/stores'
import Drawer from './common/drawer/Drawer.svelte'

View File

@@ -19,7 +19,6 @@
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
import { buildWorkerDefinition } from 'monaco-editor-workers'
import type {
Disposable,
DocumentUri,
@@ -90,13 +89,7 @@
const uri = `file:///tmp/monaco/${hash}.${langToExt(lang)}`
if (browser) {
if (dev) {
buildWorkerDefinition(
'../../../node_modules/monaco-editor-workers/dist/workers',
import.meta.url,
false
)
} else {
if (!dev) {
// @ts-ignore
self.MonacoEnvironment = {
getWorker: function (_moduleId: any, label: string) {
@@ -408,6 +401,14 @@
}
async function loadMonaco() {
if (dev) {
let { buildWorkerDefinition } = await import('monaco-editor-workers')
buildWorkerDefinition(
'../../../node_modules/monaco-editor-workers/dist/workers',
import.meta.url,
false
)
}
const model = meditor.createModel(code, lang, mUri.parse(uri))
model.updateOptions(updateOptions)

View File

@@ -8,7 +8,6 @@
import DynamicInputHelpBox from './flows/content/DynamicInputHelpBox.svelte'
import type { PropPickerWrapperContext } from './flows/propPicker/PropPickerWrapper.svelte'
import { codeToStaticTemplate, getDefaultExpr, isCodeInjection } from './flows/utils'
import SimpleEditor from './SimpleEditor.svelte'
import { Button, ToggleButton, ToggleButtonGroup } from './common'
import { faCode } from '@fortawesome/free-solid-svg-icons'
import type VariableEditor from './VariableEditor.svelte'
@@ -17,6 +16,7 @@
import TemplateEditor from './TemplateEditor.svelte'
import Tooltip from './Tooltip.svelte'
import { setInputCat as computeInputCat } from '$lib/utils'
import JavascriptEditor from './JavascriptEditor.svelte'
export let schema: Schema
export let arg: InputTransform | any
@@ -29,7 +29,7 @@
export let itemPicker: ItemPicker | undefined = undefined
export let noDynamicToggle = false
let monaco: SimpleEditor | undefined = undefined
let monaco: JavascriptEditor | undefined = undefined
let monacoTemplate: TemplateEditor | undefined = undefined
let argInput: ArgInput | undefined = undefined
@@ -284,7 +284,7 @@
/>
{:else if arg.expr != undefined}
<div class="border rounded mt-2 border-gray-300">
<SimpleEditor
<JavascriptEditor
bind:this={monaco}
bind:code={arg.expr}
{extraLib}

View File

@@ -0,0 +1,212 @@
<script lang="ts">
import { browser, dev } from '$app/environment'
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
import { createEventDispatcher, onDestroy, onMount } from 'svelte'
import { createHash, editorConfig, langToExt, updateOptions } from '$lib/editorUtils'
import { languages, editor as meditor, KeyCode, KeyMod, Uri as mUri } from 'monaco-editor'
import libStdContent from '$lib/es5.d.ts.txt?raw'
meditor.defineTheme('myTheme', {
base: 'vs',
inherit: true,
rules: [],
colors: {
'editorLineNumber.foreground': '#999',
'editorGutter.background': '#F9FAFB'
}
})
meditor.setTheme('myTheme')
languages.typescript.javascriptDefaults.setCompilerOptions({
target: languages.typescript.ScriptTarget.Latest,
allowNonTsExtensions: true,
noLib: true
})
let divEl: HTMLDivElement | null = null
let editor: meditor.IStandaloneCodeEditor
let model: meditor.ITextModel
export let lang: string
export let code: string = ''
export let hash: string = createHash()
export let cmdEnterAction: (() => void) | undefined = undefined
export let formatAction: (() => void) | undefined = undefined
export let automaticLayout = true
export let extraLib: string = ''
export let shouldBindKey: boolean = true
export let autoHeight = false
export let fixedOverflowWidgets = true
const dispatch = createEventDispatcher()
const uri = `file:///${hash}.${langToExt(lang)}`
if (browser) {
if (!dev) {
// @ts-ignore
self.MonacoEnvironment = {
getWorker: function (_moduleId: any, label: string) {
if (label === 'typescript' || label === 'javascript') {
return new tsWorker()
} else {
return new editorWorker()
}
}
}
}
}
export function getCode(): string {
return editor?.getValue() ?? ''
}
export function insertAtCursor(code: string): void {
if (editor) {
editor.trigger('keyboard', 'type', { text: code })
}
}
export function setCode(ncode: string): void {
code = ncode
if (editor) {
editor.setValue(ncode)
}
}
function format() {
if (editor) {
code = getCode()
editor.getAction('editor.action.formatDocument').run()
if (formatAction) {
formatAction()
code = getCode()
}
}
}
let width = 0
async function loadMonaco() {
if (dev) {
let { buildWorkerDefinition } = await import('monaco-editor-workers')
buildWorkerDefinition(
'../../../node_modules/monaco-editor-workers/dist/workers',
import.meta.url,
false
)
}
model = meditor.createModel(code, lang, mUri.parse(uri))
model.updateOptions(updateOptions)
editor = meditor.create(
divEl as HTMLDivElement,
editorConfig(model, code, lang, automaticLayout, fixedOverflowWidgets)
)
let timeoutModel: NodeJS.Timeout | undefined = undefined
editor.onDidChangeModelContent((event) => {
timeoutModel && clearTimeout(timeoutModel)
timeoutModel = setTimeout(() => {
code = getCode()
dispatch('change', { code })
}, 200)
})
editor.onDidFocusEditorText(() => {
dispatch('focus')
editor.addCommand(KeyMod.CtrlCmd | KeyCode.KeyS, function () {
code = getCode()
shouldBindKey && format && format()
})
})
if (autoHeight) {
let ignoreEvent = false
const updateHeight = () => {
const contentHeight = Math.min(1000, editor.getContentHeight())
if (divEl) {
divEl.style.height = `${contentHeight}px`
}
try {
ignoreEvent = true
editor.layout({ width, height: contentHeight })
} finally {
ignoreEvent = false
}
}
editor.onDidContentSizeChange(updateHeight)
updateHeight()
}
editor.onDidFocusEditorText(() => {
editor.addCommand(KeyMod.CtrlCmd | KeyCode.KeyS, function () {
code = getCode()
shouldBindKey && format && format()
})
editor.addCommand(KeyMod.CtrlCmd | KeyCode.Enter, function () {
code = getCode()
shouldBindKey && cmdEnterAction && cmdEnterAction()
})
dispatch('focus')
})
editor.onDidBlurEditorText(() => {
code = getCode()
dispatch('blur')
})
if (lang == 'javascript') {
const stdLib = { content: libStdContent, filePath: 'es5.d.ts' }
if (extraLib != '') {
languages.typescript.javascriptDefaults.setExtraLibs([
{
content: extraLib,
filePath: 'windmill.d.ts'
},
stdLib
])
} else {
languages.typescript.javascriptDefaults.setExtraLibs([stdLib])
}
}
}
onMount(() => {
if (browser) {
loadMonaco()
}
})
onDestroy(() => {
try {
model && model.dispose()
editor && editor.dispose()
} catch (err) {}
})
</script>
<div bind:this={divEl} class="{$$props.class} editor" bind:clientWidth={width} />
<style>
.editor {
@apply rounded-lg p-0;
}
.small-editor {
/* stylelint-disable-next-line unit-allowed-list */
height: 26vh;
}
.few-lines-editor {
/* stylelint-disable-next-line unit-allowed-list */
height: 100px;
}
</style>

View File

@@ -7,11 +7,9 @@
import { slide } from 'svelte/transition'
import ArgInput from './ArgInput.svelte'
import { Button } from './common'
import InputTransformForm from './InputTransformForm.svelte'
import ItemPicker from './ItemPicker.svelte'
import VariableEditor from './VariableEditor.svelte'
export let inputTransform = false
export let schema: Schema
export let args: Record<string, InputTransform | any> = {}
export let disabledArgs: string[] = []
@@ -19,16 +17,13 @@
export let editableSchema = false
export let isValid: boolean = true
export let extraLib: string = 'missing extraLib'
export let autofocus = false
export let previousModuleId: string | undefined = undefined
export let shouldHideNoInputs: boolean = false
export let compact = false
export let password: string | undefined = undefined
export let noVariablePicker = false
export let filter: string[] | undefined = undefined
export let noDynamicToggle = false
export let flexWrap = false
export let noDelete = false
@@ -71,20 +66,7 @@
{#each keys as argName, i (argName)}
{#if !filter || filter.includes(argName)}
<div transition:slide|local>
{#if inputTransform}
<InputTransformForm
{previousModuleId}
bind:arg={args[argName]}
bind:schema
bind:argName
bind:inputCheck={inputCheck[argName]}
bind:extraLib
{variableEditor}
{itemPicker}
bind:pickForField
{noDynamicToggle}
/>
{:else if typeof args == 'object'}
{#if typeof args == 'object'}
<ArgInput
autofocus={i == 0 && autofocus}
label={argName}
@@ -125,11 +107,7 @@
bind:this={itemPicker}
pickCallback={(path, _) => {
if (pickForField) {
if (inputTransform) {
args[pickForField].value = '$var:' + path
} else {
args[pickForField] = '$var:' + path
}
args[pickForField] = '$var:' + path
}
}}
itemName="Variable"

View File

@@ -0,0 +1,120 @@
<script lang="ts">
import type { Schema } from '$lib/common'
import { VariableService, type InputTransform } from '$lib/gen'
import { workspaceStore } from '$lib/stores'
import { allTrue } from '$lib/utils'
import { faPlus } from '@fortawesome/free-solid-svg-icons'
import { slide } from 'svelte/transition'
import { Button } from './common'
import InputTransformForm from './InputTransformForm.svelte'
import ItemPicker from './ItemPicker.svelte'
import VariableEditor from './VariableEditor.svelte'
export let schema: Schema
export let args: Record<string, InputTransform | any> = {}
export let isValid: boolean = true
export let extraLib: string = 'missing extraLib'
export let previousModuleId: string | undefined = undefined
export let shouldHideNoInputs: boolean = false
export let noVariablePicker = false
export let filter: string[] | undefined = undefined
export let noDynamicToggle = false
export let flexWrap = false
export let noDelete = false
let clazz: string = ''
export { clazz as class }
let inputCheck: { [id: string]: boolean } = {}
$: isValid = allTrue(inputCheck) ?? false
$: if (args == undefined || typeof args !== 'object') {
args = {}
}
function removeExtraKey() {
Object.keys(args ?? {}).forEach((key) => {
if (!keys.includes(key)) {
delete args[key]
delete inputCheck[key]
}
})
}
let pickForField: string | undefined
let itemPicker: ItemPicker | undefined = undefined
let variableEditor: VariableEditor | undefined = undefined
let keys: string[] = []
$: {
let lkeys = Object.keys(schema?.properties ?? {})
if (schema?.properties && JSON.stringify(lkeys) != JSON.stringify(keys)) {
keys = lkeys
if (!noDelete) {
removeExtraKey()
}
}
}
</script>
<div class="w-full {clazz} {flexWrap ? 'flex flex-row flex-wrap gap-x-6 gap-y-2' : ''}">
{#if keys.length > 0}
{#each keys as argName, i (argName)}
{#if !filter || filter.includes(argName)}
<div transition:slide|local>
<InputTransformForm
{previousModuleId}
bind:arg={args[argName]}
bind:schema
bind:argName
bind:inputCheck={inputCheck[argName]}
bind:extraLib
{variableEditor}
{itemPicker}
bind:pickForField
{noDynamicToggle}
/>
</div>
{/if}
{/each}
{:else if !shouldHideNoInputs}
<div class="text-gray-500 text-sm">No inputs</div>
{/if}
</div>
{#if !noVariablePicker}
<ItemPicker
bind:this={itemPicker}
pickCallback={(path, _) => {
if (pickForField) {
args[pickForField].value = '$var:' + path
}
}}
itemName="Variable"
extraField="path"
loadItems={async () =>
(await VariableService.listVariable({ workspace: $workspaceStore ?? '' })).map((x) => ({
name: x.path,
...x
}))}
>
<div
slot="submission"
class="flex flex-row-reverse w-full bg-white border-t border-gray-200 rounded-bl-lg rounded-br-lg"
>
<Button
variant="border"
color="blue"
size="sm"
startIcon={{ icon: faPlus }}
on:click={() => {
variableEditor?.initNew?.()
}}
>
New variable
</Button>
</div>
</ItemPicker>
<VariableEditor bind:this={variableEditor} />
{/if}

View File

@@ -4,15 +4,16 @@
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import yamlWorker from 'monaco-yaml/yaml.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
import { buildWorkerDefinition } from 'monaco-editor-workers'
import { createEventDispatcher, onDestroy, onMount } from 'svelte'
import { createHash, editorConfig, langToExt, updateOptions } from '$lib/editorUtils'
import { languages, editor as meditor, KeyCode, KeyMod, Uri as mUri } from 'monaco-editor'
import libStdContent from '$lib/es5.d.ts.txt?raw'
import {
languages,
editor as meditor,
KeyCode,
KeyMod,
Uri as mUri
} from 'monaco-editor/esm/vs/editor/editor.main'
meditor.defineTheme('myTheme', {
base: 'vs',
@@ -25,12 +26,6 @@
})
meditor.setTheme('myTheme')
languages.typescript.javascriptDefaults.setCompilerOptions({
target: languages.typescript.ScriptTarget.Latest,
allowNonTsExtensions: true,
noLib: true
})
languages.json.jsonDefaults.setDiagnosticsOptions({
validate: true,
allowComments: false,
@@ -48,7 +43,6 @@
export let cmdEnterAction: (() => void) | undefined = undefined
export let formatAction: (() => void) | undefined = undefined
export let automaticLayout = true
export let extraLib: string = ''
export let shouldBindKey: boolean = true
export let autoHeight = false
export let fixedOverflowWidgets = true
@@ -58,13 +52,7 @@
const uri = `file:///${hash}.${langToExt(lang)}`
if (browser) {
if (dev) {
buildWorkerDefinition(
'../../../node_modules/monaco-editor-workers/dist/workers',
import.meta.url,
false
)
} else {
if (!dev) {
// @ts-ignore
self.MonacoEnvironment = {
getWorker: function (_moduleId: any, label: string) {
@@ -72,8 +60,6 @@
return new jsonWorker()
} else if (label === 'yaml') {
return new yamlWorker()
} else if (label === 'typescript' || label === 'javascript') {
return new tsWorker()
} else {
return new editorWorker()
}
@@ -174,21 +160,6 @@
code = getCode()
dispatch('blur')
})
if (lang == 'javascript') {
const stdLib = { content: libStdContent, filePath: 'es5.d.ts' }
if (extraLib != '') {
languages.typescript.javascriptDefaults.setExtraLibs([
{
content: extraLib,
filePath: 'windmill.d.ts'
},
stdLib
])
} else {
languages.typescript.javascriptDefaults.setExtraLibs([stdLib])
}
}
}
onMount(() => {

View File

@@ -12,19 +12,24 @@
EditorMode
} from '../types'
import GridEditor from './GridEditor.svelte'
import { classNames } from '$lib/utils'
import { classNames } from '../../../utils'
import type { Policy } from '$lib/gen'
import Button from '../../common/button/Button.svelte'
import { Unlock } from 'lucide-svelte'
export let app: App
export let appPath: string
export let breakpoint: Writable<EditorBreakpoint>
export let policy: Policy
export let summary: string
export let workspace: string
export let isEditor: boolean
export let context: Record<string, any>
export let app: App = {
grid: [],
fullscreen: false,
unusedInlineScripts: [],
hiddenInlineScripts: []
}
export let appPath: string = ''
export let breakpoint: Writable<EditorBreakpoint> = writable('lg')
export let policy: Policy = {}
export let summary: string = ''
export let workspace: string = 'workspace'
export let isEditor: boolean = false
export let context: Record<string, any> = {}
export let noBackend: boolean = false
export let isLocked = false

View File

@@ -3,8 +3,8 @@
import { getContext } from 'svelte'
import type { AppEditorContext } from '$lib/components/apps/types'
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
import { buildExtraLib } from '$lib/components/apps/utils'
import JavascriptEditor from '$lib/components/JavascriptEditor.svelte'
export let componentInput: EvalAppInput | undefined
export let id: string
@@ -22,7 +22,7 @@
{#if componentInput?.type === 'eval'}
<div class="border border-gray-300 ">
<SimpleEditor
<JavascriptEditor
lang="javascript"
bind:code={componentInput.expr}
shouldBindKey={false}

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import { classNames } from '$lib/utils'
import { classNames } from '../../../utils'
import Icon from 'svelte-awesome'
import { ButtonType } from './model'
import { goto } from '$app/navigation'

View File

@@ -3,11 +3,11 @@
import { getContext } from 'svelte'
import { flowStore } from '../flowStore'
import PropPickerWrapper from '../propPicker/PropPickerWrapper.svelte'
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
import { flowStateStore } from '../flowState'
import { getStepPropPicker } from '../previousResults'
import type { FlowEditorContext } from '../types'
import JavascriptEditor from '$lib/components/JavascriptEditor.svelte'
export let branch: {
summary?: string
@@ -18,7 +18,7 @@
export let previousModule: FlowModule | undefined
const { previewArgs } = getContext<FlowEditorContext>('FlowEditorContext')
let editor: SimpleEditor | undefined = undefined
let editor: JavascriptEditor | undefined = undefined
$: stepPropPicker = getStepPropPicker(
$flowStateStore,
@@ -40,7 +40,7 @@
}}
>
<div class="border border-gray-400">
<SimpleEditor
<JavascriptEditor
bind:this={editor}
lang="javascript"
bind:code={branch.expr}

View File

@@ -3,13 +3,13 @@
import FlowCard from '../common/FlowCard.svelte'
import { Alert, Badge } from '$lib/components/common'
import type { FlowModule, FlowModuleValue, InputTransform, PathScript, RawScript } from '$lib/gen'
import SchemaForm from '$lib/components/SchemaForm.svelte'
import { flowStateStore } from '../flowState'
import { setContext } from 'svelte'
import type { PropPickerWrapperContext } from '../propPicker/PropPickerWrapper.svelte'
import { writable } from 'svelte/store'
import { slide } from 'svelte/transition'
import Toggle from '../../Toggle.svelte'
import SchemaFormTransform from '$lib/components/SchemaFormTransform.svelte'
let hideOptional = false
@@ -37,7 +37,7 @@
] as [Record<string, InputTransform>, string[], FlowModule]
)
.filter(([i, f, m]) => f.length > 0)
setContext<PropPickerWrapperContext>('PropPickerWrapper', {
focusProp: () => {},
propPickerConfig: writable(undefined),
@@ -47,11 +47,7 @@
<div class="min-h-full">
<FlowCard title="All Static Inputs">
<Toggle
slot="header"
bind:checked={hideOptional}
options={{left: 'Hide optional inputs'}}
/>
<Toggle slot="header" bind:checked={hideOptional} options={{ left: 'Hide optional inputs' }} />
<div class="min-h-full flex-1">
<Alert type="info" title="Static Inputs" class="m-4"
>This page centralizes the static inputs of every steps. It is akin to a file containing all
@@ -80,9 +76,8 @@
<Badge large color="indigo">{m.id}</Badge>
</h2>
<SchemaForm
<SchemaFormTransform
noDynamicToggle
inputTransform
{filter}
class="mt-2"
schema={$flowStateStore[m.id]?.schema ?? {}}

View File

@@ -3,7 +3,6 @@
import FlowCard from '../common/FlowCard.svelte'
import type { FlowEditorContext } from '../types'
import Toggle from '$lib/components/Toggle.svelte'
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
import Tooltip from '$lib/components/Tooltip.svelte'
import PropPickerWrapper from '../propPicker/PropPickerWrapper.svelte'
import FlowModuleEarlyStop from './FlowModuleEarlyStop.svelte'
@@ -16,6 +15,7 @@
import { flowStateStore } from '../flowState'
import { flowStore } from '../flowStore'
import FlowModuleSleep from './FlowModuleSleep.svelte'
import JavascriptEditor from '$lib/components/JavascriptEditor.svelte'
const { previewArgs } = getContext<FlowEditorContext>('FlowEditorContext')
@@ -23,7 +23,7 @@
export let parentModule: FlowModule | undefined
export let previousModule: FlowModule | undefined
let editor: SimpleEditor | undefined = undefined
let editor: JavascriptEditor | undefined = undefined
let selected: string = 'early-stop'
$: stepPropPicker = getStepPropPicker(
@@ -62,7 +62,7 @@
editor?.insertAtCursor(detail)
}}
>
<SimpleEditor
<JavascriptEditor
bind:this={editor}
lang="javascript"
bind:code={mod.value.iterator.expr}

View File

@@ -7,7 +7,6 @@
import ModulePreview from '$lib/components/ModulePreview.svelte'
import { createScriptFromInlineScript, fork } from '$lib/components/flows/flowStateUtils'
import { flowStore } from '$lib/components/flows/flowStore'
import SchemaForm from '$lib/components/SchemaForm.svelte'
import { RawScript, type FlowModule, type PathFlow, type PathScript } from '$lib/gen'
import FlowCard from '../common/FlowCard.svelte'
import FlowModuleHeader from './FlowModuleHeader.svelte'
@@ -27,6 +26,7 @@
import Alert from '$lib/components/common/alert/Alert.svelte'
import FlowModuleSleep from './FlowModuleSleep.svelte'
import FlowPathViewer from './FlowPathViewer.svelte'
import SchemaFormTransform from '$lib/components/SchemaFormTransform.svelte'
const { selectedId, previewArgs } = getContext<FlowEditorContext>('FlowEditorContext')
@@ -211,9 +211,8 @@
pickableProperties={stepPropPicker.pickableProperties}
error={failureModule}
>
<SchemaForm
<SchemaFormTransform
schema={$flowStateStore[$selectedId]?.schema ?? {}}
inputTransform={true}
previousModuleId={previousModule?.id}
bind:args={value.input_transforms}
bind:extraLib={stepPropPicker.extraLib}

View File

@@ -1,15 +1,15 @@
<script lang="ts">
import SimpleEditor from '$lib/components/SimpleEditor.svelte'
import Toggle from '$lib/components/Toggle.svelte'
import PropPickerWrapper from '$lib/components/flows/propPicker/PropPickerWrapper.svelte'
import type { FlowModule } from '$lib/gen'
import { flowStateStore } from '../flowState'
import Tooltip from '$lib/components/Tooltip.svelte'
import { NEVER_TESTED_THIS_FAR } from '../utils'
import JavascriptEditor from '$lib/components/JavascriptEditor.svelte'
export let flowModule: FlowModule
let editor: SimpleEditor | undefined = undefined
let editor: JavascriptEditor | undefined = undefined
$: isStopAfterIfEnabled = Boolean(flowModule.stop_after_if)
@@ -59,7 +59,7 @@
editor?.insertAtCursor(detail)
}}
>
<SimpleEditor
<JavascriptEditor
bind:this={editor}
lang="javascript"
bind:code={flowModule.stop_after_if.expr}

View File

@@ -0,0 +1,12 @@
import { readable } from 'svelte/store'
export async function goto(x) {
console.error('Goto not implemented')
}
export const browser = true
export const dev = true
export const page = readable({ url: document.URL }, function start(set) {
return function stop() {}
})

View File

@@ -9,7 +9,7 @@ import {
UserService,
type Flow,
type User
} from '$lib/gen'
} from '$lib/gen/index'
import { toast } from '@zerodevx/svelte-toast'
import type { Schema, SupportedLanguage } from './common'
import { hubScripts, workspaceStore, type UserExt } from './stores'

View File

@@ -0,0 +1,59 @@
// import { sveltekit } from '@sveltejs/kit/vite'
import { readFileSync } from 'fs'
import { fileURLToPath } from 'url'
import { svelte } from '@sveltejs/vite-plugin-svelte'
const file = fileURLToPath(new URL('package.json', import.meta.url))
const json = readFileSync(file, 'utf8')
const version = JSON.parse(json)
/** @type {import('vite').UserConfig} */
const config = {
server: {
port: 3000
},
preview: {
port: 3000
},
plugins: [svelte()],
define: {
__pkg__: version
},
optimizeDeps: {
include: ['highlight.js', 'highlight.js/lib/core']
},
resolve: {
alias: {
path: 'path-browserify',
$lib: ['/src/lib'],
'$lib/*': ['/src/lib/*'],
'$app/navigation': ['/src/lib/fakesvelte.js'],
'$app/stores': ['/src/lib/fakesvelte.js'],
'$app/environment': ['/src/lib/fakesvelte.js']
}
},
build: {
lib: {
// Could also be a dictionary or array of multiple entry points
entry: ['src/embed.js'],
name: 'AppViewer',
// the proper extensions will be added
fileName: 'appviewer',
formats: ['iife']
}
// rollupOptions: {
// external: ['highlight.js'],
// input: 'src/embed.js',
// output: {
// format: 'esm',
// name: 'app',
// // We output it to public. This way, our svelte kit
// // app will also host the web components.
// dir: 'build'
// // file: 'build/app.js'
// }
// }
}
}
export default config