Организация
-
-
- +
diff --git a/.gitignore b/.gitignore index 58c6b60..b1e9fed 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ static/.DS_Store package-lock.json package-lock.json package-lock.json +package-lock.json diff --git a/package-lock.json b/package-lock.json index d0ba5fd..27e17ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,10 +13,12 @@ "express": "^4.18.2", "fs": "^0.0.1-security", "handlebars": "^4.7.7", + "http": "^0.0.1-security", "mapbox-gl": "^2.15.0", "multer": "^1.4.5-lts.1", "path": "^0.12.7", - "pg": "^8.11.1" + "pg": "^8.11.1", + "ws": "^8.13.0" } }, "node_modules/@mapbox/geojson-rewind": { @@ -478,6 +480,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/http": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/http/-/http-0.0.1-security.tgz", + "integrity": "sha512-RnDvP10Ty9FxqOtPZuxtebw1j4L/WiqNMDtuc1YMH1XQm5TgDRaR1G9u8upL6KD1bXHSp9eSXo/ED+8Q7FAr+g==" + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -1199,6 +1206,26 @@ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" }, + "node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -1564,6 +1591,11 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, + "http": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/http/-/http-0.0.1-security.tgz", + "integrity": "sha512-RnDvP10Ty9FxqOtPZuxtebw1j4L/WiqNMDtuc1YMH1XQm5TgDRaR1G9u8upL6KD1bXHSp9eSXo/ED+8Q7FAr+g==" + }, "http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -2121,6 +2153,12 @@ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" }, + "ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "requires": {} + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 96f03fc..fe70dea 100644 --- a/package.json +++ b/package.json @@ -14,9 +14,11 @@ "express": "^4.18.2", "fs": "^0.0.1-security", "handlebars": "^4.7.7", + "http": "^0.0.1-security", "mapbox-gl": "^2.15.0", "multer": "^1.4.5-lts.1", "path": "^0.12.7", - "pg": "^8.11.1" + "pg": "^8.11.1", + "ws": "^8.13.0" } } diff --git a/server.js b/server.js index cf27b10..c48ea26 100644 --- a/server.js +++ b/server.js @@ -6,11 +6,26 @@ const fs = require("fs"); const handlebars = require("handlebars"); require("dotenv").config(); const multer = require("multer"); +const http = require("http"); +const WebSocket = require("ws"); -const upload = multer(); +const server = http.createServer(app); +const wss = new WebSocket.Server({ server }); + +// Для сохранения загруженных фотографий +const storage = multer.diskStorage({ + destination: function (req, file, cb) { + cb(null, "uploads"); // Папка для сохранения фотографий + }, + filename: function (req, file, cb) { + cb(null, Date.now() + "-" + file.originalname); + }, +}); +const upload = multer({ storage: storage }); app.use(express.static(path.join(__dirname, "static"))); app.use(express.json()); +app.use(express.urlencoded({ extended: false })); app.get("/", index); app.get("/login", login); @@ -20,21 +35,19 @@ app.get("/reports", reports); app.get("/reports/346", reports346); app.get("/devices", devices); app.get("/devices/drivers", drivers); -app.get("/devices/newdevice", newdevice); -app.get("/devices/newdriver", newdriver); app.get("/devices/update", update); -// const DB_User = process.env.DB_USER; -// const DB_Password = process.env.DB_PASSWORD; -// const DB_Host = process.env.DB_HOST; -// const DB_Port = process.env.DB_PORT; -// const DB_Name = process.env.DB_NAME; +const DB_User = process.env.DB_USER; +const DB_Password = process.env.DB_PASSWORD; +const DB_Host = process.env.DB_HOST; +const DB_Port = process.env.DB_PORT; +const DB_Name = process.env.DB_NAME; -const DB_User = "postgres"; -const DB_Password = "password"; -const DB_Host = "postgres"; -const DB_Port = "5432"; -const DB_Name = "postgres"; +// const DB_User = "postgres"; +// const DB_Password = "password"; +// const DB_Host = "postgres"; +// const DB_Port = "5432"; +// const DB_Name = "postgres"; async function index(req, res) { var templateData = { @@ -179,6 +192,12 @@ app.post("/devices-geo", async (req, res) => { }); async function reports(req, res) { + let templateData = { + Organisation: "Название организации", + User: "Тестовое Имя", + ifDBError: false, + Registrars: [], + }; try { const pool = new Pool({ user: DB_User, @@ -190,16 +209,22 @@ async function reports(req, res) { const client = await pool.connect(); // Выполняем запрос и получаем результат const query = ` - SELECT id, cmdno, time, serial, st - FROM ( - SELECT id, cmdno, time, serial, st - FROM alarms - ORDER BY time DESC - LIMIT 100 - ) AS subquery - ORDER BY time ASC; + SELECT a.id, a.cmdno, a.time, a.serial, a.st, r.plate, g.latitude, g.longitude + FROM ( + SELECT id, cmdno, time, serial, st + FROM alarms + ORDER BY time DESC + LIMIT 100 + ) AS a + LEFT JOIN registrars AS r ON a.serial = r.serial + LEFT JOIN ( + SELECT *, + ROW_NUMBER() OVER (PARTITION BY serial ORDER BY ABS(EXTRACT(EPOCH FROM (time - $1)))) AS row_num + FROM geo + ) AS g ON a.serial = g.serial AND g.row_num = 1 + ORDER BY a.time DESC; `; - const alarms = await client.query(query); + const alarms = await client.query(query, [new Date()]); // Pass current date/time to the query for finding the nearest geoposition. function formatDate(date) { const options = { @@ -213,36 +238,120 @@ async function reports(req, res) { return formattedDate.replace(",", ""); } - var templateData = { - Organisation: "Название организации", - User: "Тестовое Имя", - Alarms: alarms.rows.map((alarm) => { - let type; - switch (alarm.st) { - case "0": - type = "Усталость"; - break; - case "1": - type = "Отсутствие водителя"; - break; - case "2": - type = "Разговор по телефону"; - break; - default: - type = "Неизвестный тип"; - } - return { - id: alarm.id, - cmdno: alarm.cmdno, - time: formatDate(alarm.time), - serial: alarm.serial, - st: alarm.st, - type: type, - }; - }), - }; + (templateData.Alarms = alarms.rows.map((alarm) => { + let type; + switch (alarm.st) { + case "0": + type = "Усталость"; + break; + case "1": + type = "Водитель пропал"; + break; + case "2": + type = "Разговор по телефону"; + break; + case "3": + type = "Курение за рулём"; + break; + case "4": + type = "Водитель отвлекся"; + break; + case "5": + type = "Выезд с полосы движения"; + break; + case "6": + type = "!!! Лобовое столкновение"; + break; + case "7": + type = "Скорость превышена"; + break; + case "8": + type = "Распознавание номерных знаков"; + break; + case "9": + type = "!! Маленькое расстояние спереди"; + break; + case "10": + type = "Водитель зевает"; + break; + case "11": + type = "!!! Столкновение с пешеходом"; + break; + case "12": + type = "Проходы переполнены"; + break; + case "13": + type = "!! Посадка/высадка вне остановки"; + break; + case "14": + type = "!! Смена полосы с нарушением ПДД"; + break; + case "15": + type = "! Включенный телефон у водителя"; + break; + case "16": + type = "!!! Ремень безопасности"; + break; + case "17": + type = "Проверка не удалась"; + break; + case "18": + type = "Слепые зоны справа"; + break; + case "19": + type = "!!! Заднее столкновение"; + break; + case "20": + type = "!!! Управление без рук"; + break; + case "21": + type = "!! Управление одной рукой"; + break; + case "22": + type = "Очки, блокирующие инфракрасное излучение"; + break; + case "23": + type = "Слепые зоны слева"; + break; + case "24": + type = "Помехи для пассажиров"; + break; + case "25": + type = "На перекрестке ограничена скорость"; + break; + case "26": + type = "Обнаружен перекресток"; + break; + case "27": + type = "Пешеходы на переходе"; + break; + case "28": + type = "! Неучтивое отношение к пешеходам"; + break; + case "29": + type = "Обнаружен пешеходный переход"; + break; + case "30": + type = "Водитель матерится"; + break; + default: + type = "Неизвестный тип"; + } - console.log(templateData); + return { + id: alarm.id, + cmdno: alarm.cmdno, + time: formatDate(alarm.time), + serial: alarm.serial, + st: alarm.st, + type: type, + plate: alarm.plate, + latitude: alarm.latitude, + longitude: alarm.longitude, + geo: alarm.latitude + "," + alarm.longitude, + }; + })), + console.log(templateData); const source = fs.readFileSync( "static/templates/reports/index.html", @@ -255,7 +364,7 @@ async function reports(req, res) { res.send(resultT); } catch (error) { console.error(error); - // templateData.ifDBError = true; + templateData.ifDBError = true; const source = fs.readFileSync( "static/templates/reports/index.html", @@ -265,8 +374,93 @@ async function reports(req, res) { const resultT = template(templateData); res.send(resultT); } - // res.sendFile(path.join(__dirname, "static/templates/reports/index.html")); } +app.get("/api/devices", async (req, res) => { + try { + const pool = new Pool({ + user: DB_User, + host: DB_Host, + database: DB_Name, + password: DB_Password, + port: DB_Port, + }); + const { page = 1, limit = 10 } = req.query; + const offset = (page - 1) * limit; + + const query = ` + SELECT a.id, a.cmdno, a.time, a.serial, a.st, r.plate, g.latitude, g.longitude + FROM ( + SELECT id, cmdno, time, serial, st + FROM alarms + ORDER BY time DESC + LIMIT $1 OFFSET $2 + ) AS a + LEFT JOIN registrars AS r ON a.serial = r.serial + LEFT JOIN ( + SELECT *, + ROW_NUMBER() OVER (PARTITION BY serial ORDER BY ABS(EXTRACT(EPOCH FROM (time - $3)))) AS row_num + FROM geo + ) AS g ON a.serial = g.serial AND g.row_num = 1 + ORDER BY a.time DESC; + `; + const alarms = await pool.query(query, [limit, offset, new Date()]); // Pass current date/time to the query for finding the nearest geoposition. + + function formatDate(date) { + const options = { + year: "2-digit", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + }; + const formattedDate = new Date(date).toLocaleString("ru-RU", options); + return formattedDate.replace(",", ""); + } + + const alarmsData = alarms.rows.map((alarm) => { + let type; + switch (alarm.st) { + case "0": + type = "Усталость"; + break; + case "1": + type = "Отсутствие водителя"; + break; + case "2": + type = "Разговор по телефону"; + break; + default: + type = "Неизвестный тип"; + } + return { + id: alarm.id, + cmdno: alarm.cmdno, + time: formatDate(alarm.time), + serial: alarm.serial, + st: alarm.st, + type: type, + plate: alarm.plate, + latitude: alarm.latitude, + longitude: alarm.longitude, + geo: alarm.latitude + "," + alarm.longitude, + }; + }); + + const totalCountQuery = "SELECT COUNT(*) FROM alarms;"; + const totalCount = await pool.query(totalCountQuery); + + const totalPages = Math.ceil(totalCount.rows[0].count / limit); + + res.json({ + data: alarmsData, + totalPages: totalPages, + }); + } catch (error) { + console.error("Error executing query:", error); + res.status(500).json({ error: "Internal server error" }); + } +}); + function reports346(req, res) { res.sendFile(path.join(__dirname, "static/templates/reports/346.html")); } @@ -380,6 +574,13 @@ app.post("/devicedata", async (req, res) => { }); app.post("/updatedevice", async (req, res) => { + const pool = new Pool({ + user: DB_User, + host: DB_Host, + database: DB_Name, + password: DB_Password, + port: DB_Port, + }); const client = await pool.connect(); var { @@ -503,15 +704,267 @@ app.post("/updatedevice", async (req, res) => { } }); -function drivers(req, res) { - res.sendFile(path.join(__dirname, "static/templates/devices/drivers.html")); -} -function newdevice(req, res) { - res.sendFile(path.join(__dirname, "static/templates/devices/newdevice.html")); -} -function newdriver(req, res) { - res.sendFile(path.join(__dirname, "static/templates/devices/newdriver.html")); +app.post("/updatedriver", upload.single("upload-file"), async (req, res) => { + const pool = new Pool({ + user: DB_User, + host: DB_Host, + database: DB_Name, + password: DB_Password, + port: DB_Port, + }); + const client = await pool.connect(); + + var { + driverName, + driverSurname, + driverCard, + driverGender, + driverLicense, + driverPassport, + driverPhone, + driverEmail, + driverTransport, + driverDescription, + driverID, + } = req.body; + + try { + // Вставка новой строки в таблицу drivers + const query = ` + UPDATE drivers + SET name = $1, + surname = $2, + card = $3, + gender = $4, + license = $5, + passport = $6, + phone = $7, + email = $8, + transport = $9, + description = $10 + WHERE id = $11 + RETURNING *; + `; + + const values = [ + driverName, + driverSurname, + driverCard, + driverGender, + driverLicense, + driverPassport, + driverPhone, + driverEmail, + driverTransport, + driverDescription, + driverID, + ]; + + const result = await client.query(query, values); + + const newRow = result.rows[0]; + console.log("New driver added:", newRow); + + res.send("Data added successfully"); + } catch (error) { + console.error("Error adding data:", error); + res.status(500).send("An error occurred while adding data"); + } finally { + client.release(); + } +}); + +app.post("/adddriver", upload.single("upload-file"), async (req, res) => { + const pool = new Pool({ + user: DB_User, + host: DB_Host, + database: DB_Name, + password: DB_Password, + port: DB_Port, + }); + const client = await pool.connect(); + + var { + driverName, + driverSurname, + driverCard, + driverGender, + driverLicense, + driverPassport, + driverPhone, + driverEmail, + driverTransport, + driverDescription, + } = req.body; + + try { + // Вставка новой строки в таблицу drivers + const query = ` + INSERT INTO drivers ( + name, + surname, + card, + gender, + license, + passport, + phone, + email, + transport, + description + ) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) + RETURNING *; + `; + + const values = [ + driverName, + driverSurname, + driverCard, + driverGender, + driverLicense, + driverPassport, + driverPhone, + driverEmail, + driverTransport, + driverDescription, + ]; + + const result = await client.query(query, values); + + const newRow = result.rows[0]; + console.log("New driver added:", newRow); + + res.send("Data added successfully"); + } catch (error) { + console.error("Error adding data:", error); + res.status(500).send("An error occurred while adding data"); + } finally { + client.release(); + } +}); + +app.post("/driverdata", async (req, res) => { + const id = req.body.id; + + const pool = new Pool({ + user: DB_User, + host: DB_Host, + database: DB_Name, + password: DB_Password, + port: DB_Port, + }); + const client = await pool.connect(); + + try { + // Выполняем запрос и получаем результат + const query = "SELECT * FROM drivers WHERE id = $1;"; + const driverdata = await client.query(query, [id]); + + // Формирование и отправка ответа + const response = driverdata.rows[0]; + res.json(response); + } finally { + client.release(); + } +}); + +app.post("/deletedriver", async (req, res) => { + const id = req.body.id; + + const pool = new Pool({ + user: DB_User, + host: DB_Host, + database: DB_Name, + password: DB_Password, + port: DB_Port, + }); + const client = await pool.connect(); + + try { + // Выполняем запрос и получаем результат + const query = "DELETE FROM drivers WHERE id = $1;"; + const driverdata = await client.query(query, [id]); + + // Формирование и отправка ответа + res.send("Data deleted successfully"); + } finally { + client.release(); + } +}); + +async function drivers(req, res) { + let templateData = { + Organisation: "Название организации", + User: "Тестовое Имя", + ifDBError: false, + Drivers: [], + Registrars: [], + }; + + try { + const pool = new Pool({ + user: DB_User, + host: DB_Host, + database: DB_Name, + password: DB_Password, + port: DB_Port, + }); + const client = await pool.connect(); + + // Выполняем запрос для объединения данных из таблиц drivers и registrars + const queryDrivers = ` + SELECT d.id, d.name, d.surname, d.transport, d.phone, d.email, d.card, r.connected + FROM drivers d + LEFT JOIN registrars r ON d.transport = r.serial + ORDER BY r.connected DESC NULLS LAST, CASE WHEN r.connected = true THEN 0 ELSE 1 END, d.id + `; + const driversResult = await client.query(queryDrivers); + + templateData.Drivers = driversResult.rows.map((driver) => ({ + id: driver.id, + name: driver.name, + surname: driver.surname, + transport: driver.transport, + phone: driver.phone, + email: driver.email, + card: driver.card, + })); + + const queryRegistrars = ` + SELECT serial + FROM registrars + `; + const registrarsResult = await client.query(queryRegistrars); + + templateData.Registrars = registrarsResult.rows.map( + (registrar) => registrar.serial + ); + + console.log(templateData); + + const source = fs.readFileSync( + "static/templates/devices/drivers.html", + "utf8" + ); + const template = handlebars.compile(source); + const resultT = template(templateData); + res.send(resultT); + + client.release(); + } catch (error) { + console.error(error); + templateData.ifDBError = true; + + const source = fs.readFileSync( + "static/templates/devices/drivers.html", + "utf8" + ); + const template = handlebars.compile(source); + const resultT = template(templateData); + res.send(resultT); + } } + function update(req, res) { res.sendFile(path.join(__dirname, "static/templates/devices/update.html")); } diff --git a/static/img/file.svg b/static/img/file.svg new file mode 100644 index 0000000..3974d92 --- /dev/null +++ b/static/img/file.svg @@ -0,0 +1,3 @@ + diff --git a/static/scripts/drivers-form.js b/static/scripts/drivers-form.js new file mode 100644 index 0000000..627de3c --- /dev/null +++ b/static/scripts/drivers-form.js @@ -0,0 +1,114 @@ +$("#continue-main").click(function () { + document.getElementById("stage-details").checked = true; +}); + +$("#continue-main-edit").click(function () { + document.getElementById("stage-details-edit").checked = true; +}); + +const container = document.getElementById("new-parameters"); +const content1 = document.getElementById("main"); +const content2 = document.getElementById("details"); +const btn1 = document.getElementById("continue-main"); +const content3 = document.getElementById("main-edit"); +const content4 = document.getElementById("details-edit"); +const btn2 = document.getElementById("continue-main-edit"); +const radioButtons = document.querySelectorAll( + 'input[type="radio"][name="newStage"]' +); +const radioButtonsEdit = document.querySelectorAll( + 'input[type="radio"][name="newStageEdit"]' +); +const duration = 100; + +let activeContent = content1; + +function switchContent(newContent) { + fadeOut(activeContent, () => { + fadeIn(newContent); + activeContent = newContent; + }); +} + +function fadeIn(element) { + element.style.opacity = 0; + element.style.display = "block"; + let start = performance.now(); + + function animate(time) { + let timeFraction = (time - start) / duration; + if (timeFraction > 1) { + element.style.opacity = 1; + } else { + element.style.opacity = timeFraction; + requestAnimationFrame(animate); + } + } + + requestAnimationFrame(animate); +} + +function fadeOut(element, callback) { + element.style.opacity = 1; + let start = performance.now(); + + function animate(time) { + let timeFraction = (time - start) / duration; + if (timeFraction > 1) { + element.style.opacity = 0; + element.style.display = "none"; + if (callback) { + callback(); + } + } else { + element.style.opacity = 1 - timeFraction; + requestAnimationFrame(animate); + } + } + + requestAnimationFrame(animate); +} + +btn1.addEventListener("click", () => { + if (activeContent === content1) { + switchContent(content2); + } else { + switchContent(content1); + } +}); + +btn2.addEventListener("click", () => { + if (activeContent === content3) { + switchContent(content4); + } else { + switchContent(content3); + } +}); + +for (let radioButton of radioButtons) { + radioButton.addEventListener("change", () => { + if (radioButton.value === "main") { + switchContent(content1); + } else if (radioButton.value === "details") { + switchContent(content2); + } + }); +} + +for (let radioButton of radioButtonsEdit) { + radioButton.addEventListener("change", () => { + if (radioButton.value === "main") { + switchContent(content3); + } else if (radioButton.value === "details") { + switchContent(content4); + } + }); +} + +function truncateText(select) { + var maxLength = 30; + var option = select.options[select.selectedIndex]; + if (option.text.length > maxLength) { + option.text = option.text.substring(0, maxLength) + "..."; + } +} diff --git a/static/scripts/table-drivers.js b/static/scripts/table-drivers.js index ff1415d..2aa5e9c 100644 --- a/static/scripts/table-drivers.js +++ b/static/scripts/table-drivers.js @@ -1,115 +1,115 @@ -const devices = [ - { - id: "2", - group: "2-device-2", - driverID: "233", - name: "Иван", - surname: "Спахов", - numberTS: "008803559E", - phone: "+7 999 123 45 67", - mail: "spahov@mail.ru", - driverCard: "RUD0000000000111", - }, - { - id: "6", - group: "2-device-1", - driverID: "782", - name: "Александр", - surname: "Богаченко", - numberTS: "0088036B78", - phone: "+7 989 443 23 46", - mail: "bogachenko@mail.ru", - driverCard: "RUD0000000000111", - }, - { - id: "7", - group: "2-device-4", - driverID: "2943", - name: "Михаил", - surname: "Гукасян", - numberTS: "009800852A", - phone: "+7 909 133 55 67", - mail: "agucasyan@mail.ru", - driverCard: "RUD0000000000111", - }, - { - id: "8", - group: "2-device-4", - driverID: "87", - name: "Марат", - surname: "Шмидт", - numberTS: "009800858D", - phone: "+7 915 555 45 89", - mail: "shmidt@mail.ru", - driverCard: "RUD0000000000111", - }, - { - id: "9", - group: "1-device-1", - driverID: "823", - name: "Никита", - surname: "Ильяшенко", - numberTS: "00980084FD", - phone: "+7 909 123 45 67", - mail: "iluashenko@mail.ru", - driverCard: "RUD0000000000111", - }, - { - id: "10", - group: "2-device-4", - driverID: "15", - name: "Валерий", - surname: "Сараев", - numberTS: "0088036B7F", - phone: "+7 909 123 45 67", - mail: "saraev@mail.ru", - driverCard: "RUD0000000000111", - }, - { - id: "11", - group: "2-device-3", - driverID: "423", - name: "Александр", - surname: "Курочкин", - numberTS: "00880302CD", - phone: "+7 999 123 45 67", - mail: "curochkin@mail.ru", - driverCard: "RUD0000000000111", - }, - { - id: "12", - group: "1-device-2", - driverID: "6456", - name: "Екатерина", - surname: "Миненко", - numberTS: "008802A035", - phone: "+7 999 123 45 67", - mail: "minenko@mail.ru", - driverCard: "RUD0000000000111", - }, - { - id: "13", - group: "3-device-1", - driverID: "887", - name: "Виталий", - surname: "Гаспарян", - numberTS: "008802A96A", - phone: "+7 999 123 45 67", - mail: "gosparyan@mail.ru", - driverCard: "RUD0000000000111", - }, - { - id: "15", - group: "1-device-1", - driverID: "742", - name: "Светлана", - surname: "Амусова", - numberTS: "00880302C7", - phone: "+7 999 123 45 67", - mail: "amusova@mail.ru", - driverCard: "RUD0000000000111", - }, -]; +// const devices = [ +// { +// id: "2", +// group: "2-device-2", +// driverID: "233", +// name: "Иван", +// surname: "Спахов", +// numberTS: "008803559E", +// phone: "+7 999 123 45 67", +// mail: "spahov@mail.ru", +// driverCard: "RUD0000000000111", +// }, +// { +// id: "6", +// group: "2-device-1", +// driverID: "782", +// name: "Александр", +// surname: "Богаченко", +// numberTS: "0088036B78", +// phone: "+7 989 443 23 46", +// mail: "bogachenko@mail.ru", +// driverCard: "RUD0000000000111", +// }, +// { +// id: "7", +// group: "2-device-4", +// driverID: "2943", +// name: "Михаил", +// surname: "Гукасян", +// numberTS: "009800852A", +// phone: "+7 909 133 55 67", +// mail: "agucasyan@mail.ru", +// driverCard: "RUD0000000000111", +// }, +// { +// id: "8", +// group: "2-device-4", +// driverID: "87", +// name: "Марат", +// surname: "Шмидт", +// numberTS: "009800858D", +// phone: "+7 915 555 45 89", +// mail: "shmidt@mail.ru", +// driverCard: "RUD0000000000111", +// }, +// { +// id: "9", +// group: "1-device-1", +// driverID: "823", +// name: "Никита", +// surname: "Ильяшенко", +// numberTS: "00980084FD", +// phone: "+7 909 123 45 67", +// mail: "iluashenko@mail.ru", +// driverCard: "RUD0000000000111", +// }, +// { +// id: "10", +// group: "2-device-4", +// driverID: "15", +// name: "Валерий", +// surname: "Сараев", +// numberTS: "0088036B7F", +// phone: "+7 909 123 45 67", +// mail: "saraev@mail.ru", +// driverCard: "RUD0000000000111", +// }, +// { +// id: "11", +// group: "2-device-3", +// driverID: "423", +// name: "Александр", +// surname: "Курочкин", +// numberTS: "00880302CD", +// phone: "+7 999 123 45 67", +// mail: "curochkin@mail.ru", +// driverCard: "RUD0000000000111", +// }, +// { +// id: "12", +// group: "1-device-2", +// driverID: "6456", +// name: "Екатерина", +// surname: "Миненко", +// numberTS: "008802A035", +// phone: "+7 999 123 45 67", +// mail: "minenko@mail.ru", +// driverCard: "RUD0000000000111", +// }, +// { +// id: "13", +// group: "3-device-1", +// driverID: "887", +// name: "Виталий", +// surname: "Гаспарян", +// numberTS: "008802A96A", +// phone: "+7 999 123 45 67", +// mail: "gosparyan@mail.ru", +// driverCard: "RUD0000000000111", +// }, +// { +// id: "15", +// group: "1-device-1", +// driverID: "742", +// name: "Светлана", +// surname: "Амусова", +// numberTS: "00880302C7", +// phone: "+7 999 123 45 67", +// mail: "amusova@mail.ru", +// driverCard: "RUD0000000000111", +// }, +// ]; // Получаем высоту таблицы и определяем, сколько строк помещается на странице let currentPage = 1; @@ -151,7 +151,7 @@ const createTable = () => { // Добавляем ячейки с данными const driverID = document.createElement("td"); - driverID.textContent = device.driverID; + driverID.textContent = device.id; row.appendChild(driverID); const name = document.createElement("td"); name.textContent = device.name; @@ -177,9 +177,11 @@ const createTable = () => { trashCell.setAttribute("class", "optionsCell"); const trashButton = document.createElement("button"); trashButton.setAttribute("class", "trash"); + trashButton.setAttribute("onclick", `deleteDriver(${device.id})`); trashButton.value = `delete-device-${device.id}`; trashButton.id = `delete-device-${device.id}`; const optionsButton = document.createElement("button"); + optionsButton.setAttribute("onclick", `openEdit(${device.id})`); optionsButton.setAttribute("class", "options"); optionsButton.value = `options-device-${device.id}`; optionsButton.id = `options-device-${device.id}`; diff --git a/static/scripts/table-reports.js b/static/scripts/table-reports.js index ae437c1..8210753 100644 --- a/static/scripts/table-reports.js +++ b/static/scripts/table-reports.js @@ -1,105 +1,105 @@ -const devices = [ - { - id: "1", - group: "0001", - name: "Разговор по телефону", - reportID: "354", - plate: "AO30877", - numberTS: "008803559E", - time: "12.03.23 17:33", - place: "59.852371, 30.344543", - }, - { - id: "2", - group: "0001", - name: "Водитель зевает", - reportID: "353", - plate: "AO64377", - numberTS: "0088036B78", - time: "12.03.23 14:26", - place: "60.058236, 30.315283", - }, - { - id: "3", - group: "0002", - name: "Усталость", - reportID: "352", - plate: "ГД44377", - numberTS: "009800852A", - time: "12.03.23 10:07", - place: "59.878256, 30.31962", - }, - { - id: "4", - group: "0003", - name: "Водитель зевает", - reportID: "351", - plate: "УА86577", - numberTS: "009800858D", - time: "12.03.23 09:56", - place: "60.045981, 30.4134", - }, - { - id: "5", - group: "0003", - name: "Разговор по телефону", - reportID: "350", - plate: "БВ74665", - numberTS: "00980084FD", - time: "11.03.23 20:43", - place: "59.83257, 30.389893", - }, - { - id: "6", - group: "0004", - name: "Разговор по телефону", - reportID: "349", - plate: "ЦУ445101", - numberTS: "0088036B7F", - time: "11.03.23 19:17", - place: "59.959926, 30.42224", - }, - { - id: "7", - group: "0005", - name: "Усталость", - reportID: "348", - plate: "КТ32376", - numberTS: "00880302CD", - time: "11.03.23 15:32", - place: "60.046346, 30.405688", - }, - { - id: "8", - group: "0006", - name: "Курение за рулём", - reportID: "347", - plate: "ОА33277", - numberTS: "008802A035", - time: "11.03.23 15:06", - place: "59.956626, 30.234408", - }, - { - id: "9", - group: "0007", - name: "Водитель отвлекся", - reportID: "346", - plate: "КЛ987102", - numberTS: "008802A96A", - time: "11.03.23 12:44", - place: "59.956626, 30.234408", - }, - { - id: "10", - group: "0002", - name: "Водитель отвлекся", - reportID: "345", - plate: "АУ22377", - numberTS: "00880302C7", - time: "11.03.23 11:40", - place: "59.956626, 30.234408", - }, -]; +// const devices = [ +// { +// id: "1", +// group: "0001", +// name: "Разговор по телефону", +// reportID: "354", +// plate: "AO30877", +// numberTS: "008803559E", +// time: "12.03.23 17:33", +// place: "59.852371, 30.344543", +// }, +// { +// id: "2", +// group: "0001", +// name: "Водитель зевает", +// reportID: "353", +// plate: "AO64377", +// numberTS: "0088036B78", +// time: "12.03.23 14:26", +// place: "60.058236, 30.315283", +// }, +// { +// id: "3", +// group: "0002", +// name: "Усталость", +// reportID: "352", +// plate: "ГД44377", +// numberTS: "009800852A", +// time: "12.03.23 10:07", +// place: "59.878256, 30.31962", +// }, +// { +// id: "4", +// group: "0003", +// name: "Водитель зевает", +// reportID: "351", +// plate: "УА86577", +// numberTS: "009800858D", +// time: "12.03.23 09:56", +// place: "60.045981, 30.4134", +// }, +// { +// id: "5", +// group: "0003", +// name: "Разговор по телефону", +// reportID: "350", +// plate: "БВ74665", +// numberTS: "00980084FD", +// time: "11.03.23 20:43", +// place: "59.83257, 30.389893", +// }, +// { +// id: "6", +// group: "0004", +// name: "Разговор по телефону", +// reportID: "349", +// plate: "ЦУ445101", +// numberTS: "0088036B7F", +// time: "11.03.23 19:17", +// place: "59.959926, 30.42224", +// }, +// { +// id: "7", +// group: "0005", +// name: "Усталость", +// reportID: "348", +// plate: "КТ32376", +// numberTS: "00880302CD", +// time: "11.03.23 15:32", +// place: "60.046346, 30.405688", +// }, +// { +// id: "8", +// group: "0006", +// name: "Курение за рулём", +// reportID: "347", +// plate: "ОА33277", +// numberTS: "008802A035", +// time: "11.03.23 15:06", +// place: "59.956626, 30.234408", +// }, +// { +// id: "9", +// group: "0007", +// name: "Водитель отвлекся", +// reportID: "346", +// plate: "КЛ987102", +// numberTS: "008802A96A", +// time: "11.03.23 12:44", +// place: "59.956626, 30.234408", +// }, +// { +// id: "10", +// group: "0002", +// name: "Водитель отвлекся", +// reportID: "345", +// plate: "АУ22377", +// numberTS: "00880302C7", +// time: "11.03.23 11:40", +// place: "59.956626, 30.234408", +// }, +// ]; // Получаем высоту таблицы и определяем, сколько строк помещается на странице let currentPage = 1; @@ -143,22 +143,22 @@ const createTable = () => { // Добавляем ячейки с данными const name = document.createElement("td"); - name.textContent = device.name; + name.textContent = device.type; row.appendChild(name); const reportID = document.createElement("td"); - reportID.textContent = device.reportID; + reportID.textContent = device.id; row.appendChild(reportID); const plate = document.createElement("td"); plate.textContent = device.plate; row.appendChild(plate); const numberTS = document.createElement("td"); - numberTS.textContent = device.numberTS; + numberTS.textContent = device.serial; row.appendChild(numberTS); const time = document.createElement("td"); time.textContent = device.time; row.appendChild(time); const place = document.createElement("td"); - place.textContent = device.place; + place.textContent = device.geo; row.appendChild(place); // Добавляем кнопку удаления после каждого ряда @@ -243,7 +243,7 @@ const applyFilterAndSearch = () => { filteredDevices = devices.filter((device) => { const searchString = - `${device.group} ${device.name} ${device.reportID} ${device.place} ${device.numberTS} ${device.time} ${device.place}`.toLowerCase(); + `${device.group} ${device.name} ${device.id} ${device.place} ${device.numberTS} ${device.time} ${device.place} ${device.geo} ${device.serial}`.toLowerCase(); const matchGroup = groupFilters.length === 0 || groupFilters.includes(device.group); const matchSearch = !searchValue || searchString.includes(searchValue); diff --git a/static/styles/main.css b/static/styles/main.css index 8b20155..e0c42ee 100644 --- a/static/styles/main.css +++ b/static/styles/main.css @@ -445,6 +445,27 @@ header h2 span { background-color: #8086f9; } +.organisation button { + position: absolute; + width: fit-content; + text-decoration: none; + font-size: 18px; + font-weight: 400; + color: rgba(0, 0, 0, 0.5); + padding: 7px; + border-radius: 6px; + transition: 0.2s; + border: none; + background-color: transparent; + cursor: pointer; + bottom: 15px; + left: 35px; +} + +.organisation button:hover { + background-color: rgba(0, 0, 0, 0.05); +} + .content .table { display: inline-block; width: calc(100% - 275px); @@ -1054,6 +1075,69 @@ tr:nth-child(even) { margin-top: 2px; } +.upload-result { + /* width: calc(100% - 200px); */ + width: 100%; + /* float: right; */ + margin-bottom: 10px; + display: block; + border-radius: 5px; + border: 1px solid rgba(0, 0, 0, 0.1); + display: flex; + position: relative; +} + +.image-container #image-preview { + margin-top: 5px; + max-width: 150px; + max-height: 150px; + border-radius: 5px; + border: 1px solid rgba(0, 0, 0, 0.1); +} + +.upload-result #file-name { + position: absolute; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: normal; + color: rgba(0, 0, 0, 0.75); + /* margin-right: 50px; */ + /* display: flex; */ + top: 6px; + left: 40px; +} + +.upload-result #file-size { + position: absolute; + bottom: 6px; + left: 40px; + /* display: flex; */ + font-size: 10px; + font-style: normal; + font-weight: 400; + line-height: normal; + color: rgba(0, 0, 0, 0.5); +} + +.upload-result #file-icon { + display: flex; + padding: 8px; + height: 24px; + width: 24px; +} + +.upload-result #clear-button { + /* display: flex; */ + /* padding: 14px; */ + cursor: pointer; + position: absolute; + top: 14px; + right: 16px; + width: 12px; + height: 12px; +} + .drivers select { width: 100% !important; } diff --git a/static/templates/devices/drivers.html b/static/templates/devices/drivers.html index 008fed2..cc6abf2 100644 --- a/static/templates/devices/drivers.html +++ b/static/templates/devices/drivers.html @@ -4,7 +4,7 @@ -