mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
integrate codeedit loader (just hello world for now)
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { CodeEditView } from "@/app/view/codeedit";
|
||||
import { PlotView } from "@/app/view/plotview";
|
||||
import { PreviewView } from "@/app/view/preview";
|
||||
import { TerminalView } from "@/app/view/term";
|
||||
import { ErrorBoundary } from "@/element/errorboundary";
|
||||
import { CenteredDiv } from "@/element/quickelems";
|
||||
import * as WOS from "@/store/wos";
|
||||
import * as React from "react";
|
||||
@@ -32,6 +34,7 @@ const Block = ({ tabId, blockId }: { tabId: string; blockId: string }) => {
|
||||
|
||||
let blockElem: JSX.Element = null;
|
||||
const [blockData, blockDataLoading] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", blockId));
|
||||
console.log("blockData: ", blockData);
|
||||
if (blockDataLoading) {
|
||||
blockElem = <CenteredDiv>Loading...</CenteredDiv>;
|
||||
} else if (blockData.view === "term") {
|
||||
@@ -40,6 +43,8 @@ const Block = ({ tabId, blockId }: { tabId: string; blockId: string }) => {
|
||||
blockElem = <PreviewView blockId={blockId} />;
|
||||
} else if (blockData.view === "plot") {
|
||||
blockElem = <PlotView />;
|
||||
} else if (blockData.view === "codeedit") {
|
||||
blockElem = <CodeEditView />;
|
||||
}
|
||||
return (
|
||||
<div className="block" ref={blockRef}>
|
||||
@@ -53,7 +58,9 @@ const Block = ({ tabId, blockId }: { tabId: string; blockId: string }) => {
|
||||
</div>
|
||||
</div>
|
||||
<div key="content" className="block-content">
|
||||
<React.Suspense fallback={<CenteredDiv>Loading...</CenteredDiv>}>{blockElem}</React.Suspense>
|
||||
<ErrorBoundary>
|
||||
<React.Suspense fallback={<CenteredDiv>Loading...</CenteredDiv>}>{blockElem}</React.Suspense>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import React, { ReactNode } from "react";
|
||||
|
||||
export class ErrorBoundary extends React.Component<{ children: ReactNode }, { error: Error }> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { error: null };
|
||||
}
|
||||
|
||||
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
||||
this.setState({ error: error });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { error } = this.state;
|
||||
if (error) {
|
||||
const errorMsg = `Error: ${error?.message}\n\n${error?.stack}`;
|
||||
return <pre className="error-boundary">{errorMsg}</pre>;
|
||||
} else {
|
||||
return <>{this.props.children}</>;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
.codeedit {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import "./codeedit.less";
|
||||
|
||||
import { globalStore } from "@/store/global";
|
||||
import loader from "@monaco-editor/loader";
|
||||
import { Editor, Monaco } from "@monaco-editor/react";
|
||||
import * as jotai from "jotai";
|
||||
import type * as MonacoTypes from "monaco-editor/esm/vs/editor/editor.api";
|
||||
import * as React from "react";
|
||||
|
||||
// there is a global monaco variable (TODO get the correct TS type)
|
||||
declare var monaco: Monaco;
|
||||
let monacoLoadedAtom = jotai.atom(false);
|
||||
|
||||
function loadMonaco() {
|
||||
loader.config({ paths: { vs: "./monaco" } });
|
||||
loader
|
||||
.init()
|
||||
.then(() => {
|
||||
monaco.editor.defineTheme("wave-theme-dark", {
|
||||
base: "hc-black",
|
||||
inherit: true,
|
||||
rules: [],
|
||||
colors: {
|
||||
"editor.background": "#000000",
|
||||
},
|
||||
});
|
||||
monaco.editor.defineTheme("wave-theme-light", {
|
||||
base: "hc-light",
|
||||
inherit: true,
|
||||
rules: [],
|
||||
colors: {
|
||||
"editor.background": "#fefefe",
|
||||
},
|
||||
});
|
||||
globalStore.set(monacoLoadedAtom, true);
|
||||
console.log("monaco loaded", monaco);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("error loading monaco", e);
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: need to update these on theme change (pull from CSS vars)
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
setTimeout(loadMonaco, 30);
|
||||
});
|
||||
|
||||
function defaultEditorOptions(): MonacoTypes.editor.IEditorOptions {
|
||||
const opts: MonacoTypes.editor.IEditorOptions = {
|
||||
scrollBeyondLastLine: false,
|
||||
fontSize: 12,
|
||||
fontFamily: "Hack",
|
||||
};
|
||||
return opts;
|
||||
}
|
||||
|
||||
export function CodeEdit() {
|
||||
const divRef = React.useRef<HTMLDivElement>(null);
|
||||
const monacoRef = React.useRef<MonacoTypes.editor.IStandaloneCodeEditor | null>(null);
|
||||
const theme = "wave-theme-dark";
|
||||
const [divDims, setDivDims] = React.useState(null);
|
||||
const monacoLoaded = jotai.useAtomValue(monacoLoadedAtom);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!divRef.current) {
|
||||
return;
|
||||
}
|
||||
const height = divRef.current.clientHeight;
|
||||
const width = divRef.current.clientWidth;
|
||||
setDivDims({ height, width });
|
||||
}, [divRef.current]);
|
||||
|
||||
function handleEditorMount(editor: MonacoTypes.editor.IStandaloneCodeEditor) {
|
||||
monacoRef.current = editor;
|
||||
const monacoModel = editor.getModel();
|
||||
monaco.editor.setModelLanguage(monacoModel, "text/markdown");
|
||||
}
|
||||
|
||||
function handleEditorChange(newText: string, ev: MonacoTypes.editor.IModelContentChangedEvent) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
const text = "Hello, world!";
|
||||
const editorOpts = defaultEditorOptions();
|
||||
|
||||
return (
|
||||
<div className="codeedit" ref={divRef}>
|
||||
{divDims != null && monacoLoaded ? (
|
||||
<Editor
|
||||
theme={theme}
|
||||
height={divDims.height}
|
||||
defaultLanguage={"text/markdown"}
|
||||
value={text}
|
||||
onMount={handleEditorMount}
|
||||
options={editorOpts}
|
||||
onChange={handleEditorChange}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function CodeEditView() {
|
||||
return (
|
||||
<div className="view-codeedit">
|
||||
<CodeEdit />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
import { FileInfo } from "@/bindings/fileservice";
|
||||
import { Table, createColumnHelper, flexRender, getCoreRowModel, useReactTable } from "@tanstack/react-table";
|
||||
import * as jotai from "jotai";
|
||||
import path from "path";
|
||||
import React from "react";
|
||||
|
||||
import "./directorypreview.less";
|
||||
@@ -108,7 +107,7 @@ function TableBody({ table, setFileName }: TableBodyProps) {
|
||||
key={cell.id}
|
||||
style={{ width: `calc(var(--col-${cell.column.id}-size) * 1px)` }}
|
||||
>
|
||||
{path.basename(cell.renderValue<any>())}
|
||||
{cell.renderValue<any>()}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -26,6 +26,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
.view-codeedit {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.view-preview {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@@ -84,6 +84,13 @@ function Widgets() {
|
||||
createBlock(plotDef);
|
||||
}
|
||||
|
||||
async function clickEdit() {
|
||||
const editDef: BlockDef = {
|
||||
view: "codeedit",
|
||||
};
|
||||
createBlock(editDef);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="workspace-widgets">
|
||||
<div className="widget" onClick={() => clickTerminal()}>
|
||||
@@ -104,6 +111,9 @@ function Widgets() {
|
||||
<div className="widget" onClick={() => clickPlot()}>
|
||||
<i className="fa fa-solid fa-chart-simple fa-fw" />
|
||||
</div>
|
||||
<div className="widget" onClick={() => clickEdit()}>
|
||||
<i className="fa-sharp fa-solid fa-pen-to-square"></i>
|
||||
</div>
|
||||
<div className="widget no-hover">
|
||||
<i className="fa fa-solid fa-plus fa-fw" />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user