windmill-components 1.383.8 → 1.389.1

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.
Files changed (195) hide show
  1. package/package/assets/app.css +25 -1
  2. package/package/components/ArgInput.svelte +2 -1
  3. package/package/components/ChangeInstanceUsername.svelte +9 -108
  4. package/package/components/ChangeInstanceUsernameInner.svelte +112 -0
  5. package/package/components/ChangeInstanceUsernameInner.svelte.d.ts +21 -0
  6. package/package/components/DiffDrawer.svelte +27 -20
  7. package/package/components/DiffEditor.svelte +13 -1
  8. package/package/components/DisplayResult.svelte +39 -9
  9. package/package/components/DropdownV2.svelte +4 -26
  10. package/package/components/DropdownV2.svelte.d.ts +9 -1
  11. package/package/components/DropdownV2Inner.svelte +42 -0
  12. package/package/components/DropdownV2Inner.svelte.d.ts +40 -0
  13. package/package/components/Editor.svelte +142 -128
  14. package/package/components/Editor.svelte.d.ts +5 -4
  15. package/package/components/EditorBar.svelte +9 -11
  16. package/package/components/EditorSettings.svelte +44 -0
  17. package/package/components/EditorSettings.svelte.d.ts +17 -0
  18. package/package/components/EditorTheme.svelte +1 -1
  19. package/package/components/ErrorOrRecoveryHandler.svelte +27 -20
  20. package/package/components/FlowBuilder.svelte +17 -3
  21. package/package/components/FlowBuilder.svelte.d.ts +3 -0
  22. package/package/components/FlowGraphViewerStep.svelte +1 -1
  23. package/package/components/FlowStatusViewer.svelte +3 -1
  24. package/package/components/FlowStatusViewer.svelte.d.ts +1 -0
  25. package/package/components/FlowStatusViewerInner.svelte +5 -2
  26. package/package/components/FlowViewerInner.svelte +3 -7
  27. package/package/components/FormatOnSave.svelte +12 -29
  28. package/package/components/GraphqlSchemaViewer.svelte +1 -1
  29. package/package/components/GraphqlSchemaViewer.svelte.d.ts +1 -1
  30. package/package/components/HighlightCode.svelte +3 -0
  31. package/package/components/InstanceNameEditor.svelte +64 -0
  32. package/package/components/InstanceNameEditor.svelte.d.ts +23 -0
  33. package/package/components/LightweightArgInput.svelte +6 -11
  34. package/package/components/LogViewer.svelte +37 -29
  35. package/package/components/LogViewer.svelte.d.ts +2 -0
  36. package/package/components/ObjectResourceInput.svelte +1 -1
  37. package/package/components/ObjectResourceInput.svelte.d.ts +1 -0
  38. package/package/components/Path.svelte +3 -3
  39. package/package/components/QueueMetricsDrawer.svelte +6 -218
  40. package/package/components/QueueMetricsDrawer.svelte.d.ts +2 -3
  41. package/package/components/QueueMetricsDrawerInner.svelte +211 -0
  42. package/package/components/QueueMetricsDrawerInner.svelte.d.ts +15 -0
  43. package/package/components/ResourceEditorDrawer.svelte +14 -11
  44. package/package/components/ResourceEditorDrawer.svelte.d.ts +1 -1
  45. package/package/components/ResultJobLoader.svelte.d.ts +1 -1
  46. package/package/components/S3FilePicker.svelte +20 -8
  47. package/package/components/ScheduleEditorInner.svelte +497 -469
  48. package/package/components/ScriptBuilder.svelte +12 -1
  49. package/package/components/ScriptBuilder.svelte.d.ts +3 -0
  50. package/package/components/ScriptEditor.svelte +2 -0
  51. package/package/components/ScriptEditor.svelte.d.ts +2 -1
  52. package/package/components/ServiceLogsInner.svelte +511 -0
  53. package/package/components/ServiceLogsInner.svelte.d.ts +20 -0
  54. package/package/components/SimpleEditor.svelte +75 -37
  55. package/package/components/SimpleEditor.svelte.d.ts +9 -3
  56. package/package/components/Summary.svelte +33 -31
  57. package/package/components/Summary.svelte.d.ts +1 -0
  58. package/package/components/SuperadminSettings.svelte +28 -10
  59. package/package/components/TemplateEditor.svelte +1 -1
  60. package/package/components/TestJobLoader.svelte.d.ts +1 -1
  61. package/package/components/VimMode.svelte +16 -0
  62. package/package/components/VimMode.svelte.d.ts +14 -0
  63. package/package/components/WorkerTagPicker.svelte +4 -1
  64. package/package/components/WorkspaceGroup.svelte +139 -68
  65. package/package/components/WorkspaceGroup.svelte.d.ts +3 -0
  66. package/package/components/apps/components/display/table/AppAggridExplorerTable.svelte +19 -2
  67. package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte +1 -0
  68. package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte.d.ts +2 -1
  69. package/package/components/apps/components/display/table/AppAggridInfiniteTableEe.svelte +2 -0
  70. package/package/components/apps/components/display/table/AppAggridInfiniteTableEe.svelte.d.ts +2 -1
  71. package/package/components/apps/components/display/table/AppAggridTable.svelte +45 -3
  72. package/package/components/apps/components/display/table/AppAggridTable.svelte.d.ts +2 -1
  73. package/package/components/apps/components/display/table/AppAggridTableEe.svelte +2 -0
  74. package/package/components/apps/components/display/table/AppAggridTableEe.svelte.d.ts +2 -1
  75. package/package/components/apps/editor/AppEditor.svelte +239 -92
  76. package/package/components/apps/editor/AppEditorBottomPanel.svelte +22 -0
  77. package/package/components/apps/editor/AppEditorBottomPanel.svelte.d.ts +24 -0
  78. package/package/components/apps/editor/AppEditorHeader.svelte +44 -2
  79. package/package/components/apps/editor/AppEditorHeader.svelte.d.ts +9 -0
  80. package/package/components/apps/editor/AppExportButton.svelte +1 -1
  81. package/package/components/apps/editor/AppPreview.svelte +4 -0
  82. package/package/components/apps/editor/DeploymentHistory.svelte +7 -3
  83. package/package/components/apps/editor/GridEditor.svelte +4 -13
  84. package/package/components/apps/editor/RunnableJobPanel.svelte +25 -58
  85. package/package/components/apps/editor/RunnableJobPanel.svelte.d.ts +10 -1
  86. package/package/components/apps/editor/RunnalbeJobPanelInner.svelte +56 -0
  87. package/package/components/apps/editor/RunnalbeJobPanelInner.svelte.d.ts +18 -0
  88. package/package/components/apps/editor/SubGridEditor.svelte +3 -1
  89. package/package/components/apps/editor/component/Component.svelte +26 -4
  90. package/package/components/apps/editor/component/Component.svelte.d.ts +1 -0
  91. package/package/components/apps/editor/component/components.d.ts +5 -0
  92. package/package/components/apps/editor/componentsPanel/CssProperty.svelte +2 -0
  93. package/package/components/apps/editor/componentsPanel/tailwindUtils.js +267 -1
  94. package/package/components/apps/editor/contextPanel/ContextPanel.svelte +9 -1
  95. package/package/components/apps/editor/contextPanel/ContextPanel.svelte.d.ts +2 -0
  96. package/package/components/apps/editor/inlineScriptsPanel/CacheTtlPopup.svelte +1 -0
  97. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +4 -0
  98. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte +7 -2
  99. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte.d.ts +5 -1
  100. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte +14 -2
  101. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte.d.ts +1 -0
  102. package/package/components/apps/editor/settingsPanel/ComponentPanel.svelte +25 -5
  103. package/package/components/apps/editor/settingsPanel/HideButton.svelte +47 -0
  104. package/package/components/apps/editor/settingsPanel/HideButton.svelte.d.ts +22 -0
  105. package/package/components/apps/editor/settingsPanel/TableActions.svelte +43 -4
  106. package/package/components/apps/editor/settingsPanel/TableActions.svelte.d.ts +2 -1
  107. package/package/components/apps/editor/settingsPanel/inputEditor/JsonEditor.svelte +2 -1
  108. package/package/components/apps/editor/settingsPanel/inputEditor/JsonEditor.svelte.d.ts +1 -0
  109. package/package/components/apps/svelte-grid/Grid.svelte +6 -2
  110. package/package/components/apps/svelte-grid/Grid.svelte.d.ts +1 -0
  111. package/package/components/apps/svelte-grid/MoveResize.svelte +11 -3
  112. package/package/components/apps/svelte-grid/MoveResize.svelte.d.ts +1 -0
  113. package/package/components/apps/svelte-grid/utils/item.d.ts +4 -1
  114. package/package/components/apps/svelte-grid/utils/item.js +11 -4
  115. package/package/components/build_workers.d.ts +1 -1
  116. package/package/components/build_workers.js +16 -122
  117. package/package/components/common/button/Button.svelte.d.ts +2 -2
  118. package/package/components/common/calendarPicker/CalendarPicker.svelte +6 -2
  119. package/package/components/common/calendarPicker/CalendarPicker.svelte.d.ts +2 -0
  120. package/package/components/common/drawer/ConditionalPortal.svelte +2 -1
  121. package/package/components/common/drawer/ConditionalPortal.svelte.d.ts +1 -0
  122. package/package/components/common/languageIcons/LanguageIcon.svelte +5 -2
  123. package/package/components/common/popup/Popup.svelte +2 -1
  124. package/package/components/common/popup/Popup.svelte.d.ts +1 -0
  125. package/package/components/common/table/AppRow.svelte +11 -8
  126. package/package/components/common/table/AppRow.svelte.d.ts +1 -2
  127. package/package/components/common/table/FlowRow.svelte +3 -3
  128. package/package/components/common/table/FlowRow.svelte.d.ts +1 -2
  129. package/package/components/common/table/RawAppRow.svelte +3 -3
  130. package/package/components/common/table/RawAppRow.svelte.d.ts +1 -2
  131. package/package/components/common/table/ScriptRow.svelte +3 -3
  132. package/package/components/common/table/ScriptRow.svelte.d.ts +1 -2
  133. package/package/components/copilot/CodeCompletionStatus.svelte +21 -46
  134. package/package/components/copilot/StepGen.svelte +2 -1
  135. package/package/components/custom_ui.d.ts +4 -1
  136. package/package/components/flows/CreateActionsApp.svelte +11 -8
  137. package/package/components/flows/CreateActionsFlow.svelte +11 -8
  138. package/package/components/flows/FlowEditor.svelte +1 -2
  139. package/package/components/flows/FlowEditor.svelte.d.ts +0 -1
  140. package/package/components/flows/FlowHistory.svelte +6 -3
  141. package/package/components/flows/content/FlowModuleComponent.svelte +1 -0
  142. package/package/components/flows/content/FlowModuleScript.svelte +15 -11
  143. package/package/components/flows/content/FlowSettings.svelte +1 -4
  144. package/package/components/flows/content/ScriptEditorDrawer.svelte +3 -0
  145. package/package/components/flows/header/FlowYamlEditor.svelte +55 -0
  146. package/package/components/flows/header/FlowYamlEditor.svelte.d.ts +17 -0
  147. package/package/components/flows/map/InsertTriggerButton.svelte +1 -1
  148. package/package/components/flows/map/InsertTriggerButton.svelte.d.ts +1 -0
  149. package/package/components/flows/map/VirtualItem.svelte +1 -1
  150. package/package/components/flows/pickers/PickHubScript.svelte +1 -0
  151. package/package/components/flows/types.d.ts +7 -6
  152. package/package/components/flows/utils.d.ts +9 -0
  153. package/package/components/flows/utils.js +21 -0
  154. package/package/components/graph/graphBuilder.js +1 -0
  155. package/package/components/graph/model.d.ts +1 -0
  156. package/package/components/graph/renderers/edges/BaseEdge.svelte +16 -0
  157. package/package/components/graph/renderers/nodes/BranchOneStart.svelte +1 -1
  158. package/package/components/graph/renderers/nodes/NoBranchNode.svelte +5 -1
  159. package/package/components/graph/renderers/nodes/NoBranchNode.svelte.d.ts +1 -0
  160. package/package/components/home/Item.svelte +0 -17
  161. package/package/components/home/deploy_ui.d.ts +2 -0
  162. package/package/components/home/deploy_ui.js +21 -0
  163. package/package/components/icons/RustIcon.svelte +70 -0
  164. package/package/components/icons/RustIcon.svelte.d.ts +25 -0
  165. package/package/components/icons/rust-logo.svg +1 -0
  166. package/package/components/instanceSettings.js +2 -2
  167. package/package/components/monaco_keybindings.d.ts +3 -0
  168. package/package/components/monaco_keybindings.js +9 -0
  169. package/package/components/preview/FlowPreviewStatus.svelte +6 -2
  170. package/package/components/runs/JobLoader.svelte +12 -3
  171. package/package/components/runs/JobLoader.svelte.d.ts +1 -1
  172. package/package/components/runs/ManuelDatePicker.svelte +31 -44
  173. package/package/components/runs/ManuelDatePicker.svelte.d.ts +6 -2
  174. package/package/components/runs/RunsFilter.svelte +4 -1
  175. package/package/components/runs/RunsFilter.svelte.d.ts +1 -0
  176. package/package/components/search/GlobalSearchModal.svelte +36 -25
  177. package/package/components/vscode.js +1 -1
  178. package/package/components/wizards/TableActionsWizard.svelte +84 -0
  179. package/package/components/wizards/TableActionsWizard.svelte.d.ts +22 -0
  180. package/package/editorUtils.js +2 -0
  181. package/package/gen/core/OpenAPI.js +1 -1
  182. package/package/gen/schemas.gen.d.ts +8 -8
  183. package/package/gen/schemas.gen.js +8 -8
  184. package/package/gen/services.gen.d.ts +4 -0
  185. package/package/gen/services.gen.js +16 -0
  186. package/package/gen/types.gen.d.ts +20 -8
  187. package/package/infer.d.ts +1 -1
  188. package/package/infer.js +48 -7
  189. package/package/script_helpers.d.ts +1 -0
  190. package/package/script_helpers.js +39 -1
  191. package/package/scripts.d.ts +1 -1
  192. package/package/scripts.js +12 -4
  193. package/package/stores.d.ts +5 -1
  194. package/package/stores.js +7 -2
  195. package/package.json +18 -9
@@ -244,6 +244,7 @@ async function editScript(stay, deploymentMsg) {
244
244
  }
245
245
  }
246
246
  catch (error) {
247
+ dispatch('deployError', error);
247
248
  sendUserToast(`Error while saving the script: ${error.body || error.message}`, true);
248
249
  }
249
250
  loadingSave = false;
@@ -335,14 +336,18 @@ async function saveDraft(forceSave = false) {
335
336
  : savedScript),
336
337
  draft: structuredClone(script)
337
338
  };
339
+ let savedAtNewPath = false;
338
340
  if (initialPath == '' || (savedScript?.draft_only && script.path !== initialPath)) {
341
+ savedAtNewPath = true;
339
342
  initialPath = script.path;
340
343
  dispatch('saveInitial', script.path);
341
344
  }
345
+ dispatch('saveDraft', { path: script.path, savedAtNewPath, script });
342
346
  sendUserToast('Saved as draft');
343
347
  }
344
348
  catch (error) {
345
349
  sendUserToast(`Error while saving the script as a draft: ${error.body || error.message}`, true);
350
+ dispatch('saveDraftError', error);
346
351
  }
347
352
  loadingDraft = false;
348
353
  }
@@ -949,7 +954,10 @@ function langToLanguage(lang) {
949
954
  <LanguageIcon lang={script.language} height={20} />
950
955
  </button>
951
956
  </div>
952
- <Summary bind:value={script.summary} />
957
+ <Summary
958
+ disabled={customUi?.topBar?.editableSummary == false}
959
+ bind:value={script.summary}
960
+ />
953
961
  </div>
954
962
 
955
963
  <div class="gap-4 flex">
@@ -1098,6 +1106,9 @@ function langToLanguage(lang) {
1098
1106
  on:format={() => {
1099
1107
  saveDraft()
1100
1108
  }}
1109
+ on:saveDraft={() => {
1110
+ saveDraft()
1111
+ }}
1101
1112
  bind:editor
1102
1113
  bind:this={scriptEditor}
1103
1114
  bind:schema={script.schema}
@@ -23,7 +23,10 @@ declare const __propDef: {
23
23
  events: {
24
24
  focus: FocusEvent;
25
25
  deploy: CustomEvent<any>;
26
+ deployError: CustomEvent<any>;
26
27
  saveInitial: CustomEvent<any>;
28
+ saveDraft: CustomEvent<any>;
29
+ saveDraftError: CustomEvent<any>;
27
30
  seeDetails: CustomEvent<any>;
28
31
  } & {
29
32
  [evt: string]: CustomEvent<any>;
@@ -257,6 +257,7 @@ function collabUrl() {
257
257
  on:change={(e) => {
258
258
  inferSchema(e.detail)
259
259
  }}
260
+ on:saveDraft
260
261
  cmdEnterAction={async () => {
261
262
  await inferSchema(code)
262
263
  runTest()
@@ -281,6 +282,7 @@ function collabUrl() {
281
282
  class="h-full"
282
283
  bind:this={diffEditor}
283
284
  automaticLayout
285
+ defaultLang={scriptLangToEditorLang(lang)}
284
286
  {fixedOverflowWidgets}
285
287
  />
286
288
  {/key}
@@ -30,6 +30,7 @@ declare const __propDef: {
30
30
  };
31
31
  events: {
32
32
  createScriptFromInlineScript: CustomEvent<any>;
33
+ saveDraft: CustomEvent<any>;
33
34
  format: CustomEvent<any>;
34
35
  change: CustomEvent<any>;
35
36
  } & {
@@ -41,7 +42,7 @@ export type ScriptEditorProps = typeof __propDef.props;
41
42
  export type ScriptEditorEvents = typeof __propDef.events;
42
43
  export type ScriptEditorSlots = typeof __propDef.slots;
43
44
  export default class ScriptEditor extends SvelteComponent<ScriptEditorProps, ScriptEditorEvents, ScriptEditorSlots> {
44
- get inferSchema(): (code: string, nlang?: "python3" | "deno" | "go" | "bash" | "powershell" | "postgresql" | "mysql" | "bigquery" | "snowflake" | "mssql" | "graphql" | "nativets" | "bun" | "php" | undefined) => Promise<void>;
45
+ get inferSchema(): (code: string, nlang?: "python3" | "deno" | "go" | "bash" | "powershell" | "postgresql" | "mysql" | "bigquery" | "snowflake" | "mssql" | "graphql" | "nativets" | "bun" | "php" | "rust" | undefined) => Promise<void>;
45
46
  get setCollaborationMode(): () => Promise<void>;
46
47
  get disableCollaboration(): () => void;
47
48
  }
@@ -0,0 +1,511 @@
1
+ <script>import { ServiceLogsService } from '../gen';
2
+ import { Pane, Splitpanes } from 'svelte-splitpanes';
3
+ import ManuelDatePicker from './runs/ManuelDatePicker.svelte';
4
+ import CalendarPicker from './common/calendarPicker/CalendarPicker.svelte';
5
+ import LogViewer from './LogViewer.svelte';
6
+ import Toggle from './Toggle.svelte';
7
+ import { sendUserToast } from '../toast';
8
+ import { onDestroy } from 'svelte';
9
+ import { Loader2 } from 'lucide-svelte';
10
+ import { truncateRev } from '../utils';
11
+ let minTs = undefined;
12
+ let maxTs = undefined;
13
+ let minTsManual = undefined;
14
+ let maxTsManual = undefined;
15
+ let max_lines = undefined;
16
+ // let lastSeen: undefined | string = undefined
17
+ let withError = false;
18
+ let autoRefresh = true;
19
+ let loading = false;
20
+ let timeout = undefined;
21
+ let allLogs = undefined;
22
+ let manualPicker = undefined;
23
+ let upTo = undefined;
24
+ let upToIsLatest = true;
25
+ $: minTsManual || maxTsManual || onManualChanges();
26
+ function onManualChanges() {
27
+ getAllLogs(minTsManual ?? maxTs, maxTsManual);
28
+ }
29
+ function getAllLogs(queryMinTs, queryMaxTs) {
30
+ timeout && clearTimeout(timeout);
31
+ loading = true;
32
+ allLogs = allLogs ?? {};
33
+ ServiceLogsService.listLogFiles({ withError, before: queryMaxTs, after: queryMinTs })
34
+ .then((res) => {
35
+ loading = false;
36
+ let minTsN = undefined;
37
+ let maxTsN = undefined;
38
+ if (minTsManual) {
39
+ minTsN = new Date(minTsManual).getTime();
40
+ Object.values(allLogs ?? {}).forEach((mode) => {
41
+ Object.values(mode).forEach((wg) => {
42
+ Object.keys(wg).forEach((key) => {
43
+ wg[key] = wg[key].filter((x) => !minTsManual || x.ts >= new Date(minTsManual).getTime());
44
+ });
45
+ });
46
+ });
47
+ }
48
+ res.reverse().forEach((log) => {
49
+ let ts = new Date(log.log_ts + 'Z').getTime();
50
+ if (minTsN == undefined || ts < minTsN) {
51
+ minTsN = ts;
52
+ }
53
+ if (maxTsN == undefined || ts > maxTsN) {
54
+ maxTsN = ts;
55
+ }
56
+ if (allLogs == undefined) {
57
+ allLogs = {};
58
+ }
59
+ if (!allLogs[log.mode]) {
60
+ allLogs[log.mode] = {};
61
+ }
62
+ const wg = log.worker_group ?? '';
63
+ if (!allLogs[log.mode][wg]) {
64
+ allLogs[log.mode][wg] = {};
65
+ }
66
+ const hn = log.hostname ?? '';
67
+ if (!allLogs[log.mode][wg][hn]) {
68
+ allLogs[log.mode][wg][hn] = [];
69
+ }
70
+ allLogs[log.mode][wg][hn].push({
71
+ ts: ts,
72
+ file_path: log.file_path,
73
+ ok_lines: log.ok_lines ?? 1,
74
+ err_lines: log.err_lines ?? 0,
75
+ json_fmt: log.json_fmt
76
+ });
77
+ if (log.ok_lines != undefined &&
78
+ log.err_lines != undefined &&
79
+ (max_lines == undefined || log.ok_lines + log.err_lines > max_lines)) {
80
+ max_lines = log.ok_lines + log.err_lines;
81
+ }
82
+ });
83
+ Object.values(allLogs ?? {}).forEach((mode) => {
84
+ Object.values(mode).forEach((wg) => {
85
+ Object.keys(wg).forEach((key) => {
86
+ wg[key] = wg[key].filter((x) => !minTsManual || x.ts >= new Date(minTsManual).getTime());
87
+ });
88
+ });
89
+ });
90
+ loading = false;
91
+ if (minTs == undefined) {
92
+ minTs = minTsN ? new Date(minTsN).toISOString() : undefined;
93
+ }
94
+ if (maxTsN) {
95
+ maxTs = new Date(maxTsN).toISOString();
96
+ }
97
+ if (upToIsLatest && selected) {
98
+ upTo = getLatestUpTo(selected);
99
+ }
100
+ if (autoRefresh && !maxTsManual) {
101
+ timeout = setTimeout(() => {
102
+ let minMax = manualPicker?.computeMinMax();
103
+ if (minMax) {
104
+ maxTsManual = minMax?.maxTs;
105
+ minTsManual = minMax?.minTs;
106
+ }
107
+ let maxTsPlus1 = maxTs ? new Date(new Date(maxTs).getTime() + 1000) : undefined;
108
+ getAllLogs(maxTsPlus1?.toISOString(), undefined);
109
+ }, 5000);
110
+ }
111
+ })
112
+ .catch((e) => {
113
+ sendUserToast('Failed to load service logs: ' + e.body, true);
114
+ console.error(e);
115
+ loading = false;
116
+ autoRefresh = false;
117
+ });
118
+ }
119
+ let selected = undefined;
120
+ let logsContent = {};
121
+ export async function getLogFile(hostname, path) {
122
+ if (logsContent[path]) {
123
+ return;
124
+ }
125
+ try {
126
+ const res = await ServiceLogsService.getLogFile({ path: `${hostname}/${path}` });
127
+ logsContent[path] = { content: res };
128
+ }
129
+ catch (e) {
130
+ logsContent[path] = { error: `${e.message}: ${e.body}` };
131
+ }
132
+ }
133
+ getAllLogs(undefined, undefined);
134
+ function getLogs(selected, upTo) {
135
+ if (!selected) {
136
+ return [];
137
+ }
138
+ let logs = allLogs?.[selected[0]]?.[selected[1]]?.[selected[2]];
139
+ if (!logs) {
140
+ return [];
141
+ }
142
+ if (upTo) {
143
+ let upToN = new Date(upTo).getTime();
144
+ let nlogs = logs.filter((x) => x.ts <= upToN);
145
+ logs = nlogs.slice(nlogs.length - 5, undefined);
146
+ getFiles(selected[2], logs.map((x) => x.file_path));
147
+ }
148
+ return logs;
149
+ }
150
+ async function getFiles(hostname, logs) {
151
+ await Promise.all(logs.map((x) => getLogFile(hostname, x)));
152
+ scrollToBottom();
153
+ }
154
+ function getLatestUpTo(selected) {
155
+ if (!selected) {
156
+ return undefined;
157
+ }
158
+ let logs = allLogs?.[selected[0]]?.[selected[1]]?.[selected[2]];
159
+ if (!logs) {
160
+ return undefined;
161
+ }
162
+ return logs[logs.length - 1]?.ts;
163
+ }
164
+ function scrollToBottom() {
165
+ const el = document.querySelector('#logviewer');
166
+ if (el) {
167
+ el.scrollTop = el.scrollHeight;
168
+ }
169
+ }
170
+ onDestroy(() => {
171
+ timeout && clearTimeout(timeout);
172
+ });
173
+ function processLogWithJsonFmt(log, jsonFmt) {
174
+ if (!log) {
175
+ return '';
176
+ }
177
+ if (!jsonFmt) {
178
+ return log;
179
+ }
180
+ try {
181
+ let res = '';
182
+ log.split('\n').forEach((line) => {
183
+ if (line.startsWith('{') && line.endsWith('}')) {
184
+ let obj = JSON.parse(line);
185
+ if (typeof obj == 'object') {
186
+ let nl = '';
187
+ if (obj['timestamp']) {
188
+ nl += obj['timestamp'] + ' ';
189
+ }
190
+ if (obj['level']) {
191
+ let lvl = obj['level'];
192
+ if (lvl == 'ERROR') {
193
+ nl += '\x1b[31mERROR\x1b[0m ';
194
+ }
195
+ else if (lvl == 'INFO') {
196
+ nl += '\x1b[32mINFO\x1b[0m ';
197
+ }
198
+ else {
199
+ nl += obj['level'] + ' ';
200
+ }
201
+ }
202
+ if (obj['message']) {
203
+ nl += obj['message'] + ' ';
204
+ }
205
+ delete obj['timestamp'];
206
+ delete obj['level'];
207
+ delete obj['message'];
208
+ Object.keys(obj).forEach((key) => {
209
+ nl +=
210
+ key +
211
+ '=' +
212
+ (typeof obj[key] == 'object' ? JSON.stringify(obj[key]) : obj[key]) +
213
+ ' ';
214
+ });
215
+ res += nl + '\n';
216
+ }
217
+ }
218
+ });
219
+ return res;
220
+ }
221
+ catch (e) {
222
+ return log;
223
+ }
224
+ }
225
+ </script>
226
+
227
+ <div class="w-full h-[70vh]" on:scroll|preventDefault>
228
+ <Splitpanes>
229
+ <Pane size={40} minSize={20}>
230
+ <div class="p-1">
231
+ <div
232
+ class="flex flex-col lg:flex-row gap-y-1 justify-between w-full relative pb-4 gap-x-0.5"
233
+ id="service-logs-date-pickers"
234
+ >
235
+ <div class="flex relative">
236
+ <input
237
+ type="text"
238
+ value={minTsManual
239
+ ? new Date(minTsManual).toLocaleTimeString([], {
240
+ day: '2-digit',
241
+ month: '2-digit',
242
+ hour: '2-digit',
243
+ minute: '2-digit'
244
+ })
245
+ : 'min datetime'}
246
+ disabled
247
+ />
248
+ <CalendarPicker label="min datetime" date={minTs} />
249
+ </div>
250
+ <ManuelDatePicker
251
+ bind:minTs={minTsManual}
252
+ bind:maxTs={maxTsManual}
253
+ bind:this={manualPicker}
254
+ {loading}
255
+ on:loadJobs={() => {
256
+ minTs = undefined
257
+ maxTs = undefined
258
+ allLogs = undefined
259
+ getAllLogs(minTsManual, maxTsManual)
260
+ }}
261
+ serviceLogsChoices
262
+ loadText="Last 1000 logfiles"
263
+ />
264
+ <div class="flex relative">
265
+ <input
266
+ type="text"
267
+ value={maxTsManual
268
+ ? new Date(maxTsManual).toLocaleTimeString([], {
269
+ day: '2-digit',
270
+ month: '2-digit',
271
+ hour: '2-digit',
272
+ minute: '2-digit'
273
+ })
274
+ : 'max datetime'}
275
+ disabled
276
+ />
277
+ <CalendarPicker label="max datetime" date={maxTs} />
278
+ </div>
279
+ </div>
280
+ <div class="flex w-full flex-row-reverse pb-4 -mt-2 gap-2"
281
+ ><Toggle
282
+ size="xs"
283
+ bind:checked={withError}
284
+ options={{ right: 'errors > 0' }}
285
+ on:change={() => {
286
+ allLogs = undefined
287
+ getAllLogs(minTs, maxTs)
288
+ }}
289
+ />
290
+ <Toggle
291
+ size="xs"
292
+ bind:checked={autoRefresh}
293
+ on:change={(e) => {
294
+ if (e.detail) {
295
+ getAllLogs(maxTs, undefined)
296
+ } else {
297
+ timeout && clearTimeout(timeout)
298
+ }
299
+ }}
300
+ options={{ right: 'auto-refresh' }}
301
+ /></div
302
+ >
303
+ {#if allLogs == undefined}
304
+ <div class="text-center pb-2"><Loader2 class="animate-spin" /></div>
305
+ {:else if Object.keys(allLogs).length == 0}
306
+ <div class="flex justify-center items-center h-full">No logs</div>
307
+ {:else if minTs && maxTs}
308
+ {@const minTsN = new Date(minTs).getTime()}
309
+ {@const maxTsN = new Date(maxTs).getTime()}
310
+ {@const diff = maxTsN - minTsN}
311
+ <div class="flex w-full text-2xs text-tertiary pb-6">
312
+ <div style="width: 60px;" />
313
+
314
+ <div class="flex justify-between w-full"
315
+ ><div
316
+ >{new Date(minTs).toLocaleTimeString([], {
317
+ day: '2-digit',
318
+ month: '2-digit',
319
+ hour: '2-digit',
320
+ minute: '2-digit'
321
+ })}</div
322
+ ><div
323
+ >{new Date(maxTs).toLocaleTimeString([], {
324
+ day: '2-digit',
325
+ month: '2-digit',
326
+ hour: '2-digit',
327
+ minute: '2-digit'
328
+ })}</div
329
+ ></div
330
+ >
331
+ </div>
332
+ {#each Object.entries(allLogs) as [mode, o1]}
333
+ <div class="w-full pb-8">
334
+ <h2 class="pb-2 text-2xl">{mode}s</h2>
335
+ {#each Object.entries(o1) as [wg, o2]}
336
+ <div class="w-full px-1">
337
+ {#if wg && wg != ''}
338
+ <h4 class="pt-4">{wg}</h4>
339
+ {/if}
340
+ <div class="divide-y flex flex-col">
341
+ {#each Object.entries(o2) as [hn, files]}
342
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
343
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
344
+ <div
345
+ class="w-full flex items-baseline rounded px-1 hover:bg-surface-hover cursor-pointer {selected &&
346
+ selected[0] == mode &&
347
+ selected[1] == wg &&
348
+ selected[2] == hn
349
+ ? 'bg-surface-secondary'
350
+ : ''}"
351
+ on:click={() => {
352
+ selected = [mode, wg, hn]
353
+ upToIsLatest = true
354
+ upTo = getLatestUpTo(selected)
355
+ scrollToBottom()
356
+ }}
357
+ >
358
+ <div
359
+ class="text-sm pt-2 pl-0.5 whitespace-nowrap"
360
+ title={hn}
361
+ style="width: 90px;">{truncateRev(hn, 8)}</div
362
+ >
363
+ <div class="relative grow h-8 mr-2">
364
+ {#each files as file}
365
+ {@const okHeight = 100.0 * ((file.ok_lines * 1.0) / (max_lines ?? 1))}
366
+ {@const errHeight = 100.0 * ((file.err_lines * 1.0) / (max_lines ?? 1))}
367
+ <div
368
+ class=" w-2 bg-red-400 absolute"
369
+ style="left: {((file.ts - minTsN) / diff) *
370
+ 100}%; height: {errHeight}%; bottom: {okHeight}%;"
371
+ />
372
+ <div
373
+ class="w-2 bg-surface-secondary-inverse absolute bottom-0"
374
+ style="left: {((file.ts - minTsN) / diff) *
375
+ 100}%; height: {okHeight}%"
376
+ />
377
+ {/each}
378
+ </div>
379
+ </div>
380
+ {/each}
381
+ </div>
382
+ </div>
383
+ {/each}
384
+ </div>
385
+ {/each}
386
+ {/if}
387
+ </div>
388
+ </Pane>
389
+ <Pane size={60} minSize={20}
390
+ ><div class="relative h-full flex flex-col gap-1"
391
+ ><div class="w-full bg-surface-primary-inverse text-tertiary text-xs text-center"
392
+ >1 min delay: logs are compacted before being available</div
393
+ >
394
+ {#if selected}
395
+ <div class="grow overflow-auto" id="logviewer">
396
+ {#each getLogs(selected, upTo) as file}
397
+ <div
398
+ style="min-height: {logsContent[file.file_path]
399
+ ? 10
400
+ : (file.ok_lines + file.err_lines) / 20}px;"
401
+ >
402
+ <div class="bg-surface-primary-inverse text-sm font-semibold px-1"
403
+ >{new Date(file.ts).toLocaleTimeString([], {
404
+ day: '2-digit',
405
+ month: '2-digit',
406
+ hour: '2-digit',
407
+ minute: '2-digit'
408
+ })}</div
409
+ >
410
+ {#if logsContent[file.file_path] == undefined}
411
+ <div
412
+ class="animate-skeleton dark:bg-frost-900/50 [animation-delay:1000ms] h-full w-full"
413
+ />
414
+ {:else if logsContent[file.file_path]}
415
+ {#if logsContent[file.file_path].error}
416
+ {#if logsContent[file.file_path].error?.startsWith('Not Found')}
417
+ <div class="text-xs pb-4 pt-2 text-secondary"
418
+ >Log file is missing. Log files require a shared log volume to be mounted
419
+ across servers and workers or to use the EE S3/object storage integration
420
+ for logs. To avoid mounting a shared volume, set the EE object store logs in
421
+ the instance settings</div
422
+ >
423
+ {:else}
424
+ <div class="text-xs text-red-400 pb-4"
425
+ >{logsContent[file.file_path].error}</div
426
+ >
427
+ {/if}
428
+ {:else if logsContent[file.file_path].content}
429
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
430
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
431
+ <div on:click|preventDefault
432
+ ><LogViewer
433
+ noAutoScroll
434
+ noMaxH
435
+ isLoading={false}
436
+ tag={undefined}
437
+ content={processLogWithJsonFmt(
438
+ logsContent[file.file_path].content,
439
+ file.json_fmt
440
+ )}
441
+ /></div
442
+ >
443
+ {:else}
444
+ <div>No logs</div>
445
+ {/if}
446
+ {/if}
447
+ </div>
448
+ {/each}
449
+ </div>
450
+ <div class="flex w-full items-center gap-4">
451
+ <div class="text-tertiary px-1 text-2xs">Last 5 log files up to:</div>
452
+ <div class="flex grow text-xs justify-center px-2 items-center gap-2">
453
+ {#if upTo}
454
+ <button
455
+ on:click={() => {
456
+ if (upTo) {
457
+ upToIsLatest = false
458
+ upTo = new Date(new Date(upTo).getTime() - 5 * 60 * 1000).toISOString()
459
+ }
460
+ }}>{'<'} 5m</button
461
+ >
462
+ {:else}
463
+ <div />
464
+ {/if}
465
+
466
+ <div class="flex gap-1 relative items-center"
467
+ ><div class="flex gap-1 relative">
468
+ <input
469
+ type="text"
470
+ value={upTo
471
+ ? new Date(upTo).toLocaleTimeString([], {
472
+ day: '2-digit',
473
+ month: '2-digit',
474
+ hour: '2-digit',
475
+ minute: '2-digit'
476
+ })
477
+ : ''}
478
+ disabled
479
+ /><CalendarPicker bind:date={upTo} label="Logs up to" /></div
480
+ ></div
481
+ >
482
+ {#if upTo}
483
+ <button
484
+ on:click={() => {
485
+ if (upTo) {
486
+ upToIsLatest = false
487
+ upTo = new Date(new Date(upTo).getTime() + 5 * 60 * 1000).toISOString()
488
+ }
489
+ }}>5m {'>'}</button
490
+ >
491
+ {:else}
492
+ <div />
493
+ {/if}
494
+ </div>
495
+ <div>
496
+ <button
497
+ class="text-xs"
498
+ on:click={() => {
499
+ upTo = new Date().toISOString()
500
+ upToIsLatest = true
501
+ }}>now</button
502
+ >
503
+ </div>
504
+ </div>
505
+ {:else}
506
+ <div class="flex justify-center items-center pt-8">Select a host to see its logs</div>
507
+ {/if}</div
508
+ ></Pane
509
+ >
510
+ </Splitpanes>
511
+ </div>
@@ -0,0 +1,20 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ getLogFile?: ((hostname: string, path: string) => Promise<void>) | undefined;
5
+ };
6
+ events: {
7
+ scroll: Event;
8
+ click: MouseEvent;
9
+ } & {
10
+ [evt: string]: CustomEvent<any>;
11
+ };
12
+ slots: {};
13
+ };
14
+ export type ServiceLogsInnerProps = typeof __propDef.props;
15
+ export type ServiceLogsInnerEvents = typeof __propDef.events;
16
+ export type ServiceLogsInnerSlots = typeof __propDef.slots;
17
+ export default class ServiceLogsInner extends SvelteComponent<ServiceLogsInnerProps, ServiceLogsInnerEvents, ServiceLogsInnerSlots> {
18
+ get getLogFile(): (hostname: string, path: string) => Promise<void>;
19
+ }
20
+ export {};