2021-05-26 10:13:38 +01:00
|
|
|
import { CodeEditor } from "../../../elements/CodeEditor";
|
2022-01-13 18:09:03 +00:00
|
|
|
import { Component, createRef, JSX } from "preact";
|
2022-01-06 23:02:34 +00:00
|
|
|
import { DefaultPageProps } from "../../../../types/DefaultPageProps";
|
2021-05-19 10:27:00 +01:00
|
|
|
import { SecretTitleElement } from "../SecretTitleElement";
|
2021-11-21 11:06:10 +00:00
|
|
|
import { setErrorText } from "../../../../pageUtils";
|
2022-01-13 18:09:03 +00:00
|
|
|
import { sortedObjectMap } from "../../../../utils";
|
2022-01-13 18:31:19 +00:00
|
|
|
import { InputWithTitle } from "../../../elements/InputWithTitle";
|
2022-01-13 18:09:03 +00:00
|
|
|
import Hjson from "hjson";
|
2022-01-13 18:31:19 +00:00
|
|
|
import JSON5 from "json5";
|
|
|
|
import yaml from "js-yaml";
|
2021-05-12 16:01:04 +01:00
|
|
|
import i18next from "i18next";
|
2022-01-13 18:09:03 +00:00
|
|
|
|
2022-01-13 18:31:19 +00:00
|
|
|
// todo: put this in settings
|
|
|
|
const defaultIndent = 2;
|
2022-01-13 18:09:03 +00:00
|
|
|
|
2022-01-13 18:31:19 +00:00
|
|
|
function parseData(data: string, syntax: string = "json"): Record<string, unknown> {
|
|
|
|
if (syntax == "json") {
|
2022-01-13 18:09:03 +00:00
|
|
|
return JSON.parse(data);
|
2022-01-13 18:31:19 +00:00
|
|
|
} else if (syntax == "json5") {
|
|
|
|
return JSON5.parse(data);
|
|
|
|
} else if (syntax == "hjson") {
|
|
|
|
return Hjson.parse(data);
|
|
|
|
} else if (syntax == "yaml") {
|
|
|
|
return yaml.load(data) as Record<string, unknown>;
|
2022-01-13 18:09:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-13 18:31:19 +00:00
|
|
|
function dumpData(data: Record<string, unknown>, space: number = defaultIndent, syntax: string = "json"): string {
|
|
|
|
if (syntax == "json") {
|
2022-01-13 18:09:03 +00:00
|
|
|
return JSON.stringify(data, null, space);
|
2022-01-13 18:31:19 +00:00
|
|
|
} else if (syntax == "json5") {
|
|
|
|
return JSON5.stringify(data, null, space);
|
|
|
|
} else if (syntax == "hjson") {
|
|
|
|
return Hjson.stringify(data, { space: space });
|
|
|
|
} else if (syntax == "yaml") {
|
|
|
|
return yaml.dump(data, { indent: space });
|
2022-01-13 18:09:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-13 18:31:19 +00:00
|
|
|
export function validateData(str: string, syntax: string = "json"): boolean {
|
2022-01-13 18:09:03 +00:00
|
|
|
try {
|
2022-01-13 18:31:19 +00:00
|
|
|
parseData(str, syntax);
|
2022-01-13 18:09:03 +00:00
|
|
|
} catch (e) {
|
2022-01-13 18:39:02 +00:00
|
|
|
console.log(e);
|
2022-01-13 18:09:03 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2021-04-20 23:02:18 +01:00
|
|
|
|
2022-01-07 15:27:10 +00:00
|
|
|
export type KVEditProps = DefaultPageProps & {
|
2022-01-06 18:53:38 +00:00
|
|
|
baseMount: string;
|
|
|
|
secretPath: string[];
|
|
|
|
secretItem: string;
|
2021-05-24 11:49:49 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
type KVEditState =
|
|
|
|
| {
|
2022-01-13 18:09:03 +00:00
|
|
|
dataLoaded: false;
|
2022-01-13 18:31:19 +00:00
|
|
|
syntax: string;
|
2022-01-13 18:09:03 +00:00
|
|
|
}
|
2021-05-24 11:49:49 +01:00
|
|
|
| {
|
2022-01-13 18:09:03 +00:00
|
|
|
dataLoaded: true;
|
|
|
|
kvData: Record<string, unknown>;
|
|
|
|
code: string;
|
2022-01-13 18:31:19 +00:00
|
|
|
syntax: string;
|
2022-01-13 18:09:03 +00:00
|
|
|
};
|
2021-05-24 11:49:49 +01:00
|
|
|
|
|
|
|
export class KVEditor extends Component<KVEditProps, KVEditState> {
|
2021-04-15 13:01:58 +01:00
|
|
|
constructor() {
|
|
|
|
super();
|
2022-01-13 18:31:19 +00:00
|
|
|
// TODO: add a global syntax option to settings for default
|
2021-05-24 11:49:49 +01:00
|
|
|
this.state = {
|
|
|
|
dataLoaded: false,
|
2022-01-13 18:31:19 +00:00
|
|
|
syntax: "json",
|
2021-05-24 11:49:49 +01:00
|
|
|
};
|
2021-04-15 13:01:58 +01:00
|
|
|
}
|
2021-05-24 11:49:49 +01:00
|
|
|
|
|
|
|
async editorSave(): Promise<void> {
|
|
|
|
if (!this.state.dataLoaded) return;
|
|
|
|
const editorContent = this.state.code;
|
2021-05-25 10:46:07 +01:00
|
|
|
|
2022-01-13 18:31:19 +00:00
|
|
|
if (!validateData(editorContent, this.state.syntax)) {
|
2021-05-24 11:49:49 +01:00
|
|
|
setErrorText(i18next.t("kv_sec_edit_invalid_json_err"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-01-07 15:27:10 +00:00
|
|
|
await this.props.api.createOrUpdateSecret(
|
2022-01-06 18:53:38 +00:00
|
|
|
this.props.baseMount,
|
|
|
|
this.props.secretPath.map((e) => e + "/"),
|
|
|
|
this.props.secretItem,
|
2022-01-13 18:31:19 +00:00
|
|
|
parseData(editorContent, this.state.syntax),
|
2021-05-24 11:49:49 +01:00
|
|
|
);
|
2022-01-06 18:53:38 +00:00
|
|
|
window.history.back();
|
2021-04-15 13:01:58 +01:00
|
|
|
}
|
2021-05-24 11:49:49 +01:00
|
|
|
|
|
|
|
onCodeUpdate(code: string): void {
|
|
|
|
this.setState({
|
|
|
|
code: code,
|
2021-04-15 13:01:58 +01:00
|
|
|
});
|
2021-05-24 11:49:49 +01:00
|
|
|
}
|
|
|
|
|
2022-01-13 18:09:03 +00:00
|
|
|
async loadData() {
|
|
|
|
let kvData = await this.props.api.getSecret(
|
|
|
|
this.props.baseMount,
|
|
|
|
this.props.secretPath.map((e) => e + "/"),
|
|
|
|
this.props.secretItem,
|
|
|
|
)
|
|
|
|
this.setState({
|
|
|
|
dataLoaded: true,
|
|
|
|
kvData: kvData,
|
|
|
|
code: this.getStringKVData(kvData)
|
|
|
|
});
|
2021-05-24 11:49:49 +01:00
|
|
|
}
|
2021-05-15 10:54:39 +01:00
|
|
|
|
2022-01-13 18:09:03 +00:00
|
|
|
async componentDidMount() {
|
2021-05-24 11:49:49 +01:00
|
|
|
if (!this.state.dataLoaded) {
|
2022-01-13 18:09:03 +00:00
|
|
|
await this.loadData();
|
2021-05-24 11:49:49 +01:00
|
|
|
}
|
|
|
|
}
|
2021-04-15 13:01:58 +01:00
|
|
|
|
2021-05-25 10:46:07 +01:00
|
|
|
getStringKVData(data: Record<string, unknown>): string {
|
2022-01-13 18:31:19 +00:00
|
|
|
return dumpData(Object.fromEntries(sortedObjectMap(data)), defaultIndent, this.state.syntax);
|
2021-05-25 10:46:07 +01:00
|
|
|
}
|
|
|
|
|
2022-01-13 18:31:19 +00:00
|
|
|
syntaxSelectRef = createRef<HTMLSelectElement>()
|
2022-01-13 18:09:03 +00:00
|
|
|
|
2021-05-24 11:49:49 +01:00
|
|
|
render(): JSX.Element {
|
|
|
|
if (!this.state.dataLoaded) {
|
2021-05-26 13:23:59 +01:00
|
|
|
return <p>{i18next.t("content_loading")}</p>;
|
2021-05-24 11:49:49 +01:00
|
|
|
}
|
2021-04-15 13:01:58 +01:00
|
|
|
|
2022-01-13 18:31:19 +00:00
|
|
|
let codeEditorLanguage: string;
|
|
|
|
|
|
|
|
if (this.state.syntax == "json") {
|
|
|
|
codeEditorLanguage = "json"
|
|
|
|
} else if (this.state.syntax == "json5") {
|
|
|
|
codeEditorLanguage = "json5"
|
|
|
|
}else if (this.state.syntax == "hjson") {
|
|
|
|
codeEditorLanguage = "js"
|
|
|
|
} else if (this.state.syntax == "yaml") {
|
|
|
|
codeEditorLanguage = "yaml"
|
|
|
|
}
|
|
|
|
|
2021-05-24 11:49:49 +01:00
|
|
|
return (
|
|
|
|
<div>
|
2022-01-13 18:39:02 +00:00
|
|
|
<InputWithTitle title={i18next.t("kv_sec_edit_syntax")}>
|
2022-01-13 18:31:19 +00:00
|
|
|
<select ref={this.syntaxSelectRef} class="uk-select uk-form-width-medium" onChange={() => {
|
|
|
|
this.setState({ syntax: this.syntaxSelectRef.current.value })
|
|
|
|
|
|
|
|
}}>
|
|
|
|
<option label="JSON" value="json" />
|
|
|
|
<option label="JSON5" value="json5" />
|
|
|
|
<option label="Hjson" value="hjson" />
|
|
|
|
<option label="Yaml" value="yaml" />
|
|
|
|
</select>
|
2022-01-13 18:09:03 +00:00
|
|
|
</InputWithTitle>
|
2021-05-24 11:49:49 +01:00
|
|
|
<p class="uk-text-danger" id="errorText" />
|
2021-05-26 10:13:38 +01:00
|
|
|
<CodeEditor
|
2022-01-13 18:31:19 +00:00
|
|
|
language={codeEditorLanguage}
|
|
|
|
tabSize={defaultIndent}
|
2021-05-25 10:46:07 +01:00
|
|
|
code={this.getStringKVData(this.state.kvData)}
|
2021-05-24 11:49:49 +01:00
|
|
|
onUpdate={(code) => this.onCodeUpdate(code)}
|
|
|
|
/>
|
|
|
|
<button class="uk-button uk-button-primary" onClick={() => this.editorSave()}>
|
2022-01-10 14:57:53 +00:00
|
|
|
{i18next.t("common_edit")}
|
2021-05-24 11:49:49 +01:00
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-07 12:05:24 +00:00
|
|
|
export class KeyValueEdit extends Component<DefaultPageProps> {
|
2022-01-06 18:53:38 +00:00
|
|
|
render() {
|
2022-01-06 22:57:12 +00:00
|
|
|
const baseMount = this.props.matches["baseMount"];
|
|
|
|
const secretPath = this.props.matches["secretPath"].split("/");
|
2022-01-06 18:53:38 +00:00
|
|
|
const item = this.props.matches["item"];
|
2021-04-15 13:01:58 +01:00
|
|
|
|
2022-01-06 18:53:38 +00:00
|
|
|
return (
|
|
|
|
<>
|
2022-01-06 22:57:12 +00:00
|
|
|
<SecretTitleElement
|
|
|
|
type="kv"
|
|
|
|
baseMount={baseMount}
|
|
|
|
secretPath={secretPath}
|
|
|
|
item={this.props.matches["item"]}
|
|
|
|
suffix={i18next.t("kv_sec_edit_suffix")}
|
|
|
|
/>
|
2022-01-07 15:27:10 +00:00
|
|
|
<KVEditor
|
|
|
|
settings={this.props.settings}
|
|
|
|
api={this.props.api}
|
|
|
|
baseMount={baseMount}
|
|
|
|
secretPath={secretPath}
|
|
|
|
secretItem={item}
|
|
|
|
/>
|
2022-01-06 18:53:38 +00:00
|
|
|
</>
|
2021-05-24 10:14:01 +01:00
|
|
|
);
|
2021-04-17 11:06:34 +01:00
|
|
|
}
|
2021-05-12 16:01:04 +01:00
|
|
|
}
|