This commit is contained in:
2023-06-26 21:51:50 +08:00
parent 4a9687a045
commit ddf3a0a878
11 changed files with 157 additions and 14 deletions

View File

@@ -3,6 +3,7 @@ import { GlobalCtx } from "./GlobalContext.tsx";
import Fab from "preact-material-components/Fab";
import Icon from "preact-material-components/Icon";
import { set_state } from "../server/state.ts";
import t from "../server/i18n.ts";
export type NewTaskProps = {
show: boolean;
@@ -15,15 +16,22 @@ export default class NewTask extends Component<NewTaskProps> {
if (!this.props.show) return null;
return (
<div class="new_task">
<Fab class="close" mini={true}>
<Icon
onClick={() => {
set_state((p) => p.slice(0, p.length - 4));
}}
>
close
</Icon>
</Fab>
<div class="container">
<div class="top">
<div class="title">{t("task.add")}</div>
<Fab class="close" mini={true}>
<Icon
onClick={() => {
set_state((p) => p.slice(0, p.length - 4));
}}
>
close
</Icon>
</Fab>
</div>
<div class="content"></div>
<div class="bottom"></div>
</div>
</div>
);
}

View File

@@ -14,6 +14,7 @@ import NewTask from "../components/NewTask.tsx";
import { parse_int } from "../server/parse.ts";
import { detect_darkmode } from "../server/dark.ts";
import { registeServiceWorker } from "../server/sw.ts";
import { initCfg } from "../server/cfg.ts";
export type ContainerProps = {
i18n: I18NMap;
@@ -75,6 +76,7 @@ export default class Container extends Component<ContainerProps> {
console.error(e);
},
);
initCfg();
}, []);
return (
<div>

View File

@@ -1,8 +1,13 @@
import { Handlers } from "$fresh/server.ts";
import { ConfigType, load_settings, save_settings } from "../../config.ts";
import { get_cfg_path, get_task_manager } from "../../server.ts";
import {
ConfigClientSocketData,
ConfigSeverSocketData,
} from "../../server/config.ts";
import { parse_bool } from "../../server/parse_form.ts";
import { return_json } from "../../server/utils.ts";
import { ExitTarget } from "../../signal_handler.ts";
const UNSAFE_TYPE: (keyof ConfigType)[] = [
"base",
@@ -20,7 +25,51 @@ export const handler: Handlers = {
const u = new URL(req.url);
const current = await parse_bool(u.searchParams.get("current"), false);
if (current) {
const type = u.searchParams.get("type");
const t = get_task_manager();
if (type === "ws") {
const { socket, response } = Deno.upgradeWebSocket(req);
const handle = (e: CustomEvent<ConfigType>) => {
sendMessage({ type: "cfg", cfg: e.detail });
};
const sendMessage = (mes: ConfigSeverSocketData) => {
if (socket.readyState === socket.OPEN) {
socket.send(JSON.stringify(mes));
}
};
const close_handle = () => {
sendMessage({ type: "close" });
socket.close();
};
const removeListener = () => {
t.removeEventListener("current_cfg_updated", handle);
ExitTarget.removeEventListener("close", close_handle);
};
socket.onclose = () => {
removeListener();
};
socket.onerror = () => {
removeListener();
console.error("WebSocket error.");
};
socket.onmessage = (e) => {
try {
const d: ConfigClientSocketData = JSON.parse(e.data);
if (d.type == "close") {
sendMessage({ type: "close" });
socket.close();
}
} catch (_) {
null;
}
};
socket.onopen = () => {
t.addEventListener("current_cfg_updated", handle);
ExitTarget.addEventListener("close", close_handle);
sendMessage({ type: "cfg", cfg: t.cfg.to_json() });
};
return response;
}
return return_json(t.cfg.to_json());
}
const path = get_cfg_path();
@@ -35,16 +84,21 @@ export const handler: Handlers = {
const m = get_task_manager();
let is_unsafe = false;
const cfg = await load_settings(path);
let updated = false;
Object.getOwnPropertyNames(d).forEach((k) => {
if (UNSAFE_TYPE2.indexOf(k) === -1) {
cfg._data[k] = d[k];
m.cfg._data[k] = d[k];
updated = true;
} else {
cfg._data[k] = d[k];
is_unsafe = true;
}
});
await save_settings(path, cfg, m.force_aborts);
if (updated) {
m.dispatchEvent("current_cfg_updated", m.cfg.to_json());
}
return return_json({ is_unsafe });
} else {
return new Response("Bad Request", { status: 400 });

View File

@@ -32,7 +32,9 @@ export const handler: Handlers<Task[]> = {
ExitTarget.removeEventListener("close", close_handle);
};
function sendMessage(mes: TaskServerSocketData) {
socket.send(JSON.stringify(mes));
if (socket.readyState === socket.OPEN) {
socket.send(JSON.stringify(mes));
}
}
socket.onclose = () => {
removeListener();

25
server/cfg.ts Normal file
View File

@@ -0,0 +1,25 @@
import { signal } from "@preact/signals";
import { ConfigType } from "../config.ts";
import { get_ws_host } from "./utils.ts";
import { ConfigClientSocketData, ConfigSeverSocketData } from "./config.ts";
export const cfg = signal<ConfigType | undefined>(undefined);
export function initCfg() {
const ws = new WebSocket(`${get_ws_host()}/api/config?current=1&type=ws`);
console.log(ws);
function sendMessage(mes: ConfigClientSocketData) {
ws.send(JSON.stringify(mes));
}
ws.onmessage = (e) => {
const d: ConfigSeverSocketData = JSON.parse(e.data);
if (d.type === "close") {
ws.close();
} else if (d.type === "cfg") {
cfg.value = d.cfg;
}
};
self.addEventListener("beforeunload", () => {
sendMessage({ type: "close" });
});
}

7
server/config.ts Normal file
View File

@@ -0,0 +1,7 @@
import { ConfigType } from "../config.ts";
export type ConfigClientSocketData = { type: "close" };
export type ConfigSeverSocketData = { type: "close" } | {
type: "cfg";
cfg: ConfigType;
};

View File

@@ -224,3 +224,45 @@ body {
right: 50px;
bottom: 50px;
}
div.new_task {
overflow: hidden;
width: 100vw;
height: calc(100vh - 64px);
max-width: 100vw;
max-height: calc(100vh - 64px);
}
div.new_task>div.container {
position: relative;
margin: 5% 10%;
height: calc(100% - 10% - 64px);
min-width: 400px;
width: calc(100% - 20%);
}
div.new_task .top {
display: flex;
min-height: 40px;
line-height: 40px;
justify-content: space-between;
align-items: center;
}
div.new_task .top .title {
margin-left: 40px;
width: calc(100% - 80px);
font-size: 24px;
text-align: center;
}
div.new_task>div.container>div.content {
overflow-y: auto;
height: calc(100% - 80px);
min-height: 300px;
}
div.new_task>div.container>div.bottom {
line-height: 40px;
min-height: 40px;
}

View File

@@ -1,3 +1,3 @@
html::-webkit-scrollbar {
::-webkit-scrollbar {
display: none;
}

View File

@@ -1,5 +1,5 @@
import { Client } from "./client.ts";
import { Config } from "./config.ts";
import { Config, ConfigType } from "./config.ts";
import { EhDb } from "./db.ts";
import { MeiliSearchServer } from "./meilisearch.ts";
import { check_running } from "./pid_check.ts";
@@ -28,6 +28,7 @@ export class AlreadyClosedError extends Error {
}
type EventMap = {
current_cfg_updated: ConfigType;
new_task: Task;
task_started: Task;
task_finished: Task;

View File

@@ -4,5 +4,6 @@
"running": "Running",
"waiting": "Waiting",
"failed": "Failed",
"finished": "Finished"
"finished": "Finished",
"add": "Add task"
}

View File

@@ -4,5 +4,6 @@
"running": "运行中",
"waiting": "等待中",
"failed": "已失败",
"finished": "已完成"
"finished": "已完成",
"add": "新建任务"
}