regular
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,8 @@
|
|||||||
/html.html
|
/html.html
|
||||||
/json
|
/json
|
||||||
/hours.json
|
/hours.json
|
||||||
|
/regular.json
|
||||||
|
/record.json
|
||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
|
|||||||
@@ -11,10 +11,15 @@ interface ConflictsTmp {
|
|||||||
interface IndexToElement {
|
interface IndexToElement {
|
||||||
[index: string]: HTMLInputElement;
|
[index: string]: HTMLInputElement;
|
||||||
}
|
}
|
||||||
|
interface IndexToCell {
|
||||||
|
[index: string]: HTMLTableCellElement;
|
||||||
|
}
|
||||||
|
|
||||||
const indexToElement: IndexToElement = {};
|
const indexToElement: IndexToElement = {};
|
||||||
|
const indexToCell: IndexToCell = {};
|
||||||
const conflicts: Conflicts = {};
|
const conflicts: Conflicts = {};
|
||||||
const marks: (HTMLInputElement | null)[][] = [];
|
const marks: (HTMLInputElement | null)[][] = [];
|
||||||
|
const tds: (HTMLTableCellElement | null)[][] = [];
|
||||||
|
|
||||||
const downloadObjectAsJson = (exportObj: any, exportName: string) => {
|
const downloadObjectAsJson = (exportObj: any, exportName: string) => {
|
||||||
const dataStr =
|
const dataStr =
|
||||||
@@ -33,6 +38,8 @@ const Timetable = ({
|
|||||||
disableNetwork = false,
|
disableNetwork = false,
|
||||||
disableConflictCheck = false,
|
disableConflictCheck = false,
|
||||||
replaceInputType = "checkbox",
|
replaceInputType = "checkbox",
|
||||||
|
apiRecordEndPoint = "/api/record",
|
||||||
|
openRecordMode = false,
|
||||||
}) => {
|
}) => {
|
||||||
const [editable, setEditable] = React.useState(true);
|
const [editable, setEditable] = React.useState(true);
|
||||||
const ref = React.useRef();
|
const ref = React.useRef();
|
||||||
@@ -102,6 +109,8 @@ const Timetable = ({
|
|||||||
|
|
||||||
// empty marks
|
// empty marks
|
||||||
marks.length = 0;
|
marks.length = 0;
|
||||||
|
// empty tds
|
||||||
|
tds.length = 0;
|
||||||
|
|
||||||
const table = target.children[0];
|
const table = target.children[0];
|
||||||
table.setAttribute("border", "1");
|
table.setAttribute("border", "1");
|
||||||
@@ -112,8 +121,9 @@ const Timetable = ({
|
|||||||
for (const tr_index in tbody.children) {
|
for (const tr_index in tbody.children) {
|
||||||
const tr = tbody.children[tr_index];
|
const tr = tbody.children[tr_index];
|
||||||
const row: (HTMLInputElement | null)[] = [];
|
const row: (HTMLInputElement | null)[] = [];
|
||||||
|
const rowTD: (HTMLTableCellElement | null)[] = [];
|
||||||
for (const td_index in tr.children) {
|
for (const td_index in tr.children) {
|
||||||
const td = tr.children[td_index];
|
const td: HTMLTableCellElement = tr.children[td_index];
|
||||||
if (td.tagName !== "TD") continue;
|
if (td.tagName !== "TD") continue;
|
||||||
if (td.getAttribute("bgcolor")?.toUpperCase() !== "#39CEFF") {
|
if (td.getAttribute("bgcolor")?.toUpperCase() !== "#39CEFF") {
|
||||||
row.push(null);
|
row.push(null);
|
||||||
@@ -135,10 +145,13 @@ const Timetable = ({
|
|||||||
td.innerHTML = "";
|
td.innerHTML = "";
|
||||||
td.appendChild(input);
|
td.appendChild(input);
|
||||||
indexToElement[index] = input;
|
indexToElement[index] = input;
|
||||||
|
indexToCell[index] = td;
|
||||||
|
|
||||||
row.push(input);
|
row.push(input);
|
||||||
|
rowTD.push(td);
|
||||||
}
|
}
|
||||||
marks.push(row);
|
marks.push(row);
|
||||||
|
tds.push(rowTD);
|
||||||
// console.log("marks", marks);
|
// console.log("marks", marks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +172,20 @@ const Timetable = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const refresh = async () => {
|
const refresh = async () => {
|
||||||
const json = await get(`/api/record?name=${user}`);
|
const json = await get(`${apiRecordEndPoint}?name=${user}`);
|
||||||
|
if (openRecordMode) {
|
||||||
|
for (const index in json) {
|
||||||
|
const input = indexToElement[index];
|
||||||
|
const td= indexToCell[index];
|
||||||
|
if (json[index] !== user) {
|
||||||
|
td.innerHTML = json[index]
|
||||||
|
} else {
|
||||||
|
input.checked = true;
|
||||||
|
input.disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
const occupied: string[] = json.occupied;
|
const occupied: string[] = json.occupied;
|
||||||
const myselect: string[] = json.myselect;
|
const myselect: string[] = json.myselect;
|
||||||
console.log(json);
|
console.log(json);
|
||||||
@@ -172,6 +198,7 @@ const Timetable = ({
|
|||||||
const includes = myselect.includes(index);
|
const includes = myselect.includes(index);
|
||||||
indexToElement[index].checked = includes;
|
indexToElement[index].checked = includes;
|
||||||
// after checked, find conflicts input
|
// after checked, find conflicts input
|
||||||
|
if (disableConflictCheck) continue;
|
||||||
if (includes) {
|
if (includes) {
|
||||||
for (const input of conflicts[index]) {
|
for (const input of conflicts[index]) {
|
||||||
if (input.name === index) continue;
|
if (input.name === index) continue;
|
||||||
@@ -232,7 +259,7 @@ const Timetable = ({
|
|||||||
overflow: "scroll",
|
overflow: "scroll",
|
||||||
}}
|
}}
|
||||||
onInput={handleInput}
|
onInput={handleInput}
|
||||||
></div>
|
></div>{" "}
|
||||||
<div style={{ display: "none" }} id="download-dom"></div>
|
<div style={{ display: "none" }} id="download-dom"></div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
export default {
|
const obj = {
|
||||||
begin: false,
|
begin: false,
|
||||||
limit: 2,
|
limit: 2,
|
||||||
}
|
token: process.env.TOKEN || "woshimima",
|
||||||
|
};
|
||||||
|
export default obj;
|
||||||
|
|||||||
16
pages/api/regular.ts
Normal file
16
pages/api/regular.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
import { regular } from "@/store";
|
||||||
|
import config from "@/config";
|
||||||
|
|
||||||
|
export default function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
if (req.method === "POST") {
|
||||||
|
if (req.headers.token !== config.token) {
|
||||||
|
res.status(403).json({
|
||||||
|
error: "wrong token",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
regular.update(req.body);
|
||||||
|
}
|
||||||
|
res.status(200).json(regular.get());
|
||||||
|
}
|
||||||
32
pages/regular.tsx
Normal file
32
pages/regular.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Head from "next/head";
|
||||||
|
import Timetable from "@/components/Timetable";
|
||||||
|
import UserInputWrap from "@/components/UserInputWrap";
|
||||||
|
|
||||||
|
const ReportPage = () => {
|
||||||
|
const [user, setUser] = React.useState("");
|
||||||
|
const [begin, setBegin] = React.useState(false);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>Create Next App</title>
|
||||||
|
<meta name="description" content="Generated by create next app" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
</Head>
|
||||||
|
<main>
|
||||||
|
<UserInputWrap setUser={setUser}>
|
||||||
|
<Timetable
|
||||||
|
user={user}
|
||||||
|
disableConflictCheck={true}
|
||||||
|
disableNetwork={true}
|
||||||
|
apiRecordEndPoint="/api/regular"
|
||||||
|
openRecordMode={true}
|
||||||
|
/>
|
||||||
|
</UserInputWrap>
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ReportPage;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import fs from "fs";
|
import fs, { readFileSync } from "fs";
|
||||||
import { MongoClient } from "mongodb";
|
import { MongoClient } from "mongodb";
|
||||||
import util from "util";
|
import util from "util";
|
||||||
|
|
||||||
@@ -6,9 +6,15 @@ const write = util.promisify(fs.writeFile);
|
|||||||
const read = util.promisify(fs.readFile);
|
const read = util.promisify(fs.readFile);
|
||||||
|
|
||||||
class Store {
|
class Store {
|
||||||
|
filename: string;
|
||||||
record: Record<string, string>;
|
record: Record<string, string>;
|
||||||
constructor() {
|
constructor(filename: string) {
|
||||||
this.record = {};
|
this.filename = filename;
|
||||||
|
try {
|
||||||
|
this.record = JSON.parse(readFileSync(filename, "utf8"));
|
||||||
|
} catch {
|
||||||
|
this.record = {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public get() {
|
public get() {
|
||||||
return this.record;
|
return this.record;
|
||||||
@@ -19,15 +25,8 @@ class Store {
|
|||||||
public delete(key: string) {
|
public delete(key: string) {
|
||||||
delete this.record[key];
|
delete this.record[key];
|
||||||
}
|
}
|
||||||
public update(record: Record<string, string>) {
|
public async update(record: Record<string, string>) {
|
||||||
for (const key in record) {
|
await write(this.filename, JSON.stringify(this.record), "utf8");
|
||||||
this.record[key] = record[key];
|
|
||||||
}
|
|
||||||
for (const key in this.record) {
|
|
||||||
if (record[key] === undefined) {
|
|
||||||
delete this.record[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,4 +51,5 @@ class HTML {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const html = new HTML();
|
export const html = new HTML();
|
||||||
export const store = new Store();
|
export const store = new Store("store.json");
|
||||||
|
export const regular = new Store("regular.json");
|
||||||
|
|||||||
Reference in New Issue
Block a user