windmill-components 1.28.1 → 1.28.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,15 +4,12 @@ import TableCustom from './TableCustom.svelte';
4
4
  import { truncate } from '../utils';
5
5
  export let result;
6
6
  let resultKind = inferResultKind(result);
7
- function isArray(obj) {
8
- return Object.prototype.toString.call(obj) === '[object Array]';
9
- }
10
7
  function isRectangularArray(obj) {
11
- if (!isArray(obj) || obj.length == 0) {
8
+ if (!Array.isArray(obj) || obj.length == 0) {
12
9
  return false;
13
10
  }
14
11
  if (!Object.values(obj)
15
- .map(isArray)
12
+ .map(Array.isArray)
16
13
  .reduce((a, b) => a && b)) {
17
14
  return false;
18
15
  }
@@ -28,10 +25,10 @@ function inferResultKind(result) {
28
25
  if (result) {
29
26
  try {
30
27
  let keys = Object.keys(result);
31
- if (keys.length == 1 && isRectangularArray(result[keys[0]])) {
28
+ if (isRectangularArray(result)) {
32
29
  return 'table-row';
33
30
  }
34
- else if (keys.map((k) => isArray(result[k])).reduce((a, b) => a && b)) {
31
+ else if (keys.map((k) => Array.isArray(result[k])).reduce((a, b) => a && b)) {
35
32
  return 'table-col';
36
33
  }
37
34
  else if (keys.length == 1 && keys[0] == 'png') {
@@ -51,7 +48,7 @@ function inferResultKind(result) {
51
48
  </script>
52
49
 
53
50
  {#if result}
54
- {#if Object.keys(result).length > 0}<div>
51
+ {#if typeof result == 'object' && Object.keys(result).length > 0}<div>
55
52
  The result keys are: <b>{Object.keys(result).join(', ')}</b>
56
53
  </div>
57
54
  {/if}
@@ -102,6 +102,9 @@ async function saveFlow() {
102
102
  goto(`/flows/get/${$flowStore.path}`);
103
103
  }
104
104
  async function changeStep(step) {
105
+ if (step === 2 && previewOpen) {
106
+ previewOpen = false;
107
+ }
105
108
  goto(`?step=${step}`);
106
109
  }
107
110
  flowStore.subscribe((flow) => {
@@ -120,7 +123,7 @@ onDestroy(() => {
120
123
  </script>
121
124
 
122
125
  <div class="flex flex-row w-full h-full justify-between">
123
- <div class="flex flex-col max-w-screen-md mb-96 m-auto">
126
+ <div class={`flex flex-col mb-96 m-auto w-1/2`}>
124
127
  <!-- Nav between steps-->
125
128
  <div class="justify-between flex flex-row w-full my-4">
126
129
  <Breadcrumb>
@@ -186,19 +189,6 @@ onDestroy(() => {
186
189
 
187
190
  <Icon data={faPlay} class="ml-2" />
188
191
  </Button>
189
- <div class={`relative h-screen w-1/3 ${previewOpen ? '' : 'hidden'}`}>
190
- <div class="absolute top-0 h-full">
191
- <div class="fixed border-l-2 right-0 h-screen w-1/3">
192
- <FlowPreviewContent
193
- bind:args={scheduleArgs}
194
- on:close={() => (previewOpen = !previewOpen)}
195
- on:change={(e) => {
196
- previewResults.set(jobsToResults(e.detail))
197
- }}
198
- />
199
- </div>
200
- </div>
201
- </div>
202
192
  {:else if step === 2}
203
193
  <ScriptSchema
204
194
  synchronizedHeader={false}
@@ -211,4 +201,20 @@ onDestroy(() => {
211
201
  <p>Loading</p>
212
202
  {/if}
213
203
  </div>
204
+
205
+ <div class={`relative h-screen w-1/3 ${previewOpen ? '' : 'hidden'}`}>
206
+ <div class="absolute top-0 h-full">
207
+ {#if $flowStore && step === 1}
208
+ <div class="fixed border-l-2 right-0 h-screen w-1/3">
209
+ <FlowPreviewContent
210
+ bind:args={scheduleArgs}
211
+ on:close={() => (previewOpen = !previewOpen)}
212
+ on:change={(e) => {
213
+ previewResults.set(jobsToResults(e.detail))
214
+ }}
215
+ />
216
+ </div>
217
+ {/if}
218
+ </div>
219
+ </div>
214
220
  </div>
@@ -7,6 +7,7 @@ import { slide } from 'svelte/transition';
7
7
  import Tabs from './Tabs.svelte';
8
8
  import SchemaViewer from './SchemaViewer.svelte';
9
9
  import FieldHeader from './FieldHeader.svelte';
10
+ import InputTransformsViewer from './InputTransformsViewer.svelte';
10
11
  export let flow;
11
12
  let flowFiltered = {
12
13
  summary: flow.summary,
@@ -104,9 +105,10 @@ function toAny(x) {
104
105
  }}
105
106
  class="mb-2 underline text-black"
106
107
  >
107
- View code {open[i] ? '(-)' : '(+)'}</button
108
+ View code and inputs {open[i] ? '(-)' : '(+)'}</button
108
109
  >
109
110
  {#if open[i]}
111
+ <InputTransformsViewer inputTransforms={mod?.input_transform} />
110
112
  <div class="w-full h-full">
111
113
  <iframe
112
114
  style="height: 400px;"
@@ -131,6 +133,8 @@ function toAny(x) {
131
133
 
132
134
  {#if open[i]}
133
135
  <div transition:slide class="border border-black p-2 bg-gray-50 w-full">
136
+ <InputTransformsViewer inputTransforms={mod?.input_transform} />
137
+
134
138
  <Highlight
135
139
  language={mod?.value?.language == 'deno' ? typescript : python}
136
140
  code={mod?.value?.content}
@@ -0,0 +1,19 @@
1
+ <script>import { Highlight } from 'svelte-highlight';
2
+ import ObjectViewer from './propertyPicker/ObjectViewer.svelte';
3
+ import typescript from 'svelte-highlight/languages/typescript';
4
+ export let inputTransforms;
5
+ </script>
6
+
7
+ <ul class="mb-1">
8
+ {#each Object.entries(inputTransforms) as [key, val]}
9
+ <li>
10
+ <span class="font-black text-gray-700">{key}</span>: {#if val.type == 'static'}<ObjectViewer
11
+ json={val.value}
12
+ />{:else}
13
+ <span class="inline-block inline-highlight">
14
+ <Highlight offsetTop={0} language={typescript} code={val.expr} />
15
+ </span>
16
+ {/if}
17
+ </li>
18
+ {/each}
19
+ </ul>
@@ -0,0 +1,17 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { InputTransform } from '../gen';
3
+ declare const __propDef: {
4
+ props: {
5
+ inputTransforms: Record<string, InputTransform>;
6
+ };
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export declare type InputTransformsViewerProps = typeof __propDef.props;
13
+ export declare type InputTransformsViewerEvents = typeof __propDef.events;
14
+ export declare type InputTransformsViewerSlots = typeof __propDef.slots;
15
+ export default class InputTransformsViewer extends SvelteComponentTyped<InputTransformsViewerProps, InputTransformsViewerEvents, InputTransformsViewerSlots> {
16
+ }
17
+ export {};
@@ -13,6 +13,9 @@ export function flowToMode(flow, mode) {
13
13
  if (inp.type == 'javascript') {
14
14
  //@ts-ignore
15
15
  inp.value = undefined;
16
+ inp.expr = inp.expr.split('\n')
17
+ .filter((x) => x != '' && !x.startsWith(`import { previous_result, flow_input, step, variable, resource, params } from 'windmill@`))
18
+ .join('\n');
16
19
  }
17
20
  else {
18
21
  //@ts-ignore
@@ -24,7 +27,7 @@ export function flowToMode(flow, mode) {
24
27
  const triggerModule = newFlow.value.modules[0];
25
28
  const oldModules = newFlow.value.modules.slice(1);
26
29
  if (triggerModule) {
27
- triggerModule.stop_after_if_expr = 'result.res1.length == 0';
30
+ triggerModule.stop_after_if_expr = 'result.length == 0';
28
31
  triggerModule.skip_if_stopped = true;
29
32
  }
30
33
  newFlow.value.modules = newFlow.value.modules.slice(0, 1);
@@ -33,7 +36,7 @@ export function flowToMode(flow, mode) {
33
36
  input_transform: oldModules[0].input_transform,
34
37
  value: {
35
38
  type: 'forloopflow',
36
- iterator: { type: 'javascript', expr: 'result.res1' },
39
+ iterator: { type: 'javascript', expr: 'result' },
37
40
  value: {
38
41
  modules: oldModules
39
42
  },
@@ -192,13 +195,17 @@ export async function runFlowPreview(args, flow) {
192
195
  });
193
196
  }
194
197
  function computeFlowInputPull(previewResult, flowInputAsObject) {
195
- const iteratorValues = (previewResult?.res1 && Array.isArray(previewResult.res1)) ?
198
+ const iteratorValues = (previewResult && Array.isArray(previewResult)) ?
196
199
  {
197
- _value: previewResult.res1[0],
198
- _index: `The current index of the iteration as a number (here from 0 to ${previewResult.res1.length - 1})`
200
+ iter: {
201
+ value: previewResult[0],
202
+ index: `The current index of the iteration as a number (here from 0 to ${previewResult.length - 1})`
203
+ }
199
204
  } : {
200
- _value: 'The current value of the iteration as an object',
201
- _index: 'The current index of the iteration as a number'
205
+ iter: {
206
+ value: 'The current value of the iteration as an object',
207
+ index: 'The current index of the iteration as a number'
208
+ }
202
209
  };
203
210
  return Object.assign(Object.assign(flowInputAsObject, previewResult), iteratorValues);
204
211
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "windmill-components",
3
- "version": "1.28.1",
3
+ "version": "1.28.2",
4
4
  "devDependencies": {
5
5
  "@playwright/test": "^1.24.2",
6
6
  "@sveltejs/adapter-static": "^1.0.0-next.37",
@@ -82,6 +82,7 @@
82
82
  "./components/GroupModal.svelte": "./components/GroupModal.svelte",
83
83
  "./components/IconedResourceType.svelte": "./components/IconedResourceType.svelte",
84
84
  "./components/InputTransformForm.svelte": "./components/InputTransformForm.svelte",
85
+ "./components/InputTransformsViewer.svelte": "./components/InputTransformsViewer.svelte",
85
86
  "./components/InviteGlobalUser.svelte": "./components/InviteGlobalUser.svelte",
86
87
  "./components/InviteUser.svelte": "./components/InviteUser.svelte",
87
88
  "./components/ItemPicker.svelte": "./components/ItemPicker.svelte",
@@ -273,4 +274,4 @@
273
274
  "./user": "./user.js",
274
275
  "./utils": "./utils.js"
275
276
  }
276
- }
277
+ }
@@ -1,4 +1,4 @@
1
- export declare const PYTHON_INIT_CODE = "import os\nimport wmill\nfrom datetime import datetime\n# Our webeditor includes a syntax, type checker through a language server running pyright\n# and the autoformatter Black in our servers. Use Cmd/Ctrl + S to autoformat the code.\n# Beware that the code is only saved when you click Save and not across reload.\n# You can however navigate to any steps safely.\n\"\"\"\nThe client is used to interact with windmill itself through its standard API.\nOne can explore the methods available through autocompletion of `client.XXX`.\nOnly the most common methods are included for ease of use. Request more as\nfeedback if you feel you are missing important ones.\n\"\"\"\ndef main(name: str = \"Nicolas Bourbaki\",\n age: int = 42,\n obj: dict = {\"even\": \"dicts\"},\n l: list = [\"or\", \"lists!\"],\n file_: bytes = bytes(0),\n dtime: datetime = datetime.now()):\n \"\"\"A main function is required for the script to be able to accept arguments.\n Types are recommended.\"\"\"\n print(f\"Hello World and a warm welcome especially to {name}\")\n print(\"and its acolytes..\", age, obj, l, len(file_), dtime)\n # retrieve variables, including secrets by querying the windmill platform.\n # secret fetching is audited by windmill.\n secret = wmill.get_variable(\"g/all/pretty_secret\")\n print(f\"The env variable at `g/all/pretty_secret`: {secret}\")\n # interact with the windmill platform to get the version\n version = wmill.get_version()\n # fetch reserved variables as environment variables\n user = os.environ.get(\"WM_USERNAME\")\n # the return value is then parsed and can be retrieved by other scripts conveniently\n return {\"version\": version, \"splitted\": name.split(), \"user\": user}\n";
1
+ export declare const PYTHON_INIT_CODE = "import os\nimport wmill\nfrom datetime import datetime\n\n\"\"\"\nUse Cmd/Ctrl + S to autoformat the code.\nThe client is used to interact with windmill itself through its standard API.\nOne can explore the methods available through autocompletion of `wmill.XXX`.\n\"\"\"\n\ndef main(name: str = \"Nicolas Bourbaki\",\n age: int = 42,\n obj: dict = {\"even\": \"dicts\"},\n l: list = [\"or\", \"lists!\"],\n file_: bytes = bytes(0),\n dtime: datetime = datetime.now()):\n \"\"\"A main function is required for the script to be able to accept arguments.\n Types are recommended.\"\"\"\n print(f\"Hello World and a warm welcome especially to {name}\")\n print(\"and its acolytes..\", age, obj, l, len(file_), dtime)\n # retrieve variables, including secrets by querying the windmill platform.\n # secret fetching is audited by windmill.\n secret = wmill.get_variable(\"g/all/pretty_secret\")\n print(f\"The env variable at `g/all/pretty_secret`: {secret}\")\n # interact with the windmill platform to get the version\n version = wmill.get_version()\n # fetch reserved variables as environment variables\n user = os.environ.get(\"WM_USERNAME\")\n # the return value is then parsed and can be retrieved by other scripts conveniently\n return {\"version\": version, \"splitted\": name.split(), \"user\": user}\n";
2
2
  export declare const DENO_INIT_CODE: string;
3
3
  export declare const DENO_INIT_CODE_TRIGGER: string;
4
4
  export declare function initialCode(language: 'deno' | 'python3', is_trigger: boolean): string;
package/script_helpers.js CHANGED
@@ -1,16 +1,13 @@
1
1
  export const PYTHON_INIT_CODE = `import os
2
2
  import wmill
3
3
  from datetime import datetime
4
- # Our webeditor includes a syntax, type checker through a language server running pyright
5
- # and the autoformatter Black in our servers. Use Cmd/Ctrl + S to autoformat the code.
6
- # Beware that the code is only saved when you click Save and not across reload.
7
- # You can however navigate to any steps safely.
4
+
8
5
  """
6
+ Use Cmd/Ctrl + S to autoformat the code.
9
7
  The client is used to interact with windmill itself through its standard API.
10
- One can explore the methods available through autocompletion of \`client.XXX\`.
11
- Only the most common methods are included for ease of use. Request more as
12
- feedback if you feel you are missing important ones.
8
+ One can explore the methods available through autocompletion of \`wmill.XXX\`.
13
9
  """
10
+
14
11
  def main(name: str = "Nicolas Bourbaki",
15
12
  age: int = 42,
16
13
  obj: dict = {"even": "dicts"},