This commit is contained in:
Rizky 2023-10-28 09:27:13 +07:00
parent 0fc538b14e
commit 07ca4afb0c
7 changed files with 84 additions and 23 deletions

View File

@ -33,7 +33,7 @@ export const site_update: SAction["site"]["update"] = async function (
if (ws) if (ws)
sendWS(ws, { sendWS(ws, {
type: SyncType.Event, type: SyncType.Event,
event: "site_js_updated", event: "site_updated",
data: site, data: site,
}); });
} }

View File

@ -108,7 +108,7 @@ export const edInitSync = (p: PG) => {
p.site = site; p.site = site;
p.render(); p.render();
}, },
site_js_updated(site) { site_updated(site) {
for (const [k, v] of Object.entries(site)) { for (const [k, v] of Object.entries(site)) {
if (k === "js" || k === "js_compiled") { if (k === "js" || k === "js_compiled") {
p.site[k] = decoder.decode(decompress(v as any)); p.site[k] = decoder.decode(decompress(v as any));

View File

@ -6,7 +6,7 @@ export const EdApi = () => {
<TopBtn <TopBtn
style="slim" style="slim"
className="font-bold font-mono text-[10px]" className="font-bold font-mono text-[10px]"
popover={<EdApiServer />} popover={(popover) => <EdApiServer popover={popover} />}
placement="right" placement="right"
> >
<div className="h-[26px] flex items-center justify-center">API</div> <div className="h-[26px] flex items-center justify-center">API</div>

View File

@ -1,6 +1,7 @@
import { ReactElement, ReactNode } from "react"; import { ReactElement, ReactNode } from "react";
import { Popover } from "../../../../utils/ui/popover"; import { Popover } from "../../../../utils/ui/popover";
import { Placement } from "@floating-ui/react"; import { Placement } from "@floating-ui/react";
import { useLocal } from "web-utils";
export const TopBtn = ({ export const TopBtn = ({
children, children,
@ -18,9 +19,10 @@ export const TopBtn = ({
underlight?: string; underlight?: string;
onClick?: React.MouseEventHandler<HTMLDivElement>; onClick?: React.MouseEventHandler<HTMLDivElement>;
style?: "slim" | "normal"; style?: "slim" | "normal";
popover?: ReactElement; popover?: ReactElement | ((popover: { onClose: () => void }) => ReactElement);
placement?: Placement; placement?: Placement;
}) => { }) => {
const local = useLocal({ open: false, onClose: () => {} });
const result = ( const result = (
<div <div
className={cx( className={cx(
@ -39,7 +41,15 @@ export const TopBtn = ({
`, `,
className className
)} )}
onClick={onClick} onClick={(e) => {
if (popover) {
local.open = true;
local.render();
}
if (onClick) {
onClick(e);
}
}}
> >
{underlight && ( {underlight && (
<div <div
@ -59,7 +69,13 @@ export const TopBtn = ({
return ( return (
<Popover <Popover
autoFocus={false} autoFocus={false}
content={popover} content={typeof popover === "function" ? popover(local) : popover}
open={local.open}
onOpenChange={(open) => {
if (!open) local.onClose();
local.open = open;
local.render();
}}
placement={placement} placement={placement}
> >
{result} {result}

View File

@ -1,9 +1,14 @@
import { forwardRef } from "react"; import { forwardRef } from "react";
import { useGlobal, useLocal } from "web-utils"; import { useGlobal, useLocal } from "web-utils";
import { EDGlobal, PG } from "../../../logic/ed-global"; import { EDGlobal } from "../../../logic/ed-global";
import { checkAPI, dev } from "./api-utils"; import { apiUrl, checkAPI, dev } from "./api-utils";
export const EdApiServer = forwardRef<HTMLDivElement>((arg, ref) => { export const EdApiServer = forwardRef<
HTMLDivElement,
{
popover: { onClose: () => void };
}
>(({ popover }, ref) => {
const p = useGlobal(EDGlobal, "EDITOR"); const p = useGlobal(EDGlobal, "EDITOR");
const local = useLocal( const local = useLocal(
{ {
@ -26,6 +31,8 @@ export const EdApiServer = forwardRef<HTMLDivElement>((arg, ref) => {
} }
); );
const url = apiUrl(p);
const check = () => { const check = () => {
local.status = "checking"; local.status = "checking";
local.render(); local.render();
@ -42,6 +49,15 @@ export const EdApiServer = forwardRef<HTMLDivElement>((arg, ref) => {
local.render(); local.render();
} }
}; };
const update = async () => {
p.site.config.api_url = local.api_url;
await p.sync.site.update(p.site.id, {
config: { api_url: local.api_url },
});
check();
};
popover.onClose = update;
return ( return (
<div <div
ref={ref} ref={ref}
@ -49,21 +65,27 @@ export const EdApiServer = forwardRef<HTMLDivElement>((arg, ref) => {
> >
<div className="flex justify-between items-center pr-1"> <div className="flex justify-between items-center pr-1">
<div className="p-1">Server URL:</div> <div className="p-1">Server URL:</div>
<div className="text-[12px]"> {url && (
{local.status === "online" && ( <div className="text-[12px]">
<div className="bg-green-700 px-2 text-white">ONLINE</div> {local.status === "online" && (
)} <div className="bg-green-700 px-2 text-white">ONLINE</div>
{local.status === "offline" && ( )}
<div className="text-white px-2 bg-slate-500">OFFLINE</div> {local.status === "offline" && (
)} <div className="text-white px-2 bg-slate-500">OFFLINE</div>
{local.status === "checking" && ( )}
<div className="text-blue-500">Checking...</div> {local.status === "checking" && (
)} <div className="text-blue-500">Checking...</div>
</div> )}
</div>
)}
{!url && (
<div className="text-[12px] text-slate-500">INVALID SERVER</div>
)}
</div> </div>
<div className="flex border-y"> <div className="flex border-y">
<div className="flex flex-1 p-1 "> <div className="flex flex-1 p-1 ">
<input <input
spellCheck={false}
value={local.api_url} value={local.api_url}
onChange={(e) => { onChange={(e) => {
local.api_url = e.currentTarget.value; local.api_url = e.currentTarget.value;
@ -85,7 +107,7 @@ export const EdApiServer = forwardRef<HTMLDivElement>((arg, ref) => {
e.currentTarget.blur(); e.currentTarget.blur();
} }
}} }}
onBlur={check} onBlur={update}
placeholder="https://..." placeholder="https://..."
/> />
</div> </div>
@ -107,6 +129,7 @@ export const EdApiServer = forwardRef<HTMLDivElement>((arg, ref) => {
dev.enabled = !dev.enabled; dev.enabled = !dev.enabled;
localStorage.setItem("prasi-dev", JSON.stringify(dev)); localStorage.setItem("prasi-dev", JSON.stringify(dev));
local.render(); local.render();
check();
}} }}
> >
<span>DEV</span>{" "} <span>DEV</span>{" "}
@ -116,6 +139,7 @@ export const EdApiServer = forwardRef<HTMLDivElement>((arg, ref) => {
<input <input
type="text" type="text"
spellCheck={false}
className={cx( className={cx(
"px-1 m-1 border flex-1 font-mono text-[11px] outline-none focus:border-blue-500", "px-1 m-1 border flex-1 font-mono text-[11px] outline-none focus:border-blue-500",
dev.enabled && "border-green-700" dev.enabled && "border-green-700"

View File

@ -3,13 +3,34 @@ import { PG } from "../../../logic/ed-global";
export const dev = JSON.parse(localStorage.getItem("prasi-dev") || "{}") as { export const dev = JSON.parse(localStorage.getItem("prasi-dev") || "{}") as {
enabled: boolean; enabled: boolean;
url: string; url: string;
lastURL: { valid: boolean; url: string };
}; };
export const apiUrl = function (p: PG): string { export const apiUrl = function (p: PG): string {
if (dev.enabled) { if (dev.enabled) {
return dev.url; return dev.url;
} }
return p.site.config.api_url;
if (!dev.lastURL) {
dev.lastURL = { valid: false, url: "" };
}
if (!dev.lastURL.valid || dev.lastURL.url !== p.site.config.api_url) {
try {
const url = new URL(p.site.config.api_url);
if (url && url.hostname && url.protocol.startsWith("http")) {
dev.lastURL.valid = true;
return url.toString();
}
dev.lastURL.valid = false;
} catch (e) {
dev.lastURL.valid = false;
}
}
if (dev.lastURL.valid) return p.site.config.api_url;
return "";
}; };
export const checkAPI = (p: PG) => { export const checkAPI = (p: PG) => {

View File

@ -82,7 +82,7 @@ export const clientStartSync = async (arg: {
id: string; id: string;
sv_local: Uint8Array; sv_local: Uint8Array;
}) => void; }) => void;
site_js_updated: ( site_updated: (
arg: Partial< arg: Partial<
Omit<ESite, "js" | "js_compiled"> & { Omit<ESite, "js" | "js_compiled"> & {
js: Uint8Array; js: Uint8Array;