From 1ad22095715cdade604735ea9eaf48a7f777ba76 Mon Sep 17 00:00:00 2001 From: Kitteh Date: Mon, 24 May 2021 11:49:49 +0100 Subject: [PATCH] Add tsx syntax to KVSE. --- src/elements/CodeJar/CodeJarEditor.tsx | 53 ++++++ .../Secrets/KeyValue/KeyValueSecretsEdit.tsx | 162 +++++++++++------- 2 files changed, 151 insertions(+), 64 deletions(-) create mode 100644 src/elements/CodeJar/CodeJarEditor.tsx diff --git a/src/elements/CodeJar/CodeJarEditor.tsx b/src/elements/CodeJar/CodeJarEditor.tsx new file mode 100644 index 0000000..47799ad --- /dev/null +++ b/src/elements/CodeJar/CodeJarEditor.tsx @@ -0,0 +1,53 @@ +import { CodeJar } from "codejar"; +import { JSX } from "preact"; +import { Ref, useEffect, useRef } from "preact/compat"; + +interface EditorProps { + highlight: unknown; + options?: { tab: string }; + code: string; + onUpdate: (code: string) => void; +} + +export const useCodeJar = (props: EditorProps): Ref => { + const editorRef = useRef(null); + const jar = useRef(null); + + useEffect(() => { + if (!editorRef.current) return; + + jar.current = CodeJar( + editorRef.current, + props.highlight as (e: HTMLElement, pos?: unknown) => void, + { ...props.options, window: window }, + ); + + jar.current.updateCode(props.code); + + jar.current.onUpdate((txt) => { + if (!editorRef.current) return; + props.onUpdate(txt); + }); + + return () => jar.current.destroy(); + }, []); + + useEffect(() => { + if (!jar.current || !editorRef.current) return; + jar.current.updateCode(props.code); + }, [props.code]); + + useEffect(() => { + if (!jar.current || !props.options) return; + + jar.current.updateOptions(props.options); + }, [props.options]); + + return editorRef; +}; + +export function CodeJarEditor(props: EditorProps): JSX.Element { + const editorRef = useCodeJar(props); + + return
; +} diff --git a/src/pages/Secrets/KeyValue/KeyValueSecretsEdit.tsx b/src/pages/Secrets/KeyValue/KeyValueSecretsEdit.tsx index 042146c..1ef2eda 100644 --- a/src/pages/Secrets/KeyValue/KeyValueSecretsEdit.tsx +++ b/src/pages/Secrets/KeyValue/KeyValueSecretsEdit.tsx @@ -1,13 +1,107 @@ -import { CodeJar } from "codejar"; +import { CodeJarEditor } from "../../../elements/CodeJar/CodeJarEditor"; +import { Component, JSX, render } from "preact"; import { Page } from "../../../types/Page"; import { SecretTitleElement } from "../SecretTitleElement"; import { createOrUpdateSecret } from "../../../api/kv/createOrUpdateSecret"; import { getSecret } from "../../../api/kv/getSecret"; -import { makeElement } from "z-makeelement"; -import { render } from "preact"; import { setErrorText } from "../../../pageUtils"; import { sortedObjectMap, verifyJSONString } from "../../../utils"; import i18next from "i18next"; +//import { highlightElement } from "prismjs"; + +export type KVEditProps = { + page: Page; +}; + +type KVEditState = + | { + dataLoaded: false; + } + | { + dataLoaded: true; + kvData: Record; + code: string; + }; + +export class KVEditor extends Component { + constructor() { + super(); + this.state = { + dataLoaded: false, + }; + } + + async editorSave(): Promise { + if (!this.state.dataLoaded) return; + const editorContent = this.state.code; + if (!verifyJSONString(editorContent)) { + setErrorText(i18next.t("kv_sec_edit_invalid_json_err")); + return; + } + + await createOrUpdateSecret( + this.props.page.state.baseMount, + this.props.page.state.secretMountType, + this.props.page.state.secretPath, + this.props.page.state.secretItem, + JSON.parse(editorContent), + ); + await this.props.page.router.changePage("KEY_VALUE_SECRET"); + } + + onCodeUpdate(code: string): void { + this.setState({ + code: code, + }); + } + + loadData(): void { + void getSecret( + this.props.page.state.baseMount, + this.props.page.state.secretMountType, + this.props.page.state.secretPath, + this.props.page.state.secretItem, + ).then((kvData) => { + this.setState({ + dataLoaded: true, + kvData: kvData, + }); + }); + return; + } + + componentDidMount(): void { + if (!this.state.dataLoaded) { + this.loadData(); + } + } + + render(): JSX.Element { + if (!this.state.dataLoaded) { + return

{i18next.t("kv_sec_edit_loading")}

; + } + + const secretsJSON = JSON.stringify( + Object.fromEntries(sortedObjectMap(this.state.kvData)), + null, + 4, + ); + + return ( +
+

+ {}} + code={secretsJSON} + onUpdate={(code) => this.onCodeUpdate(code)} + /> + +

+ ); + } +} export class KeyValueSecretEditPage extends Page { constructor() { @@ -17,67 +111,7 @@ export class KeyValueSecretEditPage extends Page { await this.router.changePage("KEY_VALUE_SECRET"); } async render(): Promise { - const loadingText = makeElement({ - tag: "p", - text: i18next.t("kv_sec_edit_loading"), - }); - const editor = makeElement({ - tag: "div", - class: ["editor", "language-json"], - }); - const saveButton = makeElement({ - tag: "button", - class: ["uk-button", "uk-button-primary"], - text: i18next.t("kv_sec_edit_btn"), - }); - await this.router.setPageContent( - makeElement({ - tag: "div", - children: [ - loadingText, - editor, - makeElement({ - tag: "p", - id: "errorText", - class: ["uk-text-danger", "uk-margin-top"], - }), - saveButton, - ], - }), - ); - const secretInfo = await getSecret( - this.state.baseMount, - this.state.secretMountType, - this.state.secretPath, - this.state.secretItem, - ); - - loadingText.remove(); - - const secretsJSON = JSON.stringify(Object.fromEntries(sortedObjectMap(secretInfo)), null, 4); - - const jar = CodeJar(editor, () => {}, { tab: " ".repeat(4) }); - jar.updateCode(secretsJSON); - saveButton.onclick = async () => { - if (!verifyJSONString(jar.toString())) { - setErrorText(i18next.t("kv_sec_edit_invalid_json_err")); - return; - } - - try { - await createOrUpdateSecret( - this.state.baseMount, - this.state.secretMountType, - this.state.secretPath, - this.state.secretItem, - JSON.parse(jar.toString()), - ); - await this.router.changePage("KEY_VALUE_SECRET"); - } catch (e: unknown) { - const error = e as Error; - setErrorText(error.message); - } - }; + render(, this.router.pageContentElement); } async renderPageTitle(): Promise {