wip fix
This commit is contained in:
parent
86ef473710
commit
db45f936fc
File diff suppressed because one or more lines are too long
|
|
@ -15,6 +15,7 @@
|
|||
"@monaco-editor/react": "^4.6.0",
|
||||
"@paralleldrive/cuid2": "2.2.2",
|
||||
"react-contenteditable": "^3.3.7",
|
||||
"react-dropzone": "14.2.3",
|
||||
"@parcel/packager-wasm": "^2.10.3",
|
||||
"@parcel/service-worker": "^2.10.3",
|
||||
"recast": "^0.23.4",
|
||||
|
|
|
|||
|
|
@ -46,11 +46,19 @@ export const apiProxy = (api_url: string) => {
|
|||
}
|
||||
|
||||
if (api_ref) {
|
||||
if (actionName === "_raw") {
|
||||
const url = `${base_url}${rest.join("")}`;
|
||||
|
||||
const result = await fetchSendApi(url, rest);
|
||||
resolve(result);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!api_ref.apiEntry) api_ref.apiEntry = {};
|
||||
if (api_ref.apiEntry && !api_ref.apiEntry[actionName]) {
|
||||
reject(
|
||||
`API ${actionName.toString()} not found, existing API: \n - ${Object.keys(
|
||||
api_ref || {}
|
||||
api_ref.apiEntry || {}
|
||||
).join("\n - ")}`
|
||||
);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ export const Root: FC<{}> = ({}) => {
|
|||
prasiContext.render = local.render;
|
||||
|
||||
const Provider = GlobalContext.Provider as FC<{ value: any; children: any }>;
|
||||
|
||||
const found = local.router.lookup(location.pathname);
|
||||
|
||||
if (found) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import { EdPopScript } from "./panel/popup/script/pop-script";
|
|||
import { EdPopSite } from "./panel/popup/site/site-popup";
|
||||
import { EdPageHistoryMain } from "./panel/main/main-history";
|
||||
import { jscript } from "../../utils/script/jscript";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export const EdBase = () => {
|
||||
const p = useGlobal(EDGlobal, "EDITOR");
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { useGlobal } from "web-utils";
|
|||
import { ResponsiveToggle } from "./panel/header/right/responsive-toggle";
|
||||
import { EdCompEditable } from "./panel/header/mid/comp-editable";
|
||||
import { MobileQRButton } from "./panel/side/style/tools/mobile-qr";
|
||||
import { EdFileBrowser } from "./panel/file/file-browser";
|
||||
|
||||
export const EdMid: FC<{}> = () => {
|
||||
const p = useGlobal(EDGlobal, "EDITORF");
|
||||
|
|
@ -37,6 +38,7 @@ export const EdMid: FC<{}> = () => {
|
|||
</div>
|
||||
</div>
|
||||
<div className="flex items-stretch flex-1 justify-end">
|
||||
<EdFileBrowser />
|
||||
{p.site.responsive !== "desktop-only" && <MobileQRButton />}
|
||||
<label className=" text-slate-400 flex items-center pr-1">
|
||||
<div className=" px-1"> Zoom</div>
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ export const EDGlobal = {
|
|||
open: {} as Record<string, string[]>,
|
||||
},
|
||||
popup: {
|
||||
file: { enabled: false },
|
||||
file: { enabled: false, open: true },
|
||||
code: {
|
||||
init: false,
|
||||
open: false,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,119 @@
|
|||
import { useCallback, useEffect } from "react";
|
||||
import { useDropzone } from "react-dropzone";
|
||||
import { useGlobal, useLocal } from "web-utils";
|
||||
import { apiProxy } from "../../../../base/load/api/api-proxy";
|
||||
import { Modal } from "../../../../utils/ui/modal";
|
||||
import { EDGlobal } from "../../logic/ed-global";
|
||||
import { EdFileTree } from "./file-tree";
|
||||
import { FEntry } from "./type";
|
||||
|
||||
export const EdFileBrowser = () => {
|
||||
const p = useGlobal(EDGlobal, "EDITOR");
|
||||
const local = useLocal({
|
||||
entry: {} as Record<string, FEntry[]>,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!p.script.api && p.site.config?.api_url) {
|
||||
p.script.api = apiProxy(p.site.config.api_url);
|
||||
p.render();
|
||||
}
|
||||
|
||||
p.script.api._raw(`/_file/?dir`).then((e: FEntry[]) => {
|
||||
if (Array.isArray(e)) {
|
||||
local.entry = { "/": e };
|
||||
p.ui.popup.file.enabled = true;
|
||||
p.render();
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
const onDrop = useCallback((acceptedFiles: any[]) => {
|
||||
console.log(acceptedFiles);
|
||||
}, []);
|
||||
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
||||
onDrop,
|
||||
noClick: true,
|
||||
});
|
||||
|
||||
if (!p.ui.popup.file.enabled) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="items-center flex px-2 cursor-pointer border border-transparent hover:bg-slate-200 transition-all hover:border-black"
|
||||
onClick={() => {
|
||||
p.ui.popup.file.open = true;
|
||||
p.render();
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="12"
|
||||
height="12"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M20 10a1 1 0 001-1V6a1 1 0 00-1-1h-2.5a1 1 0 01-.8-.4l-.9-1.2A1 1 0 0015 3h-2a1 1 0 00-1 1v5a1 1 0 001 1zM20 21a1 1 0 001-1v-3a1 1 0 00-1-1h-2.9a1 1 0 01-.88-.55l-.42-.85a1 1 0 00-.92-.6H13a1 1 0 00-1 1v5a1 1 0 001 1zM3 5a2 2 0 002 2h3"></path>
|
||||
<path d="M3 3v13a2 2 0 002 2h3"></path>
|
||||
</svg>{" "}
|
||||
<div className="pl-1">Files</div>
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
fade={false}
|
||||
open={p.ui.popup.file.open}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
p.ui.popup.file.open = false;
|
||||
p.render();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div
|
||||
{...getRootProps()}
|
||||
className={cx(
|
||||
"bg-white select-none fixed inset-[50px] flex",
|
||||
css`
|
||||
outline: none;
|
||||
`
|
||||
)}
|
||||
>
|
||||
<input {...getInputProps()} />
|
||||
{isDragActive && (
|
||||
<div className="absolute inset-0 flex items-center justify-center flex-col bg-blue-50 border-4 border-blue-500">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
className="lucide lucide-upload"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"></path>
|
||||
<path d="M17 8L12 3 7 8"></path>
|
||||
<path d="M12 3L12 15"></path>
|
||||
</svg>
|
||||
<div>Drag Here to Upload</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-1 items-stretch">
|
||||
<div className="flex min-w-[200px] border-r">
|
||||
<EdFileTree entry={local.entry} />
|
||||
</div>
|
||||
<div>Moko</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import {
|
||||
MultiBackend,
|
||||
NodeModel,
|
||||
Tree as DNDTree,
|
||||
getBackendOptions,
|
||||
} from "@minoru/react-dnd-treeview";
|
||||
import { DndProvider } from "react-dnd";
|
||||
import { FEntry } from "./type";
|
||||
import { FC } from "react";
|
||||
|
||||
const Tree = DNDTree<FEntry>;
|
||||
|
||||
export const EdFileTree: FC<{ entry: Record<string, FEntry[]> }> = ({
|
||||
entry,
|
||||
}) => {
|
||||
const tree: NodeModel<FEntry>[] = [];
|
||||
for (const [path, entries] of Object.entries(entry)) {
|
||||
const arr = path.split("/");
|
||||
const name = arr.pop() || "/";
|
||||
tree.push({ id: path, text: name, parent: arr.join("/") });
|
||||
for (const e of entries) {
|
||||
if (e.type === "dir") {
|
||||
tree.push({
|
||||
id: (path === "/" ? "" : path) + "/" + e.name,
|
||||
text: e.name,
|
||||
parent: path,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<DndProvider backend={MultiBackend} options={getBackendOptions()}>
|
||||
<Tree
|
||||
tree={tree}
|
||||
dragPreviewRender={() => <></>}
|
||||
rootId=""
|
||||
initialOpen={true}
|
||||
onDrop={async (newTree, opt) => {}}
|
||||
render={(node, { depth, isOpen, onToggle, hasChild }) => (
|
||||
<div
|
||||
className={cx(css`
|
||||
padding-left: ${(depth * 10) + 10}px;
|
||||
`)}
|
||||
>
|
||||
{node.text}
|
||||
</div>
|
||||
)}
|
||||
></Tree>
|
||||
</DndProvider>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export type FEntry = {
|
||||
name: string;
|
||||
size: number;
|
||||
type: "dir" | "file";
|
||||
};
|
||||
Loading…
Reference in New Issue