diff --git a/api/config/db.js b/api/config/db.js
index 3f030fc..cdc8924 100644
--- a/api/config/db.js
+++ b/api/config/db.js
@@ -15,7 +15,8 @@ db.serialize(() => {
uuid_manager TEXT,
appointment TEXT DEFAULT 'lamb',
mode INTEGER DEFAULT 0,
- mode_title TEXT DEFAULT 'Користувач'
+ mode_title TEXT DEFAULT 'Користувач',
+ FOREIGN KEY (group_id) REFERENCES groups(group_number)
)
`);
@@ -40,7 +41,7 @@ db.serialize(() => {
db.run(`
CREATE TABLE IF NOT EXISTS groups (
id INTEGER PRIMARY KEY AUTOINCREMENT,
- group_number INTEGER,
+ group_number INTEGER UNIQUE,
share_hash TEXT
)
`);
@@ -49,7 +50,11 @@ db.serialize(() => {
CREATE TABLE IF NOT EXISTS subscription (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sheep_id INTEGER,
- token TEXT,
+ endpoint TEXT,
+ keys TEXT,
+ device_name TEXT,
+ device_model TEXT,
+ created_at TIMESTAMP,
FOREIGN KEY (sheep_id) REFERENCES sheeps(id)
)
`);
@@ -66,7 +71,6 @@ db.serialize(() => {
db.run(`
CREATE TABLE IF NOT EXISTS house (
id INTEGER PRIMARY KEY AUTOINCREMENT,
- group_id INTEGER,
title TEXT,
number TEXT,
points TEXT DEFAULT '[]',
@@ -76,8 +80,7 @@ db.serialize(() => {
settlement TEXT,
description TEXT,
created_at TIMESTAMP,
- updated_at TIMESTAMP,
- FOREIGN KEY (group_id) REFERENCES groups(group_number)
+ updated_at TIMESTAMP
)
`);
@@ -87,10 +90,6 @@ db.serialize(() => {
house_id INTEGER,
entrance_number INTEGER,
title TEXT,
- points TEXT DEFAULT '[]',
- points_number TEXT DEFAULT '[]',
- floors_quantity TEXT,
- apartments_quantity TEXT,
description TEXT,
created_at TIMESTAMP,
updated_at TIMESTAMP,
@@ -106,9 +105,11 @@ db.serialize(() => {
date_start TIMESTAMP,
date_end TIMESTAMP,
group_id INTEGER,
- sheep_id TEXT,
+ sheep_id INTEGER,
working INTEGER DEFAULT 0,
- FOREIGN KEY (entrance_id) REFERENCES entrance(id)
+ FOREIGN KEY (entrance_id) REFERENCES entrance(id),
+ FOREIGN KEY (sheep_id) REFERENCES sheeps(id),
+ FOREIGN KEY (group_id) REFERENCES groups(group_number)
)
`);
@@ -121,20 +122,22 @@ db.serialize(() => {
floors_number INTEGER,
status INTEGER,
description TEXT,
- sheep_id TEXT,
+ sheep_id INTEGER,
updated_at TIMESTAMP,
- FOREIGN KEY (entrance_id) REFERENCES entrance(id)
+ FOREIGN KEY (entrance_id) REFERENCES entrance(id),
+ FOREIGN KEY (sheep_id) REFERENCES sheeps(id)
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS apartments_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
- sheep_id TEXT,
+ sheep_id INTEGER,
apartments_id INTEGER,
status INTEGER,
description TEXT,
created_at TIMESTAMP,
+ FOREIGN KEY (sheep_id) REFERENCES sheeps(id),
FOREIGN KEY (apartments_id) REFERENCES apartments(id)
)
`);
@@ -142,18 +145,16 @@ db.serialize(() => {
db.run(`
CREATE TABLE IF NOT EXISTS homestead (
id INTEGER PRIMARY KEY AUTOINCREMENT,
- group_id INTEGER,
title TEXT,
number TEXT,
points TEXT DEFAULT '[]',
- point_icons TEXT DEFAULT '[]',
geo TEXT DEFAULT '[]',
+ zoom INTEGER DEFAULT 18,
osm_id TEXT DEFAULT '[]',
settlement TEXT,
description TEXT,
created_at TIMESTAMP,
- updated_at TIMESTAMP,
- FOREIGN KEY (group_id) REFERENCES groups(group_number)
+ updated_at TIMESTAMP
)
`);
@@ -165,9 +166,11 @@ db.serialize(() => {
date_start TIMESTAMP,
date_end TIMESTAMP,
group_id INTEGER,
- sheep_id TEXT,
+ sheep_id INTEGER,
working INTEGER DEFAULT 0,
- FOREIGN KEY (homestead_id) REFERENCES homestead(id)
+ FOREIGN KEY (homestead_id) REFERENCES homestead(id),
+ FOREIGN KEY (sheep_id) REFERENCES sheeps(id),
+ FOREIGN KEY (group_id) REFERENCES groups(group_number)
)
`);
@@ -177,7 +180,7 @@ db.serialize(() => {
date TIMESTAMP,
type INTEGER,
name TEXT,
- sheep_id TEXT,
+ sheep_id INTEGER,
title TEXT,
number TEXT,
FOREIGN KEY (sheep_id) REFERENCES sheeps(id)
@@ -188,23 +191,38 @@ db.serialize(() => {
CREATE TABLE IF NOT EXISTS stand_list (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
- hour_start INTEGER DEFAULT 10,
- hour_end INTEGER DEFAULT 16,
+ geo TEXT DEFAULT '[]',
+ hour_start INTEGER DEFAULT 9,
+ hour_end INTEGER DEFAULT 18,
quantity_sheep INTEGER DEFAULT 2,
- week_days TEXT DEFAULT '[0, 1, 2, 3, 4, 5, 6]'
+ week_days TEXT DEFAULT '[0, 1, 2, 3, 4, 5, 6]',
+ processing_time REAL DEFAULT 1,
+ status INTEGER DEFAULT 0,
+ updated_at TIMESTAMP
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS stand_schedule (
id INTEGER PRIMARY KEY AUTOINCREMENT,
- stand INTEGER,
+ stand_id INTEGER,
date TIMESTAMP,
hour INTEGER,
- sheep_id TEXT,
+ sheep_id INTEGER,
number_sheep TEXT,
updated_at TIMESTAMP,
- FOREIGN KEY (stand) REFERENCES stand_list(id),
+ FOREIGN KEY (stand_id) REFERENCES stand_list(id),
+ FOREIGN KEY (sheep_id) REFERENCES sheeps(id)
+ )
+ `);
+
+ db.run(`
+ CREATE TABLE IF NOT EXISTS stand_schedule_history (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ stand_schedule_id INTEGER,
+ sheep_id INTEGER,
+ created_at TIMESTAMP,
+ FOREIGN KEY (stand_schedule_id) REFERENCES stand_schedule(id),
FOREIGN KEY (sheep_id) REFERENCES sheeps(id)
)
`);
diff --git a/api/controllers/homesteads.controller.js b/api/controllers/homesteads.controller.js
index a45c6f8..16349d2 100644
--- a/api/controllers/homesteads.controller.js
+++ b/api/controllers/homesteads.controller.js
@@ -2,26 +2,20 @@ const HomesteadsService = require('../services/homesteads.service');
class HomesteadsController {
async getList(req, res) {
- const { mode } = req.query;
+ const { mode, sheep_id } = req.query;
if (req.possibilities.can_view_territory) {
- let group_id = 0;
- let sheepName = false;
+ let id = null;
- // if (req.mode == 2) {
- // group_id = 0;
- // } else if (req.mode == 1) {
- // group_id = req.group_id;
- // }
-
- if (mode == "sheep") {
- group_id = req.group_id;
- sheepName = req.sheepName;
- } else if (mode == "group"){
- group_id = req.group_id;
+ if (mode == "admin" && req.possibilities.can_manager_territory) {
+ id = sheep_id;
+ } else if (mode == "sheep") {
+ id = req.sheepId;
+ } else if (mode == "group") {
+ id = req.group_id;
}
- let result = await HomesteadsService.getList(group_id, sheepName);
+ let result = await HomesteadsService.getList(mode, id);
if (result) {
return res
.status(200)
diff --git a/api/controllers/houses.controller.js b/api/controllers/houses.controller.js
index b7dadf3..1a9224e 100644
--- a/api/controllers/houses.controller.js
+++ b/api/controllers/houses.controller.js
@@ -22,26 +22,20 @@ class HousesController {
}
async getList(req, res) {
- const { mode } = req.query;
+ const { mode, sheep_id } = req.query;
if (req.possibilities.can_view_territory) {
- let group_id = 0;
- let sheepName = false;
+ let id = null;
- // if (req.mode == 2) {
- // group_id = 0;
- // } else if (req.mode == 1) {
- // group_id = req.group_id;
- // }
-
- if (mode == "sheep") {
- group_id = req.group_id;
- sheepName = req.sheepName;
- } else if (mode == "group"){
- group_id = req.group_id;
+ if (mode == "admin" && req.possibilities.can_manager_territory) {
+ id = sheep_id;
+ } else if (mode == "sheep") {
+ id = req.sheepId;
+ } else if (mode == "group") {
+ id = req.group_id;
}
-
- let result = await HousesService.getList(group_id, sheepName);
+
+ let result = await HousesService.getList(mode, id);
if (result) {
return res
.status(200)
diff --git a/api/controllers/stand.controller.js b/api/controllers/stand.controller.js
index 9fb132e..8b9270b 100644
--- a/api/controllers/stand.controller.js
+++ b/api/controllers/stand.controller.js
@@ -4,7 +4,26 @@ class StandController {
async getStand(req, res) {
const { stand_id } = req.params;
- return res.status(200).send({ stand_id });
+ if (stand_id) {
+ if (req.possibilities.can_view_stand) {
+ const result = await StandService.getStand(stand_id);
+ if (result) {
+ return res.status(200).send(result);
+ } else {
+ return res.status(404).send({
+ message: 'Stand not found.'
+ });
+ }
+ } else {
+ return res
+ .status(403)
+ .send({ message: 'The sheep does not have enough rights.' });
+ }
+ } else {
+ return res
+ .status(401)
+ .send({ message: 'Stand not found.' });
+ }
}
async getList(req, res) {
@@ -23,7 +42,6 @@ class StandController {
.status(404)
.send({ message: 'The sheep does not have enough rights.' });
}
-
}
async createStand(req, res) {
@@ -130,7 +148,29 @@ class StandController {
}
async getScheduleList(req, res) {
- return res.status(200).send({});
+ const { stand_id } = req.params;
+
+ if (stand_id) {
+ if (req.possibilities.can_view_stand) {
+ const result = await StandService.getScheduleList(stand_id);
+
+ if (result) {
+ return res.status(200).send(result);
+ } else {
+ return res
+ .status(404)
+ .send({ message: 'Schedule not found.' });
+ }
+ } else {
+ return res
+ .status(404)
+ .send({ message: 'The sheep does not have enough rights.' });
+ }
+ } else {
+ return res
+ .status(401)
+ .send({ message: 'Stand id not found.' });
+ }
}
async getScheduleHistory(req, res) {
diff --git a/api/package-lock.json b/api/package-lock.json
index e7158b8..1a2fe1b 100644
--- a/api/package-lock.json
+++ b/api/package-lock.json
@@ -14,6 +14,7 @@
"exceljs": "^4.4.0",
"express": "^4.21.0",
"node-telegram-bot-api": "^0.66.0",
+ "pg": "^8.16.3",
"puppeteer": "^24.4.0",
"sharp": "^0.33.5",
"sqlite3": "^5.1.7",
@@ -4251,6 +4252,87 @@
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
},
+ "node_modules/pg": {
+ "version": "8.16.3",
+ "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz",
+ "integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==",
+ "dependencies": {
+ "pg-connection-string": "^2.9.1",
+ "pg-pool": "^3.10.1",
+ "pg-protocol": "^1.10.3",
+ "pg-types": "2.2.0",
+ "pgpass": "1.0.5"
+ },
+ "engines": {
+ "node": ">= 16.0.0"
+ },
+ "optionalDependencies": {
+ "pg-cloudflare": "^1.2.7"
+ },
+ "peerDependencies": {
+ "pg-native": ">=3.0.1"
+ },
+ "peerDependenciesMeta": {
+ "pg-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/pg-cloudflare": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.7.tgz",
+ "integrity": "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==",
+ "optional": true
+ },
+ "node_modules/pg-connection-string": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz",
+ "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w=="
+ },
+ "node_modules/pg-int8": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
+ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/pg-pool": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz",
+ "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==",
+ "peerDependencies": {
+ "pg": ">=8.0"
+ }
+ },
+ "node_modules/pg-protocol": {
+ "version": "1.10.3",
+ "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz",
+ "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ=="
+ },
+ "node_modules/pg-types": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
+ "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
+ "dependencies": {
+ "pg-int8": "1.0.1",
+ "postgres-array": "~2.0.0",
+ "postgres-bytea": "~1.0.0",
+ "postgres-date": "~1.0.4",
+ "postgres-interval": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pgpass": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
+ "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
+ "dependencies": {
+ "split2": "^4.1.0"
+ }
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -4264,6 +4346,41 @@
"node": ">= 0.4"
}
},
+ "node_modules/postgres-array": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
+ "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postgres-bytea": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
+ "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-date": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
+ "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-interval": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
+ "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/prebuild-install": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
@@ -5228,6 +5345,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/split2": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
+ "engines": {
+ "node": ">= 10.x"
+ }
+ },
"node_modules/sqlite3": {
"version": "5.1.7",
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz",
@@ -6007,6 +6132,14 @@
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
},
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
diff --git a/api/package.json b/api/package.json
index 37084be..4edc293 100644
--- a/api/package.json
+++ b/api/package.json
@@ -11,12 +11,12 @@
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^17.2.0",
+ "exceljs": "^4.4.0",
"express": "^4.21.0",
"node-telegram-bot-api": "^0.66.0",
"puppeteer": "^24.4.0",
"sharp": "^0.33.5",
"sqlite3": "^5.1.7",
- "web-push": "^3.6.7",
- "exceljs": "^4.4.0"
+ "web-push": "^3.6.7"
}
}
diff --git a/api/routes/stand.routes.js b/api/routes/stand.routes.js
index e5d6c1f..6117606 100644
--- a/api/routes/stand.routes.js
+++ b/api/routes/stand.routes.js
@@ -15,7 +15,7 @@ router
.delete(authenticate, StandController.deleteStand);
router
- .route('/schedule/list')
+ .route('/schedule/list/:stand_id')
.get(authenticate, StandController.getScheduleList)
router
diff --git a/api/services/homesteads.service.js b/api/services/homesteads.service.js
index beb0371..cb92125 100644
--- a/api/services/homesteads.service.js
+++ b/api/services/homesteads.service.js
@@ -1,7 +1,7 @@
const db = require("../config/db");
class HomesteadsService {
- getList(group, sheepName) {
+ getList(mode, id) {
return new Promise((res, rej) => {
let sql = `
SELECT
@@ -17,7 +17,7 @@ class HomesteadsService {
homestead
`;
- if (group != "0" && !sheepName) {
+ if (mode == "group") {
sql = `
SELECT
homestead.*,
@@ -39,11 +39,9 @@ class HomesteadsService {
AND
homestead_history.name = 'Групова'
AND
- homestead_history.group_id == '${group}'
+ homestead_history.group_id = '${id}'
`;
- }
-
- if (sheepName) {
+ } else if (mode == "sheep" || mode == "admin") {
sql = `
SELECT
homestead.*,
@@ -63,7 +61,7 @@ class HomesteadsService {
AND
homestead_history.working = 1
AND
- homestead_history.name = '${sheepName}';
+ homestead_history.sheep_id = '${id}';
`;
}
diff --git a/api/services/houses.service.js b/api/services/houses.service.js
index c1d00eb..62b4e30 100644
--- a/api/services/houses.service.js
+++ b/api/services/houses.service.js
@@ -45,7 +45,7 @@ class HousesService {
"history": {
"id": row.entrance_history_id ? Number(row.entrance_history_id) : null,
"name": row.entrance_history_name,
- "group_id": row.entrance_history_group_id ? Number(row.entrance_history_group_id) : null,
+ "group_id": row.entrance_history_group_id ? Number(row.entrance_history_group_id) : null,
"sheep_id": row.entrance_history_sheep_id ? Number(row.entrance_history_sheep_id) : null,
"date": {
"start": row.entrance_history_date_start ? Number(row.entrance_history_date_start) : null,
@@ -61,7 +61,7 @@ class HousesService {
});
}
- getList(group, sheepName) {
+ getList(mode, id) {
return new Promise((res, rej) => {
let sql = `
SELECT
@@ -72,7 +72,7 @@ class HousesService {
house
`;
- if (group != "0" && !sheepName) {
+ if (mode == "group") {
sql = `
SELECT DISTINCT
house.*,
@@ -89,11 +89,9 @@ class HousesService {
AND
entrance_history.name = 'Групова'
AND
- entrance_history.group_id == '${group}'
+ entrance_history.group_id = '${id}'
`;
- }
-
- if (sheepName) {
+ } else if (mode == "sheep" || mode == "admin") {
sql = `
SELECT DISTINCT
house.*,
@@ -108,7 +106,7 @@ class HousesService {
WHERE
entrance_history.working = 1
AND
- entrance_history.name = '${sheepName}'
+ entrance_history.sheep_id = '${id}'
`;
}
diff --git a/api/services/stand.service.js b/api/services/stand.service.js
index 784da64..aec6a40 100644
--- a/api/services/stand.service.js
+++ b/api/services/stand.service.js
@@ -4,7 +4,34 @@ const db = require("../config/db");
class StandService {
getStand(id) {
return new Promise((res, rej) => {
- return res({ id });
+ const sql = `SELECT * FROM stand_list WHERE id = ?`;
+
+ db.get(sql, [id], (err, row) => {
+ if (err) {
+ console.error(err.message);
+ return res(false);
+ }
+ if (!row) {
+ console.log({ error: "id not found" });
+ return res(false);
+ }
+
+
+ let data = {
+ "id": Number(row.id),
+ "title": row.title,
+ "geo": JSON.parse(row.geo),
+ "hour_start": Number(row.hour_start),
+ "hour_end": Number(row.hour_end),
+ "quantity_sheep": Number(row.quantity_sheep),
+ "week_days": JSON.parse(row.week_days),
+ "processing_time": Number(row.processing_time),
+ "status": row.status == 1 ? true : false,
+ "updated_at": Number(row.updated_at)
+ }
+
+ return res(data);
+ });
});
}
@@ -165,7 +192,7 @@ class StandService {
if (row && row.max_date) {
date_start = getNextMonday(row.max_date); // заменить начальную дату
} else {
- date_start = getNextMonday(Date.now()); // заменить начальную дату
+ date_start = getNextMonday(Date.now()); // заменить начальную дату
}
// 3. Генерация новых записей
@@ -206,7 +233,7 @@ class StandService {
console.error(err.message);
return res(false);
}
- res({ status: "ok", inserted: list.length });
+ res({ status: "ok", inserted: list.length});
});
}
);
@@ -214,9 +241,45 @@ class StandService {
});
}
- getScheduleList(data) {
+ getScheduleList(stand_id) {
return new Promise((res, rej) => {
- return res({ data });
+ const sql = `
+ SELECT
+ ss.*,
+ s.name AS sheep_name
+ FROM
+ stand_schedule AS ss
+ LEFT JOIN
+ sheeps AS s
+ ON
+ s.id = ss.sheep_id
+ WHERE
+ ss.stand_id = ?
+ ORDER BY
+ ss.id;
+ `;
+
+ db.all(sql, [stand_id], (err, rows) => {
+ if (err) {
+ console.error(err.message);
+ return res(false);
+ } else {
+ let data = rows.map((row) => {
+ return {
+ "id": Number(row.id),
+ "stand_id": Number(row.stand_id),
+ "date": Number(row.date),
+ "hour": Number(row.hour),
+ "sheep_id": Number(row.sheep_id),
+ "sheep_name": row.sheep_name,
+ "number_sheep": Number(row.number_sheep),
+ "updated_at": Number(row.updated_at)
+ }
+ })
+
+ return res(data);
+ }
+ });
});
}
diff --git a/web/css/main.css b/web/css/main.css
index ac84f6b..c1fe9a0 100644
--- a/web/css/main.css
+++ b/web/css/main.css
@@ -412,7 +412,7 @@ body.modal-open {
#update_banner .content {
margin: 0 auto;
- max-width: 300px;
+ max-width: 340px;
display: flex;
flex-direction: column;
justify-content: center;
@@ -424,6 +424,8 @@ body.modal-open {
font-size: var(--FontSize4);
color: var(--PrimaryColorText);
font-family: 'Roboto', sans-serif;
+ margin-bottom: 5px;
+ opacity: 0.9;
}
#update_banner .subhead {
@@ -438,7 +440,7 @@ body.modal-open {
}
#update_banner[data-state="updateavailable"] {
- display: block;
+ display: flex;
cursor: pointer;
background-color: var(--PrimaryColor);
color: var(--PrimaryColorText);
@@ -446,10 +448,10 @@ body.modal-open {
opacity: 0.95;
z-index: 9999;
position: fixed;
- width: 300px;
+ width: 350px;
margin: 10px;
padding: 5px;
- border-radius: 25px;
+ border-radius: var(--border-radius);
right: 0;
}
diff --git a/web/index.html b/web/index.html
index e9e29ce..2967f9c 100644
--- a/web/index.html
+++ b/web/index.html
@@ -57,6 +57,8 @@
+
+
@@ -103,6 +105,9 @@
+
+
+
@@ -266,7 +271,7 @@
-
+
+
+
diff --git a/web/lib/pages/options/script.js b/web/lib/pages/options/script.js
index cbe1256..f717f3f 100644
--- a/web/lib/pages/options/script.js
+++ b/web/lib/pages/options/script.js
@@ -1,13 +1,14 @@
const Options = {
- init: async () => {
+ async init() {
let html = await fetch('/lib/pages/options/index.html').then((response) => response.text());
app.innerHTML = html;
await Options.optionPush.init();
Options.optionFont.init();
},
+
optionPush: {
- init: async () => {
+ async init() {
const element = document.getElementById("page-options-notifications");
const permission = await Notification.requestPermission();
@@ -25,7 +26,8 @@ const Options = {
element.checked = false;
}
},
- edit: (state) => {
+
+ edit(state) {
if (state) {
webPush.init();
} else {
@@ -33,8 +35,9 @@ const Options = {
}
}
},
+
optionFont: {
- init: () => {
+ init() {
const element = document.getElementById("page-options-fontSize");
let fontSize = localStorage.getItem("fontSize")
@@ -43,9 +46,15 @@ const Options = {
element.value = fontSize;
},
- edit: (mode) => {
+
+ edit(mode) {
localStorage.setItem("fontSize", mode);
applyFontMode(mode);
}
+ },
+
+ logout() {
+ localStorage.removeItem("uuid");
+ window.location.reload();
}
}
\ No newline at end of file
diff --git a/web/lib/pages/options/style.css b/web/lib/pages/options/style.css
index bae49ca..ffd7691 100644
--- a/web/lib/pages/options/style.css
+++ b/web/lib/pages/options/style.css
@@ -53,4 +53,16 @@
justify-content: space-between;
cursor: pointer;
margin: 5px 0;
+}
+
+.page-options>button {
+ border-radius: var(--border-radius);
+ background: var(--PrimaryColor);
+ color: var(--PrimaryColorText);
+ width: 100%;
+ height: 40px;
+ font-size: var(--FontSize3);
+ font-weight: 400;
+ margin: 20px 0;
+ text-transform: uppercase;
}
\ No newline at end of file
diff --git a/web/lib/pages/sheeps/script.js b/web/lib/pages/sheeps/script.js
index dcd37ad..621ce0d 100644
--- a/web/lib/pages/sheeps/script.js
+++ b/web/lib/pages/sheeps/script.js
@@ -27,144 +27,142 @@ let Sheeps_icon = [
''
]
-const SheepsEvents = (() => {
- let initialized = false;
+const SheepsEvents = {
+ initialized: false,
- return {
- init: () => {
- if (initialized) return;
+ init() {
+ if (this.initialized) return;
- const sheepEditorForm = document.getElementById("sheep-editor");
- const sheepEditorButton = document.getElementById('sheep-editor-button');
- sheepEditorForm.addEventListener("submit", async (event) => {
- event.preventDefault();
+ const sheepEditorForm = document.getElementById("sheep-editor");
+ const sheepEditorButton = document.getElementById('sheep-editor-button');
+ sheepEditorForm.addEventListener("submit", async (event) => {
+ event.preventDefault();
- const form = event.target;
- const formData = new FormData(form);
- const uuidValue = form.elements["uuid"].value;
- const sheep = Sheeps.sheeps_list.list.find(item => item.uuid === uuidValue);
+ const form = event.target;
+ const formData = new FormData(form);
+ const uuidValue = form.elements["uuid"].value;
+ const sheep = Sheeps.sheeps_list.list.find(item => item.uuid === uuidValue);
- if (!sheep) {
- console.error("Sheep not found for uuid:", uuidValue);
- return;
- }
+ if (!sheep) {
+ console.error("Sheep not found for uuid:", uuidValue);
+ return;
+ }
- sheep.name = form.elements["name"].value;
- sheep.group_id = Number(formData.get("group_id"));
- sheep.appointment = formData.get("appointment");
- sheep.mode = formData.get("mode");
- sheep.mode_title = ["Користувач", "Модератор", "Адміністратор"][sheep.mode] || "Користувач";
+ sheep.name = form.elements["name"].value;
+ sheep.group_id = Number(formData.get("group_id"));
+ sheep.appointment = formData.get("appointment");
+ sheep.mode = formData.get("mode");
+ sheep.mode_title = ["Користувач", "Модератор", "Адміністратор"][sheep.mode] || "Користувач";
- const permKeys = [
- "can_view_sheeps",
- "can_view_schedule",
- "can_view_stand",
- "can_view_territory",
- "can_add_sheeps",
- "can_add_territory",
- "can_manager_territory",
- "can_add_stand",
- "can_manager_stand",
- "can_add_schedule"
- ];
- for (const key of permKeys) {
- sheep.possibilities[key] = form.elements[key].checked;
- }
+ const permKeys = [
+ "can_view_sheeps",
+ "can_view_schedule",
+ "can_view_stand",
+ "can_view_territory",
+ "can_add_sheeps",
+ "can_add_territory",
+ "can_manager_territory",
+ "can_add_stand",
+ "can_manager_stand",
+ "can_add_schedule"
+ ];
+ for (const key of permKeys) {
+ sheep.possibilities[key] = form.elements[key].checked;
+ }
- sheepEditorButton.innerText = "Зачекайте...";
+ sheepEditorButton.innerText = "Зачекайте...";
- try {
- const uuid = localStorage.getItem('uuid');
- const URL = `${CONFIG.api}sheep`;
- const response = await fetch(URL, {
- method: 'PUT',
- headers: {
- "Content-Type": "application/json",
- "Authorization": uuid
- },
- body: JSON.stringify(sheep)
- });
+ try {
+ const uuid = localStorage.getItem('uuid');
+ const URL = `${CONFIG.api}sheep`;
+ const response = await fetch(URL, {
+ method: 'PUT',
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": uuid
+ },
+ body: JSON.stringify(sheep)
+ });
- if (response.ok) {
- sheepEditorButton.innerText = "Успішно збережено";
- const data = await response.json();
- console.log(data);
+ if (response.ok) {
+ sheepEditorButton.innerText = "Успішно збережено";
+ const data = await response.json();
+ console.log(data);
- Sheeps.sheeps_list.list = [];
- await Sheeps.sheeps_list.setHTML();
+ Sheeps.sheeps_list.list = [];
+ await Sheeps.sheeps_list.setHTML();
- setTimeout(() => {
- sheepEditorButton.innerText = "Зберегти";
- }, 3000);
- } else {
- console.error('Помилка збереження');
- sheepEditorButton.innerText = "Помилка збереження";
- }
- } catch (err) {
- console.error(err);
+ setTimeout(() => {
+ sheepEditorButton.innerText = "Зберегти";
+ }, 3000);
+ } else {
+ console.error('Помилка збереження');
sheepEditorButton.innerText = "Помилка збереження";
}
- });
+ } catch (err) {
+ console.error(err);
+ sheepEditorButton.innerText = "Помилка збереження";
+ }
+ });
- const sheepAddedsForm = document.getElementById("sheep-addeds");
- const sheepAddedsButton = document.getElementById('sheep-addeds-button');
- sheepAddedsForm.addEventListener("submit", async (event) => {
- event.preventDefault();
+ const sheepAddedsForm = document.getElementById("sheep-addeds");
+ const sheepAddedsButton = document.getElementById('sheep-addeds-button');
+ sheepAddedsForm.addEventListener("submit", async (event) => {
+ event.preventDefault();
- const form = event.target;
- const formData = new FormData(form);
- const data = Object.fromEntries(formData.entries());
+ const form = event.target;
+ const formData = new FormData(form);
+ const data = Object.fromEntries(formData.entries());
- sheepAddedsButton.innerText = "Зачекайте...";
+ sheepAddedsButton.innerText = "Зачекайте...";
- try {
- const uuid = localStorage.getItem('uuid');
- const URL = `${CONFIG.api}sheep`;
- const response = await fetch(URL, {
- method: 'POST',
- headers: {
- "Content-Type": "application/json",
- "Authorization": uuid
- },
- body: JSON.stringify(data)
- });
+ try {
+ const uuid = localStorage.getItem('uuid');
+ const URL = `${CONFIG.api}sheep`;
+ const response = await fetch(URL, {
+ method: 'POST',
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": uuid
+ },
+ body: JSON.stringify(data)
+ });
- if (response.ok) {
- sheepAddedsButton.innerText = "Вісника додано";
- const data = await response.json();
- console.log(data);
+ if (response.ok) {
+ sheepAddedsButton.innerText = "Вісника додано";
+ const data = await response.json();
+ console.log(data);
- Sheeps.sheeps_list.list = [];
+ Sheeps.sheeps_list.list = [];
- const randomNumber = Math.floor(Math.random() * Sheeps_icon.length);
+ const randomNumber = Math.floor(Math.random() * Sheeps_icon.length);
- Sheeps.addeds.close();
- await Sheeps.editor.setHTML(data.uuid, randomNumber);
+ Sheeps.addeds.close();
+ await Sheeps.editor.setHTML(data.id, randomNumber);
- setTimeout(() => {
- sheepAddedsButton.innerText = "Додати";
- }, 3000);
- } else {
- console.error('Помилка додавання');
- sheepAddedsButton.innerText = "Помилка додавання";
- }
- } catch (err) {
- console.error(err);
+ setTimeout(() => {
+ sheepAddedsButton.innerText = "Додати";
+ }, 3000);
+ } else {
+ console.error('Помилка додавання');
sheepAddedsButton.innerText = "Помилка додавання";
}
- });
+ } catch (err) {
+ console.error(err);
+ sheepAddedsButton.innerText = "Помилка додавання";
+ }
+ });
- initialized = true;
- }
+ this.initialized = true;
}
-})();
+};
const Sheeps = {
init: async (id) => {
let html = await fetch('/lib/pages/sheeps/index.html').then((response) => response.text());
app.innerHTML = html;
- Sheeps.sheeps_list.setHTML();
+ await Sheeps.sheeps_list.setHTML();
if (id) Sheeps.editor.setHTML(id);
SheepsEvents.init();
@@ -196,6 +194,8 @@ const Sheeps = {
? Sheeps.sheeps_list.list
: await Sheeps.sheeps_list.loadAPI();
+ Sheeps.sheeps_list.list.sort((a, b) => a.group_id - b.group_id);
+
let block_sheeps = document.getElementById('block-sheeps-list');
let butt_add = USER.possibilities.can_add_sheeps ? `
@@ -245,7 +245,7 @@ const Sheeps = {
if (search_value && !element.name.toLowerCase().includes(search_value)) {
continue; // пропустить, если имя не содержит строку поиска
}
-
+
html += `
${Sheeps_icon[element.group_id]}
@@ -386,11 +386,13 @@ const Sheeps = {
sheep_editor_can_view_territory.checked = sheep.possibilities.can_view_territory;
if (USER.possibilities.can_manager_territory) {
- document.getElementById('editor-blocks-territory').style.display = "";
+ document.getElementById('editor-blocks-territory').style.display = "none";
+ document.getElementById(`editor-blocks-territory`).innerHTML = "
Території вісника";
+ Sheeps.territory.house(id);
+ Sheeps.territory.homestead(id);
}
if (USER.mode == 2) {
- document.getElementById('editor-blocks-territory').style.display = "";
document.getElementById('sheep-editor-button').style.display = "";
sheep_editor_mode.disabled = false;
} else {
@@ -462,5 +464,69 @@ const Sheeps = {
search_value = value?.trim()?.toLowerCase() || "";
Sheeps.sheeps_list.setHTML(search_value);
}
+ },
+ territory: {
+ async loadAPI(URL) {
+ const uuid = localStorage.getItem("uuid");
+ const res = await fetch(URL, {
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": uuid
+ }
+ });
+ return await res.json();
+ },
+
+ async house(id) {
+ const URL = `${CONFIG.api}house/list?mode=admin&sheep_id=${id}`;
+ const list = await Sheeps.territory.loadAPI(URL);
+
+ if ((USER.possibilities.can_view_territory || USER.mode == 2) && list.length > 0){
+ document.getElementById('editor-blocks-territory').style.display = "";
+ Sheeps.territory.renderCards(list, "house");
+ }
+ },
+
+ async homestead(id) {
+ const URL = `${CONFIG.api}homestead/list?mode=admin&sheep_id=${id}`;
+ const list = await Sheeps.territory.loadAPI(URL);
+
+ if ((USER.possibilities.can_view_territory || USER.mode == 2) && list.length > 0){
+ document.getElementById('editor-blocks-territory').style.display = "";
+ Sheeps.territory.renderCards(list, "homestead");
+ }
+ },
+
+ renderCards: (list, type) => {
+ const container = document.getElementById(`editor-blocks-territory`);
+ const fragment = document.createDocumentFragment();
+
+ for (const el of list) {
+ const card = document.createElement("div");
+ card.innerHTML = `
+
+
${el.title} ${el.number}
+
+
+
+
+
+
+ `;
+ fragment.appendChild(card);
+ }
+
+ container.appendChild(fragment);
+ }
}
}
\ No newline at end of file
diff --git a/web/lib/pages/sheeps/style.css b/web/lib/pages/sheeps/style.css
index 2b85cff..55a3934 100644
--- a/web/lib/pages/sheeps/style.css
+++ b/web/lib/pages/sheeps/style.css
@@ -552,17 +552,17 @@
align-items: flex-start;
margin: 10px;
padding: 10px;
- min-height: 100px;
+ min-height: 30px;
justify-content: center;
position: relative;
- border-radius: calc(var(--border-radius) - 5px - 6px);
+ border-radius: calc(var(--border-radius) - 5px - 6px);
}
#editor-blocks-territory>div>#title {
display: flex;
align-items: center;
height: 30px;
- margin-bottom: 10px;
+ /* margin-bottom: 10px; */
justify-content: space-between;
}
@@ -595,14 +595,14 @@
}
#editor-blocks-territory>div>#title>a>svg {
- width: 25px;
- height: 25px;
+ width: 20px;
+ height: 20px;
fill: var(--PrimaryColorText);
}
#editor-blocks-territory>div>div {
display: flex;
- margin-bottom: 10px;
+ /* margin-bottom: 10px; */
flex-direction: row;
align-items: center;
width: 100%;
diff --git a/web/lib/pages/stand/card/index.html b/web/lib/pages/stand/card/index.html
index 5a51515..fbae17c 100644
--- a/web/lib/pages/stand/card/index.html
+++ b/web/lib/pages/stand/card/index.html
@@ -6,277 +6,14 @@
Інформація про стенд
Розташування:
-
Тест
+
--
![]()
-
-
-
-
+
diff --git a/web/lib/pages/stand/card/script.js b/web/lib/pages/stand/card/script.js
index 553c652..8322c49 100644
--- a/web/lib/pages/stand/card/script.js
+++ b/web/lib/pages/stand/card/script.js
@@ -1,123 +1,541 @@
const Stand_card = {
- schedule: [],
- init: async (id) => {
+ id: null,
+ async init(id) {
let html = await fetch('/lib/pages/stand/card/index.html').then((response) => response.text());
app.innerHTML = html;
- let listDate = [1, 4];
+ Stand_card.id = id;
- function generateAvailableDates() {
- let select = document.getElementById("dateSelect");
- select.innerHTML = "";
+ this.info.setHTML();
+ },
- let today = new Date();
- today.setHours(0, 0, 0, 0);
- let months = [today.getMonth(), today.getMonth() + 1];
- let year = today.getFullYear();
+ async loadAPI(url) {
+ const uuid = localStorage.getItem("uuid");
+ const response = await fetch(url, {
+ method: 'GET',
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": uuid
+ }
+ });
+ return await response.json();
+ },
- months.forEach(month => {
- let date = new Date(year, month, 1);
- while (date.getMonth() === month) {
- if (date >= today) {
- let day = date.getDay();
- if (listDate.includes(day)) {
- let option = document.createElement("option");
- option.value = date.toISOString().split("T")[0];
- option.textContent = date.toLocaleDateString("uk-UA", {
- weekday: "long", year: "numeric", month: "long", day: "numeric"
- });
- select.appendChild(option);
+ info: {
+ list: [],
+
+ async setHTML() {
+ const url = `${CONFIG.api}stand/${Stand_card.id}`;
+ this.list = await Stand_card.loadAPI(url);
+
+ document.getElementById('stand-info-title').innerText = this.list.title;
+ document.getElementById('stand-info-geo').innerHTML = 'Відкрити Google Maps';
+ document.getElementById('stand-info-geo').href = `https://www.google.com/maps?q=${this.list.geo[0]},${this.list.geo[1]}`;
+ document.getElementById('stand-info-image').setAttribute('src', '');
+
+ Stand_card.schedule.setHTML();
+ }
+ },
+
+ // Робота з WebSocket
+ cloud: {
+ update(msg) {
+ const { type, data, user } = msg;
+ const el = document.getElementById(`name-${data?.id}`);
+ if (!el) return; // если элемент не найден — выходим
+
+ const isSelf = user.id == USER.id;
+
+ switch (type) {
+ case "stand_locking":
+ if (!isSelf) {
+ el.disabled = true;
+ el.style.border = "2px solid var(--PrimaryColor)";
+ el.style.backgroundColor = "#EAFF0024";
+ }
+ break;
+
+ case "stand_unlocking":
+ // Разблокируем только если событие от другого пользователя
+ if (!isSelf) {
+ el.style.border = "";
+ el.style.backgroundColor = "";
+ }
+ if ((!isSelf && !el.value) || USER.possibilities.can_manager_stand) {
+ el.removeAttribute("disabled");
+ }
+ break;
+
+ case "stand_update": {
+ const sid = data.sheep_id;
+ const sname = data.sheep_name ?? "";
+
+ // Менеджеру показываем весь список
+ if (USER.possibilities.can_manager_stand && Array.isArray(Sheeps?.sheeps_list?.list)) {
+ el.innerHTML = "";
+
+ // пустой вариант
+ el.appendChild(Object.assign(document.createElement("option"), {
+ value: "",
+ textContent: " "
+ }));
+
+ // заполняем всех овечек
+ Sheeps.sheeps_list.list.forEach(s => {
+ const opt = document.createElement("option");
+ opt.value = s.id;
+ opt.textContent = s.name;
+ if (s.id == sid) opt.selected = true;
+ el.appendChild(opt);
+ });
+
+ el.removeAttribute("disabled");
+ } else {
+ // Обычное поведение для обычных пользователей
+ if (sid == USER.id) {
+ el.innerHTML = ``;
+ el.removeAttribute("disabled");
+ } else if (!sid) {
+ el.innerHTML = ``;
+ el.removeAttribute("disabled");
+ } else {
+ el.innerHTML = ``;
+ el.disabled = true;
}
}
- date.setDate(date.getDate() + 1);
- }
- });
- }
- // generateAvailableDates();
- Stand_card.generator();
+ el.style.border = "";
+ el.style.backgroundColor = "";
+ break;
+ }
+
+ default:
+ return;
+ }
+ },
+
+ // update(msg) {
+ // console.log(msg.type, msg.data.id);
+
+ // if (msg.type == "stand_locking") {
+ // const id = msg.data.id;
+ // const el = document.getElementById(`name-${id}`);
+
+ // if (msg.user.id != USER.id) {
+ // el.disabled = true;
+ // el.style.border = "2px solid var(--PrimaryColor);"
+ // el.style.backgroundColor = "red"
+ // }
+ // } else if (msg.type == "stand_unlocking") {
+ // const id = msg.data.id;
+ // const el = document.getElementById(`name-${id}`);
+ // if (msg.user.id != USER.id || !msg.data.sheep_id) {
+ // el.style.border = "";
+ // el.style.backgroundColor = ""
+ // el.removeAttribute('disabled');
+ // }
+ // } else if (msg.type == "stand_update") {
+ // const id = msg.data.id;
+ // const el = document.getElementById(`name-${id}`);
+ // if (msg.data.sheep_id == USER.id) {
+ // el.innerHTML = ``;
+ // el.removeAttribute('disabled');
+ // } else if (msg.data.sheep_id == "" || msg.data.sheep_id == null || msg.data.sheep_id == USER.id) {
+ // el.innerHTML = ``;
+ // el.removeAttribute('disabled');
+ // } else {
+ // el.innerHTML = ``;
+ // el.disabled = true;
+ // }
+ // el.style.border = "";
+ // el.style.backgroundColor = ""
+ // } else return;
+ // },
+
+ mess: {
+ locking({ id }) {
+ const message = {
+ event: 'message',
+ user: {
+ name: USER.name,
+ id: USER.id
+ },
+ type: "stand_locking",
+ data: {
+ id: id,
+ stand_id: Stand_card.id,
+ sheep_name: null
+ }
+ };
+
+ if (Cloud.socket?.readyState === WebSocket.OPEN) {
+ Cloud.socket.send(JSON.stringify(message));
+ } else {
+ if (confirm("З'єднання розірвано! Перепідключитись?")) {
+ Cloud.start();
+ }
+ }
+ },
+ unlocking({ id }) {
+ const message = {
+ event: 'message',
+ user: {
+ name: USER.name,
+ id: USER.id
+ },
+ type: "stand_unlocking",
+ data: {
+ id: id,
+ stand_id: Stand_card.id
+ }
+ };
+
+ if (Cloud.socket?.readyState === WebSocket.OPEN) {
+ Cloud.socket.send(JSON.stringify(message));
+ } else {
+ if (confirm("З'єднання розірвано! Перепідключитись?")) {
+ Cloud.start();
+ }
+ }
+ },
+ update({ sheep_id, id }) {
+ const message = {
+ event: 'message',
+ user: {
+ name: USER.name,
+ id: USER.id
+ },
+ type: "stand_update",
+ data: {
+ id: id,
+ stand_id: Stand_card.id,
+ sheep_id: sheep_id,
+ sheep_name: null
+ }
+ };
+
+ if (USER.possibilities.can_manager_stand) {
+ const pos = Sheeps.sheeps_list.list.map(e => e.id).indexOf(Number(sheep_id));
+ if (pos != -1) {
+ let name = Sheeps.sheeps_list.list[pos].name;
+ message.data.sheep_name = name;
+ }
+ }
+
+ if (Cloud.socket?.readyState === WebSocket.OPEN) {
+ Cloud.socket.send(JSON.stringify(message));
+ } else {
+ if (confirm("З'єднання розірвано! Перепідключитись?")) {
+ Cloud.start();
+ }
+ }
+ }
+ },
},
- generator: () => {
- let block_schedule = document.getElementById('stand-schedule');
- let html = "";
+ schedule: {
+ list: [],
+ async setHTML() {
+ const block = document.getElementById('stand-schedule');
+ block.innerHTML = '';
- let stand = {
- id: 1,
- title: "Універсам",
- geo: { lat: 0, lng: 0 },
- hour_start: 9,
- hour_end: 14,
- quantity_sheep: 2,
- week_days: [0, 2, 4, 6],
- processing_time: 0.5,
- updated_at: null
- }
+ const url = `${CONFIG.api}stand/schedule/list/${Stand_card.id}`;
+ this.list = Stand_card.grouped(await Stand_card.loadAPI(url));
- Stand_card.schedule = [];
+ const fragment = document.createDocumentFragment();
- // Кількість годин служіння
- let stand_length = (stand.hour_end - stand.hour_start) / stand.processing_time;
+ const createSelect = (sheep) => {
+ const select = document.createElement("select");
+ select.id = `name-${sheep.id}`;
- for (let z = 0; z < stand.week_days.length; z++) {
- Stand_card.schedule.push([]);
+ // пустой option
+ select.appendChild(Object.assign(document.createElement("option"), {
+ value: "",
+ textContent: " "
+ }));
- let date = new Date();
- date.setDate(date.getDate() + stand.week_days[z]);
- let dayName = date.toLocaleDateString('uk-UA', { weekday: 'long' });
-
- html += `
-
-
${date.toLocaleDateString()} • ${dayName}
- `;
-
- let stand_date = 1 + stand.week_days[z];
-
- for (let i = 0; i < stand_length; i++) {
- let time_now = stand.hour_start + (stand.processing_time * i);
- let timeFormat = (a) => a > 9 ? a : `0${a}`;
-
- function formatTime(hours) {
- let h = Math.floor(hours);
- let m = (hours % 1 === 0.5) ? "30" : "00";
- let hh = h.toString().padStart(2, "0");
- return `${hh}:${m}`;
- }
-
- html += `
-
- ${formatTime(time_now)}-${formatTime(time_now + stand.processing_time)}
- `;
-
- for (let q = 0; q < stand.quantity_sheep; q++) {
- html += `
-
- `;
-
- Stand_card.schedule[z].push({
- id: (i + z) * stand.quantity_sheep + q,
- hour: stand.hour_start + (stand.processing_time * i),
- number_sheep: q,
- date: stand_date,
- sheep_id: null,
- stand_id: stand.id,
- updated_at: Date.now()
+ // если есть права менеджера — добавляем всех пользователей
+ if (USER.possibilities.can_manager_stand && Array.isArray(Sheeps?.sheeps_list?.list)) {
+ Sheeps.sheeps_list.list.sort((a, b) => a.name.localeCompare(b.name, 'uk'));
+ Sheeps.sheeps_list.list.forEach(s => {
+ const option = document.createElement("option");
+ option.value = s.id;
+ option.textContent = s.name;
+ if (s.id === sheep.sheep_id) option.selected = true;
+ select.appendChild(option);
});
+ } else {
+ // если есть владелец — показываем его
+ const opt = document.createElement("option");
+ if (sheep.sheep_id) {
+ opt.value = sheep.sheep_id;
+ opt.textContent = sheep.sheep_name ?? USER.name;
+ opt.selected = sheep.sheep_id === USER.id;
+ } else {
+ opt.value = USER.id;
+ opt.textContent = USER.name;
+ }
+ select.appendChild(opt);
}
- html += `
`; // закриваємо hour
+ // если занят другим пользователем — блокируем
+ if (sheep.sheep_id && sheep.sheep_id !== USER.id && !USER.possibilities.can_manager_stand) {
+ select.disabled = true;
+ select.value = sheep.sheep_id;
+ }
+
+ // --- обработчики ---
+ select.addEventListener("mousedown", () => Stand_card.cloud.mess.locking({ id: sheep.id }));
+ select.addEventListener("change", () => Stand_card.cloud.mess.update({ sheep_id: select.value, id: sheep.id }));
+ select.addEventListener("blur", () => Stand_card.cloud.mess.unlocking({ id: sheep.id }));
+
+ return select;
+ };
+
+ this.list.forEach((day, dayIndex) => {
+ const timestamp = day[0][0].date;
+ const dayDiv = Object.assign(document.createElement("div"), {
+ className: "block-day",
+ id: `day-${dayIndex}`
+ });
+
+ dayDiv.appendChild(Object.assign(document.createElement("h3"), {
+ textContent: `${formattedDate(timestamp)} • ${formattedDayName(timestamp)}`
+ }));
+
+ day.forEach((hour, hourIndex) => {
+ const hourDiv = Object.assign(document.createElement("div"), {
+ id: `hour-${dayIndex}-${hourIndex}`
+ });
+
+ hourDiv.appendChild(Object.assign(document.createElement("span"), {
+ className: "time",
+ textContent: `${Stand_card.formatTime(hour[0].hour)}-${Stand_card.formatTime(hour[0].hour + Stand_card.info.list.processing_time)}`
+ }));
+
+ hour.forEach(sheep => hourDiv.appendChild(createSelect(sheep)));
+ dayDiv.appendChild(hourDiv);
+ });
+
+ fragment.appendChild(dayDiv);
+ });
+
+ // кнопка добавления
+ if (USER.possibilities.can_add_stand) {
+ const btn = Object.assign(document.createElement("button"), {
+ id: "stand-new-button",
+ textContent: "Додати стенд(и)",
+ onclick: () => Stand_card.addStand()
+ });
+ fragment.appendChild(btn);
}
- html += `
`; // закриваємо day
+ block.appendChild(fragment);
+ }
+ // async setHTML() {
+ // const block_schedule = document.getElementById('stand-schedule');
+ // block_schedule.innerHTML = '';
+
+ // const url = `${CONFIG.api}stand/schedule/list/${Stand_card.id}`;
+ // this.list = Stand_card.grouped(await Stand_card.loadAPI(url));
+
+ // let dayIndex = 0;
+ // for (const day of this.list) {
+ // const timestamp = day[0][0].date;
+
+ // const dayDiv = document.createElement("div");
+ // dayDiv.className = "block-day";
+ // dayDiv.id = `day-${dayIndex}`;
+
+ // const header = document.createElement("h3");
+ // header.textContent = `${formattedDate(timestamp)} • ${formattedDayName(timestamp)}`;
+ // dayDiv.appendChild(header);
+
+ // let hourIndex = 0;
+ // for (const hour of day) {
+ // const hourDiv = document.createElement("div");
+ // hourDiv.id = `hour-${dayIndex}-${hourIndex}`;
+
+ // const span = document.createElement("span");
+ // span.className = "time";
+ // span.textContent = `${Stand_card.formatTime(hour[0].hour)}-${Stand_card.formatTime(hour[0].hour + Stand_card.info.list.processing_time)}`;
+ // hourDiv.appendChild(span);
+
+ // for (const sheep of hour) {
+ // const select = document.createElement("select");
+ // select.id = `name-${sheep.id}`;
+
+ // const emptyOption = document.createElement("option");
+ // emptyOption.value = "";
+ // emptyOption.textContent = " ";
+ // select.appendChild(emptyOption);
+
+ // if (sheep.sheep_id && sheep.sheep_id == USER.id) {
+ // const opt = document.createElement("option");
+ // opt.value = USER.id;
+ // opt.textContent = USER.name;
+ // opt.selected = true;
+ // select.appendChild(opt);
+
+ // // --- Обработчики событий ---
+ // select.addEventListener("focus", () => {
+ // // пользователь начал взаимодействие → блокируем
+ // Stand_card.cloud.mess.locking({ id: sheep.id });
+ // });
+
+ // select.addEventListener("blur", () => {
+ // // пользователь ушёл → разблокируем
+ // Stand_card.cloud.mess.unlocking({ id: sheep.id });
+ // });
+
+ // select.addEventListener("change", () => {
+ // // пользователь выбрал что-то → обновляем
+ // Stand_card.cloud.mess.update({ sheep_id: select.value, id: sheep.id });
+ // });
+ // } else if (sheep.sheep_id && sheep.sheep_id != USER.id) {
+ // const opt = document.createElement("option");
+ // opt.value = sheep.sheep_id;
+ // opt.textContent = sheep.sheep_name;
+ // opt.selected = true;
+ // select.appendChild(opt);
+
+ // // --- Обработчики событий ---
+ // select.addEventListener("focus", () => {
+ // // пользователь начал взаимодействие → блокируем
+ // Stand_card.cloud.mess.locking({ id: sheep.id });
+ // });
+
+ // select.addEventListener("blur", () => {
+ // // пользователь ушёл → разблокируем
+ // Stand_card.cloud.mess.unlocking({ id: sheep.id });
+ // });
+
+ // select.addEventListener("change", () => {
+ // // пользователь выбрал что-то → обновляем
+ // Stand_card.cloud.mess.update({ sheep_id: select.value, id: sheep.id });
+ // });
+
+ // select.disabled = true;
+ // } else {
+ // const opt = document.createElement("option");
+ // opt.value = USER.id;
+ // opt.textContent = USER.name;
+ // select.appendChild(opt);
+
+ // // --- Обработчики событий ---
+ // select.addEventListener("focus", () => {
+ // // пользователь начал взаимодействие → блокируем
+ // Stand_card.cloud.mess.locking({ id: sheep.id });
+ // });
+
+ // select.addEventListener("blur", () => {
+ // // пользователь ушёл → разблокируем
+ // Stand_card.cloud.mess.unlocking({ id: sheep.id });
+ // });
+
+ // select.addEventListener("change", () => {
+ // // пользователь выбрал что-то → обновляем
+ // Stand_card.cloud.mess.update({ sheep_id: select.value, id: sheep.id });
+ // });
+ // }
+
+ // hourDiv.appendChild(select);
+ // }
+
+ // dayDiv.appendChild(hourDiv);
+ // hourIndex++;
+ // }
+
+ // block_schedule.appendChild(dayDiv);
+ // dayIndex++;
+ // }
+
+ // if (USER.possibilities.can_add_stand) {
+ // const btn = document.createElement("button");
+ // btn.id = "stand-new-button";
+ // btn.onclick = () => Stand_card.addStand();
+ // btn.textContent = "Додати стенд(и)";
+ // block_schedule.appendChild(btn);
+ // }
+ // }
+ },
+
+ grouped(list) {
+ const groupedByDate = {};
+ for (const item of list) {
+ if (!groupedByDate[item.date]) groupedByDate[item.date] = [];
+ groupedByDate[item.date].push(item);
}
- document.getElementById('stand-info-title').innerText = Stand_card.title;
- document.getElementById('stand-info-geo').innerHTML = '';
- document.getElementById('stand-info-image').setAttribute('src', '');
+ const result = Object.values(groupedByDate).map(dateGroup => {
+ const groupedByHour = [];
+ let currentGroup = [];
+ let lastHour = null;
+
+ for (const item of dateGroup) {
+ if (item.hour !== lastHour) {
+ if (currentGroup.length > 0) groupedByHour.push(currentGroup);
+ currentGroup = [];
+ lastHour = item.hour;
+ }
+ currentGroup.push(item);
+ }
+ if (currentGroup.length > 0) groupedByHour.push(currentGroup);
+
+ return groupedByHour;
+ });
+
+ return result;
+ },
+
+ formatTime(hours) {
+ let h = Math.floor(hours);
+ let m = (hours % 1 === 0.5) ? "30" : "00";
+ let hh = h.toString().padStart(2, "0");
+ return `${hh}:${m}`;
+ },
+
+ async addStand() {
+ const button = document.getElementById('stand-new-button');
+
+ const uuid = localStorage.getItem('uuid');
+ const URL = `${CONFIG.api}stand/schedule/${Stand_card.id}`;
+ await fetch(URL, {
+ method: 'POST',
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": uuid
+ }
+ })
+ .then(response => {
+ if (response.status == 200) {
+ console.log({ 'setPack': 'ok' });
+ button.innerText = "Стенд(и) додано";
+
+ return response.json()
+ } else {
+ console.log('err');
+ button.innerText = "Помилка запису";
+
+ return
+ }
+ })
+ .then(data => {
+ console.log(data);
+
+ Stand_card.schedule.setHTML();
+
+ setTimeout(() => {
+ button.innerText = "Додати стенд(и)";
+ }, 3000);
+ })
+ .catch(err => {
+ console.log(err);
+ button.innerText = "Помилка запису";
+ })
+ },
+
+ edit({ sheep_id, stand_id }) {
- block_schedule.innerHTML = html;
}
}
\ No newline at end of file
diff --git a/web/lib/pages/stand/card/style.css b/web/lib/pages/stand/card/style.css
index 328dc3f..8c99b7c 100644
--- a/web/lib/pages/stand/card/style.css
+++ b/web/lib/pages/stand/card/style.css
@@ -73,7 +73,7 @@
#stand-schedule {
width: 100%;
- min-height: calc(100vh - 40px - 50px);
+ /* min-height: calc(100vh - 40px - 50px); */
height: fit-content;
margin: 0 10px 15px;
border-radius: var(--border-radius);
@@ -137,6 +137,9 @@
background-color: var(--ColorThemes0);
color: var(--ColorThemes3);
}
+#stand-schedule>.block-day div select:disabled {
+ opacity: 0.9 !important;
+}
#stand-schedule>.block-day div:nth-child(2n) {
background: var(--ColorThemes0);
@@ -145,4 +148,17 @@
#stand-schedule>.block-day div:nth-child(2n) select {
background-color: var(--ColorThemes2);
+}
+
+#stand-schedule> #stand-new-button{
+ border-radius: 6px;
+ background: var(--PrimaryColor);
+ color: var(--PrimaryColorText);
+ width: calc(100% - 20px);
+ height: 40px;
+ font-size: var(--FontSize3);
+ font-weight: 400;
+ margin: 10px;
+ text-transform: uppercase;
+ cursor: pointer;
}
\ No newline at end of file
diff --git a/web/lib/pages/stand/constructor/index.html b/web/lib/pages/stand/constructor/index.html
new file mode 100644
index 0000000..dc1986d
--- /dev/null
+++ b/web/lib/pages/stand/constructor/index.html
@@ -0,0 +1,115 @@
+
diff --git a/web/lib/pages/stand/constructor/script.js b/web/lib/pages/stand/constructor/script.js
new file mode 100644
index 0000000..0bd32d9
--- /dev/null
+++ b/web/lib/pages/stand/constructor/script.js
@@ -0,0 +1,75 @@
+const Stand_constructor = {
+ init: async () => {
+ let html = await fetch('/lib/pages/stand/constructor/index.html').then((response) => response.text());
+ app.innerHTML = html;
+
+ const form = document.getElementById('stand-constructor-form');
+
+ form.addEventListener('submit', (event) => {
+ event.preventDefault();
+
+ let values = {
+ "title": document.getElementById('info-title').value,
+ "quantity_sheep": Number(document.getElementById('info-quantity_sheep').value),
+ "hour_start": Number(document.getElementById('info-hour_start').value),
+ "hour_end": Number(document.getElementById('info-hour_end').value),
+ "geo": [Number(document.getElementById('info-geo_lat').value), Number(document.getElementById('info-geo_lng').value)],
+ "processing_time": Number(document.getElementById('info-processing_time').value)
+ };
+
+ const checkboxes = form.querySelectorAll('input[type="checkbox"][name^="day-"]');
+ let week_days = () => {
+ let a = [];
+ for (const key in checkboxes) {
+ const element = checkboxes[key];
+ if(element.checked) a.push(Number((element.name).replace("day-", "")))
+ }
+ return a
+ }
+ values.week_days = week_days();
+
+ console.log(values);
+
+ Stand_constructor.save(values);
+ });
+ },
+ async save(values) {
+ const button = document.getElementById('stand-constructor-button');
+
+ const uuid = localStorage.getItem('uuid');
+ const URL = `${CONFIG.api}stand/list`;
+ await fetch(URL, {
+ method: 'POST',
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": uuid
+ },
+ body: JSON.stringify(values)
+ })
+ .then(response => {
+ if (response.status == 200) {
+ console.log({ 'setPack': 'ok' });
+ button.innerText = "Стенд додано";
+
+ return response.json()
+ } else {
+ console.log('err');
+ button.innerText = "Помилка запису";
+
+ return
+ }
+ })
+ .then(data => {
+ console.log(data);
+ Router.navigate(`/stand/card/${data.id}`);
+
+ setTimeout(() => {
+ button.innerText = "Зберегти";
+ }, 3000);
+ })
+ .catch(err => {
+ console.log(err);
+ button.innerText = "Помилка запису";
+ })
+ }
+}
\ No newline at end of file
diff --git a/web/lib/pages/stand/constructor/style.css b/web/lib/pages/stand/constructor/style.css
new file mode 100644
index 0000000..62e735c
--- /dev/null
+++ b/web/lib/pages/stand/constructor/style.css
@@ -0,0 +1,120 @@
+.page-stand-constructor {
+ width: calc(100% - 40px);
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ margin: 20px 20px 0 20px;
+}
+
+.page-stand-constructor>form {
+ border-radius: 10px;
+ width: calc(100% - 40px);
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ margin-bottom: 20px;
+ background: var(--ColorThemes1);
+ color: var(--ColorThemes3);
+ border: 1px solid var(--ColorThemes2);
+ box-shadow: var(--shadow-l1);
+ padding: 0 20px;
+ position: relative;
+}
+
+.page-stand-constructor>form>h1 {
+ width: calc(100% - 40px);
+ color: var(--ColorThemes3);
+ border-radius: var(--border-radius);
+ font-size: var(--FontSize5);
+ font-weight: 300;
+ padding: 20px 0;
+ position: relative;
+
+}
+
+.page-stand-constructor>form>div {
+ width: 100%;
+ display: flex;
+ margin: 20px 0;
+ align-items: flex-start;
+ flex-direction: column;
+}
+
+.page-stand-constructor>form>div>label {
+ display: flex;
+ justify-content: center;
+ flex-direction: column;
+ font-size: var(--FontSize1);
+ font-weight: 500;
+ margin-bottom: 5px;
+}
+
+.page-stand-constructor>form>div>select {
+ width: 100%;
+ min-width: 140px;
+ padding: 0 5px;
+ border-radius: calc(var(--border-radius) - 5px - 4px);
+ height: 30px;
+ background-color: var(--ColorThemes0);
+ color: var(--ColorThemes3);
+}
+
+.page-stand-constructor>form>div>input,
+.page-stand-constructor>form>div>div>input {
+ width: calc(100% - 10px);
+ min-width: 140px;
+ padding: 0 5px;
+ border-radius: 6px;
+ height: 30px;
+ background: var(--ColorThemes0);
+ color: var(--ColorThemes3);
+ font-size: var(--FontSize2);
+}
+
+.page-stand-constructor>form>div>.geo-inputs {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+}
+
+.page-stand-constructor>form>div>.geo-inputs>input {
+ width: calc(50% - 15px);
+}
+
+.page-stand-constructor>form>div>.week-days {
+ background: var(--ColorThemes0);
+ border-radius: calc(var(--border-radius) - 5px - 4px);
+ width: calc(100% - 15px);
+ padding: 0 5px 0 10px;
+}
+
+.page-stand-constructor>form>div>.week-days>div {
+ margin: 10px 0;
+ width: 100%;
+ font-size: var(--FontSize3);
+}
+
+.page-stand-constructor>form>div>.week-days>div>.custom-checkbox+label {
+ font-size: var(--FontSize4);
+ font-weight: 400;
+ width: 100%;
+ display: flex;
+ align-items: center;
+ user-select: none;
+ flex-direction: row-reverse;
+ justify-content: space-between;
+ cursor: pointer;
+ margin: 5px 0;
+}
+
+.page-stand-constructor>form>button {
+ border-radius: 6px;
+ background: var(--PrimaryColor);
+ color: var(--PrimaryColorText);
+ width: 100%;
+ height: 40px;
+ font-size: var(--FontSize3);
+ font-weight: 400;
+ margin: 20px 0;
+ text-transform: uppercase;
+}
\ No newline at end of file
diff --git a/web/lib/pages/stand/index.html b/web/lib/pages/stand/index.html
new file mode 100644
index 0000000..9e98ac2
--- /dev/null
+++ b/web/lib/pages/stand/index.html
@@ -0,0 +1,282 @@
+
+
+
+
+ Інформація про стенд
+
+
+
+
+
+
+
+
+
+
diff --git a/web/lib/pages/stand/list/index.html b/web/lib/pages/stand/list/index.html
index a08dcc7..278e7b4 100644
--- a/web/lib/pages/stand/list/index.html
+++ b/web/lib/pages/stand/list/index.html
@@ -1,3 +1,25 @@
+
+
+
+ Доступні стенди
+
+
+
+
diff --git a/web/lib/pages/stand/list/script.js b/web/lib/pages/stand/list/script.js
index 658b765..ac737e9 100644
--- a/web/lib/pages/stand/list/script.js
+++ b/web/lib/pages/stand/list/script.js
@@ -1,6 +1,53 @@
const Stand_list = {
+ list: [],
init: async () => {
let html = await fetch('/lib/pages/stand/list/index.html').then((response) => response.text());
app.innerHTML = html;
+
+ Stand_list.setHTML();
+
+ if (USER.possibilities.can_add_stand) {
+ document.getElementById("buttons-list").style.display = "flex";
+ document.getElementById("constructorButton").style.display = "";
+ }
+ },
+ loadAPI: async function (url) {
+ const uuid = localStorage.getItem("uuid");
+ const response = await fetch(url, {
+ method: 'GET',
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": uuid
+ }
+ });
+ Stand_list.list = await response.json();
+ return Stand_list.list;
+ },
+ setHTML: async function () {
+ const block_list = document.getElementById('list');
+
+ const url = `${CONFIG.api}stand/list`;
+ let list = this.list.length > 0 ? this.list : await this.loadAPI(url);
+
+ let html = "";
+ for (const element of list) {
+ html += this.renderCard({ element });
+ }
+
+ block_list.innerHTML = html;
+ },
+ renderCard: ({ element }) => {
+ return `
+
+ `;
},
}
\ No newline at end of file
diff --git a/web/lib/pages/stand/list/style.css b/web/lib/pages/stand/list/style.css
index 483364a..1e45ff7 100644
--- a/web/lib/pages/stand/list/style.css
+++ b/web/lib/pages/stand/list/style.css
@@ -2,6 +2,243 @@
width: calc(100% - 40px);
display: flex;
flex-direction: column;
- align-items: center;
+ align-items: stretch;
margin: 20px 20px 0 20px;
+}
+
+.page-stand-list>.buttons-list {
+ padding: 10px;
+ margin-bottom: 40px;
+ background: var(--ColorThemes1);
+ color: var(--ColorThemes3);
+ border: 1px solid var(--ColorThemes2);
+ box-shadow: var(--shadow-l1);
+ border-radius: var(--border-radius);
+ overflow: auto;
+ display: none;
+}
+
+.page-stand-list>.buttons-list>button,
+.page-stand-list>.buttons-list>a {
+ cursor: pointer;
+ border-radius: calc(var(--border-radius) - 5px);
+ padding: 0 10px;
+ margin-right: 20px;
+ min-width: fit-content;
+ min-height: 40px;
+ background: var(--PrimaryColor);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.page-stand-list>.buttons-list>button>span,
+.page-stand-list>.buttons-list>a>span {
+ color: var(--PrimaryColorText);
+ font-size: var(--FontSize3);
+ font-weight: normal;
+}
+
+.page-stand-list>.buttons-list>button>svg,
+.page-stand-list>.buttons-list>a>svg {
+ width: 20px;
+ height: 20px;
+ fill: var(--PrimaryColorText);
+ margin-right: 10px;
+}
+
+.page-stand-list>.list-controls {
+ padding: 10px;
+ margin: 0px 0 10px 0;
+ background: var(--ColorThemes1);
+ color: var(--ColorThemes3);
+ border: 1px solid var(--ColorThemes2);
+ box-shadow: var(--shadow-l1);
+ border-radius: var(--border-radius);
+ overflow: auto;
+ display: flex;
+}
+
+.page-stand-list>.list-controls select {
+ min-width: 140px;
+ height: 30px;
+ background-color: var(--ColorThemes2);
+ border: 1px solid var(--ColorThemes0);
+ box-shadow: var(--shadow-l1);
+ color: var(--ColorThemes3);
+ font-size: var(--FontSize1);
+ cursor: pointer;
+ padding: 0 5px;
+ margin-right: 10px;
+ border-radius: calc(var(--border-radius) - 5px - 2px);
+}
+
+.page-stand-list details {
+ border-radius: var(--border-radius);
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ margin-bottom: 10px;
+ background: var(--ColorThemes1);
+ color: var(--ColorThemes3);
+ border: 1px solid var(--ColorThemes2);
+ box-shadow: var(--shadow-l1);
+}
+
+.page-stand-list>details[disabled] summary,
+.page-stand-list>details.disabled summary {
+ pointer-events: none;
+ user-select: none;
+}
+
+.page-stand-list>details summary::-webkit-details-marker,
+.page-stand-list>details summary::marker {
+ display: none;
+ content: "";
+}
+
+
+.page-stand-list summary {
+ width: calc(100% - 40px);
+ cursor: pointer;
+ color: var(--ColorThemes3);
+ border-radius: var(--border-radius);
+ font-size: var(--FontSize5);
+ font-weight: 300;
+ padding: 20px;
+ position: relative;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.page-stand-list #list {
+ width: 100%;
+ margin: 0;
+ display: flex;
+ flex-wrap: wrap;
+ flex-direction: row;
+ align-content: flex-start;
+ justify-content: center;
+ overflow-y: auto;
+ align-items: flex-start;
+ transition: .3s ease;
+}
+
+.page-stand-list .card {
+ position: relative;
+ width: 300px;
+ height: 200px;
+ background-color: var(--ColorThemes2);
+ margin: 0px 10px 20px 10px;
+ overflow: hidden;
+ cursor: pointer;
+ border-radius: calc(var(--border-radius) - 5px);
+}
+
+@media (max-width: 2300px) {
+ .page-stand-list .card {
+ width: calc((100% / 5) - 40px);
+ }
+}
+
+@media (max-width: 1960px) {
+ .page-stand-list .card {
+ width: calc((100% / 4) - 40px);
+ }
+}
+
+@media (max-width: 1640px) {
+ .page-stand-list .card {
+ width: calc((100% / 3) - 40px);
+ }
+}
+
+@media (max-width: 1280px) {
+ .page-stand-list .card {
+ width: calc((100% / 2) - 40px);
+ }
+}
+
+@media (max-width: 650px) {
+ .page-stand-list .card {
+ width: 100%;
+ }
+}
+
+@media(hover: hover) {
+ .page-stand-list .card:hover {
+ opacity: 0.8;
+ }
+}
+
+.page-stand-list .card>i {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ z-index: 1;
+ filter: blur(2px);
+ /* background-repeat: round; */
+ background-size: cover;
+ background-position: center;
+ background-color: var(--PrimaryColor);
+}
+
+.page-stand-list .card>a {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ z-index: 10;
+}
+
+
+.page-stand-list .card>.contents {
+ position: absolute;
+ z-index: 2;
+ background: rgb(64 64 64 / 0.7);
+ width: 100%;
+ height: 100%;
+ font-size: 40px;
+ font-weight: 500;
+ color: #fff;
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ justify-content: space-between;
+}
+
+
+.page-stand-list .card>.contents>.info {
+ margin: 10px;
+}
+
+.page-stand-list .card>.contents>.info>div {
+ width: 100%;
+ height: 35px;
+ display: flex;
+ background: var(--ColorThemes0);
+ align-items: center;
+ justify-content: center;
+ font-size: var(--FontSize1);
+ color: var(--ColorThemes3);
+ border-radius: calc(var(--border-radius) - 5px - 4px);
+ position: relative;
+ overflow: hidden;
+}
+
+.page-stand-list .card>.contents>.info>div>span {
+ color: var(--ColorThemes3);
+ font-size: var(--FontSize3);
+ font-weight: 300;
+ z-index: 2;
+}
+
+.page-stand-list .card>.contents>.info>div>p {
+ color: var(--ColorThemes3);
+ font-size: var(--FontSize3);
+ font-weight: 400;
+ padding: 10px;
+ z-index: 2;
}
\ No newline at end of file
diff --git a/web/lib/pages/stand/script.js b/web/lib/pages/stand/script.js
new file mode 100644
index 0000000..ec53b76
--- /dev/null
+++ b/web/lib/pages/stand/script.js
@@ -0,0 +1,123 @@
+const Stand = {
+ schedule: [],
+ init: async () => {
+ let html = await fetch('/lib/pages/stand/index.html').then((response) => response.text());
+ app.innerHTML = html;
+
+ let listDate = [1, 4];
+
+ function generateAvailableDates() {
+ let select = document.getElementById("dateSelect");
+ select.innerHTML = "";
+
+ let today = new Date();
+ today.setHours(0, 0, 0, 0);
+ let months = [today.getMonth(), today.getMonth() + 1];
+ let year = today.getFullYear();
+
+ months.forEach(month => {
+ let date = new Date(year, month, 1);
+ while (date.getMonth() === month) {
+ if (date >= today) {
+ let day = date.getDay();
+ if (listDate.includes(day)) {
+ let option = document.createElement("option");
+ option.value = date.toISOString().split("T")[0];
+ option.textContent = date.toLocaleDateString("uk-UA", {
+ weekday: "long", year: "numeric", month: "long", day: "numeric"
+ });
+ select.appendChild(option);
+ }
+ }
+ date.setDate(date.getDate() + 1);
+ }
+ });
+ }
+
+ // generateAvailableDates();
+ Stand.generator();
+ },
+ generator: () => {
+ let block_schedule = document.getElementById('stand-schedule');
+
+ let html = "";
+
+ let stand = {
+ id: 1,
+ title: "Універсам",
+ geo: { lat: 0, lng: 0 },
+ hour_start: 9,
+ hour_end: 14,
+ quantity_sheep: 2,
+ week_days: [0, 2, 4, 6],
+ processing_time: 0.5,
+ updated_at: null
+ }
+
+ Stand.schedule = [];
+
+ // Кількість годин служіння
+ let stand_length = (stand.hour_end - stand.hour_start) / stand.processing_time;
+
+ for (let z = 0; z < stand.week_days.length; z++) {
+ Stand.schedule.push([]);
+
+ let date = new Date();
+ date.setDate(date.getDate() + stand.week_days[z]);
+ let dayName = date.toLocaleDateString('uk-UA', { weekday: 'long' });
+
+ html += `
+
+
${date.toLocaleDateString()} • ${dayName}
+ `;
+
+ let stand_date = 1 + stand.week_days[z];
+
+ for (let i = 0; i < stand_length; i++) {
+ let time_now = stand.hour_start + (stand.processing_time * i);
+ let timeFormat = (a) => a > 9 ? a : `0${a}`;
+
+ function formatTime(hours) {
+ let h = Math.floor(hours);
+ let m = (hours % 1 === 0.5) ? "30" : "00";
+ let hh = h.toString().padStart(2, "0");
+ return `${hh}:${m}`;
+ }
+
+ html += `
+
+ ${formatTime(time_now)}-${formatTime(time_now + stand.processing_time)}
+ `;
+
+ for (let q = 0; q < stand.quantity_sheep; q++) {
+ html += `
+
+ `;
+
+ Stand.schedule[z].push({
+ id: (i + z) * stand.quantity_sheep + q,
+ hour: stand.hour_start + (stand.processing_time * i),
+ number_sheep: q,
+ date: stand_date,
+ sheep_id: null,
+ stand_id: stand.id,
+ updated_at: Date.now()
+ });
+ }
+
+ html += `
`; // закриваємо hour
+ }
+
+ html += `
`; // закриваємо day
+ }
+
+ document.getElementById('stand-info-title').innerText = stand.title;
+ document.getElementById('stand-info-geo').innerHTML = '';
+ document.getElementById('stand-info-image').setAttribute('src', '');
+
+ block_schedule.innerHTML = html;
+ }
+}
\ No newline at end of file
diff --git a/web/lib/pages/stand/style.css b/web/lib/pages/stand/style.css
new file mode 100644
index 0000000..96ac335
--- /dev/null
+++ b/web/lib/pages/stand/style.css
@@ -0,0 +1,148 @@
+.page-stand {
+ width: calc(100% - 40px);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin: 20px 20px 0 20px;
+}
+
+.page-stand details {
+ border-radius: var(--border-radius);
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ margin-bottom: 20px;
+ background: var(--ColorThemes1);
+ color: var(--ColorThemes3);
+ border: 1px solid var(--ColorThemes2);
+ box-shadow: var(--shadow-l1);
+}
+
+.page-stand summary {
+ width: calc(100% - 40px);
+ cursor: pointer;
+ color: var(--ColorThemes3);
+ border-radius: var(--border-radius);
+ font-size: var(--FontSize5);
+ font-weight: 300;
+ padding: 20px;
+ position: relative;
+}
+
+#stand-info div {
+ display: flex;
+ flex-direction: row;
+ display: flex;
+ flex-direction: row;
+ padding: 10px;
+ color: var(--ColorThemes3);
+ align-items: center;
+}
+
+#stand-info div span {
+ opacity: 0.8;
+ font-weight: 400;
+ font-size: var(--FontSize2);
+ margin-right: 5px;
+}
+
+#stand-info div p {
+ font-weight: 300;
+ font-size: var(--FontSize4);
+}
+
+#stand-info img {
+ position: relative;
+ display: inline-block;
+ width: calc(100% - 20px);
+ border-radius: calc(var(--border-radius) - 8px);
+ margin: 10px;
+ height: auto;
+ aspect-ratio: 16 / 9;
+ background-color: #f2e5c9;
+}
+
+#stand-info img::before {
+ content: "Приклад розташування";
+ display: block;
+ color: #555;
+ text-align: center;
+ padding: 10px;
+}
+
+#stand-schedule {
+ width: 100%;
+ min-height: calc(100vh - 40px - 50px);
+ height: fit-content;
+ margin: 0 10px 15px;
+ border-radius: var(--border-radius);
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ background: var(--ColorThemes1);
+ color: var(--ColorThemes3);
+ border: 1px solid var(--ColorThemes2);
+ box-shadow: var(--shadow-l1);
+ transition: all .2sease 0s;
+}
+
+#stand-schedule>.block-day {
+ display: flex;
+ flex-direction: column;
+ width: calc(100% - 20px);
+ margin: 10px;
+ padding: 10px 0;
+ border: 1px solid var(--PrimaryColor);
+ background-color: var(--ColorThemes2);
+ border: 1px solid var(--ColorThemes0);
+ min-height: 100px;
+ justify-content: center;
+ position: relative;
+ border-radius: calc(var(--border-radius) - 5px);
+ overflow-x: auto;
+}
+
+#stand-schedule>.block-day h3 {
+ font-size: 17px;
+ font-weight: 500;
+ padding: 10px;
+ text-transform: capitalize;
+ width: calc(100% - 20px);
+ text-align: center;
+}
+
+#stand-schedule>.block-day div {
+ display: flex;
+ flex-direction: row;
+ padding: 5px 0;
+ margin: 0 10px;
+ align-items: center;
+ min-width: calc(100% - 20px);
+ width: fit-content;
+}
+
+#stand-schedule>.block-day div span {
+ min-width: 85px;
+ padding: 0 5px;
+}
+
+#stand-schedule>.block-day div select {
+ width: 100%;
+ min-width: 140px;
+ padding: 0 5px;
+ margin: 0 5px;
+ border-radius: calc(var(--border-radius) - 5px - 4px);
+ height: 30px;
+ background-color: var(--ColorThemes0);
+ color: var(--ColorThemes3);
+}
+
+#stand-schedule>.block-day div:nth-child(2n) {
+ background: var(--ColorThemes0);
+ border-radius: 8px;
+}
+
+#stand-schedule>.block-day div:nth-child(2n) select {
+ background-color: var(--ColorThemes2);
+}
\ No newline at end of file
diff --git a/web/lib/pages/territory/card/script.js b/web/lib/pages/territory/card/script.js
index 43456f8..03ff2c1 100644
--- a/web/lib/pages/territory/card/script.js
+++ b/web/lib/pages/territory/card/script.js
@@ -3,9 +3,6 @@ let map_card;
const Territory_card = {
// Глобальні змінні стану
id: null,
- socket: null,
- reconnectTimeout: null,
- reconnectAttempts: 0,
listEntrances: [],
listApartment: [],
listBuilding: [],
@@ -28,11 +25,6 @@ const Territory_card = {
app.innerHTML = html;
Territory_card.id = Id;
- // Закриваємо старий WebSocket
- if (this.socket) this.socket.close(1000, "Перезапуск з'єднання");
- // this.cloud.start(makeid(6));
- this.cloud.start()
-
// Якщо це сторінка будинку, отримуємо під’їзди та стартуємо WebSocket
if (type === "house") {
const controls = document.getElementById('page-card-controls');
@@ -45,6 +37,13 @@ const Territory_card = {
this.getHomestead.map({});
}
+ const ids = ['cloud_1', 'cloud_2', 'cloud_3'];
+ ids.forEach((id, idx) => {
+ const el = document.getElementById(id);
+ if(!el) return;
+ el.setAttribute('data-state', ['sync', 'ok', 'err'].indexOf(Cloud.status) === idx ? 'active' : '');
+ });
+
// Додаємо обробник закриття попапу
const popup = document.getElementById('card-new-date');
if (!popup.dataset.listenerAdded) {
@@ -59,71 +58,6 @@ const Territory_card = {
// Робота з WebSocket
cloud: {
- start() {
- const uuid = localStorage.getItem("uuid");
- const ws = new WebSocket(CONFIG.wss, uuid);
- Territory_card.socket = ws;
-
- ws.onopen = () => {
- console.log("[WebSocket] З'єднання встановлено");
- Territory_card.cloud.setStatus('ok');
- ws.send(JSON.stringify({
- event: 'connection',
- id: getTimeInSeconds(),
- date: getTimeInSeconds(),
- uuid,
- user: {
- name: USER.name,
- id: USER.id
- },
- data: {}
- }));
- Territory_card.reconnectAttempts = 0;
- clearTimeout(Territory_card.reconnectTimeout);
- };
-
- ws.onmessage = (e) => {
- const data = JSON.parse(e.data);
- if (data.event === 'connection' && data.user.id !== USER.id) {
- console.log(`Новий користувач: ${data.user}`);
- }
- if (data.event === 'message') {
- Territory_card.cloud.update(data);
- }
- };
-
- ws.onclose = () => {
- console.warn("[WebSocket] З'єднання розірвано");
- Territory_card.cloud.setStatus('err');
- Territory_card.reconnectAttempts++;
- if (Territory_card.reconnectAttempts <= 5) {
- Territory_card.reconnectTimeout = setTimeout(() => {
- Territory_card.getEntrances({ update: true });
- Territory_card.cloud.start();
- }, 1000);
- } else {
- if (confirm("З'єднання розірвано! Перепідключитись?")) {
- Territory_card.reconnectAttempts = 0;
- Territory_card.getEntrances({ update: true });
- Territory_card.cloud.start();
- }
- }
- };
-
- ws.onerror = (err) => {
- console.error("[WebSocket] Помилка", err);
- Territory_card.cloud.setStatus('err');
- };
- },
-
- setStatus(mode) {
- const ids = ['cloud_1', 'cloud_2', 'cloud_3'];
- ids.forEach((id, idx) => {
- const el = document.getElementById(id);
- el.setAttribute('data-state', ['sync', 'ok', 'err'].indexOf(mode) === idx ? 'active' : '');
- });
- },
-
update(msg) {
if (msg.type !== "apartment" && msg.type !== "building") return;
@@ -189,25 +123,20 @@ const Territory_card = {
const message = {
event: 'message',
- id: getTimeInSeconds(),
- date: getTimeInSeconds(),
user: {
name: USER.name,
id: USER.id
},
type: "apartment",
- data: {
- ...apt,
- sheep_id: USER.id
- }
+ data: apt
};
- if (Territory_card.socket?.readyState === WebSocket.OPEN) {
- Territory_card.socket.send(JSON.stringify(message));
+ if (Cloud.socket?.readyState === WebSocket.OPEN) {
+ Cloud.socket.send(JSON.stringify(message));
} else {
if (confirm("З'єднання розірвано! Перепідключитись?")) {
Territory_card.getEntrances({ update: true });
- Territory_card.cloud.start();
+ Cloud.start();
}
}
},
@@ -241,21 +170,16 @@ const Territory_card = {
const message = {
event: 'message',
- id: getTimeInSeconds(),
- date: getTimeInSeconds(),
user: {
name: USER.name,
id: USER.id
},
type: "building",
- data: {
- ...apt,
- sheep_id: USER.id
- }
+ data: apt
};
- if (Territory_card.socket?.readyState === WebSocket.OPEN) {
- Territory_card.socket.send(JSON.stringify(message));
+ if (Cloud.socket?.readyState === WebSocket.OPEN) {
+ Cloud.socket.send(JSON.stringify(message));
} else {
if (confirm("З'єднання розірвано! Перепідключитись?")) {
Territory_card.getEntrances({ update: true });
@@ -434,9 +358,9 @@ const Territory_card = {
let lng = data.geo?.lng ?? data.points?.[0]?.[0]?.[0]?.lng ?? 25.6145625;
let zoom = 15;
- if (map_card && map_Territory_card.remove) {
- map_Territory_card.stopLocate();
- map_Territory_card.remove();
+ if (map_card && map_card.remove) {
+ map_card.stopLocate();
+ map_card.remove();
}
const mapElement = document.getElementById('map_card');
@@ -471,13 +395,13 @@ const Territory_card = {
});
// слежение в реальном времени
- map_Territory_card.locate({ setView: false, watch: true, enableHighAccuracy: true });
- map_Territory_card.on('locationfound', (e) => {
- if (!map_Territory_card._userMarker) {
- map_Territory_card._userMarker = L.marker(e.latlng).addTo(map_card)
+ map_card.locate({ setView: false, watch: true, enableHighAccuracy: true });
+ map_card.on('locationfound', (e) => {
+ if (!map_card._userMarker) {
+ map_card._userMarker = L.marker(e.latlng).addTo(map_card)
.bindPopup("Ви тут!");
} else {
- map_Territory_card._userMarker.setLatLng(e.latlng);
+ map_card._userMarker.setLatLng(e.latlng);
}
});
@@ -489,7 +413,7 @@ const Territory_card = {
let layerControl = L.control.layers(baseMaps, [], { position: 'bottomright' }).addTo(map_card);
- map_Territory_card.pm.setLang("ua");
+ map_card.pm.setLang("ua");
const polygonOptions = {
color: "#f2bd53",
@@ -501,9 +425,9 @@ const Territory_card = {
L.polygon(data.points, polygonOptions).addTo(map_card);
- map_Territory_card.setZoom(data.zoom);
+ map_card.setZoom(data.zoom);
- // map_Territory_card.getZoom()
+ // map_card.getZoom()
// console.log(data.zoom);
diff --git a/web/lib/router/routes.js b/web/lib/router/routes.js
index a301a38..37e576b 100644
--- a/web/lib/router/routes.js
+++ b/web/lib/router/routes.js
@@ -43,6 +43,10 @@ Router
pageActive('schedule');
Schedule.init();;
})
+ .add('stand/constructor', function () {
+ pageActive();
+ Stand_constructor.init();;
+ })
.add('stand/card/(.*)', function (id) {
pageActive();
Stand_card.init(id);;
diff --git a/web/server.js b/web/server.js
index 38b639d..aa421c5 100644
--- a/web/server.js
+++ b/web/server.js
@@ -18,7 +18,7 @@ app.use(express.static(__dirname));
// Обработка 404 ошибки
app.use((req, res) => {
- res.status(404).sendFile(path.join(__dirname, "index.html"));
+ res.sendFile(path.join(__dirname, "index.html"));
});
app.listen(PORT, () => {
diff --git a/web/sw.js b/web/sw.js
index 9c52ce2..64236b5 100644
--- a/web/sw.js
+++ b/web/sw.js
@@ -1,56 +1,158 @@
-self.addEventListener('install', async event => {
+const STATIC_CACHE_NAME = 'v2.0.1';
-})
+const FILES_TO_CACHE = [
+ '/',
+ "/css/main.css",
+ "/config.js",
+ "/lib/router/router.js",
+ "/lib/router/routes.js",
-self.addEventListener('activate', async event => {
+ "/lib/components/leaflet/leaflet.css",
+ "/lib/components/leaflet/leaflet.js",
-})
+ "/lib/components/geoman/leaflet-geoman.css",
+ "/lib/components/geoman/leaflet-geoman.min.js",
-self.addEventListener('fetch', event => {
+ "/lib/components/turf.min.js",
-})
+ "/lib/components/cloud.js",
-// Обработка входящих push-сообщений
-self.addEventListener("push", event => {
- let data = {};
- try {
- data = event.data.json(); // если сервер прислал JSON
- } catch {
- data = { title: "Уведомление", body: event.data?.text() };
- }
+ "/lib/components/clipboard.js",
+ "/lib/components/colorGroup.js",
+ "/lib/components/makeid.js",
+ "/lib/components/swipeUpdater.js",
+ "/lib/components/detectBrowser.js",
+ "/lib/components/detectOS.js",
+ "/lib/components/formattedDate.js",
+ "/lib/components/setLeafletCursor.js",
+ "/lib/components/webPush.js",
- console.log(data);
-
+ "/lib/pages/auth/script.js",
+ "/lib/pages/auth/style.css",
- const title = data.title || "Уведомление";
- const options = {
- body: data.body || "",
- icon: "/img/icon.png", // иконка уведомления
- badge: "/img/badge.png", // маленький значок (Android)
- data: data.url || "/" // можно передать URL
- };
+ "/lib/pages/home/script.js",
+ "/lib/pages/home/style.css",
+ "/lib/pages/territory/list/script.js",
+ "/lib/pages/territory/list/style.css",
+
+ "/lib/pages/territory/manager/script.js",
+ "/lib/pages/territory/manager/style.css",
+
+ "/lib/pages/territory/history/script.js",
+ "/lib/pages/territory/history/style.css",
+
+ "/lib/pages/territory/constructor/script.js",
+ "/lib/pages/territory/constructor/style.css",
+
+ "/lib/pages/territory/editor/script.js",
+ "/lib/pages/territory/editor/style.css",
+
+ "/lib/pages/territory/card/script.js",
+ "/lib/pages/territory/card/style.css",
+
+ "/lib/pages/options/script.js",
+ "/lib/pages/options/style.css",
+
+ "/lib/pages/sheeps/script.js",
+ "/lib/pages/sheeps/style.css",
+
+ "/lib/pages/stand/list/script.js",
+ "/lib/pages/stand/list/style.css",
+
+ "/lib/pages/stand/card/script.js",
+ "/lib/pages/stand/card/style.css",
+
+ "/lib/pages/stand/constructor/script.js",
+ "/lib/pages/stand/constructor/style.css",
+
+ "/lib/pages/schedule/script.js",
+ "/lib/pages/schedule/style.css",
+
+ "/lib/app.js"
+];
+
+// ----------------------- INSTALL -----------------------
+self.addEventListener('install', event => {
event.waitUntil(
- self.registration.showNotification(title, options)
+ caches.open(STATIC_CACHE_NAME).then(cache => {
+ return Promise.all(FILES_TO_CACHE.map(url =>
+ fetch(url).then(res => {
+ if (!res.ok) throw new Error(`${url} not found`);
+ return cache.put(url, res);
+ }).catch(err => console.warn(err))
+ ));
+ })
);
});
-// Обработка клика по уведомлению
+
+// ----------------------- ACTIVATE -----------------------
+self.addEventListener('activate', event => {
+ event.waitUntil(
+ caches.keys().then(keys => {
+ return Promise.all(keys.map(key => {
+ if (key !== STATIC_CACHE_NAME) return caches.delete(key);
+ }));
+ }).then(() => self.clients.claim())
+ );
+});
+
+// ----------------------- FETCH -----------------------
+self.addEventListener('fetch', event => {
+ event.respondWith(
+ caches.match(event.request).then(cached => cached ?? fetch(event.request))
+ );
+});
+
+// ----------------------- PUSH -----------------------
+self.addEventListener("push", event => {
+ let data = {};
+ try { data = event.data.json(); } catch { data = { title: "Уведомлення", body: event.data?.text() }; }
+
+ const title = data.title || "Уведомлення";
+ const options = {
+ body: data.body || "",
+ icon: "/img/icon.png",
+ badge: "/img/badge.png",
+ data: data.url || "/"
+ };
+
+ event.waitUntil(self.registration.showNotification(title, options));
+});
+
self.addEventListener("notificationclick", event => {
event.notification.close();
-
event.waitUntil(
clients.matchAll({ type: "window", includeUncontrolled: true }).then(clientList => {
- // если вкладка уже открыта — фокусируем её
for (const client of clientList) {
- if (client.url === event.notification.data && "focus" in client) {
- return client.focus();
- }
- }
- // иначе открываем новую вкладку
- if (clients.openWindow) {
- return clients.openWindow(event.notification.data);
+ if (client.url === event.notification.data && "focus" in client) return client.focus();
}
+ if (clients.openWindow) return clients.openWindow(event.notification.data);
})
);
-});
\ No newline at end of file
+});
+
+// ----------------------- UPDATE CACHE -----------------------
+self.addEventListener('message', event => {
+ if (event.data === 'skipWaiting') {
+ self.skipWaiting(); // активує новий воркер, але не оновлює кеш автоматично
+ }
+ if (event.data === 'updateCache') {
+ updateALL(); // кеш оновлюється тільки після натискання на банер
+ }
+});
+
+async function updateALL() {
+ const cacheNames = await caches.keys();
+ await Promise.all(cacheNames.map(name => caches.delete(name)));
+
+ const cache = await caches.open(STATIC_CACHE_NAME);
+ await Promise.all(FILES_TO_CACHE.map(url =>
+ fetch(url).then(res => {
+ if (!res.ok) throw new Error(`${url} not found`);
+ return cache.put(url, res);
+ }).catch(err => console.warn(err))
+ ));
+ console.log('All caches updated');
+}
\ No newline at end of file
diff --git a/ws/routes/message.js b/ws/routes/message.js
index d5c1eca..b25e7ab 100644
--- a/ws/routes/message.js
+++ b/ws/routes/message.js
@@ -1,6 +1,6 @@
const { updateApartment } = require("../services/apartments.service");
const { updateBuilding } = require("../services/buildings.service");
-const { updateStand } = require("../services/stand.service");
+const { lockingStand, unlockingStand, updateStand } = require("../services/stand.service");
const { broadcast } = require("../utils/broadcaster");
module.exports = async (wss, ws, message) => {
@@ -12,8 +12,17 @@ module.exports = async (wss, ws, message) => {
case "building":
await updateBuilding(ws.user, message.data);
break;
- case "stand":
+ case "stand_locking":
+ await lockingStand(ws.user, message.data);
+ if(!message.data.sheep_name) message.data.sheep_name = ws.user.name;
+ break;
+ case "stand_unlocking":
+ await unlockingStand(ws.user, message.data);
+ if(!message.data.sheep_name) message.data.sheep_name = ws.user.name;
+ break;
+ case "stand_update":
await updateStand(ws.user, message.data);
+ if(!message.data.sheep_name) message.data.sheep_name = ws.user.name;
break;
default:
return ws.send(JSON.stringify({ error: `Unknown message type: ${message.type}` }));
diff --git a/ws/services/apartments.service.js b/ws/services/apartments.service.js
index ad1dc62..0f56360 100644
--- a/ws/services/apartments.service.js
+++ b/ws/services/apartments.service.js
@@ -11,7 +11,7 @@ function updateApartment(user, data) {
SET status = ?, description = ?, sheep_id = ?, updated_at = ?
WHERE id = ?`;
- db.run(sql, [Number(data.status), data.description, data.sheep_id, data.updated_at, data.id], function (err) {
+ db.run(sql, [Number(data.status), data.description, user.id, data.updated_at, data.id], function (err) {
if (err) return reject(err);
if (this.changes === 0) return reject(new Error("Apartment not found"));
@@ -20,7 +20,7 @@ function updateApartment(user, data) {
(apartments_id, status, description, sheep_id, created_at)
VALUES (?, ?, ?, ?, ?)`;
- db.run(insertSql, [Number(data.id), Number(data.status), data.description, data.sheep_id, Date.now()], function (err) {
+ db.run(insertSql, [Number(data.id), Number(data.status), data.description, user.id, Date.now()], function (err) {
if (err) return reject(err);
resolve({ update: "ok", id: data.id, historyId: this.lastID });
});
diff --git a/ws/services/buildings.service.js b/ws/services/buildings.service.js
index dd7e490..2e9e03b 100644
--- a/ws/services/buildings.service.js
+++ b/ws/services/buildings.service.js
@@ -11,7 +11,7 @@ function updateBuilding(user, data) {
SET status = ?, description = ?, sheep_id = ?, updated_at = ?
WHERE id = ?`;
- db.run(sql, [Number(data.status), data.description, data.sheep_id, data.updated_at, data.id], function (err) {
+ db.run(sql, [Number(data.status), data.description, user.id, data.updated_at, data.id], function (err) {
if (err) return reject(err);
if (this.changes === 0) return reject(new Error("Building not found"));
@@ -20,7 +20,7 @@ function updateBuilding(user, data) {
(buildings_id, status, description, sheep_id, created_at)
VALUES (?, ?, ?, ?, ?)`;
- db.run(insertSql, [Number(data.id), Number(data.status), data.description, data.sheep_id, Date.now()], function (err) {
+ db.run(insertSql, [Number(data.id), Number(data.status), data.description, user.id, Date.now()], function (err) {
if (err) return reject(err);
resolve({ update: "ok", id: data.id, historyId: this.lastID });
});
diff --git a/ws/services/stand.service.js b/ws/services/stand.service.js
index d610580..c5f9e54 100644
--- a/ws/services/stand.service.js
+++ b/ws/services/stand.service.js
@@ -1,26 +1,61 @@
const db = require("../config/db");
+function lockingStand(user, data) {
+ return new Promise((resolve, reject) => {
+ const sheepId = Number(data.sheep_id) || null;
+
+ if (!user.possibilities.can_view_stand) {
+ return reject(new Error("Forbidden: no rights to view stand"));
+ }
+ if ((sheepId !== user.id && sheepId !== null) && !user.possibilities.can_manager_stand) {
+ return reject(new Error("Forbidden: no rights to view stand"));
+ }
+
+ resolve({ update: "ok", id: data.id });
+ });
+}
+
+function unlockingStand(user, data) {
+ return new Promise((resolve, reject) => {
+ const sheepId = Number(data.sheep_id) || null;
+
+ if (!user.possibilities.can_view_stand) {
+ return reject(new Error("Forbidden: no rights to view stand"));
+ }
+ if ((sheepId !== user.id && sheepId !== null) && !user.possibilities.can_manager_stand) {
+ return reject(new Error("Forbidden: no rights to view stand"));
+ }
+
+ resolve({ update: "ok", id: data.id });
+ });
+}
+
function updateStand(user, data) {
return new Promise((resolve, reject) => {
- if (!user.possibilities.can_manager_territory) {
- return reject(new Error("Forbidden: no rights to manage territory"));
+ const sheepId = Number(data.sheep_id) || null;
+
+ if (!user.possibilities.can_view_stand) {
+ return reject(new Error("Forbidden: no rights to view stand"));
+ }
+ if ((sheepId !== user.id && sheepId !== null) && !user.possibilities.can_manager_stand) {
+ return reject(new Error("Forbidden: no rights to view stand"));
}
const sql = `
- UPDATE buildings
- SET status = ?, description = ?, sheep_id = ?, updated_at = ?
+ UPDATE stand_schedule
+ SET sheep_id = ?, updated_at = ?
WHERE id = ?`;
- db.run(sql, [Number(data.status), data.description, data.sheep_id, data.updated_at, data.id], function (err) {
+ db.run(sql, [sheepId, Date.now(), data.id], function (err) {
if (err) return reject(err);
- if (this.changes === 0) return reject(new Error("Building not found"));
+ if (this.changes === 0) return reject(new Error("Stand not found"));
const insertSql = `
- INSERT INTO buildings_history
- (buildings_id, status, description, sheep_id, created_at)
- VALUES (?, ?, ?, ?, ?)`;
+ INSERT INTO stand_schedule_history
+ (stand_schedule_id, sheep_id, created_at)
+ VALUES (?, ?, ?)`;
- db.run(insertSql, [Number(data.id), Number(data.status), data.description, data.sheep_id, Date.now()], function (err) {
+ db.run(insertSql, [Number(data.id), sheepId, Date.now()], function (err) {
if (err) return reject(err);
resolve({ update: "ok", id: data.id, historyId: this.lastID });
});
@@ -28,4 +63,4 @@ function updateStand(user, data) {
});
}
-module.exports = { updateStand };
\ No newline at end of file
+module.exports = { lockingStand, unlockingStand, updateStand };
\ No newline at end of file
diff --git a/ws_old/Dockerfile b/ws_old/Dockerfile
deleted file mode 100644
index 3f98267..0000000
--- a/ws_old/Dockerfile
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM node:20.18
-
-WORKDIR /app
-
-COPY package.json package-lock.json ./
-
-RUN npm install
-
-COPY . .
-
-EXPOSE 4001
-
-CMD npm start
diff --git a/ws_old/package-lock.json b/ws_old/package-lock.json
deleted file mode 100644
index cc2cfff..0000000
--- a/ws_old/package-lock.json
+++ /dev/null
@@ -1,1644 +0,0 @@
-{
- "name": "WS Sheep Service",
- "version": "1.0.1",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "WS Sheep Service",
- "version": "1.0.1",
- "license": "ISC",
- "dependencies": {
- "dotenv": "^17.2.0",
- "sqlite3": "^5.1.7",
- "url": "^0.11.4",
- "ws": "^8.18.0"
- }
- },
- "node_modules/@gar/promisify": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
- "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
- "optional": true
- },
- "node_modules/@npmcli/fs": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
- "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==",
- "optional": true,
- "dependencies": {
- "@gar/promisify": "^1.0.1",
- "semver": "^7.3.5"
- }
- },
- "node_modules/@npmcli/move-file": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
- "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==",
- "deprecated": "This functionality has been moved to @npmcli/fs",
- "optional": true,
- "dependencies": {
- "mkdirp": "^1.0.4",
- "rimraf": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@tootallnate/once": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
- "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
- "optional": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/abbrev": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
- "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
- "optional": true
- },
- "node_modules/agent-base": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
- "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
- "optional": true,
- "dependencies": {
- "debug": "4"
- },
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/agentkeepalive": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
- "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==",
- "optional": true,
- "dependencies": {
- "humanize-ms": "^1.2.1"
- },
- "engines": {
- "node": ">= 8.0.0"
- }
- },
- "node_modules/aggregate-error": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
- "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
- "optional": true,
- "dependencies": {
- "clean-stack": "^2.0.0",
- "indent-string": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "optional": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/aproba": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
- "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
- "optional": true
- },
- "node_modules/are-we-there-yet": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz",
- "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==",
- "deprecated": "This package is no longer supported.",
- "optional": true,
- "dependencies": {
- "delegates": "^1.0.0",
- "readable-stream": "^3.6.0"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "optional": true
- },
- "node_modules/base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/bindings": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
- "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
- "dependencies": {
- "file-uri-to-path": "1.0.0"
- }
- },
- "node_modules/bl": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
- "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
- "dependencies": {
- "buffer": "^5.5.0",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
- }
- },
- "node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
- "optional": true,
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/buffer": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
- "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.1.13"
- }
- },
- "node_modules/cacache": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz",
- "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==",
- "optional": true,
- "dependencies": {
- "@npmcli/fs": "^1.0.0",
- "@npmcli/move-file": "^1.0.1",
- "chownr": "^2.0.0",
- "fs-minipass": "^2.0.0",
- "glob": "^7.1.4",
- "infer-owner": "^1.0.4",
- "lru-cache": "^6.0.0",
- "minipass": "^3.1.1",
- "minipass-collect": "^1.0.2",
- "minipass-flush": "^1.0.5",
- "minipass-pipeline": "^1.2.2",
- "mkdirp": "^1.0.3",
- "p-map": "^4.0.0",
- "promise-inflight": "^1.0.1",
- "rimraf": "^3.0.2",
- "ssri": "^8.0.1",
- "tar": "^6.0.2",
- "unique-filename": "^1.1.1"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
- "dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/call-bound": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
- "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/chownr": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
- "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/clean-stack": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
- "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
- "optional": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/color-support": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
- "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
- "optional": true,
- "bin": {
- "color-support": "bin.js"
- }
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "optional": true
- },
- "node_modules/console-control-strings": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
- "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
- "optional": true
- },
- "node_modules/debug": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
- "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
- "optional": true,
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/decompress-response": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
- "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
- "dependencies": {
- "mimic-response": "^3.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/delegates": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
- "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
- "optional": true
- },
- "node_modules/detect-libc": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
- "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/dotenv": {
- "version": "17.2.0",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.0.tgz",
- "integrity": "sha512-Q4sgBT60gzd0BB0lSyYD3xM4YxrXA9y4uBDof1JNYGzOXrQdQ6yX+7XIAqoFOGQFOTK1D3Hts5OllpxMDZFONQ==",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://dotenvx.com"
- }
- },
- "node_modules/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "optional": true
- },
- "node_modules/encoding": {
- "version": "0.1.13",
- "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
- "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
- "optional": true,
- "dependencies": {
- "iconv-lite": "^0.6.2"
- }
- },
- "node_modules/end-of-stream": {
- "version": "1.4.5",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
- "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
- "dependencies": {
- "once": "^1.4.0"
- }
- },
- "node_modules/env-paths": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
- "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
- "optional": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/err-code": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
- "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
- "optional": true
- },
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
- "dependencies": {
- "es-errors": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/expand-template": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
- "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/file-uri-to-path": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
- "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
- },
- "node_modules/fs-constants": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
- "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
- },
- "node_modules/fs-minipass": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
- "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "optional": true
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gauge": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
- "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
- "deprecated": "This package is no longer supported.",
- "optional": true,
- "dependencies": {
- "aproba": "^1.0.3 || ^2.0.0",
- "color-support": "^1.1.3",
- "console-control-strings": "^1.1.0",
- "has-unicode": "^2.0.1",
- "signal-exit": "^3.0.7",
- "string-width": "^4.2.3",
- "strip-ansi": "^6.0.1",
- "wide-align": "^1.1.5"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
- "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
- "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/github-from-package": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
- "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "optional": true,
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "optional": true
- },
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-unicode": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
- "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
- "optional": true
- },
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/http-cache-semantics": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
- "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
- "optional": true
- },
- "node_modules/http-proxy-agent": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
- "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
- "optional": true,
- "dependencies": {
- "@tootallnate/once": "1",
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/https-proxy-agent": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
- "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
- "optional": true,
- "dependencies": {
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/humanize-ms": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
- "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
- "optional": true,
- "dependencies": {
- "ms": "^2.0.0"
- }
- },
- "node_modules/iconv-lite": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
- "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "optional": true,
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "optional": true,
- "engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/indent-string": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
- "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
- "optional": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/infer-owner": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
- "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
- "optional": true
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
- "optional": true,
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- },
- "node_modules/ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
- },
- "node_modules/ip-address": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
- "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
- "optional": true,
- "dependencies": {
- "jsbn": "1.1.0",
- "sprintf-js": "^1.1.3"
- },
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "optional": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-lambda": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
- "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
- "optional": true
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "optional": true
- },
- "node_modules/jsbn": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
- "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
- "optional": true
- },
- "node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "optional": true,
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/make-fetch-happen": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
- "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==",
- "optional": true,
- "dependencies": {
- "agentkeepalive": "^4.1.3",
- "cacache": "^15.2.0",
- "http-cache-semantics": "^4.1.0",
- "http-proxy-agent": "^4.0.1",
- "https-proxy-agent": "^5.0.0",
- "is-lambda": "^1.0.1",
- "lru-cache": "^6.0.0",
- "minipass": "^3.1.3",
- "minipass-collect": "^1.0.2",
- "minipass-fetch": "^1.3.2",
- "minipass-flush": "^1.0.5",
- "minipass-pipeline": "^1.2.4",
- "negotiator": "^0.6.2",
- "promise-retry": "^2.0.1",
- "socks-proxy-agent": "^6.0.0",
- "ssri": "^8.0.0"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/math-intrinsics": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
- "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/mimic-response": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
- "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "optional": true,
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/minipass": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
- "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minipass-collect": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
- "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
- "optional": true,
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/minipass-fetch": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz",
- "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==",
- "optional": true,
- "dependencies": {
- "minipass": "^3.1.0",
- "minipass-sized": "^1.0.3",
- "minizlib": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "optionalDependencies": {
- "encoding": "^0.1.12"
- }
- },
- "node_modules/minipass-flush": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
- "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
- "optional": true,
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/minipass-pipeline": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
- "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
- "optional": true,
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minipass-sized": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
- "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
- "optional": true,
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minizlib": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
- "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
- "dependencies": {
- "minipass": "^3.0.0",
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "bin": {
- "mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/mkdirp-classic": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
- "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "optional": true
- },
- "node_modules/napi-build-utils": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
- "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="
- },
- "node_modules/negotiator": {
- "version": "0.6.4",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
- "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
- "optional": true,
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/node-abi": {
- "version": "3.75.0",
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz",
- "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==",
- "dependencies": {
- "semver": "^7.3.5"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/node-addon-api": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
- "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="
- },
- "node_modules/node-gyp": {
- "version": "8.4.1",
- "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz",
- "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==",
- "optional": true,
- "dependencies": {
- "env-paths": "^2.2.0",
- "glob": "^7.1.4",
- "graceful-fs": "^4.2.6",
- "make-fetch-happen": "^9.1.0",
- "nopt": "^5.0.0",
- "npmlog": "^6.0.0",
- "rimraf": "^3.0.2",
- "semver": "^7.3.5",
- "tar": "^6.1.2",
- "which": "^2.0.2"
- },
- "bin": {
- "node-gyp": "bin/node-gyp.js"
- },
- "engines": {
- "node": ">= 10.12.0"
- }
- },
- "node_modules/nopt": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
- "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
- "optional": true,
- "dependencies": {
- "abbrev": "1"
- },
- "bin": {
- "nopt": "bin/nopt.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/npmlog": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz",
- "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==",
- "deprecated": "This package is no longer supported.",
- "optional": true,
- "dependencies": {
- "are-we-there-yet": "^3.0.0",
- "console-control-strings": "^1.1.0",
- "gauge": "^4.0.3",
- "set-blocking": "^2.0.0"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/object-inspect": {
- "version": "1.13.4",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
- "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/p-map": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
- "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
- "optional": true,
- "dependencies": {
- "aggregate-error": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "optional": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/prebuild-install": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
- "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
- "dependencies": {
- "detect-libc": "^2.0.0",
- "expand-template": "^2.0.3",
- "github-from-package": "0.0.0",
- "minimist": "^1.2.3",
- "mkdirp-classic": "^0.5.3",
- "napi-build-utils": "^2.0.0",
- "node-abi": "^3.3.0",
- "pump": "^3.0.0",
- "rc": "^1.2.7",
- "simple-get": "^4.0.0",
- "tar-fs": "^2.0.0",
- "tunnel-agent": "^0.6.0"
- },
- "bin": {
- "prebuild-install": "bin.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/promise-inflight": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
- "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
- "optional": true
- },
- "node_modules/promise-retry": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
- "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
- "optional": true,
- "dependencies": {
- "err-code": "^2.0.2",
- "retry": "^0.12.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/pump": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
- "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "node_modules/punycode": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
- "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="
- },
- "node_modules/qs": {
- "version": "6.14.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
- "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
- "dependencies": {
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "dependencies": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "bin": {
- "rc": "cli.js"
- }
- },
- "node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/retry": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
- "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
- "optional": true,
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "optional": true,
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "optional": true
- },
- "node_modules/semver": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
- "optional": true
- },
- "node_modules/side-channel": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
- "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3",
- "side-channel-list": "^1.0.0",
- "side-channel-map": "^1.0.1",
- "side-channel-weakmap": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-list": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
- "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-map": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
- "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-weakmap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
- "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3",
- "side-channel-map": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "optional": true
- },
- "node_modules/simple-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
- "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/simple-get": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
- "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "dependencies": {
- "decompress-response": "^6.0.0",
- "once": "^1.3.1",
- "simple-concat": "^1.0.0"
- }
- },
- "node_modules/smart-buffer": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
- "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
- "optional": true,
- "engines": {
- "node": ">= 6.0.0",
- "npm": ">= 3.0.0"
- }
- },
- "node_modules/socks": {
- "version": "2.8.6",
- "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.6.tgz",
- "integrity": "sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA==",
- "optional": true,
- "dependencies": {
- "ip-address": "^9.0.5",
- "smart-buffer": "^4.2.0"
- },
- "engines": {
- "node": ">= 10.0.0",
- "npm": ">= 3.0.0"
- }
- },
- "node_modules/socks-proxy-agent": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz",
- "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==",
- "optional": true,
- "dependencies": {
- "agent-base": "^6.0.2",
- "debug": "^4.3.3",
- "socks": "^2.6.2"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/sprintf-js": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
- "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
- "optional": true
- },
- "node_modules/sqlite3": {
- "version": "5.1.7",
- "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz",
- "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==",
- "hasInstallScript": true,
- "dependencies": {
- "bindings": "^1.5.0",
- "node-addon-api": "^7.0.0",
- "prebuild-install": "^7.1.1",
- "tar": "^6.1.11"
- },
- "optionalDependencies": {
- "node-gyp": "8.x"
- },
- "peerDependencies": {
- "node-gyp": "8.x"
- },
- "peerDependenciesMeta": {
- "node-gyp": {
- "optional": true
- }
- }
- },
- "node_modules/ssri": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
- "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
- "optional": true,
- "dependencies": {
- "minipass": "^3.1.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
- "node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "optional": true,
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "optional": true,
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/tar": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
- "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
- "dependencies": {
- "chownr": "^2.0.0",
- "fs-minipass": "^2.0.0",
- "minipass": "^5.0.0",
- "minizlib": "^2.1.1",
- "mkdirp": "^1.0.3",
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/tar-fs": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz",
- "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==",
- "dependencies": {
- "chownr": "^1.1.1",
- "mkdirp-classic": "^0.5.2",
- "pump": "^3.0.0",
- "tar-stream": "^2.1.4"
- }
- },
- "node_modules/tar-fs/node_modules/chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
- },
- "node_modules/tar-stream": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
- "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
- "dependencies": {
- "bl": "^4.0.3",
- "end-of-stream": "^1.4.1",
- "fs-constants": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.1.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/tar/node_modules/minipass": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
- "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/unique-filename": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
- "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
- "optional": true,
- "dependencies": {
- "unique-slug": "^2.0.0"
- }
- },
- "node_modules/unique-slug": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
- "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
- "optional": true,
- "dependencies": {
- "imurmurhash": "^0.1.4"
- }
- },
- "node_modules/url": {
- "version": "0.11.4",
- "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz",
- "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==",
- "dependencies": {
- "punycode": "^1.4.1",
- "qs": "^6.12.3"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
- },
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "optional": true,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/wide-align": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
- "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
- "optional": true,
- "dependencies": {
- "string-width": "^1.0.2 || 2 || 3 || 4"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
- },
- "node_modules/ws": {
- "version": "8.18.3",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
- "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
- "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/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
- }
- }
-}
diff --git a/ws_old/package.json b/ws_old/package.json
deleted file mode 100644
index 0ad00f1..0000000
--- a/ws_old/package.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "name": "WS Sheep Service",
- "version": "1.0.1",
- "main": "ws.js",
- "scripts": {
- "start": "node ws.js"
- },
- "keywords": [],
- "author": "",
- "license": "ISC",
- "description": "",
- "dependencies": {
- "sqlite3": "^5.1.7",
- "url": "^0.11.4",
- "ws": "^8.18.0",
- "dotenv": "^17.2.0"
- }
-}
diff --git a/ws_old/ws.js b/ws_old/ws.js
deleted file mode 100644
index 65404ed..0000000
--- a/ws_old/ws.js
+++ /dev/null
@@ -1,260 +0,0 @@
-const WebSocket = require("ws");
-const { URL } = require('url');
-const sqlite3 = require('sqlite3');
-const path = require('path');
-require("dotenv").config();
-
-const dbPath = process.env.DATABASE_PATH || '../';
-const db = new sqlite3.Database(path.join(dbPath, 'database.sqlite'));
-
-const port = 4004;
-const api_version = '1.0.0';
-
-const wss = new WebSocket.Server({
- port: port
-}, () => console.log(`Server started on port ${port}`));
-
-
-wss.on('connection', async (ws, request) => {
- const url = new URL(request.url, `http://${request.headers.host}`)
- const params = Object.fromEntries(url.searchParams.entries());
- const uuid = params.uuid;
-
- if (!uuid) return
-
- let check = await checkUUID(uuid);
-
- console.log(check);
-
-
- if (!check && check.possibilities.can_view_territory) return
-
- // Periodic ping to maintain a connection
- const pingInterval = setInterval(() => {
- if (ws.readyState === WebSocket.OPEN) {
- ws.ping('ping');
- }
- }, 30000);
-
-
- ws.send(JSON.stringify({ "connection": "success", "api_version": api_version }));
-
- ws.on('message', (message) => {
- message = JSON.parse(message);
-
- console.log(message.username, check.name);
-
- switch (message.event) {
- case "connection":
- broadcastMessage(message);
- break;
-
- case "message":
- updateDatabase(message);
- broadcastMessage(message);
- break;
- };
- });
-
- ws.on('pong', (data) => {
- console.log('PONG received from the client:', data.toString());
- });
-
- ws.on('close', () => {
- console.log('Client close');
- });
-
- ws.on('error', (err) => {
- console.error('ERROR WebSocket:', err);
- });
-});
-
-
-function broadcastMessage(message) {
- wss.clients.forEach(client => {
- if (client.readyState === WebSocket.OPEN) {
- client.send(JSON.stringify(message));
- }
- });
-}
-
-function updateDatabase(message) {
-
- console.log(message.type);
-
-
- if (message.type === "apartment") {
-
- let sql = 'UPDATE apartments SET status = ?, description = ?, sheep_id = ?, updated_at = ? WHERE id = ?';
-
- db.run(sql, [
- Number(message.data.status),
- message.data.description,
- message.data.sheep_id,
- message.data.updated_at,
- message.data.id
- ], function (err) {
- if (err) {
- console.error(err.message);
- } else if (this.changes === 0) {
- console.error('Product not found');
- } else {
- console.log({ "update": "ok", "id": message.data.id });
-
- let sql = `INSERT INTO apartments_history (apartments_id, status, description, sheep_id, created_at) VALUES (?, ?, ?, ?, ?)`;
-
- db.run(sql, [
- Number(message.data.id),
- Number(message.data.status),
- message.data.description,
- message.data.sheep_id,
- Math.floor(Date.now())
- ], function (err) {
- if (err) {
- console.error(err.message);
- } else if (this.changes === 0) {
- console.error('Apartments not found');
- } else {
- console.log({ "insert": "ok", "id": this.lastID });
- }
- });
- }
- });
- } else if(message.type === "building") {
- let sql = 'UPDATE buildings SET status = ?, description = ?, sheep_id = ?, updated_at = ? WHERE id = ?';
-
- db.run(sql, [
- Number(message.data.status),
- message.data.description,
- message.data.sheep_id,
- message.data.updated_at,
- message.data.id
- ], function (err) {
- if (err) {
- console.error(err.message);
- } else if (this.changes === 0) {
- console.error('Product not found');
- } else {
- console.log({ "update": "ok", "id": message.data.id });
-
- let sql = `INSERT INTO buildings_history (buildings_id, status, description, sheep_id, created_at) VALUES (?, ?, ?, ?, ?)`;
-
- db.run(sql, [
- Number(message.data.id),
- Number(message.data.status),
- message.data.description,
- message.data.sheep_id,
- Math.floor(Date.now())
- ], function (err) {
- if (err) {
- console.error(err.message);
- } else if (this.changes === 0) {
- console.error('Apartments not found');
- } else {
- console.log({ "insert": "ok", "id": this.lastID });
- }
- });
- }
- });
- } else if(message.type === "stand") {
- let sql = 'UPDATE stand SET status = ?, sheep_id = ?, updated_at = ? WHERE id = ?';
-
- db.run(sql, [
- Number(message.data.status),
- message.data.sheep_id,
- message.data.updated_at,
- message.data.id
- ], function (err) {
- if (err) {
- console.error(err.message);
- } else if (this.changes === 0) {
- console.error('Product not found');
- } else {
- console.log({ "update": "ok", "id": message.data.id });
-
- let sql = `INSERT INTO stand_history (stand_id, status, sheep_id, created_at) VALUES (?, ?, ?, ?, ?)`;
-
- db.run(sql, [
- Number(message.data.id),
- Number(message.data.status),
- message.data.sheep_id,
- Math.floor(Date.now())
- ], function (err) {
- if (err) {
- console.error(err.message);
- } else if (this.changes === 0) {
- console.error('Stand not found');
- } else {
- console.log({ "insert": "ok", "id": this.lastID });
- }
- });
- }
- });
- }
-}
-
-async function checkUUID(uuid) {
- return new Promise((res, rej) => {
- db.get(`
- SELECT
- sheeps.*,
- possibilities.can_view_territory AS can_view_territory
- FROM
- sheeps
- LEFT JOIN
- possibilities ON possibilities.sheep_id = sheeps.id
- WHERE
- sheeps.uuid_manager = ?`,
- [uuid],
- (err, moderator) => {
- if (moderator) {
- let data = {
- id: moderator.sheep_id,
- group_id: moderator.group_id,
- name: moderator.name,
- icon: moderator.icon,
- uuid: moderator.uuid,
- appointment: moderator.appointment,
- sheepRole: moderator.mode_title,
- possibilities: {
- can_view_territory: moderator.can_view_territory == 1 ? true : false
- }
- }
- return res(data);
- }
-
- db.get(`
- SELECT
- sheeps.*,
- possibilities.can_view_territory AS can_view_territory
- FROM
- sheeps
- LEFT JOIN
- possibilities ON possibilities.sheep_id = sheeps.id
- WHERE
- sheeps.uuid = ?`,
- [uuid],
- (err, sheep) => {
- if (sheep) {
- let data = {
- id: sheep.sheep_id,
- group_id: sheep.group_id,
- name: sheep.name,
- icon: sheep.icon,
- uuid: sheep.uuid,
- appointment: sheep.appointment,
- sheepRole: sheep.mode_title,
- possibilities: {
- can_view_territory: sheep.can_view_territory == 1 ? true : false
- }
- }
- return res(data);
- }
-
- return res(false);
- }
- );
- }
- );
- });
-}
\ No newline at end of file