PIbd-22_Filippov_D.S._SUBD_.../server.js
2024-05-24 03:22:28 +04:00

738 lines
28 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//#region import
var http = require('http');
var fs = require('fs');
const express = require('express');
const WebSocket = require('ws');
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
server.listen(80, () => {
console.log(`Server started on port ${server.address().port} :)`);
});
const pg = require('pg');
const { Pool, Client } = pg
const pool = new Pool({
user: 'd',
password: '123',
host: '192.168.56.104',
port: 5432,
database: 'mydb',
})
async function query(q) {
return (await pool.query(q)).rows;
}
//#endregion
//#region Server CRUD Interface
function getTables() {
return query(`SELECT table_name
FROM information_schema.tables
WHERE table_schema='public'
AND table_type='BASE TABLE';`);
}
async function getTable(data) {
let table = data[0], filters = data[1];
if (table == "moovie") {
//q =
}
let q = `select * from ` + table;
let isFilters = false;
if (Array.isArray(filters) && filters.length != 0) {
q += " WHERE ";
filters.forEach(f => {
isFilters = true;
let n = typeof f[1] == "string" && f[1].length > 1 && (f[1][0] == ">" || f[1][0] == "<");
if (f[0] != null && f[1] != "") {
if (typeof f[1] == "number")
q += f[0] + "=" + f[1] + " AND ";
else
q += f[0] + (n ? "" : " LIKE '%") + f[1] + (n ? "" : "%'") + " AND ";
}
})
}
if (isFilters) q = q.slice(0, -4);
let querry = q;
try {
q = await query(q);
} catch {
return null;
}
q[q.length] = table;
q["querry"] = querry;
return q;
}
async function getDifficultMoovies() {
let q = `SELECT moovie_id, moovie_name, rating_rate, moovie_productionYear, moovie_about, moovie_timeAdded, subscription_name, subscription_price
FROM moovie
INNER JOIN rating ON moovie.moovie_id = rating.rating__fk_moovie
INNER JOIN subscription ON subscription_id = (
select customer__fk_subsription from customer
where customer_id = 9
)
where moovie_id IN (
select mooviesubscription_fk_moovie_id from moovieSubscription
Where moovieSubscription_fk_subscription_id = (
select customer__fk_subsription from customer
where customer_id = 9
)
);
`;
let querry = q;
q = await query(q);
q["querry"] = querry;
return q;
}
//#region Generate Interface
function createTabless() {
let q = `DROP TABLE if exists moovie cascade;
DROP SEQUENCE if exists SEQ_moovie;
CREATE SEQUENCE SEQ_moovie INCREMENT BY 1 START WITH 1;
CREATE TABLE moovie (
moovie_id integer PRIMARY KEY DEFAULT nextval('SEQ_moovie'),
moovie_name varchar(50) NOT NULL,
moovie_productionYear integer NOT NULL,
moovie_about varchar(50) NOT NULL,
moovie_timeAdded date NOT NULL
);
DROP TABLE if exists genre cascade;
DROP SEQUENCE if exists SEQ_genre;
CREATE SEQUENCE SEQ_genre INCREMENT BY 1 START WITH 1;
CREATE TABLE genre (
genre_id integer PRIMARY KEY DEFAULT nextval('SEQ_genre'),
genre_name varchar(50) NOT NULL
);
DROP TABLE if exists moovieGenre cascade;
DROP SEQUENCE if exists SEQ_moovieGenre;
CREATE SEQUENCE SEQ_moovieGenre INCREMENT BY 1 START WITH 1;
CREATE TABLE moovieGenre (
moovieGenre_id integer PRIMARY KEY DEFAULT nextval('SEQ_moovieGenre'),
moovieGenre_fk_moovie_id int REFERENCES moovie (moovie_id),
moovieGenre_fk_genre_id int REFERENCES genre (genre_id)
);
DROP TABLE if exists subscription cascade;
DROP SEQUENCE if exists SEQ_subscription;
CREATE SEQUENCE SEQ_subscription INCREMENT BY 1 START WITH 1;
CREATE TABLE subscription (
subscription_id integer PRIMARY KEY DEFAULT nextval('SEQ_subscription'),
subscription_name varchar(50) NOT NULL,
subscription_price integer NOT NULL,
subscription_fk_parentSubscription_id int NULL REFERENCES subscription (subscription_id)
);
DROP TABLE if exists moovieSubscription cascade;
DROP SEQUENCE if exists SEQ_moovieSubscription;
CREATE SEQUENCE SEQ_moovieSubscription INCREMENT BY 1 START WITH 1;
CREATE TABLE moovieSubscription (
moovieSubscription_id integer PRIMARY KEY DEFAULT nextval('SEQ_moovieSubscription'),
moovieSubscription_fk_moovie_id int REFERENCES moovie (moovie_id),
moovieSubscription_fk_subscription_id int REFERENCES subscription (subscription_id)
);
DROP TABLE if exists customer cascade;
DROP SEQUENCE if exists SEQ_customer;
CREATE SEQUENCE SEQ_customer INCREMENT BY 1 START WITH 1;
CREATE TABLE customer (
customer_id integer PRIMARY KEY DEFAULT nextval('SEQ_customer'),
customer_name varchar(50) NOT NULL,
customer_email varchar(50) NOT NULL,
customer_password varchar(50) NOT NULL,
customer_age int NOT NULL,
customer_phone varchar(50) NOT NULL,
customer__fk_subsription int NOT NULL REFERENCES subscription (subscription_id)
);
DROP TABLE if exists rating cascade;
DROP SEQUENCE if exists SEQ_rating;
CREATE SEQUENCE SEQ_rating INCREMENT BY 1 START WITH 1;
CREATE TABLE rating (
rating_id integer PRIMARY KEY DEFAULT nextval('SEQ_rating'),
rating_rate int NOT NULL,
rating_fk_user int NOT NULL REFERENCES customer (customer_id),
rating__fk_moovie int NOT NULL REFERENCES moovie (moovie_id)
);
COMMENT ON TABLE public.moovie IS 'Это таблица о Фильмах';
ALTER TABLE public.moovie ALTER COLUMN moovie_name SET NOT NULL;
ALTER TABLE public.moovie ALTER COLUMN moovie_name SET DEFAULT 'Название фильма';
ALTER TABLE public.moovie ALTER COLUMN moovie_productionYear SET NOT NULL;
--ALTER TABLE public.moovie ALTER COLUMN moovie_productionYear SET DEFAULT 2000;
ALTER TABLE public.moovie ALTER COLUMN moovie_about SET NOT NULL;
ALTER TABLE public.moovie ALTER COLUMN moovie_about SET DEFAULT 'Описание фильма';
ALTER TABLE public.moovie ALTER COLUMN moovie_timeAdded SET NOT NULL;
ALTER TABLE public.moovie ALTER COLUMN moovie_timeAdded SET DEFAULT '2024-06-16 12:00:00';
COMMENT ON TABLE public.genre IS 'Это таблица о Жанрах фильмов';
ALTER TABLE public.genre ALTER COLUMN genre_name SET NOT NULL;
ALTER TABLE public.genre ALTER COLUMN genre_name SET DEFAULT 'Название жанра';
COMMENT ON TABLE public.moovieGenre IS 'Это таблица много ко многим для таблиц Фильм и Жанр';
ALTER TABLE public.moovieGenre ALTER COLUMN moovieGenre_fk_moovie_id SET NOT NULL;
ALTER TABLE public.moovieGenre ALTER COLUMN moovieGenre_fk_genre_id SET NOT NULL;
COMMENT ON TABLE public.subscription IS 'Это таблица о подписках на фильмы';
ALTER TABLE public.subscription ALTER COLUMN subscription_name SET NOT NULL;
ALTER TABLE public.subscription ALTER COLUMN subscription_name SET DEFAULT 'Подписка';
ALTER TABLE public.subscription ALTER COLUMN subscription_price SET NOT NULL;
ALTER TABLE public.subscription ALTER COLUMN subscription_price SET DEFAULT 999;
COMMENT ON TABLE public.customer IS 'Это таблица о пользователях';
ALTER TABLE public.customer ALTER COLUMN customer_name SET NOT NULL;
ALTER TABLE public.customer ALTER COLUMN customer_name SET DEFAULT 'Пользователь 1';
ALTER TABLE public.customer ALTER COLUMN customer_password SET NOT NULL;
ALTER TABLE public.customer ALTER COLUMN customer_password SET DEFAULT '123';
ALTER TABLE public.customer ALTER COLUMN customer_age SET NOT NULL;
ALTER TABLE public.customer ALTER COLUMN customer_age SET DEFAULT '18';
ALTER TABLE public.customer ALTER COLUMN customer_phone SET NOT NULL;
ALTER TABLE public.customer ALTER COLUMN customer__fk_subsription SET NOT NULL;
COMMENT ON TABLE public.rating IS 'Это таблица об отзывах про фильмы';
ALTER TABLE public.rating ALTER COLUMN rating_rate SET NOT NULL;
ALTER TABLE public.rating ALTER COLUMN rating_rate SET DEFAULT 10;
ALTER TABLE public.rating ALTER COLUMN rating_fk_user SET NOT NULL;
ALTER TABLE public.rating ALTER COLUMN rating_fk_user SET DEFAULT 0;
ALTER TABLE public.rating ALTER COLUMN rating__fk_moovie SET NOT NULL;
ALTER TABLE public.rating ALTER COLUMN rating__fk_moovie SET DEFAULT 0;
ALTER TABLE public.mooviegenre DROP CONSTRAINT mooviegenre_mooviegenre_fk_genre_id_fkey;
ALTER TABLE public.mooviegenre ADD CONSTRAINT mooviegenre_mooviegenre_fk_genre_id_fkey FOREIGN KEY (mooviegenre_fk_genre_id) REFERENCES public.genre(genre_id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.mooviegenre DROP CONSTRAINT mooviegenre_mooviegenre_fk_moovie_id_fkey;
ALTER TABLE public.mooviegenre ADD CONSTRAINT mooviegenre_mooviegenre_fk_moovie_id_fkey FOREIGN KEY (mooviegenre_fk_moovie_id) REFERENCES public.moovie(moovie_id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.mooviesubscription DROP CONSTRAINT mooviesubscription_mooviesubscription_fk_moovie_id_fkey;
ALTER TABLE public.mooviesubscription ADD CONSTRAINT mooviesubscription_mooviesubscription_fk_moovie_id_fkey FOREIGN KEY (mooviesubscription_fk_moovie_id) REFERENCES public.moovie(moovie_id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.mooviesubscription DROP CONSTRAINT mooviesubscription_mooviesubscription_fk_subscription_id_fkey;
ALTER TABLE public.mooviesubscription ADD CONSTRAINT mooviesubscription_mooviesubscription_fk_subscription_id_fkey FOREIGN KEY (mooviesubscription_fk_subscription_id) REFERENCES public."subscription"(subscription_id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public."subscription" DROP CONSTRAINT subscription_subscription_fk_parentsubscription_id_fkey;
ALTER TABLE public."subscription" ADD CONSTRAINT subscription_subscription_fk_parentsubscription_id_fkey FOREIGN KEY (subscription_fk_parentsubscription_id) REFERENCES public."subscription"(subscription_id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.customer DROP CONSTRAINT customer_customer__fk_subsription_fkey;
ALTER TABLE public.customer ADD CONSTRAINT customer_customer__fk_subsription_fkey FOREIGN KEY (customer__fk_subsription) REFERENCES public."subscription"(subscription_id) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE public.rating DROP CONSTRAINT rating_rating__fk_moovie_fkey;
ALTER TABLE public.rating ADD CONSTRAINT rating_rating__fk_moovie_fkey FOREIGN KEY (rating__fk_moovie) REFERENCES public.moovie(moovie_id) ON DELETE CASCADE ON UPDATE CASCADE;
`;
return pool.query(q);
}
async function del() {
let q = `
DELETE FROM moovieSubscription;
DELETE FROM customer;
DELETE FROM genre;
DELETE FROM subscription;
DELETE FROM moovie;
ALTER SEQUENCE SEQ_moovie RESTART WITH 1;
ALTER SEQUENCE SEQ_genre RESTART WITH 1;
ALTER SEQUENCE SEQ_moovieGenre RESTART WITH 1;
ALTER SEQUENCE SEQ_subscription RESTART WITH 1;
ALTER SEQUENCE SEQ_moovieSubscription RESTART WITH 1;
ALTER SEQUENCE SEQ_customer RESTART WITH 1;
ALTER SEQUENCE SEQ_rating RESTART WITH 1;
`;
await pool.query(q);
}
let genress = ` Action Thriller Western Fantasy Science fiction Comedy Satire Drama Adventure Mystery Romantic comedy Melodrama Romance Hybrid genre Fairy tale Coming-of-age story Fantasy Suspense Detective fiction Biography Dark comedy Mystery Apocalyptic and post-apocalyptic fiction Slapstick Screenplay Historical drama Comedy horror Historical fantasy Body horror Tech noir Legal drama Film criticism`.split(" ");
async function createRandomGenres() {
let q = `
INSERT INTO genre VALUES
`;
for (let i = 0; i < count; i++) {
q += "(DEFAULT, '" + genress[Math.round((genress.length - 1) * Math.random())] + "'),";
}
let w = await pool.query(q.slice(0, -1));
w["querry"] = "INSERT INTO genre VALUES";
return w;
}
async function createRandomUsers(subscriptionsLength = count) {
let q = `
INSERT INTO customer VALUES
`;
for (let i = 0; i < count; i++) {
let w = Math.round(Math.random() * (subscriptionsLength - 2) + 1);
//console.log(w);
q += "(DEFAULT, " +
"'user" + i + "', 'email" + i + "@gmail.com'," + " 'password" + i + "', "
+ Math.round(Math.random() * (50 - 18) + 18) + ", " + "'phoneNumber" + i + "', "
+ w
+ "),";
}
let w = await pool.query(q.slice(0, -1));
w["querry"] = "INSERT INTO customer VALUES";
return w;
}
async function createRandomSubscriptions() {
let q = `
INSERT INTO subscription VALUES
`;
for (let i = 0; i < count; i++) {
q += "(DEFAULT, 'Подписка " + i.toString() + "', "
+ Math.round(Math.random() * 5000) + " " + ""/* Math.max(1, Math.round(Math.random() * (i-1))) */ + "),";
}
let w = await pool.query(q.slice(0, -1));
w["querry"] = " INSERT INTO subscription VALUES";
return w;
//query(q);
}
async function createRandomMoovies() {
let q = `
INSERT INTO moovie VALUES
`;
for (let i = 0; i < count; i++) {
q += "(DEFAULT, 'Фильм" + i + "', "
+ Math.round(Math.random() * (2024 - 1980) + 1980) + ", 'Описание" + i + "', '" + "2004-01-22" + "'),";
}
let w = await pool.query(q.slice(0, -1));
w["querry"] = "INSERT INTO moovie VALUES";
return w;
//query(q);
}
async function createRandomMoovieSubscriptions() {
let q = `
INSERT INTO moovieSubscription VALUES
`;
for (let i = 1; i < count / 10; i++) {
for (let t = 1; t < count / 5; t++) {
q += "(DEFAULT, " + t.toString() + ", " + i.toString() + "),";
}
}
let w = await pool.query(q.slice(0, -1));
w["querry"] = "INSERT INTO moovieSubscription VALUES";
return w;
//query(q);
}
async function createRandomRatings() {
let q = `
INSERT INTO rating VALUES
`;
for (let t = 1; t < count; t++) {
q += "(DEFAULT, " + Math.round(Math.random() * 10) + ", " +
Math.round(Math.random() * (count - 2) + 1) + ", " +
Math.round(Math.random() * (count - 2) + 1) + "),";
}
let w = await pool.query(q.slice(0, -1));
w["querry"] = "INSERT INTO rating VALUES";
return w;
//query(q);
}
//#endregion
//#endregion
//#region Measure
var result = [];
async function measure(f, args = [], multipleTimes = true) {
return new Promise(async resolve => {
let commonTime = null, res = "";
for (let i = 0; i < 10; i++) {
let t1 = process.hrtime.bigint();
res = await f(...args);
let t2 = process.hrtime.bigint();
if (commonTime == null) commonTime = (Number(t2 - t1) / 10 ** 6);
else commonTime = (commonTime + (Number(t2 - t1) / 10 ** 6)) / 2;
if (multipleTimes == false) break;
}
//console.log(Number(t2 - t1).toString() + " nanoseconds");
result.push(res["querry"] + " : " + commonTime.toFixed(1).toString() + "мс"/* " милиСекунд (10*-3)" */);
resolve();
})
}
var count = 15;
async function createTables() {
let ts = await getTables();
if (true || ts.length == 0) {
await createTabless();
}
//await del();
await measure(createRandomSubscriptions, [], false);
await measure(createRandomGenres, [], false);
await measure(createRandomUsers, [], false);
await measure(createRandomMoovies, [], false);
await measure(createRandomMoovieSubscriptions, [], false);
await measure(createRandomRatings, [], false);
await measure(getTable, [["subscription", []]])
await measure(getTable, [["moovie", []]])
await measure(getTable, [["moovie", [["moovie_productionYear", ">2021"], ["moovie_name", "2"]]]]);
await measure(getTable, [["genre", []]]);
await measure(getTable, [["moovieGenre", []]]);
await measure(getTable, [["subscription", []]]);
await measure(getTable, [["moovieSubscription", []]]);
await measure(getTable, [["customer", []]]);
await measure(getTable, [["rating", []]]);
await measure(getDifficultMoovies);
result.unshift("№ Запрос:Среднее время")
console.log(result.slice(0, -1).map((a, index) => ((index).toString() + ": " + a + ": ")).join(" "));
console.log(result[result.length - 1]);
}
//#endregion
function wsInterface() {
try {
ws = new WebSocket('ws://localhost:80')
} catch { }
ws.onopen = () => {
//document.getElementById('selects').children[0].select = true;
getTableInterface(document.getElementById('selects'));
console.log('ws opened on browser')
//ws.send('hello world')
}
ws.onclose = () => {
location.reload()
};
ws.onmessage = (message) => {
let data = JSON.parse(message.data).data;
callbacks[data[0].toString()](data[1]);
//console.log(`message received ${message}`)
}
}
wss.on('connection', (ws) => {
wsocket = ws;
ws.on('message', async (message) => {
let data = JSON.parse(message);
if (data?.type == "getTable") {
send([data.querry[0], await getTable(data.querry[1])]);
}
else if (data?.type == "create") {
pool.query(data.querry)
}
else if (data?.type == "update") {
pool.query(data.querry)
}
else if (data?.type == "delete") {
let qe = `
SET FOREIGN_KEY_CHECKS=0;
` + data.querry + `
SET FOREIGN_KEY_CHECKS=1;
`;
pool.query(data.querry)
}
});
});
//#region HTML CRUD Interface
function create(th) {
let newValues = Array.from(th.parentElement.children).slice(0, -1).map(a => "'" + a.children[0].value + "'");
ws.send(JSON.stringify({
"type": "create",
"querry": "INSERT INTO " + th.parentElement.parentElement.parentElement.getAttribute("name") + " VALUES (DEFAULT, " + newValues.slice(1, newValues.length).join(", ") + ")"
}));
setTimeout(() => {
getTableInterface(document.getElementById("selects"))
}, 100);
}
function change(th) {
let textarea = true;
let a = Array.from(th.parentElement.children);
a.slice(0, -2).forEach(element => {
if (textarea)
element.innerHTML = `<textarea type="text" style="width: 100%;">` + element.outerText + `</textarea>`;
else
element.innerHTML = `<input type="text" value="` + element.outerText + `" style="width: 100%;"></input>`;
})
a[a.length - 2].onclick = function () { update(this) };
a[a.length - 2].innerHTML = `
<td onclick=update(this)>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-return-left" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M14.5 1.5a.5.5 0 0 1 .5.5v4.8a2.5 2.5 0 0 1-2.5 2.5H2.707l3.347 3.346a.5.5 0 0 1-.708.708l-4.2-4.2a.5.5 0 0 1 0-.708l4-4a.5.5 0 1 1 .708.708L2.707 8.3H12.5A1.5 1.5 0 0 0 14 6.8V2a.5.5 0 0 1 .5-.5"/>
</svg>
</td>
`;
}
function update(th) {
let a = Array.from(th.parentElement.children);
let querry = `UPDATE ` + th.parentElement.parentElement.parentElement.getAttribute("name") + " SET ";
let types = Array.from(th.parentElement.parentElement.children[0].children).map(a => a.getAttribute("type"));
let at = Array.from(th.parentElement.parentElement.children[0].children).map(a => a.outerText);
a.slice(1, -2).forEach((element, index) => {
querry += at[index + 1] + " = ";
if (types[index + 1] == "number")
querry += element.children[0].value + ",";
else
querry += "'" + element.children[0].value + "',";
})
querry = querry.slice(0, -1);
querry += " WHERE " + at[0] + "=" + a[0].children[0].value;
ws.send(JSON.stringify({
"type": "update",
"querry": querry
}));
a.slice(0, -2).forEach(element => {
element.innerHTML = element.children[0].value
})
a[a.length - 2].onclick = function () { change(this) };
a[a.length - 2].innerHTML = `
<td onclick=change(this)>
<svg width="10" height="10" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2z"/>
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466"/>
</svg>
</td> `;
}
function remove(th) {
let a = Array.from(th.parentElement.children);
let at = Array.from(th.parentElement.parentElement.children[0].children).map(a => a.outerText);
ws.send(JSON.stringify({
"type": "delete",
"querry": "DELETE FROM " + th.parentElement.parentElement.parentElement.getAttribute("name") + " Cascade WHERE " + at[0] + "=" + + a[0].outerText
}));
th.parentElement.remove();
}
async function getTableInterface(th) {
let newFilter = th.id == "selects";
var g = document.getElementById("filter");
if (newFilter == false && g != null) {
let types = Array.from(document.getElementById("table").children[0].children[0].children).map(a => a.getAttribute("type"));
let at = Array.from(document.getElementById("table").children[0].children[0].children).map(a => a.outerText);;
g = Array.from(g.children[0].children[0].children)
.map((a, index) => [at[index], (types[index] == "number" && a.children[0].value != "" && a.children[0].value[0] != "<" && a.children[0].value[0] != ">" ? Number(a.children[0].value) : a.children[0].value)]);
}
else {
g = null
}
let table = [await sendInterface("getTable", [document.querySelector("#selects")[document.querySelector("#selects").selectedIndex].value, g])];
//let tables = await createTables();
if (table[0] == null) {
return;
}
table = table.map(t => createTableFromJSON(t, newFilter));
let d = document.getElementById("table")
if (newFilter) d = document.body.children[1];
if (table[0].length < 50) {
while (d.children[0].childNodes.length > 1) {
d.children[0].removeChild(d.children[0].lastChild);
}
} else {
d.innerHTML = table;
}
document.body.children[1].id = "";
}
//#endregion
//#region html Table Interfaces
function createTableFromJSON(jsonData, newFilter = false) {
let name = jsonData[jsonData.length - 1];
delete jsonData[jsonData.length - 1];
let text = "";
if (newFilter || document.getElementById("filter") == null) {
text = "<table id='filter'>";
Object.values(jsonData).forEach((row, index) => {
if (index == 0) {
text += "<tr>";
Object.keys(row).forEach((t, index) => {
text += "<td>" + `<textarea onkeyup =getTableInterface(this) type="text" style="width: 100%;">` + "" + `</textarea>` + "</td>";
});
text += "<td>" + `<textarea onkeyup =getTableInterface(this) type="text" style="width: 100%;">` + "" + `</textarea>` + "</td>";
text += "<td>" + `<textarea onkeyup =getTableInterface(this) type="text" style="width: 100%;">` + "" + `</textarea>` + "</td>";
text += "</tr>";
}
});
text += "</table> ";
}
text += "<table id='table' border='1' name='" + name + "'>";
Object.values(jsonData).forEach((row, index) => {
if (index == 0) {
text += "<tr>";
let v = Object.values(row);
Object.keys(row).forEach((t, index) => {
text += "<td type=" + (typeof v[index]).toString() + ">" + t + "</td>";
});
text += "</tr>";
}
text += "<tr>";
Object.values(row).forEach(t => {
if (t instanceof Date) t = t.toLocaleString('ru-RU')
text += "<td>" + (t == null ? "" : t.toString()) + "</td>";
});
text += `
<td onclick=change(this)>
<svg width="10" height="10" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 1-4.546 2.914.5.5 0 0 0-.908-.417A6 6 0 1 0 8 2z"/>
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466"/>
</svg>
</td>
<td onclick=remove(this)>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-x" viewBox="0 0 16 16">
<path d="M6.146 6.146a.5.5 0 0 1 .708 0L8 7.293l1.146-1.147a.5.5 0 1 1 .708.708L8.707 8l1.147 1.146a.5.5 0 0 1-.708.708L8 8.707 6.854 9.854a.5.5 0 0 1-.708-.708L7.293 8 6.146 6.854a.5.5 0 0 1 0-.708"/>
<path d="M4 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zm0 1h8a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1"/>
</svg>
</td>
</tr>`;
if (index == Object.values(jsonData).length - 1) {
Object.values(row).forEach(t => {
if (t instanceof Date) t = t.toLocaleString('ru-RU')
text += "<td>" + `<textarea type="text" style="width: 100%;">` + (t == null ? "" : t.toString()) + `</textarea>` + "</td>";
});
text += "<td onclick=create(this)>" + `Create` + "</td>";
}
//text += " </tr>";
});
return text;
};
let functionsToImport = [
createTableFromJSON,
create, change, update, remove, getTableInterface,
wsInterface, sendInterface,
"var ws; var id = 0, callbacks = []; wsInterface(); let w; ",
];
var once = true;
app.get('/', async function (request, response) {
if (once) {
once = false;
let tables = await createTables();
}
let ts = await getTables();
ts = ts.map(t => {
return "<option value=" + t.table_name + ">" + t.table_name + "</option>"
var option = document.createElement("option");
option.value = t.table_name;
option.text = t.table_name;
return option.toString();
})
let qw = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
font-size: 14px;
}
table {
width: 100%;
table-layout: fixed;
border-collapse: collapse;
margin: 20px;
}
th, td {
padding-right: 7px;
padding-left: 7px;
}
td {
overflow: hidden;
}
</style>
</head>
<body>
<select id="selects" onchange=getTableInterface(this) name="Таблица">
`+ ts.join(" ") + `
</select>
<div id="table"></div>`
+ " <script> " + (functionsToImport.map(a => a.toString())).join(" ") +
" </script> " + `
</body>
</html>
`;
response.writeHeader(200, { 'Content-Type': 'html' });
response.write(qw);
response.end();
})
let wsocket;
function send(data) {
wsocket.send(JSON.stringify({
data: data
}));
}
function sendInterface(s, data) {
return new Promise(resolve => {
ws.send(JSON.stringify({
"type": s,
"querry": [id, data]
}));
callbacks[id] = resolve;
id++
})
}
//#endregion