From cc5f629a7b142a2bd0ce7ca8950e24f6cb5473ff Mon Sep 17 00:00:00 2001 From: Faton Ramadani Date: Mon, 14 Nov 2022 17:30:49 +0100 Subject: [PATCH] fix(frontend): App Editor v0 (#886) --- backend/sqlx-data.json | 46 +-- backend/windmill-api/openapi.yaml | 14 + backend/windmill-api/src/apps.rs | 36 ++- backend/windmill-worker/src/worker.rs | 3 +- frontend/package-lock.json | 89 +++--- frontend/package.json | 1 + frontend/src/global.d.ts | 9 + frontend/src/lib/components/Path.svelte | 2 +- frontend/src/lib/components/SchemaForm.svelte | 3 + .../src/lib/components/TestJobLoader.svelte | 64 +++-- .../apps/components/BarChartComponent.svelte | 55 ++++ .../apps/components/DisplayComponent.svelte | 28 ++ .../apps/components/RunFormComponent.svelte | 130 +++++++++ .../apps/components/TableComponent.svelte | 109 ++++++++ .../components/apps/editor/AppEditor.svelte | 88 ++++++ .../apps/editor/AppEditorHeader.svelte | 58 ++++ .../apps/editor/ComponentEditor.svelte | 74 +++++ .../apps/editor/ComponentsEditor.svelte | 232 +++++++++++++++ .../apps/editor/SectionsEditor.svelte | 264 ++++++++++++++++++ .../componentsPanel/ComponentList.svelte | 105 +++++++ .../ComponentInputsSpecsEditor.svelte | 31 ++ .../settingsPanel/ComponentPanel.svelte | 113 ++++++++ .../settingsPanel/DynamicInputEditor.svelte | 69 +++++ .../settingsPanel/InputsSpecEditor.svelte | 15 + .../settingsPanel/InputsSpecsEditor.svelte | 44 +++ .../apps/editor/settingsPanel/PickFlow.svelte | 34 +++ .../editor/settingsPanel/SectionPanel.svelte | 93 ++++++ .../settingsPanel/StaticInputEditor.svelte | 9 + .../settingsPanel/UserInputEditor.svelte | 2 + .../settingsPanel/common/PanelSection.svelte | 8 + frontend/src/lib/components/apps/rx.ts | 113 ++++++++ frontend/src/lib/components/apps/types.ts | 126 +++++++++ frontend/src/lib/components/apps/utils.ts | 75 +++++ .../components/common/button/Button.svelte | 2 +- .../common/toggleButton/ToggleButton.svelte | 23 +- .../toggleButton/ToggleButtonGroup.svelte | 26 +- .../flows/content/FlowModuleComponent.svelte | 2 +- .../lib/components/flows/flowStateUtils.ts | 42 ++- .../flows/pickers/FlowScriptPicker.svelte | 1 - .../src/lib/components/jobs/JobDetail.svelte | 2 +- frontend/src/lib/utils.ts | 20 +- frontend/src/routes/__layout@root.svelte | 2 +- frontend/src/routes/apps.svelte | 134 +++++++++ .../src/routes/apps/edit/[...path].svelte | 29 ++ frontend/src/routes/apps/get/[...path].svelte | 35 +++ frontend/tailwind.config.cjs | 226 +++++++++------ 46 files changed, 2456 insertions(+), 230 deletions(-) create mode 100644 frontend/src/lib/components/apps/components/BarChartComponent.svelte create mode 100644 frontend/src/lib/components/apps/components/DisplayComponent.svelte create mode 100644 frontend/src/lib/components/apps/components/RunFormComponent.svelte create mode 100644 frontend/src/lib/components/apps/components/TableComponent.svelte create mode 100644 frontend/src/lib/components/apps/editor/AppEditor.svelte create mode 100644 frontend/src/lib/components/apps/editor/AppEditorHeader.svelte create mode 100644 frontend/src/lib/components/apps/editor/ComponentEditor.svelte create mode 100644 frontend/src/lib/components/apps/editor/ComponentsEditor.svelte create mode 100644 frontend/src/lib/components/apps/editor/SectionsEditor.svelte create mode 100644 frontend/src/lib/components/apps/editor/componentsPanel/ComponentList.svelte create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/ComponentInputsSpecsEditor.svelte create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/DynamicInputEditor.svelte create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecEditor.svelte create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/PickFlow.svelte create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/SectionPanel.svelte create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/StaticInputEditor.svelte create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/UserInputEditor.svelte create mode 100644 frontend/src/lib/components/apps/editor/settingsPanel/common/PanelSection.svelte create mode 100644 frontend/src/lib/components/apps/rx.ts create mode 100644 frontend/src/lib/components/apps/types.ts create mode 100644 frontend/src/lib/components/apps/utils.ts create mode 100644 frontend/src/routes/apps.svelte create mode 100644 frontend/src/routes/apps/edit/[...path].svelte create mode 100644 frontend/src/routes/apps/get/[...path].svelte diff --git a/backend/sqlx-data.json b/backend/sqlx-data.json index e428102342..83c658bf94 100644 --- a/backend/sqlx-data.json +++ b/backend/sqlx-data.json @@ -428,29 +428,6 @@ }, "query": "SELECT dependency_job FROM flow WHERE path = $1 AND workspace_id = $2" }, - "190cb52762c82b4c7f318decf73cfb4377825c93b5777904b82f8940bb18be3e": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int8" - } - ], - "nullable": [ - false - ], - "parameters": { - "Left": [ - "Varchar", - "Varchar", - "Varchar", - "Jsonb" - ] - } - }, - "query": "INSERT INTO app\n (workspace_id, path, summary, policy)\n VALUES ($1, $2, $3, $4) RETURNING id" - }, "1ad8677694aca94ee0e6da287d7cc028dcf673583a0e3e4fedd0e5d6766c5860": { "describe": { "columns": [], @@ -2683,6 +2660,29 @@ }, "query": "DELETE FROM token WHERE token = $1 RETURNING email" }, + "9def921a0b697e4cbcb6ad88196ff6f66358f3b819aaf4e279596ccfc433fa92": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int8" + } + ], + "nullable": [ + false + ], + "parameters": { + "Left": [ + "Varchar", + "Varchar", + "Varchar", + "Jsonb" + ] + } + }, + "query": "INSERT INTO app\n (workspace_id, path, summary, policy, versions)\n VALUES ($1, $2, $3, $4, '{}') RETURNING id" + }, "a227548b6604c56bfc15eb780bd8ee72a89dc6701a50f5048e928bd87baa7b9a": { "describe": { "columns": [ diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index dfe002543f..cc93a4cbf8 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -2486,6 +2486,8 @@ paths: required: - content - language + force_viewer_static_fields: + type: object required: - args @@ -4758,6 +4760,18 @@ components: type: object additionalProperties: type: boolean + required: + - id + - workspace_id + - path + - summary + - versions + - created_by + - created_at + - value + - policy + - execution_mode + - extra_perms SlackToken: type: object diff --git a/backend/windmill-api/src/apps.rs b/backend/windmill-api/src/apps.rs index 881e7fc751..f8e2ada973 100644 --- a/backend/windmill-api/src/apps.rs +++ b/backend/windmill-api/src/apps.rs @@ -80,7 +80,7 @@ pub struct AppWithLastVersion { pub type StaticFields = Map; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] #[serde(rename_all = "lowercase")] pub enum ExecutionMode { Anonymous, @@ -88,7 +88,7 @@ pub enum ExecutionMode { Viewer, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct Policy { pub on_behalf_of: Option, //paths: @@ -208,8 +208,8 @@ async fn create_app( let id = sqlx::query_scalar!( "INSERT INTO app - (workspace_id, path, summary, policy) - VALUES ($1, $2, $3, $4) RETURNING id", + (workspace_id, path, summary, policy, versions) + VALUES ($1, $2, $3, $4, '{}') RETURNING id", w_id, app.path, app.summary, @@ -249,7 +249,7 @@ async fn create_app( .await?; tx.commit().await?; - Ok((StatusCode::CREATED, format!("app {} created", app.path))) + Ok((StatusCode::CREATED, app.path)) } async fn delete_app( @@ -371,13 +371,15 @@ async fn update_app( Ok(format!("app {} updated (npath: {:?})", path, npath)) } -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, Clone)] pub struct ExecuteApp { pub args: Map, // - script: script/ // - flow: flow/ pub path: Option, pub raw_code: Option, + // if set, the app is executed as viewer with the given static fields + pub force_viewer_static_fields: Option, } fn digest(code: &str) -> String { @@ -422,6 +424,24 @@ async fn execute_component( let policy = serde_json::from_value::(policy).map_err(to_anyhow)?; + let policy = if let Some(static_fields) = payload.clone().force_viewer_static_fields { + let mut hm = HashMap::new(); + if let Some(path) = payload.path.clone() { + hm.insert(path, static_fields); + } else { + hm.insert( + format!( + "rawcode/{}", + digest(payload.raw_code.clone().unwrap().content.as_str()) + ), + static_fields, + ); + } + Policy { execution_mode: ExecutionMode::Viewer, triggerables: hm, on_behalf_of: None } + } else { + policy + }; + let (username, permissioned_as) = match policy.execution_mode { ExecutionMode::Anonymous => { let username = opt_authed @@ -464,14 +484,14 @@ async fn execute_component( }; let (job_payload, args) = match &payload { - ExecuteApp { args, raw_code: Some(raw_code), path: None } => { + ExecuteApp { args, raw_code: Some(raw_code), path: None, .. } => { let content = &raw_code.content; let payload = JobPayload::Code(raw_code.clone()); let path = digest(content); let args = build_args(policy, path, args)?; (payload, args) } - ExecuteApp { args, raw_code: None, path: Some(path) } => { + ExecuteApp { args, raw_code: None, path: Some(path), .. } => { let payload = if path.starts_with("script/") { script_path_to_payload(path.strip_prefix("script/").unwrap(), &mut tx, &w_id) .await? diff --git a/backend/windmill-worker/src/worker.rs b/backend/windmill-worker/src/worker.rs index 3bfdade876..d28e4042bc 100644 --- a/backend/windmill-worker/src/worker.rs +++ b/backend/windmill-worker/src/worker.rs @@ -1309,6 +1309,7 @@ run(); .spawn()? } else { let mut args = Vec::new(); + let script_path = format!("{job_dir}/main.ts"); args.push("run"); if lockfile.is_some() { args.push("--lock=/tmp/lock.json"); @@ -1316,7 +1317,7 @@ run(); args.push("--unstable"); args.push("--v8-flags=--max-heap-size=2048"); args.push("-A"); - args.push("/tmp/main.ts"); + args.push(&script_path); Command::new(deno_path) .current_dir(job_dir) .env_clear() diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 92f2a7a9b5..e7b87b6e4a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -51,6 +51,7 @@ "svelte": "^3.52.0", "svelte-awesome": "^3.0.0", "svelte-check": "^2.9.2", + "svelte-dnd-action": "^0.9.21", "svelte-heros": "^2.3.5", "svelte-highlight": "^6.2.1", "svelte-markdown": "^0.2.3", @@ -780,9 +781,9 @@ "optional": true }, "node_modules/@zerodevx/svelte-toast": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@zerodevx/svelte-toast/-/svelte-toast-0.8.1.tgz", - "integrity": "sha512-XofCfaHj79uNiKc5leWUxO6LP/Xcawvi3B6Kb1gPCaBf/X5//HdZ/OIfG3z//QuKyFRUmEkDkoMzmbYWTUW2jw==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@zerodevx/svelte-toast/-/svelte-toast-0.8.2.tgz", + "integrity": "sha512-EDtZ/Hw37T/UWCQ5drhMss0J9vItYUSDivQ3+mET5My6No7YNiNQklj2bkE61UAzut2TjHJfOJNBZsj78ODFtw==", "dev": true }, "node_modules/accepts": { @@ -2261,23 +2262,6 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-64": { - "version": "0.14.53", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.53.tgz", - "integrity": "sha512-pP/FA55j/fzAV7N9DF31meAyjOH6Bjuo3aSKPh26+RW85ZEtbJv9nhoxmGTd9FOqjx59Tc1ZbrJabuiXlMwuZQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, "node_modules/esbuild-linux-arm": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.53.tgz", @@ -2482,6 +2466,23 @@ "node": ">=12" } }, + "node_modules/esbuild/node_modules/esbuild-linux-64": { + "version": "0.14.53", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.53.tgz", + "integrity": "sha512-pP/FA55j/fzAV7N9DF31meAyjOH6Bjuo3aSKPh26+RW85ZEtbJv9nhoxmGTd9FOqjx59Tc1ZbrJabuiXlMwuZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -5881,6 +5882,12 @@ "svelte": "^3.24.0" } }, + "node_modules/svelte-dnd-action": { + "version": "0.9.21", + "resolved": "https://registry.npmjs.org/svelte-dnd-action/-/svelte-dnd-action-0.9.21.tgz", + "integrity": "sha512-uSiaGiSY5KCTx5OtColSk/1qFFUAzGvnoQYDE5xfOmcyvf3lAI1IjPv0p0LRKrTudS9rGZYWPx44qsD09ER6QQ==", + "dev": true + }, "node_modules/svelte-heros": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/svelte-heros/-/svelte-heros-2.3.5.tgz", @@ -6154,9 +6161,9 @@ "peer": true }, "node_modules/tailwindcss": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.2.tgz", - "integrity": "sha512-c2GtSdqg+harR4QeoTmex0Ngfg8IIHNeLQH5yr2B9uZbZR1Xt1rYbjWOWTcj3YLTZhrmZnPowoQDbSRFyZHQ5Q==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.3.tgz", + "integrity": "sha512-Xt9D4PK4zuuQCEB8bwK9JUCKmTgUwyac/6b0/42Vqhgl6YJkep+Wf5wq+5uXYfmrupdAD0YY2NY1hyZp1HjRrg==", "dev": true, "dependencies": { "arg": "^5.0.2", @@ -7315,9 +7322,9 @@ "optional": true }, "@zerodevx/svelte-toast": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@zerodevx/svelte-toast/-/svelte-toast-0.8.1.tgz", - "integrity": "sha512-XofCfaHj79uNiKc5leWUxO6LP/Xcawvi3B6Kb1gPCaBf/X5//HdZ/OIfG3z//QuKyFRUmEkDkoMzmbYWTUW2jw==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@zerodevx/svelte-toast/-/svelte-toast-0.8.2.tgz", + "integrity": "sha512-EDtZ/Hw37T/UWCQ5drhMss0J9vItYUSDivQ3+mET5My6No7YNiNQklj2bkE61UAzut2TjHJfOJNBZsj78ODFtw==", "dev": true }, "accepts": { @@ -8299,6 +8306,16 @@ "esbuild-windows-32": "0.14.53", "esbuild-windows-64": "0.14.53", "esbuild-windows-arm64": "0.14.53" + }, + "dependencies": { + "esbuild-linux-64": { + "version": "0.14.53", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.53.tgz", + "integrity": "sha512-pP/FA55j/fzAV7N9DF31meAyjOH6Bjuo3aSKPh26+RW85ZEtbJv9nhoxmGTd9FOqjx59Tc1ZbrJabuiXlMwuZQ==", + "dev": true, + "optional": true, + "peer": true + } } }, "esbuild-android-64": { @@ -8357,14 +8374,6 @@ "optional": true, "peer": true }, - "esbuild-linux-64": { - "version": "0.14.53", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.53.tgz", - "integrity": "sha512-pP/FA55j/fzAV7N9DF31meAyjOH6Bjuo3aSKPh26+RW85ZEtbJv9nhoxmGTd9FOqjx59Tc1ZbrJabuiXlMwuZQ==", - "dev": true, - "optional": true, - "peer": true - }, "esbuild-linux-arm": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.53.tgz", @@ -10936,6 +10945,12 @@ "typescript": "*" } }, + "svelte-dnd-action": { + "version": "0.9.21", + "resolved": "https://registry.npmjs.org/svelte-dnd-action/-/svelte-dnd-action-0.9.21.tgz", + "integrity": "sha512-uSiaGiSY5KCTx5OtColSk/1qFFUAzGvnoQYDE5xfOmcyvf3lAI1IjPv0p0LRKrTudS9rGZYWPx44qsD09ER6QQ==", + "dev": true + }, "svelte-heros": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/svelte-heros/-/svelte-heros-2.3.5.tgz", @@ -11122,9 +11137,9 @@ } }, "tailwindcss": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.2.tgz", - "integrity": "sha512-c2GtSdqg+harR4QeoTmex0Ngfg8IIHNeLQH5yr2B9uZbZR1Xt1rYbjWOWTcj3YLTZhrmZnPowoQDbSRFyZHQ5Q==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.3.tgz", + "integrity": "sha512-Xt9D4PK4zuuQCEB8bwK9JUCKmTgUwyac/6b0/42Vqhgl6YJkep+Wf5wq+5uXYfmrupdAD0YY2NY1hyZp1HjRrg==", "dev": true, "requires": { "arg": "^5.0.2", diff --git a/frontend/package.json b/frontend/package.json index b993089c83..5c8d9c4eeb 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -41,6 +41,7 @@ "svelte": "^3.52.0", "svelte-awesome": "^3.0.0", "svelte-check": "^2.9.2", + "svelte-dnd-action": "^0.9.21", "svelte-heros": "^2.3.5", "svelte-highlight": "^6.2.1", "svelte-markdown": "^0.2.3", diff --git a/frontend/src/global.d.ts b/frontend/src/global.d.ts index 63908c66cf..3cf0168db4 100644 --- a/frontend/src/global.d.ts +++ b/frontend/src/global.d.ts @@ -1 +1,10 @@ /// + +declare type Item = import('svelte-dnd-action').Item +declare type DndEvent = import('svelte-dnd-action').DndEvent +declare namespace svelte.JSX { + interface HTMLAttributes { + onconsider?: (event: CustomEvent> & { target: EventTarget & T }) => void + onfinalize?: (event: CustomEvent> & { target: EventTarget & T }) => void + } +} diff --git a/frontend/src/lib/components/Path.svelte b/frontend/src/lib/components/Path.svelte index 59e68ba6f3..aa112bae43 100644 --- a/frontend/src/lib/components/Path.svelte +++ b/frontend/src/lib/components/Path.svelte @@ -16,7 +16,7 @@ import Required from './Required.svelte' import Popover from './Popover.svelte' - type PathKind = 'resource' | 'script' | 'variable' | 'flow' | 'schedule' + type PathKind = 'resource' | 'script' | 'variable' | 'flow' | 'schedule' | 'app' export let meta: Meta = { ownerKind: 'user', owner: '', diff --git a/frontend/src/lib/components/SchemaForm.svelte b/frontend/src/lib/components/SchemaForm.svelte index d5f9ee3afc..104011c92b 100644 --- a/frontend/src/lib/components/SchemaForm.svelte +++ b/frontend/src/lib/components/SchemaForm.svelte @@ -8,6 +8,8 @@ export let inputTransform = false export let schema: Schema export let args: Record = {} + export let disabledArgs: string[] = [] + export let editableSchema = false export let isValid: boolean = true export let extraLib: string = 'missing extraLib' @@ -64,6 +66,7 @@ contentEncoding={schema.properties[argName].contentEncoding} properties={schema.properties[argName].properties} bind:itemsType={schema.properties[argName].items} + disabled={disabledArgs.includes(argName)} {editableSchema} /> {/if} diff --git a/frontend/src/lib/components/TestJobLoader.svelte b/frontend/src/lib/components/TestJobLoader.svelte index 4257d5e2ad..9511fe1a0c 100644 --- a/frontend/src/lib/components/TestJobLoader.svelte +++ b/frontend/src/lib/components/TestJobLoader.svelte @@ -1,31 +1,24 @@ + +{#if $worldStore} + +{/if} diff --git a/frontend/src/lib/components/apps/components/DisplayComponent.svelte b/frontend/src/lib/components/apps/components/DisplayComponent.svelte new file mode 100644 index 0000000000..f18c35517c --- /dev/null +++ b/frontend/src/lib/components/apps/components/DisplayComponent.svelte @@ -0,0 +1,28 @@ + + +{#if $worldStore} + +{/if} diff --git a/frontend/src/lib/components/apps/components/RunFormComponent.svelte b/frontend/src/lib/components/apps/components/RunFormComponent.svelte new file mode 100644 index 0000000000..450ab11fa7 --- /dev/null +++ b/frontend/src/lib/components/apps/components/RunFormComponent.svelte @@ -0,0 +1,130 @@ + + + { + if (testJob) { + outputs?.result.set(testJob?.result) + outputs?.loading.set(false) + } + }} + bind:isLoading={testIsLoading} + bind:job={testJob} + bind:this={testJobLoader} +/> + +{#if schemaClone !== undefined} + + +{/if} diff --git a/frontend/src/lib/components/apps/components/TableComponent.svelte b/frontend/src/lib/components/apps/components/TableComponent.svelte new file mode 100644 index 0000000000..5d0d1733c5 --- /dev/null +++ b/frontend/src/lib/components/apps/components/TableComponent.svelte @@ -0,0 +1,109 @@ + + +
+
+
+

{title}

+ {#if description} +

+ {description} +

+ {/if} +
+
+
+
+
+
+ + + + {#each headers as header} + + {/each} + + + + + {#each data as x} + + {#each headers as header} + + {/each} + + + {/each} + +
+ {header} + + Edit +
+ {x[header]} + + + Edit + , Lindsay Walton + +
+
+
+
+
+ + +
diff --git a/frontend/src/lib/components/apps/editor/AppEditor.svelte b/frontend/src/lib/components/apps/editor/AppEditor.svelte new file mode 100644 index 0000000000..fec570050a --- /dev/null +++ b/frontend/src/lib/components/apps/editor/AppEditor.svelte @@ -0,0 +1,88 @@ + + + + + + + + + + + + {#if $selection?.sectionIndex !== undefined && $selection?.componentIndex !== undefined} + { + if ($selection?.sectionIndex !== undefined && $selection?.componentIndex !== undefined) { + $appStore.sections[$selection?.sectionIndex].components.splice( + $selection?.componentIndex, + 1 + ) + $appStore = $appStore + $selection = undefined + } + }} + /> + {/if} + + {#if $selection?.sectionIndex !== undefined} + { + if ($selection?.sectionIndex !== undefined) { + $appStore.sections.splice($selection?.sectionIndex, 1) + $appStore = $appStore + $selection = undefined + } + }} + /> + {/if} + + diff --git a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte new file mode 100644 index 0000000000..073b284731 --- /dev/null +++ b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte @@ -0,0 +1,58 @@ + + +
+ {title} +
+ + + Component editor + + + Width editor + + +
+
+ + +
+
diff --git a/frontend/src/lib/components/apps/editor/ComponentEditor.svelte b/frontend/src/lib/components/apps/editor/ComponentEditor.svelte new file mode 100644 index 0000000000..fdc1c6b29f --- /dev/null +++ b/frontend/src/lib/components/apps/editor/ComponentEditor.svelte @@ -0,0 +1,74 @@ + + +{#if component} +
+ + {component.type} + +
+ {#if $connectingInput.opened && $staticOutputs[component.id]} +
+ {#each $staticOutputs[component.id] as output} + + {/each} +
+ {/if} + + {#if component.type === 'runformcomponent'} + + {:else if component.type === 'displaycomponent'} + + {:else if component.type === 'barchartcomponent'} + + {:else if component.type === 'tablecomponent'} + + {/if} +
+
+{/if} diff --git a/frontend/src/lib/components/apps/editor/ComponentsEditor.svelte b/frontend/src/lib/components/apps/editor/ComponentsEditor.svelte new file mode 100644 index 0000000000..1e4c8cda83 --- /dev/null +++ b/frontend/src/lib/components/apps/editor/ComponentsEditor.svelte @@ -0,0 +1,232 @@ + + +
+
+
+ {#if components.length > 0} + {#each components as component, componentIndex (component.id)} + +
{ + if (!$connectingInput.opened) { + $selection = { componentIndex, sectionIndex } + } + }} + > + +
+ {/each} + {:else} +
+ {#each Array(columns - components.length) as x} +
+
Empty component
+
+ {/each} +
+ {/if} +
+ {#if canDrop} +
+ {#each Array(columns - components.length) as _} +
+
Empty component
+
+ {/each} +
+ {/if} +
+
+ + diff --git a/frontend/src/lib/components/apps/editor/SectionsEditor.svelte b/frontend/src/lib/components/apps/editor/SectionsEditor.svelte new file mode 100644 index 0000000000..b659569924 --- /dev/null +++ b/frontend/src/lib/components/apps/editor/SectionsEditor.svelte @@ -0,0 +1,264 @@ + + +
+
+ {#each sections as section, sectionIndex (section.id)} + {@const selected = $selection?.sectionIndex === sectionIndex} + +
{ + $selection = { sectionIndex, componentIndex: undefined } + }} + > + {#if mode !== 'preview'} + + Section {sectionIndex + 1} + {section.id} + + {/if} + {#if mode === 'dnd'} + + {:else if mode === 'preview'} +
+ {#each section.components as component} +
+ {#if component.type === 'runformcomponent'} + + {:else if component.type === 'displaycomponent'} + + {/if} +
+ {/each} +
+ {:else if mode === 'width'} +
+ + {#each section.components as component} + + + + {/each} + + {#if section.components.length < section.columns} + accu + curr.width, 0)} + minSize={20} + class="gap-2 w-full flex flex-row" + > + {#each Array(section.columns - section.components.length) as _} +
+
Empty
+
+ {/each} +
+ {/if} +
+
+ {/if} +
+ {/each} +
+ {#if mode !== 'preview'} +
+ + Empty section + +
+ +
+
+ {/if} +
+ + diff --git a/frontend/src/lib/components/apps/editor/componentsPanel/ComponentList.svelte b/frontend/src/lib/components/apps/editor/componentsPanel/ComponentList.svelte new file mode 100644 index 0000000000..7ffeffb908 --- /dev/null +++ b/frontend/src/lib/components/apps/editor/componentsPanel/ComponentList.svelte @@ -0,0 +1,105 @@ + + +
+ {#each items as item (item.id)} +
+ +
{displayData[item.type].name}
+
+ {/each} +
diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentInputsSpecsEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentInputsSpecsEditor.svelte new file mode 100644 index 0000000000..0bf4cdf400 --- /dev/null +++ b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentInputsSpecsEditor.svelte @@ -0,0 +1,31 @@ + + +
+ {#each Object.keys(componentInputs) as inputSpecKey} + +
{ + openedProp = inputSpecKey + }} + > + {inputSpecKey} +
+ {#if inputSpecKey === openedProp} +
+ +
+ {/if} + {/each} +
diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte new file mode 100644 index 0000000000..939ddc89ae --- /dev/null +++ b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanel.svelte @@ -0,0 +1,113 @@ + + +{#if component} + {#key component.id} +
+ Component editor + + + {#if component.type === 'runformcomponent'} + + {/if} + + {#if component.type === 'runformcomponent' && component.path === undefined} + Select a script or a flow to continue + { + if (component && component.type === 'runformcomponent') { + component.path = detail.path + component.runType = 'script' + } + }} + /> + { + if (component && component.type === 'runformcomponent') { + component.path = detail.path + component.runType = 'flow' + } + }} + /> + {/if} + + {#if component.type === 'displaycomponent' && component.componentInputs} + + {/if} + + + +
Title
+ +
Description
+