windmill-components 1.383.9 → 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.
- package/package/assets/app.css +25 -1
- package/package/components/ArgInput.svelte +2 -1
- package/package/components/ChangeInstanceUsername.svelte +9 -108
- package/package/components/ChangeInstanceUsernameInner.svelte +112 -0
- package/package/components/ChangeInstanceUsernameInner.svelte.d.ts +21 -0
- package/package/components/DiffDrawer.svelte +27 -20
- package/package/components/DiffEditor.svelte +5 -1
- package/package/components/DisplayResult.svelte +39 -9
- package/package/components/DropdownV2.svelte +4 -26
- package/package/components/DropdownV2.svelte.d.ts +9 -1
- package/package/components/DropdownV2Inner.svelte +42 -0
- package/package/components/DropdownV2Inner.svelte.d.ts +40 -0
- package/package/components/Editor.svelte +24 -4
- package/package/components/Editor.svelte.d.ts +5 -4
- package/package/components/EditorBar.svelte +9 -11
- package/package/components/EditorSettings.svelte +44 -0
- package/package/components/EditorSettings.svelte.d.ts +17 -0
- package/package/components/EditorTheme.svelte +1 -1
- package/package/components/ErrorOrRecoveryHandler.svelte +27 -20
- package/package/components/FlowBuilder.svelte +17 -3
- package/package/components/FlowBuilder.svelte.d.ts +3 -0
- package/package/components/FlowGraphViewerStep.svelte +1 -1
- package/package/components/FlowStatusViewer.svelte +3 -1
- package/package/components/FlowStatusViewer.svelte.d.ts +1 -0
- package/package/components/FlowStatusViewerInner.svelte +5 -2
- package/package/components/FlowViewerInner.svelte +3 -7
- package/package/components/FormatOnSave.svelte +12 -29
- package/package/components/GraphqlSchemaViewer.svelte +1 -1
- package/package/components/GraphqlSchemaViewer.svelte.d.ts +1 -1
- package/package/components/HighlightCode.svelte +3 -0
- package/package/components/InstanceNameEditor.svelte +64 -0
- package/package/components/InstanceNameEditor.svelte.d.ts +23 -0
- package/package/components/LightweightArgInput.svelte +6 -11
- package/package/components/LogViewer.svelte +37 -29
- package/package/components/LogViewer.svelte.d.ts +2 -0
- package/package/components/ObjectResourceInput.svelte +1 -1
- package/package/components/ObjectResourceInput.svelte.d.ts +1 -0
- package/package/components/Path.svelte +3 -3
- package/package/components/QueueMetricsDrawer.svelte +6 -218
- package/package/components/QueueMetricsDrawer.svelte.d.ts +2 -3
- package/package/components/QueueMetricsDrawerInner.svelte +211 -0
- package/package/components/QueueMetricsDrawerInner.svelte.d.ts +15 -0
- package/package/components/ResourceEditorDrawer.svelte +14 -11
- package/package/components/ResourceEditorDrawer.svelte.d.ts +1 -1
- package/package/components/ResultJobLoader.svelte.d.ts +1 -1
- package/package/components/S3FilePicker.svelte +20 -8
- package/package/components/ScheduleEditorInner.svelte +497 -469
- package/package/components/ScriptBuilder.svelte +12 -1
- package/package/components/ScriptBuilder.svelte.d.ts +3 -0
- package/package/components/ScriptEditor.svelte +1 -0
- package/package/components/ScriptEditor.svelte.d.ts +2 -1
- package/package/components/ServiceLogsInner.svelte +511 -0
- package/package/components/ServiceLogsInner.svelte.d.ts +20 -0
- package/package/components/SimpleEditor.svelte +27 -2
- package/package/components/SimpleEditor.svelte.d.ts +5 -3
- package/package/components/Summary.svelte +33 -31
- package/package/components/Summary.svelte.d.ts +1 -0
- package/package/components/SuperadminSettings.svelte +28 -10
- package/package/components/TemplateEditor.svelte +1 -1
- package/package/components/TestJobLoader.svelte.d.ts +1 -1
- package/package/components/VimMode.svelte +16 -0
- package/package/components/VimMode.svelte.d.ts +14 -0
- package/package/components/WorkerTagPicker.svelte +4 -1
- package/package/components/WorkspaceGroup.svelte +139 -68
- package/package/components/WorkspaceGroup.svelte.d.ts +3 -0
- package/package/components/apps/components/display/table/AppAggridExplorerTable.svelte +19 -2
- package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte +1 -0
- package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte.d.ts +2 -1
- package/package/components/apps/components/display/table/AppAggridInfiniteTableEe.svelte +2 -0
- package/package/components/apps/components/display/table/AppAggridInfiniteTableEe.svelte.d.ts +2 -1
- package/package/components/apps/components/display/table/AppAggridTable.svelte +45 -3
- package/package/components/apps/components/display/table/AppAggridTable.svelte.d.ts +2 -1
- package/package/components/apps/components/display/table/AppAggridTableEe.svelte +2 -0
- package/package/components/apps/components/display/table/AppAggridTableEe.svelte.d.ts +2 -1
- package/package/components/apps/editor/AppEditor.svelte +239 -92
- package/package/components/apps/editor/AppEditorBottomPanel.svelte +22 -0
- package/package/components/apps/editor/AppEditorBottomPanel.svelte.d.ts +24 -0
- package/package/components/apps/editor/AppEditorHeader.svelte +44 -2
- package/package/components/apps/editor/AppEditorHeader.svelte.d.ts +9 -0
- package/package/components/apps/editor/AppExportButton.svelte +1 -1
- package/package/components/apps/editor/AppPreview.svelte +4 -0
- package/package/components/apps/editor/DeploymentHistory.svelte +7 -3
- package/package/components/apps/editor/GridEditor.svelte +4 -13
- package/package/components/apps/editor/RunnableJobPanel.svelte +25 -58
- package/package/components/apps/editor/RunnableJobPanel.svelte.d.ts +10 -1
- package/package/components/apps/editor/RunnalbeJobPanelInner.svelte +56 -0
- package/package/components/apps/editor/RunnalbeJobPanelInner.svelte.d.ts +18 -0
- package/package/components/apps/editor/SubGridEditor.svelte +3 -1
- package/package/components/apps/editor/component/Component.svelte +26 -4
- package/package/components/apps/editor/component/Component.svelte.d.ts +1 -0
- package/package/components/apps/editor/component/components.d.ts +5 -0
- package/package/components/apps/editor/componentsPanel/CssProperty.svelte +2 -0
- package/package/components/apps/editor/componentsPanel/tailwindUtils.js +267 -1
- package/package/components/apps/editor/contextPanel/ContextPanel.svelte +9 -1
- package/package/components/apps/editor/contextPanel/ContextPanel.svelte.d.ts +2 -0
- package/package/components/apps/editor/inlineScriptsPanel/CacheTtlPopup.svelte +1 -0
- package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +3 -0
- package/package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte +7 -2
- package/package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte.d.ts +5 -1
- package/package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte +14 -2
- package/package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte.d.ts +1 -0
- package/package/components/apps/editor/settingsPanel/ComponentPanel.svelte +25 -5
- package/package/components/apps/editor/settingsPanel/HideButton.svelte +47 -0
- package/package/components/apps/editor/settingsPanel/HideButton.svelte.d.ts +22 -0
- package/package/components/apps/editor/settingsPanel/TableActions.svelte +43 -4
- package/package/components/apps/editor/settingsPanel/TableActions.svelte.d.ts +2 -1
- package/package/components/apps/svelte-grid/Grid.svelte +6 -2
- package/package/components/apps/svelte-grid/Grid.svelte.d.ts +1 -0
- package/package/components/apps/svelte-grid/MoveResize.svelte +11 -3
- package/package/components/apps/svelte-grid/MoveResize.svelte.d.ts +1 -0
- package/package/components/apps/svelte-grid/utils/item.d.ts +4 -1
- package/package/components/apps/svelte-grid/utils/item.js +11 -4
- package/package/components/common/button/Button.svelte.d.ts +2 -2
- package/package/components/common/calendarPicker/CalendarPicker.svelte +6 -2
- package/package/components/common/calendarPicker/CalendarPicker.svelte.d.ts +2 -0
- package/package/components/common/drawer/ConditionalPortal.svelte +2 -1
- package/package/components/common/drawer/ConditionalPortal.svelte.d.ts +1 -0
- package/package/components/common/languageIcons/LanguageIcon.svelte +5 -2
- package/package/components/common/popup/Popup.svelte +2 -1
- package/package/components/common/popup/Popup.svelte.d.ts +1 -0
- package/package/components/common/table/AppRow.svelte +11 -8
- package/package/components/common/table/AppRow.svelte.d.ts +1 -2
- package/package/components/common/table/FlowRow.svelte +3 -3
- package/package/components/common/table/FlowRow.svelte.d.ts +1 -2
- package/package/components/common/table/RawAppRow.svelte +3 -3
- package/package/components/common/table/RawAppRow.svelte.d.ts +1 -2
- package/package/components/common/table/ScriptRow.svelte +3 -3
- package/package/components/common/table/ScriptRow.svelte.d.ts +1 -2
- package/package/components/copilot/CodeCompletionStatus.svelte +21 -46
- package/package/components/copilot/StepGen.svelte +2 -1
- package/package/components/custom_ui.d.ts +4 -1
- package/package/components/flows/CreateActionsApp.svelte +11 -8
- package/package/components/flows/CreateActionsFlow.svelte +11 -8
- package/package/components/flows/FlowEditor.svelte +1 -2
- package/package/components/flows/FlowEditor.svelte.d.ts +0 -1
- package/package/components/flows/FlowHistory.svelte +6 -3
- package/package/components/flows/content/FlowModuleScript.svelte +15 -11
- package/package/components/flows/content/FlowSettings.svelte +1 -4
- package/package/components/flows/content/ScriptEditorDrawer.svelte +3 -0
- package/package/components/flows/header/FlowYamlEditor.svelte +55 -0
- package/package/components/flows/header/FlowYamlEditor.svelte.d.ts +17 -0
- package/package/components/flows/map/InsertTriggerButton.svelte +1 -1
- package/package/components/flows/map/InsertTriggerButton.svelte.d.ts +1 -0
- package/package/components/flows/map/VirtualItem.svelte +1 -1
- package/package/components/flows/pickers/PickHubScript.svelte +1 -0
- package/package/components/flows/types.d.ts +7 -6
- package/package/components/flows/utils.d.ts +9 -0
- package/package/components/flows/utils.js +21 -0
- package/package/components/graph/graphBuilder.js +1 -0
- package/package/components/graph/model.d.ts +1 -0
- package/package/components/graph/renderers/edges/BaseEdge.svelte +16 -0
- package/package/components/graph/renderers/nodes/BranchOneStart.svelte +1 -1
- package/package/components/graph/renderers/nodes/NoBranchNode.svelte +5 -1
- package/package/components/graph/renderers/nodes/NoBranchNode.svelte.d.ts +1 -0
- package/package/components/home/Item.svelte +0 -17
- package/package/components/home/deploy_ui.d.ts +2 -0
- package/package/components/home/deploy_ui.js +21 -0
- package/package/components/icons/RustIcon.svelte +70 -0
- package/package/components/icons/RustIcon.svelte.d.ts +25 -0
- package/package/components/icons/rust-logo.svg +1 -0
- package/package/components/instanceSettings.js +2 -2
- package/package/components/monaco_keybindings.d.ts +3 -0
- package/package/components/monaco_keybindings.js +9 -0
- package/package/components/preview/FlowPreviewStatus.svelte +6 -2
- package/package/components/runs/JobLoader.svelte +12 -3
- package/package/components/runs/JobLoader.svelte.d.ts +1 -1
- package/package/components/runs/ManuelDatePicker.svelte +31 -44
- package/package/components/runs/ManuelDatePicker.svelte.d.ts +6 -2
- package/package/components/runs/RunsFilter.svelte +4 -1
- package/package/components/runs/RunsFilter.svelte.d.ts +1 -0
- package/package/components/search/GlobalSearchModal.svelte +36 -25
- package/package/components/wizards/TableActionsWizard.svelte +84 -0
- package/package/components/wizards/TableActionsWizard.svelte.d.ts +22 -0
- package/package/editorUtils.js +2 -0
- package/package/gen/core/OpenAPI.js +1 -1
- package/package/gen/schemas.gen.d.ts +8 -8
- package/package/gen/schemas.gen.js +8 -8
- package/package/gen/services.gen.d.ts +4 -0
- package/package/gen/services.gen.js +16 -0
- package/package/gen/types.gen.d.ts +20 -8
- package/package/infer.d.ts +1 -1
- package/package/infer.js +48 -7
- package/package/script_helpers.d.ts +1 -0
- package/package/script_helpers.js +39 -1
- package/package/scripts.d.ts +1 -1
- package/package/scripts.js +11 -3
- package/package/stores.d.ts +5 -1
- package/package/stores.js +7 -2
- package/package.json +13 -7
|
@@ -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
|
|
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>;
|
|
@@ -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 {};
|
|
@@ -42,8 +42,9 @@ import domContent from '../dom.d.ts.txt?raw';
|
|
|
42
42
|
import { buildWorkerDefinition } from './build_workers';
|
|
43
43
|
import { initializeVscode } from './vscode';
|
|
44
44
|
import EditorTheme from './EditorTheme.svelte';
|
|
45
|
-
import { tailwindClasses } from './apps/editor/componentsPanel/tailwindUtils';
|
|
46
45
|
import { writable } from 'svelte/store';
|
|
46
|
+
import { vimMode } from '../stores';
|
|
47
|
+
import { initVim } from './monaco_keybindings';
|
|
47
48
|
// import { createConfiguredEditor } from 'vscode/monaco'
|
|
48
49
|
// import type { IStandaloneCodeEditor } from 'vscode/vscode/vs/editor/standalone/browser/standaloneCodeEditor'
|
|
49
50
|
let divEl = null;
|
|
@@ -62,6 +63,8 @@ export let fixedOverflowWidgets = true;
|
|
|
62
63
|
export let small = false;
|
|
63
64
|
export let domLib = false;
|
|
64
65
|
export let autofocus = false;
|
|
66
|
+
export let allowVim = false;
|
|
67
|
+
export let tailwindClasses = [];
|
|
65
68
|
const dispatch = createEventDispatcher();
|
|
66
69
|
const uri = `file:///${hash}.${langToExt(lang)}`;
|
|
67
70
|
buildWorkerDefinition('../../../workers', import.meta.url);
|
|
@@ -125,6 +128,20 @@ let width = 0;
|
|
|
125
128
|
let initialized = false;
|
|
126
129
|
let disableTabCond;
|
|
127
130
|
$: disableTabCond?.set(!code && !!suggestion);
|
|
131
|
+
let statusDiv = null;
|
|
132
|
+
let vimDisposable = undefined;
|
|
133
|
+
$: allowVim && editor && $vimMode && statusDiv && onVimMode();
|
|
134
|
+
$: !$vimMode && vimDisposable && onVimDisable();
|
|
135
|
+
function onVimDisable() {
|
|
136
|
+
vimDisposable?.dispose();
|
|
137
|
+
}
|
|
138
|
+
function onVimMode() {
|
|
139
|
+
if (editor && statusDiv) {
|
|
140
|
+
vimDisposable = initVim(editor, statusDiv, () => {
|
|
141
|
+
console.log('vim save not possible for simple editor');
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
128
145
|
async function loadMonaco() {
|
|
129
146
|
await initializeVscode();
|
|
130
147
|
initialized = true;
|
|
@@ -321,6 +338,7 @@ onMount(async () => {
|
|
|
321
338
|
$: mounted && extraLib && initialized && loadExtraLib();
|
|
322
339
|
onDestroy(() => {
|
|
323
340
|
try {
|
|
341
|
+
vimDisposable?.dispose();
|
|
324
342
|
model && model.dispose();
|
|
325
343
|
editor && editor.dispose();
|
|
326
344
|
}
|
|
@@ -338,7 +356,14 @@ onDestroy(() => {
|
|
|
338
356
|
{suggestion}
|
|
339
357
|
</div>
|
|
340
358
|
{/if}
|
|
341
|
-
<div
|
|
359
|
+
<div
|
|
360
|
+
bind:this={divEl}
|
|
361
|
+
class="{$$props.class ?? ''} editor simple-editor {!allowVim ? 'nonmain-editor' : ''}"
|
|
362
|
+
bind:clientWidth={width}
|
|
363
|
+
/>
|
|
364
|
+
{#if allowVim && $vimMode}
|
|
365
|
+
<div class="fixed bottom-0 z-30" bind:this={statusDiv} />
|
|
366
|
+
{/if}
|
|
342
367
|
|
|
343
368
|
<style>
|
|
344
369
|
.editor {
|