prasi-bun/app/web/src/nova/ed/ed-base.tsx

299 lines
7.7 KiB
TypeScript

import { useGlobal } from "web-utils";
import { jscript } from "../../utils/script/jscript";
import { Loading } from "../../utils/ui/loading";
import { EdLeft } from "./ed-left";
import { EdMid } from "./ed-mid";
import { EdRight } from "./ed-right";
import { EDGlobal } from "./logic/ed-global";
import { edInit } from "./logic/ed-init";
import { edRoute } from "./logic/ed-route";
import { edUndoManager } from "./logic/ed-undo";
import { EdMain } from "./panel/main/main";
import { EdPageHistoryMain } from "./panel/main/main-history";
import { EdPane } from "./panel/main/pane-resize";
import { EdPopApi } from "./panel/popup/api/api-server";
import { EdPopCode } from "./panel/popup/code/code";
import { EdPopCompGroup } from "./panel/popup/comp/comp-group";
import { EdPopComp } from "./panel/popup/comp/comp-popup";
import { EdPopPage } from "./panel/popup/page/page-popup";
import { EdPopScript } from "./panel/popup/script/pop-script";
import { EdPopSite } from "./panel/popup/site/site-popup";
import { iconVSCode } from "./panel/popup/code/icons";
import { isLocalhost } from "../../utils/ui/is-localhost";
import { w } from "../../utils/types/general";
import { edInitSync } from "./logic/ed-sync";
export const EdBase = () => {
const p = useGlobal(EDGlobal, "EDITOR");
w.editorRender = p.render;
edUndoManager(p);
if (p.status === "init") {
edInit(p);
}
edRoute(p);
const vscode_url = isLocalhost()
? "http://localhost:8443?"
: "https://prasi-vsc.avolut.com/?tkn=prasi&";
if (p.status === "load-site") {
return (
<Loading
note={
<div className="flex flex-col items-center space-y-1 relative">
<div>{p.site.name || p.site.id}</div>
<div className="pb-2">{`page-${p.status}`}</div>
{p.site.id && (
<div className="absolute top-[50px]">
<a
href={`${vscode_url}folder=/site/${p.site.id}/site/src`}
target="_blank"
className={cx(
"flex space-x-1 border items-center rounded-md px-2 cursor-pointer pointer-events-auto",
css`
svg {
width: 11px;
}
`
)}
>
<div dangerouslySetInnerHTML={{ __html: iconVSCode }} />
<div>Open VSCode</div>
</a>
</div>
)}
</div>
}
/>
);
}
if (p.status === "site-not-found" || p.status === "page-not-found") {
return (
<div className="flex fixed inset-0 items-center justify-center">
{p.status === "site-not-found" ? "Site not found" : "Page not found"}
</div>
);
}
const Editor = jscript.editor;
return (
<div
className={cx("flex flex-col flex-1", style)}
onPointerLeave={() => {
w.pointer_active = false;
}}
onPointerEnter={() => {
w.pointer_active = true;
}}
>
<div className="flex justify-between"></div>
<div className="flex flex-1 items-stretch">
{p.status === "ready" && (
<>
<EdLeft />
<EdPane type="left" min_size={200} />
</>
)}
<div className="flex flex-1 flex-col items-stretch">
<EdMid />
{p.page.history.id ? (
<EdPageHistoryMain />
) : (
<div
className={cx(
"flex flex-1 items-stretch",
p.mode === "mobile" ? mobileCSS : "bg-white"
)}
>
{p.status !== "ready" ? (
<Loading note={`page-${p.status}`} />
) : (
<>
{location.search !== "?norender" ? (
<EdMain />
) : (
<div className="flex-1 flex items-center justify-center">
Editor Render: Disabled
</div>
)}
<EdPane type="right" min_size={240} />
<EdRight />
</>
)}
</div>
)}
</div>
</div>
<>
<EdPopCode />
<EdPopScript />
<EdPopSite />
<EdPopApi />
<EdPopPage />
<EdPopCompGroup />
<EdPopComp />
</>
{Editor && !jscript.editorLoaded && (
<div
className={css`
display: none;
`}
>
<Editor
onMount={() => {
jscript.editorLoaded = true;
p.render();
}}
/>
</div>
)}
{w.offline && (
<div
className={cx(
css`
position: fixed;
bottom: 20px;
left: 0px;
right: 0px;
z-index: 999;
`,
"flex justify-center cursor-pointer"
)}
>
<div className="bg-red-500 text-white px-4 py-2 rounded-full text-sm">
Reconnecting, changes are not saved...
</div>
</div>
)}
{w.sync_too_long && (
<div
onClick={() => {
w.sync_too_long = false;
p.render();
}}
className={cx(
css`
position: fixed;
bottom: 20px;
left: 0px;
right: 0px;
z-index: 999;
`,
"flex justify-center cursor-pointer"
)}
>
<div className="space-x-2 flex bg-red-100 text-red-700 px-4 py-2 rounded-full text-sm">
<div>Sync taking too long...</div>
<div
className={cx(
css`
background: white;
`,
"rounded-full px-3 cursor-pointer border border-red-500"
)}
onClick={() => {
location.reload();
}}
>
Reload Page
</div>
</div>
</div>
)}
</div>
);
};
const style = css`
.toolbar-box {
display: flex;
align-items: stretch;
border-left: 1px solid #ececeb;
border-right: 1px solid #ececeb;
margin: 0px 0px 0px 5px;
.label {
display: flex;
user-select: none;
align-items: center;
font-size: 10px;
margin-top: 1px;
color: #999;
text-transform: uppercase;
}
.items {
display: flex;
align-items: stretch;
margin-left: 5px;
color: #555;
border-left: 1px solid transparent;
.item {
display: flex;
align-items: center;
cursor: pointer;
user-select: none;
border-right: 1px solid transparent;
padding: 5px;
border-radius: 0px;
&:hover {
background: #ececeb;
}
&.disabled {
color: #ccc;
cursor: default;
}
}
.item:last-child {
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
}
}
&.no-label {
padding-left: 0px;
margin-left: 0px;
.items {
margin-left: 0px;
}
}
&:hover {
border: 1px solid black;
.items {
color: #111;
border-left: 1px solid #ececeb;
.item {
border-right: 1px solid #ececeb;
}
}
}
}
`;
export const mobileCSS = css`
background-color: white;
background-image: linear-gradient(45deg, #fafafa 25%, transparent 25%),
linear-gradient(-45deg, #fafafa 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, #fafafa 75%),
linear-gradient(-45deg, transparent 75%, #fafafa 75%);
background-size: 20px 20px;
background-position:
0 0,
0 10px,
10px -10px,
-10px 0px;
`;