Can edit Cloud init user data from UI
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2025-06-10 21:46:50 +02:00
parent feca07558e
commit 0d8ef226c1
4 changed files with 237 additions and 11 deletions

View File

@ -13,6 +13,7 @@
"@fontsource/roboto": "^5.2.5",
"@mdi/js": "^7.4.47",
"@mdi/react": "^1.6.1",
"@monaco-editor/react": "^4.7.0",
"@mui/icons-material": "^7.1.1",
"@mui/material": "^7.1.1",
"@mui/x-charts": "^8.3.1",
@ -20,6 +21,8 @@
"date-and-time": "^3.6.0",
"filesize": "^10.1.6",
"humanize-duration": "^3.32.2",
"monaco-editor": "^0.52.2",
"monaco-yaml": "^5.4.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-router-dom": "^7.6.2",
@ -958,6 +961,29 @@
"prop-types": "^15.7.2"
}
},
"node_modules/@monaco-editor/loader": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.5.0.tgz",
"integrity": "sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==",
"license": "MIT",
"dependencies": {
"state-local": "^1.0.6"
}
},
"node_modules/@monaco-editor/react": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.7.0.tgz",
"integrity": "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==",
"license": "MIT",
"dependencies": {
"@monaco-editor/loader": "^1.5.0"
},
"peerDependencies": {
"monaco-editor": ">= 0.25.0 < 1",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/@mui/core-downloads-tracker": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.1.tgz",
@ -3481,6 +3507,12 @@
"node": ">=6"
}
},
"node_modules/jsonc-parser": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
"integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",
"license": "MIT"
},
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@ -3607,6 +3639,84 @@
"node": "*"
}
},
"node_modules/monaco-editor": {
"version": "0.52.2",
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz",
"integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==",
"license": "MIT"
},
"node_modules/monaco-languageserver-types": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/monaco-languageserver-types/-/monaco-languageserver-types-0.4.0.tgz",
"integrity": "sha512-QQ3BZiU5LYkJElGncSNb5AKoJ/LCs6YBMCJMAz9EA7v+JaOdn3kx2cXpPTcZfKA5AEsR0vc97sAw+5mdNhVBmw==",
"license": "MIT",
"dependencies": {
"monaco-types": "^0.1.0",
"vscode-languageserver-protocol": "^3.0.0",
"vscode-uri": "^3.0.0"
},
"funding": {
"url": "https://github.com/sponsors/remcohaszing"
}
},
"node_modules/monaco-marker-data-provider": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/monaco-marker-data-provider/-/monaco-marker-data-provider-1.2.4.tgz",
"integrity": "sha512-4DsPgsAqpTyUDs3humXRBPUJoihTv+L6v9aupQWD80X2YXaCXUd11mWYeSCYHuPgdUmjFaNWCEOjQ6ewf/QA1Q==",
"license": "MIT",
"dependencies": {
"monaco-types": "^0.1.0"
},
"funding": {
"url": "https://github.com/sponsors/remcohaszing"
}
},
"node_modules/monaco-types": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/monaco-types/-/monaco-types-0.1.0.tgz",
"integrity": "sha512-aWK7SN9hAqNYi0WosPoMjenMeXJjwCxDibOqWffyQ/qXdzB/86xshGQobRferfmNz7BSNQ8GB0MD0oby9/5fTQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/remcohaszing"
}
},
"node_modules/monaco-worker-manager": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/monaco-worker-manager/-/monaco-worker-manager-2.0.1.tgz",
"integrity": "sha512-kdPL0yvg5qjhKPNVjJoym331PY/5JC11aPJXtCZNwWRvBr6jhkIamvYAyiY5P1AWFmNOy0aRDRoMdZfa71h8kg==",
"license": "MIT",
"peerDependencies": {
"monaco-editor": ">=0.30.0"
}
},
"node_modules/monaco-yaml": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/monaco-yaml/-/monaco-yaml-5.4.0.tgz",
"integrity": "sha512-tuBVDy1KAPrgO905GHTItu8AaA5bIzF5S4X0JVRAE/D66FpRhkDUk7tKi5bwKMVTTugtpMLsXN4ewh4CgE/FtQ==",
"license": "MIT",
"workspaces": [
"examples/*"
],
"dependencies": {
"jsonc-parser": "^3.0.0",
"monaco-languageserver-types": "^0.4.0",
"monaco-marker-data-provider": "^1.0.0",
"monaco-types": "^0.1.0",
"monaco-worker-manager": "^2.0.0",
"path-browserify": "^1.0.0",
"prettier": "^3.0.0",
"vscode-languageserver-textdocument": "^1.0.0",
"vscode-languageserver-types": "^3.0.0",
"vscode-uri": "^3.0.0",
"yaml": "^2.0.0"
},
"funding": {
"url": "https://github.com/sponsors/remcohaszing"
},
"peerDependencies": {
"monaco-editor": ">=0.36"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@ -3753,6 +3863,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/path-browserify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
"license": "MIT"
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@ -3846,6 +3962,21 @@
"node": ">= 0.8.0"
}
},
"node_modules/prettier": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/pretty-format": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
@ -4326,6 +4457,12 @@
"node": ">=8"
}
},
"node_modules/state-local": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
"integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==",
"license": "MIT"
},
"node_modules/string-ts": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/string-ts/-/string-ts-2.2.1.tgz",
@ -4714,6 +4851,43 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/vscode-jsonrpc": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz",
"integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/vscode-languageserver-protocol": {
"version": "3.17.5",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz",
"integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==",
"license": "MIT",
"dependencies": {
"vscode-jsonrpc": "8.2.0",
"vscode-languageserver-types": "3.17.5"
}
},
"node_modules/vscode-languageserver-textdocument": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz",
"integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==",
"license": "MIT"
},
"node_modules/vscode-languageserver-types": {
"version": "3.17.5",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz",
"integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==",
"license": "MIT"
},
"node_modules/vscode-uri": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz",
"integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
"license": "MIT"
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@ -4781,10 +4955,7 @@
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
"integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
"dev": true,
"license": "ISC",
"optional": true,
"peer": true,
"bin": {
"yaml": "bin.mjs"
},

View File

@ -15,6 +15,7 @@
"@fontsource/roboto": "^5.2.5",
"@mdi/js": "^7.4.47",
"@mdi/react": "^1.6.1",
"@monaco-editor/react": "^4.7.0",
"@mui/icons-material": "^7.1.1",
"@mui/material": "^7.1.1",
"@mui/x-charts": "^8.3.1",
@ -22,6 +23,8 @@
"date-and-time": "^3.6.0",
"filesize": "^10.1.6",
"humanize-duration": "^3.32.2",
"monaco-editor": "^0.52.2",
"monaco-yaml": "^5.4.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-router-dom": "^7.6.2",

View File

@ -3,16 +3,44 @@ import "@fontsource/roboto/400.css";
import "@fontsource/roboto/500.css";
import "@fontsource/roboto/700.css";
import { ThemeProvider, createTheme } from "@mui/material";
import React from "react";
import ReactDOM from "react-dom/client";
import { App } from "./App";
import { AlertDialogProvider } from "./hooks/providers/AlertDialogProvider";
import { ConfirmDialogProvider } from "./hooks/providers/ConfirmDialogProvider";
import { LoadingMessageProvider } from "./hooks/providers/LoadingMessageProvider";
import { SnackbarProvider } from "./hooks/providers/SnackbarProvider";
import "./index.css";
import { LoadServerConfig } from "./widgets/LoadServerConfig";
import { ThemeProvider, createTheme } from "@mui/material";
import { LoadingMessageProvider } from "./hooks/providers/LoadingMessageProvider";
import { AlertDialogProvider } from "./hooks/providers/AlertDialogProvider";
import { SnackbarProvider } from "./hooks/providers/SnackbarProvider";
import { ConfirmDialogProvider } from "./hooks/providers/ConfirmDialogProvider";
import { loader } from "@monaco-editor/react";
import * as monaco from "monaco-editor";
import EditorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";
import { configureMonacoYaml } from "monaco-yaml";
import YamlWorker from "monaco-yaml/yaml.worker?worker";
// This allows to use a self hosted instance of Monaco editor
loader.config({ monaco });
// Add YAML support to Monaco
configureMonacoYaml(monaco, {
enableSchemaRequest: false,
});
/// YAML worker
window.MonacoEnvironment = {
getWorker(_moduleId, label) {
switch (label) {
case "editorWorkerService":
return new EditorWorker();
case "yaml":
return new YamlWorker();
default:
throw new Error(`Unknown label ${label}`);
}
},
};
const darkTheme = createTheme({
palette: {
@ -20,9 +48,7 @@ const darkTheme = createTheme({
},
});
const root = ReactDOM.createRoot(
document.getElementById("root")!
);
const root = ReactDOM.createRoot(document.getElementById("root")!);
root.render(
<React.StrictMode>
<ThemeProvider theme={darkTheme}>

View File

@ -1,3 +1,4 @@
import Editor from "@monaco-editor/react";
import RefreshIcon from "@mui/icons-material/Refresh";
import { Grid, IconButton, InputAdornment, Tooltip } from "@mui/material";
import { v4 as uuidv4 } from "uuid";
@ -33,6 +34,10 @@ export function CloudInitEditor(p: CloudInitProps): React.ReactElement {
{...p}
editable={p.editable && p.vm.cloud_init.attach_config}
/>
<CloudInitRawUserData
{...p}
editable={p.editable && p.vm.cloud_init.attach_config}
/>
</Grid>
</>
);
@ -100,3 +105,24 @@ function CloudInitMetadata(p: CloudInitProps): React.ReactElement {
</EditSection>
);
}
function CloudInitRawUserData(p: CloudInitProps): React.ReactElement {
return (
<EditSection title="User data">
<Editor
theme="vs-dark"
options={{
readOnly: !p.editable,
quickSuggestions: { other: true, comments: true, strings: true },
}}
language="yaml"
height={"30vh"}
value={p.vm.cloud_init.user_data}
onChange={(v) => {
p.vm.cloud_init.user_data = v ?? "";
p.onChange?.();
}}
/>
</EditSection>
);
}