mirror of
https://github.com/TheGreyDiamond/elevatormapRewritten.git
synced 2025-12-16 23:10:45 +01:00
Compare commits
33 Commits
5f7385a1b6
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
492cb44505 | ||
|
|
6bec74b064 | ||
|
|
e6218c049c | ||
|
|
17d3617b90 | ||
|
|
8ac66cf71f | ||
|
|
da91e4210c | ||
|
|
e73b02ec22 | ||
|
|
fe5090a382 | ||
|
|
4e576841f8 | ||
|
|
467e635145 | ||
|
|
81b9d0b26f | ||
|
|
2e1eec4b7a | ||
|
|
7134466431 | ||
|
|
808fa94a1a | ||
|
|
f2bef7aa43 | ||
|
|
3c0b455341 | ||
|
|
5a87784ceb | ||
|
|
e69e40fec8 | ||
|
|
eadf729190 | ||
|
|
1377ae15ba | ||
|
|
e33a58e5ab | ||
|
|
fe33f7f316 | ||
|
|
ec01e7128b | ||
|
|
7eb0558e96 | ||
|
|
5f8c998aaa | ||
|
|
d1aa2868d7 | ||
|
|
ee13ae9cb2 | ||
|
|
0dfd47e258 | ||
|
|
bc2a66236e | ||
|
|
7d5fdcef9b | ||
|
|
b2708329c1 | ||
|
|
51d92c139d | ||
|
|
b05241f493 |
3
.eslintignore
Normal file
3
.eslintignore
Normal file
@@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
dist
|
||||
*.js
|
||||
17
.eslintrc.json
Normal file
17
.eslintrc.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-var-requires": 0,
|
||||
"no-control-regex": 0
|
||||
}
|
||||
|
||||
}
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -80,7 +80,6 @@ typings/
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
@@ -104,3 +103,6 @@ dist
|
||||
.tern-port
|
||||
|
||||
testingDONOTCOMMITME.json
|
||||
|
||||
static/uploads/*
|
||||
index.js
|
||||
|
||||
7
LICENSE
Normal file
7
LICENSE
Normal file
@@ -0,0 +1,7 @@
|
||||
Copyright © 2021 TheGreydiamond
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
18
README.md
18
README.md
@@ -1,2 +1,20 @@
|
||||
# Elevatormap Rewritten
|
||||
The elevator map at thegreydiamond.de/elevatormap has been offline for some time now, as it was very ineffective and didn't accept user contributions. This is an attempted by the original author to rewrite the project in Node.js.
|
||||
|
||||
## Host your own
|
||||
Requirements:
|
||||
- Node
|
||||
- MySQL Server (MariaDB)
|
||||
- Accounts for Fontawesome & hCaptcha
|
||||
|
||||
Setup steps:
|
||||
1. Setup DB access
|
||||
2. Change config file to your needs
|
||||
3. Install dependencies with `npm install`
|
||||
4. Make .js file with `npm run makeJS` (skip if you want to test it)
|
||||
5. Start it with `npm start` (or use pm2)
|
||||
It will autogenerate all tables needed. And then startup.
|
||||
|
||||
ToDo:
|
||||
- [ ] Allow user edits
|
||||
- [ ] Allow moderation
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
{
|
||||
"fontAwesome": "",
|
||||
"mapboxAccessToken": "",
|
||||
"cookieSecret": "",
|
||||
"serverAdress": "",
|
||||
"port": 3000,
|
||||
"mysql": {
|
||||
"user": "",
|
||||
"password": "",
|
||||
"database": "",
|
||||
"allowCreation": true
|
||||
},
|
||||
"hCaptcha":{
|
||||
"sitekey": "",
|
||||
"secret": ""
|
||||
},
|
||||
"mail": {
|
||||
"host": "",
|
||||
"port": 0,
|
||||
"username": "",
|
||||
"password": ""
|
||||
}
|
||||
|
||||
}
|
||||
BIN
etc/elevatormapLogo.png
Normal file
BIN
etc/elevatormapLogo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 198 KiB |
BIN
etc/elevatormapLogo.xcf
Normal file
BIN
etc/elevatormapLogo.xcf
Normal file
Binary file not shown.
332
index.ts
Normal file
332
index.ts
Normal file
@@ -0,0 +1,332 @@
|
||||
// Imports
|
||||
const express = require("express");
|
||||
const fs = require("fs");
|
||||
const Eta = require("eta");
|
||||
const winston = require("winston");
|
||||
const mysql = require("mysql");
|
||||
const bodyParser = require("body-parser");
|
||||
const session = require("express-session");
|
||||
const nodemailer = require("nodemailer");
|
||||
|
||||
// Inting the logger
|
||||
const logger = winston.createLogger({
|
||||
level: "debug",
|
||||
format: winston.format.json(),
|
||||
defaultMeta: { service: "user-service" },
|
||||
transports: [
|
||||
//
|
||||
// - Write all logs with level `error` and below to `error.log`
|
||||
// - Write all logs with level `info` and below to `combined.log`
|
||||
//
|
||||
new winston.transports.File({ filename: "error.log", level: "error" }),
|
||||
new winston.transports.File({ filename: "combined.log" }),
|
||||
],
|
||||
});
|
||||
|
||||
logger.add(
|
||||
new winston.transports.Console({
|
||||
format: winston.format.simple(),
|
||||
})
|
||||
);
|
||||
|
||||
const app = express();
|
||||
|
||||
const startUpTime = Math.floor(new Date().getTime() / 1000);
|
||||
|
||||
// Skeleton Variables
|
||||
let fontawesomeKey = "";
|
||||
let mapboxAccessToken = "";
|
||||
let mysqlData = { "user": "", "password": "", "database": "", "allowCreation": false };
|
||||
let mailConf = { "host": "", "port": 0, "username": "", "password": "" };
|
||||
let serverAdress = "";
|
||||
let cookieSecret = ""
|
||||
let jsonConfigGlobal = {};
|
||||
let port = 3000;
|
||||
|
||||
// Load config
|
||||
try {
|
||||
const data = fs.readFileSync("config/default.json", "utf8");
|
||||
const jsonContent = JSON.parse(data);
|
||||
let jsonConfig = jsonContent;
|
||||
if (jsonContent.redirectConfig) {
|
||||
const data = fs.readFileSync(
|
||||
"config/" + jsonContent.redirectConfig,
|
||||
"utf8"
|
||||
);
|
||||
jsonConfig = JSON.parse(data);
|
||||
}
|
||||
fontawesomeKey = jsonConfig.fontAwesome;
|
||||
mapboxAccessToken = jsonConfig.mapboxAccessToken;
|
||||
mysqlData = jsonConfig.mysql;
|
||||
|
||||
mailConf = jsonConfig.mail;
|
||||
serverAdress = jsonConfig.serverAdress;
|
||||
port = jsonConfig.port;
|
||||
cookieSecret =
|
||||
jsonConfig.cookieSecret || "saF0DSF65AS4DF0S4D6F0S54DF0Fad";
|
||||
jsonConfigGlobal = jsonConfig;
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
"While reading the config an error occured. The error was: " + error
|
||||
);
|
||||
}
|
||||
|
||||
// Express (server) preperation
|
||||
app.use(express.static("static"));
|
||||
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
app.use(bodyParser.json());
|
||||
app.use(session({ secret: cookieSecret }));
|
||||
app.use(function (req, res, next) {
|
||||
// PreShow Errorpage handler
|
||||
const pathesWhichRequireDB = ["map", "login", "register"];
|
||||
const pathesWhichRequireLogin = ["createElevator"];
|
||||
const path = req.path
|
||||
const pathesDes = path.split("/")
|
||||
let requiresDB = false;
|
||||
let requiresLogin = false;
|
||||
let allowContinue = true;
|
||||
console.log(pathesDes)
|
||||
|
||||
if (pathesWhichRequireLogin.indexOf(pathesDes[1]) > -1) {
|
||||
requiresLogin = true;
|
||||
}
|
||||
|
||||
if (pathesDes[1] == "api") {
|
||||
requiresDB = true;
|
||||
}
|
||||
if (pathesWhichRequireDB.indexOf(pathesDes[1]) > -1) {
|
||||
requiresDB = true;
|
||||
}
|
||||
|
||||
if (requiresDB) {
|
||||
if (!mysqlIsUpAndOkay) {
|
||||
allowContinue = false;
|
||||
const data = fs.readFileSync("templates/dbError.html", "utf8");
|
||||
let displayText =
|
||||
"This might be an artifact of a recent restart. Maybe wait a few minutes and reload this page.";
|
||||
if (startUpTime + 60 <= Math.floor(new Date().getTime() / 1000)) {
|
||||
displayText =
|
||||
"The server failed to connect to the MySQL server. This means it was unable to load any data.";
|
||||
}
|
||||
if (mySQLstate == 1) {
|
||||
displayText =
|
||||
"There is a problem with the database servers setup. Please check the log for more info.";
|
||||
}
|
||||
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Error",
|
||||
fontawesomeKey: fontawesomeKey,
|
||||
displayText: displayText,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (requiresLogin) {
|
||||
if (req.session.username == undefined) {
|
||||
allowContinue = false;
|
||||
const data = fs.readFileSync("templates/redirect.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Redirect",
|
||||
fontawesomeKey: fontawesomeKey,
|
||||
url: "/login?r=" + path,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Time:', Date.now())
|
||||
if (allowContinue) {
|
||||
next()
|
||||
} else {
|
||||
console.log("Stopped further exec of route")
|
||||
}
|
||||
})
|
||||
|
||||
// Mail preperation
|
||||
const transport = nodemailer.createTransport({
|
||||
host: mailConf.host,
|
||||
port: mailConf.port,
|
||||
requireTLS: true,
|
||||
secure: false,
|
||||
debug: true,
|
||||
disableFileAccess: true,
|
||||
auth: {
|
||||
user: mailConf.username,
|
||||
pass: mailConf.password,
|
||||
},
|
||||
});
|
||||
|
||||
logger.info("Testing SMTP connection");
|
||||
transport.verify(function (error) {
|
||||
if (error) {
|
||||
logger.error(error);
|
||||
} else {
|
||||
logger.info("SMPT server is ready to accept messages");
|
||||
}
|
||||
});
|
||||
|
||||
// Basic defines for html
|
||||
const metainfo = {
|
||||
author: "TheGreydiamond",
|
||||
desc: "The Elevatormap. A map for elevator spotters!",
|
||||
sitePrefix: "Elevatormap - "
|
||||
}
|
||||
|
||||
let mysqlIsUpAndOkay = false;
|
||||
let mySQLstate = 0; // 0 -> Default failure 1 -> Missing strucutre
|
||||
|
||||
|
||||
|
||||
// Prepare MYSQL
|
||||
let con = mysql.createConnection({
|
||||
host: "localhost",
|
||||
user: mysqlData.user,
|
||||
password: mysqlData.password,
|
||||
database: mysqlData.database,
|
||||
});
|
||||
|
||||
function checkIfMySQLStructureIsReady() {
|
||||
if (mysqlIsUpAndOkay) {
|
||||
// Only if MySQL is ready
|
||||
logger.debug("Checking MySQL strucutre");
|
||||
con.query("SHOW TABLES;", function (err, result, fields) {
|
||||
if (err) throw err;
|
||||
if (result.length == 0) {
|
||||
// There are no tables. Not good.
|
||||
logger.warn("There are no tables found");
|
||||
if (mysqlData.allowCreation) {
|
||||
// Lets create it then
|
||||
logger.warn("Creating a new table");
|
||||
const sql =
|
||||
"CREATE TABLE `" +
|
||||
mysqlData.database +
|
||||
"`.`elevators` ( `id` INT NOT NULL AUTO_INCREMENT , `lat` FLOAT NOT NULL , `lng` FLOAT NOT NULL , `manufacturer` VARCHAR(512) NOT NULL , `modell` VARCHAR(512) NOT NULL , `info` VARCHAR(512) NOT NULL , `visitabilty` INT NOT NULL , `technology` INT NOT NULL , `images` JSON NOT NULL , `amountOfFloors` INT NOT NULL , `maxPassangers` INT NOT NULL , `maxWeight` INT NOT NULL , `creator` INT NOT NULL, PRIMARY KEY (`id`)) ENGINE = InnoDB;";
|
||||
const newSql =
|
||||
"CREATE TABLE `" +
|
||||
mysqlData.database +
|
||||
"`.`users` ( `id` INT NOT NULL AUTO_INCREMENT , `email` VARCHAR(255) NOT NULL , `username` VARCHAR(255) NOT NULL , `passwordHash` VARCHAR(512) NOT NULL , `permLevel` INT NOT NULL DEFAULT '0' , `verificationState` INT NOT NULL DEFAULT '0' , PRIMARY KEY (`id`), UNIQUE KEY (`email`)) ENGINE = InnoDB;";
|
||||
const newSqlMailVeri =
|
||||
"CREATE TABLE `" +
|
||||
mysqlData.database +
|
||||
"`.`mailverification` ( `id` INT NOT NULL AUTO_INCREMENT , `targetMail` VARCHAR(512) NOT NULL , `userID` INT NOT NULL , `token` VARCHAR(255) NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB;";
|
||||
con.query(sql, function (err, result) {
|
||||
if (err) throw err;
|
||||
logger.info("Table created");
|
||||
});
|
||||
|
||||
con.query(newSql, function (err, result) {
|
||||
if (err) throw err;
|
||||
logger.info("Usertable created");
|
||||
});
|
||||
|
||||
con.query(newSqlMailVeri, function (err, result) {
|
||||
if (err) throw err;
|
||||
logger.info("Email verification table created");
|
||||
});
|
||||
} else {
|
||||
// We cannot do that. Welp.
|
||||
logger.warn(
|
||||
"MySQL tables are missing and the config denies creation of new ones."
|
||||
);
|
||||
mysqlIsUpAndOkay = false;
|
||||
mySQLstate = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
logger.warn("Tried checking the tables even though MySQL wasn't ready.");
|
||||
}
|
||||
}
|
||||
|
||||
con.connect(function (err) {
|
||||
if (err) {
|
||||
mysqlIsUpAndOkay = false;
|
||||
logger.error("Connction to MySQL failed");
|
||||
console.log(err);
|
||||
} else {
|
||||
logger.info("Mysql is ready.");
|
||||
mysqlIsUpAndOkay = true;
|
||||
checkIfMySQLStructureIsReady();
|
||||
}
|
||||
});
|
||||
|
||||
// Routes
|
||||
app.get("/", function (req, res) { // Index page
|
||||
const data = fs.readFileSync("templates/index.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Start",
|
||||
fontawesomeKey: fontawesomeKey,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
app.get("/map", function (req, res) { // Map page showing all elevators
|
||||
const data = fs.readFileSync("templates/map.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Map",
|
||||
fontawesomeKey: fontawesomeKey,
|
||||
mapboxAccessToken: mapboxAccessToken,
|
||||
})
|
||||
)
|
||||
|
||||
});
|
||||
|
||||
app.get("/createElevator", function (req, res) { // Page to create a new elvator
|
||||
const data = fs.readFileSync("templates/createElevator.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "New elevator",
|
||||
fontawesomeKey: fontawesomeKey,
|
||||
mapboxAccessToken: mapboxAccessToken,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
require('./routes/api.route.ts')(app, con, mysqlIsUpAndOkay, logger, metainfo);
|
||||
require('./routes/debug.route.ts')(app, con, logger, metainfo);
|
||||
require('./routes/auth.route.ts')(app, con, logger, metainfo, jsonConfigGlobal);
|
||||
|
||||
// Some loops for handeling stuff,
|
||||
setInterval(() => {
|
||||
if (mysqlIsUpAndOkay == false) { // SQL reconnect
|
||||
logger.warn("Retrying to connect to MySQL");
|
||||
con = mysql.createConnection({
|
||||
host: "localhost",
|
||||
user: mysqlData.user,
|
||||
password: mysqlData.password,
|
||||
database: mysqlData.database,
|
||||
});
|
||||
|
||||
con.connect(function (err) {
|
||||
if (err) {
|
||||
mysqlIsUpAndOkay = false;
|
||||
logger.error("Connction to MySQL failed");
|
||||
console.log(err);
|
||||
} else {
|
||||
logger.info("Mysql is ready.");
|
||||
mysqlIsUpAndOkay = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 60*1000); // Every minute
|
||||
|
||||
// App start
|
||||
app.listen(port, () => {
|
||||
logger.info(`Elevator map ready at http://localhost:${port}`);
|
||||
});
|
||||
5290
package-lock.json
generated
5290
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
32
package.json
32
package.json
@@ -4,30 +4,44 @@
|
||||
"description": "The elevatormap rewritten",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 0",
|
||||
"start": "node index.js"
|
||||
"makeJS": "tsc index.ts",
|
||||
"lint": "eslint . --ext .ts",
|
||||
"makeJSwatch": "tsc -w index.ts",
|
||||
"start": "tsc index.ts && node index.js",
|
||||
"preChecks": "npm outdated && npm audit",
|
||||
"startBeforeMerge": "eslint . --ext .ts && tsc index.ts && node index.js",
|
||||
"nodemon": "nodemon index.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/TheGreyDiamond/elevatormapRewritten.git"
|
||||
},
|
||||
"author": "TheGreydiamond",
|
||||
"license": "ISC",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/TheGreyDiamond/elevatormapRewritten/issues"
|
||||
},
|
||||
"homepage": "https://github.com/TheGreyDiamond/elevatormapRewritten#readme",
|
||||
"homepage": "https://github.com/TheGreyDiamond/elevatormapRewritten",
|
||||
"dependencies": {
|
||||
"bcrypt": "^5.0.1",
|
||||
"body-parser": "^1.19.0",
|
||||
"eta": "^1.12.1",
|
||||
"express": "^4.17.1",
|
||||
"body-parser": "^1.20.1",
|
||||
"eta": "^2.0.0",
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.2",
|
||||
"hcaptcha": "0.0.2",
|
||||
"greeting-time": "^1.0.0",
|
||||
"hcaptcha": "0.1.0",
|
||||
"helmet": "^4.6.0",
|
||||
"multer": "^1.4.2",
|
||||
"mysql": "^2.18.1",
|
||||
"nodemailer": "^6.6.1",
|
||||
"nodemailer": "^6.6.2",
|
||||
"winston": "^3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
||||
"@typescript-eslint/parser": "^4.33.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-strongloop": "^2.1.0",
|
||||
"typescript": "^4.2.4"
|
||||
}
|
||||
}
|
||||
|
||||
311
routes/api.route.ts
Normal file
311
routes/api.route.ts
Normal file
@@ -0,0 +1,311 @@
|
||||
module.exports = function (app, con, mysqlIsUpAndOkay, logger) {
|
||||
const multer = require("multer");
|
||||
const upload = multer({ dest: "static/uploads/" });
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
app.get("/api/getElevatorById", function (req, res) {
|
||||
console.log(req.query);
|
||||
if (req.query.id != undefined) {
|
||||
// All parameters are there
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
try {
|
||||
const id = parseFloat(req.query.id);
|
||||
} catch (error) {
|
||||
res.send(
|
||||
JSON.stringify({ state: "Failed", message: "Invalid arguments" })
|
||||
);
|
||||
res.status(400);
|
||||
return;
|
||||
}
|
||||
const id = parseFloat(req.query.id);
|
||||
|
||||
con.query(
|
||||
"SELECT * FROM elevators WHERE id=" + id,
|
||||
function (err, result) {
|
||||
if (err) {
|
||||
res.status(500);
|
||||
res.send(
|
||||
JSON.stringify({
|
||||
state: "Failed",
|
||||
message: "A server side error occured.",
|
||||
results: [],
|
||||
})
|
||||
);
|
||||
logger.error("The server failed to execute a request");
|
||||
console.log(err);
|
||||
mysqlIsUpAndOkay = false;
|
||||
} else {
|
||||
console.log(result[0]);
|
||||
res.status(200);
|
||||
res.send(
|
||||
JSON.stringify({
|
||||
state: "Ok",
|
||||
message: "Successful.",
|
||||
results: result,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// Welp something is missing
|
||||
res.status(400);
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
res.send(JSON.stringify({ state: "Failed", message: "Missing arguments" }));
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/api/resolveNameById", function (req, res) {
|
||||
if (req.query.id != undefined && req.query.id != "") {
|
||||
const sql = "SELECT username FROM users WHERE id=?";
|
||||
con.query(sql, [req.query.id], function (err, result) {
|
||||
if (err) {
|
||||
res.status(500);
|
||||
res.send(
|
||||
JSON.stringify({
|
||||
state: "Failed",
|
||||
message: "A server side error occured.",
|
||||
results: [],
|
||||
})
|
||||
);
|
||||
logger.error("The server failed to execute a request");
|
||||
mysqlIsUpAndOkay = false;
|
||||
} else {
|
||||
console.log(result[0]);
|
||||
res.status(200);
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
res.send(
|
||||
JSON.stringify({ state: "Ok", message: "", results: result })
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
res.status(400);
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
res.send(JSON.stringify({ state: "Failed", message: "Missing argument: id" }));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
app.get("/api/getElevatorLocation", function (req, res) {
|
||||
if (
|
||||
req.query.lan != undefined &&
|
||||
req.query.lat != undefined &&
|
||||
req.query.radius != undefined
|
||||
) {
|
||||
// All parameters are there
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
try {
|
||||
const lan = parseFloat(req.query.lan);
|
||||
const lat = parseFloat(req.query.lat);
|
||||
const radius = parseFloat(req.query.radius);
|
||||
} catch (error) {
|
||||
res.send(
|
||||
JSON.stringify({ state: "Failed", message: "Invalid arguments" })
|
||||
);
|
||||
res.status(400);
|
||||
return;
|
||||
}
|
||||
const lan = parseFloat(req.query.lan);
|
||||
const lat = parseFloat(req.query.lat);
|
||||
const radius = parseFloat(req.query.radius);
|
||||
|
||||
// TODO: Return just the elevators in the viewers area
|
||||
|
||||
con.query(
|
||||
"SELECT id, lat, lng FROM elevators",
|
||||
function (err, result, fields) {
|
||||
if (err) {
|
||||
res.status(500);
|
||||
res.send(
|
||||
JSON.stringify({
|
||||
state: "Failed",
|
||||
message: "A server side error occured.",
|
||||
results: [],
|
||||
})
|
||||
);
|
||||
logger.error("The server failed to execute a request");
|
||||
mysqlIsUpAndOkay = false;
|
||||
} else {
|
||||
console.log(result[0]);
|
||||
res.status(200);
|
||||
res.send(
|
||||
JSON.stringify({ state: "Ok", message: "", results: result })
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// Welp something is missing
|
||||
res.status(400);
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
res.send(JSON.stringify({ state: "Failed", message: "Missing arguments" }));
|
||||
}
|
||||
});
|
||||
|
||||
// returns an object with the cookies' name as keys
|
||||
const getAppCookies = (req) => {
|
||||
// We extract the raw cookies from the request headers
|
||||
const rawCookies = req.headers.cookie.split("; ");
|
||||
// rawCookies = ['myapp=secretcookie, 'analytics_cookie=beacon;']
|
||||
|
||||
const parsedCookies = {};
|
||||
rawCookies.forEach((rawCookie) => {
|
||||
const parsedCookie = rawCookie.split("=");
|
||||
// parsedCookie = ['myapp', 'secretcookie'], ['analytics_cookie', 'beacon']
|
||||
parsedCookies[parsedCookie[0]] = parsedCookie[1];
|
||||
});
|
||||
return parsedCookies;
|
||||
};
|
||||
|
||||
app.post("/api/saveNewElevatorMeta", function (req, res) {
|
||||
const sess = req.session;
|
||||
const tempJs = JSON.parse(decodeURIComponent(getAppCookies(req)["tempStore"]));
|
||||
const sql =
|
||||
"INSERT INTO elevators (lat, lng, manufacturer, modell, info, visitabilty, technology, amountOfFloors, maxPassangers, maxWeight, images, creator) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '{ \"images\": []}', ?)";
|
||||
con.query(
|
||||
sql,
|
||||
[
|
||||
tempJs.lat,
|
||||
tempJs.lng,
|
||||
tempJs.manuf,
|
||||
tempJs.model,
|
||||
tempJs.description,
|
||||
tempJs.visit,
|
||||
tempJs.type,
|
||||
tempJs.flor,
|
||||
tempJs.pepl,
|
||||
tempJs.weig,
|
||||
sess.uid
|
||||
],
|
||||
function (err, result) {
|
||||
if (err) throw err;
|
||||
console.log("1 record inserted with id " + result.insertId);
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
|
||||
res.send(
|
||||
JSON.stringify({ state: "Okay", message: "Ok. No fault!", id: result.insertId })
|
||||
);
|
||||
res.status(200);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
app.post("/api/uploadImage", upload.any(), function (req, res) {
|
||||
console.log(req.query.id)
|
||||
let i = 0;
|
||||
const sql = 'SELECT id, images FROM elevators WHERE id=?';
|
||||
const allImages = []
|
||||
while (i < req.files.length) {
|
||||
const fObj = req.files[i];
|
||||
const currentPath = path.join(fObj["path"]);
|
||||
const destinationPath =
|
||||
currentPath +
|
||||
"." +
|
||||
fObj["originalname"].split(".")[
|
||||
fObj["originalname"].split(".").length - 1
|
||||
]; // Add the file end
|
||||
|
||||
fs.rename(currentPath, destinationPath, function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
console.log("Successfully moved the file!");
|
||||
}
|
||||
});
|
||||
allImages.push({ "path": destinationPath, "alt": "No alt was provided." })
|
||||
i++;
|
||||
}
|
||||
|
||||
con.query(
|
||||
sql, [req.query.id],
|
||||
function (err, result, fields) {
|
||||
if (err) {
|
||||
res.status(500);
|
||||
res.send(
|
||||
JSON.stringify({
|
||||
state: "Failed",
|
||||
message: "A server side error occured.",
|
||||
results: [],
|
||||
})
|
||||
);
|
||||
logger.error("The server failed to execute a request");
|
||||
mysqlIsUpAndOkay = false;
|
||||
} else {
|
||||
const jData = JSON.parse(result[0].images)
|
||||
console.log(jData)
|
||||
jData.images.push.spread(jData.images, allImages)
|
||||
console.log(jData);
|
||||
console.log(result);
|
||||
const sql = "UPDATE elevators SET images = ? WHERE id = ?";
|
||||
con.query(sql, [JSON.stringify(jData), req.query.id], function (err) {
|
||||
if (err) {
|
||||
console.log("Update failure")
|
||||
} else {
|
||||
console.log("Okay")
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Save Image End
|
||||
});
|
||||
|
||||
|
||||
app.get("/api/getElevators", function (req, res) {
|
||||
console.log(req.query);
|
||||
if (
|
||||
req.query.lan != undefined &&
|
||||
req.query.lat != undefined &&
|
||||
req.query.radius != undefined
|
||||
) {
|
||||
// All parameters are there
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
try {
|
||||
const lan = parseFloat(req.query.lan);
|
||||
const lat = parseFloat(req.query.lat);
|
||||
const radius = parseFloat(req.query.radius);
|
||||
} catch (error) {
|
||||
res.send(
|
||||
JSON.stringify({ state: "Failed", message: "Invalid arguments" })
|
||||
);
|
||||
res.status(400);
|
||||
return;
|
||||
}
|
||||
const lan = parseFloat(req.query.lan);
|
||||
const lat = parseFloat(req.query.lat);
|
||||
const radius = parseFloat(req.query.radius);
|
||||
|
||||
// TODO: Return just the elevators in the viewers area
|
||||
|
||||
con.query("SELECT * FROM elevators", function (err, result) {
|
||||
if (err) {
|
||||
res.status(500);
|
||||
res.send(
|
||||
JSON.stringify({
|
||||
state: "Failed",
|
||||
message: "A server side error occured.",
|
||||
results: [],
|
||||
})
|
||||
);
|
||||
logger.error("The server failed to execute a request");
|
||||
mysqlIsUpAndOkay = false;
|
||||
} else {
|
||||
console.log(result[0]);
|
||||
res.status(200);
|
||||
res.send(JSON.stringify({ state: "Ok", message: "", results: result }));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Welp something is missing
|
||||
res.status(400);
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
res.send(JSON.stringify({ state: "Failed", message: "Missing arguments" }));
|
||||
}
|
||||
});
|
||||
}
|
||||
443
routes/auth.route.ts
Normal file
443
routes/auth.route.ts
Normal file
@@ -0,0 +1,443 @@
|
||||
module.exports = function (app, con, logger, metainfo, jsonConfig) {
|
||||
const greetingTime = require("greeting-time");
|
||||
const fs = require("fs");
|
||||
const Eta = require("eta");
|
||||
const { verify } = require("hcaptcha");
|
||||
const bcrypt = require("bcrypt");
|
||||
const cryptoF = require("crypto");
|
||||
const saltRounds = 10;
|
||||
|
||||
const mailRegex =
|
||||
/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
|
||||
|
||||
app.get("/logout", function (req, res) {
|
||||
req.session.destroy();
|
||||
const data = fs.readFileSync("templates/redirect.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Logout",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
url: "/",
|
||||
})
|
||||
);
|
||||
});
|
||||
app.get("/verify*", function (req, res) {
|
||||
console.log(req.url.split("/")[2]);
|
||||
const stmt = "SELECT * FROM mailverification WHERE token = ?;";
|
||||
|
||||
con.query(stmt, [req.url.split("/")[2]], function (err, result) {
|
||||
if (err) {
|
||||
res.status(404);
|
||||
res.send(
|
||||
JSON.stringify({ state: "Failed", message: "Database error occured" })
|
||||
);
|
||||
logger.error(err);
|
||||
} else {
|
||||
if (result.length == 0) {
|
||||
res.status(404);
|
||||
res.send(
|
||||
JSON.stringify({ state: "Failed", message: "Link already done" })
|
||||
);
|
||||
} else {
|
||||
console.log(result);
|
||||
res.status(200);
|
||||
const stmt2 = "DELETE FROM mailverification WHERE id=?";
|
||||
console.log(result[0].id);
|
||||
con.query(stmt2, [result[0].id], function (err, result, fields) {
|
||||
// TODO handling of this
|
||||
//logger.debug(err)
|
||||
//console.log(result)
|
||||
});
|
||||
const stmt3 = "UPDATE users SET verificationState=1 WHERE email=?";
|
||||
con.query(
|
||||
stmt3,
|
||||
[result[0].targetMail],
|
||||
function (err, result, fields) {
|
||||
// TODO handling of this
|
||||
//logger.debug(err)
|
||||
//console.log(result)
|
||||
}
|
||||
);
|
||||
res.send(JSON.stringify({ state: "OK", message: "Done!" }));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
app.post("/register", function (req, res) {
|
||||
const sess = req.session;
|
||||
let resu;
|
||||
verify(jsonConfig.hCaptcha.secret, req.body["g-recaptcha-response"]).then(
|
||||
(data) => (resu = data)
|
||||
);
|
||||
/*.catch(setTimeout(() => {
|
||||
//if(resu.success == false){
|
||||
console.log("HERE");
|
||||
const data = fs.readFileSync("templates/genericError.html", "utf8");
|
||||
resu = "-1";
|
||||
con
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Error",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
displayText: "There was an issue with the Captcha",
|
||||
})
|
||||
);
|
||||
//}
|
||||
|
||||
}, 0)
|
||||
);*/
|
||||
|
||||
if (req.body.pass == req.body.pass2) {
|
||||
|
||||
if (mailRegex.test(req.body.email)) {
|
||||
setTimeout(() => {
|
||||
console.log(resu);
|
||||
if (resu.success == true) {
|
||||
bcrypt.hash(req.body.pass, saltRounds, (err, hash) => {
|
||||
const data = fs.readFileSync(
|
||||
"templates/genericError.html",
|
||||
"utf8"
|
||||
);
|
||||
// SQL INSERT
|
||||
|
||||
const stmt =
|
||||
"INSERT INTO users(email, username, passwordHash) VALUES(?, ?, ?)";
|
||||
const stmt2 =
|
||||
"INSERT INTO mailverification(targetMail, userID, token) VALUES(?, ?, ?)";
|
||||
cryptoF.randomBytes(48, function (err, buffer) {
|
||||
const token = buffer.toString("hex");
|
||||
con.query(
|
||||
stmt,
|
||||
[req.body.email, req.body.username, hash],
|
||||
(err, results1) => {
|
||||
if (err) {
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Error",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
displayText:
|
||||
"An error occured while creating your account.",
|
||||
})
|
||||
);
|
||||
return console.error(err.message);
|
||||
} else {
|
||||
// Create mail verification
|
||||
con.query(
|
||||
stmt2,
|
||||
[req.body.email, results1.insertId, token],
|
||||
(err, results) => {
|
||||
if (err) {
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Error",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
displayText:
|
||||
"An error occured while creating your account.",
|
||||
})
|
||||
);
|
||||
return console.error(err.message);
|
||||
} else {
|
||||
sess.username = req.body.username;
|
||||
sess.uid = String(results1.insertId);
|
||||
sess.mail = req.body.email;
|
||||
// get inserted id
|
||||
logger.info("Inserted Id:" + results.insertId);
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Error",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
displayText: "OK " + hash,
|
||||
})
|
||||
);
|
||||
sendVerificationMail(results.insertId);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
const data = fs.readFileSync("templates/register.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Register",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
sitekey: jsonConfig.hCaptcha.sitekey,
|
||||
error: true,
|
||||
errorMessage: "You failed the captcha, please try again.",
|
||||
})
|
||||
);
|
||||
}
|
||||
}, 200);
|
||||
} else {
|
||||
// Passwords don't match up
|
||||
const data = fs.readFileSync("templates/register.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Register",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
sitekey: jsonConfig.hCaptcha.sitekey,
|
||||
error: true,
|
||||
errorMessage: "The E-Mail given is not valid",
|
||||
})
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Passwords don't match up
|
||||
const data = fs.readFileSync("templates/register.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Register",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
sitekey: jsonConfig.hCaptcha.sitekey,
|
||||
error: true,
|
||||
errorMessage: "The password have to match up.",
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
app.get("/register", function (req, res) {
|
||||
const data = fs.readFileSync("templates/register.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Register",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
sitekey: jsonConfig.hCaptcha.sitekey,
|
||||
})
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
app.get("/profile", function (req, res) {
|
||||
if (req.session.username != undefined) {
|
||||
let greeting = greetingTime(new Date());
|
||||
greeting += " " + req.session.username;
|
||||
const hash = cryptoF
|
||||
.createHash("md5")
|
||||
.update(req.session.mail.replace(" ", "").toLowerCase())
|
||||
.digest("hex");
|
||||
const gravatarURL = "https://www.gravatar.com/avatar/" + hash;
|
||||
const data = fs.readFileSync("templates/profile.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Profile",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
greeting: greeting,
|
||||
gravatarURL: gravatarURL,
|
||||
})
|
||||
);
|
||||
} else {
|
||||
const data = fs.readFileSync("templates/redirect.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Profile",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
url: "/login",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
app.get("/login", function (req, res) {
|
||||
|
||||
const data = fs.readFileSync("templates/login.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Login",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
})
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
|
||||
app.post("/login", function (req, res) {
|
||||
const password = req.body.pass;
|
||||
const mail = req.body.email;
|
||||
const sess = req.session;
|
||||
console.log(req.body.pass);
|
||||
|
||||
// Check if okay
|
||||
if (
|
||||
mail != undefined &&
|
||||
mail != "" &&
|
||||
password != undefined &&
|
||||
password != ""
|
||||
) {
|
||||
if (mailRegex.test(mail)) {
|
||||
const stmt = "SELECT * FROM users WHERE email=?;";
|
||||
con.query(stmt, [mail], function (err, result) {
|
||||
if (err) throw err; // TODO proper error page
|
||||
if (result.length == 0) {
|
||||
const data = fs.readFileSync("templates/login.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Ok",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
error: true,
|
||||
errorMessage: "This user does not exist!",
|
||||
})
|
||||
);
|
||||
} else {
|
||||
bcrypt.compare(
|
||||
password,
|
||||
result[0].passwordHash,
|
||||
function (error, response) {
|
||||
if (response) {
|
||||
// Login okay
|
||||
sess.username = result[0].username;
|
||||
sess.uid = String(result[0].id);
|
||||
sess.mail = result[0].email;
|
||||
|
||||
const data = fs.readFileSync("templates/redirect.html", "utf8");
|
||||
if (req.query.r != undefined && req.query.r != "") {
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Ok",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
url: req.query.r,
|
||||
})
|
||||
);
|
||||
|
||||
} else {
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Ok",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
url: "/profile",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Password falsch
|
||||
const data = fs.readFileSync("templates/login.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Ok",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
error: true,
|
||||
errorMessage: "The given password is wrong.",
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const data = fs.readFileSync("templates/login.html", "utf8");
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Ok",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
error: true,
|
||||
errorMessage: "The given E-Mail is invalid.",
|
||||
})
|
||||
);
|
||||
}
|
||||
} else {
|
||||
logger.warn(
|
||||
"The login form did not sent all data. Dump: \n Password: " +
|
||||
password +
|
||||
" \n E-Mail: " +
|
||||
mail
|
||||
);
|
||||
const data = fs.readFileSync("templates/genericError.html", "utf8");
|
||||
const displayText = "The form did not sent all the information needed.";
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
author: metainfo.author,
|
||||
desc: metainfo.desc,
|
||||
siteTitel: metainfo.sitePrefix + "Error",
|
||||
fontawesomeKey: jsonConfig.fontAwesome,
|
||||
displayText: displayText,
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// sendVerificationMail(2);
|
||||
function sendVerificationMail(userId) {
|
||||
// Query for the mail
|
||||
const stmt = "SELECT * FROM mailverification WHERE id=?";// + userId;
|
||||
con.query(stmt, [userId], function (err, result, fields) {
|
||||
if (err) throw err; // TODO proper error handling
|
||||
if (result.length == 0) {
|
||||
logger.warn(
|
||||
"sendVerificationMail failed because ID " + userId + " doesnt exist!"
|
||||
);
|
||||
} else {
|
||||
const emailContent =
|
||||
"Hi! \n You have created an account for the open elevator map. To finalize the process please verify your E-Mail adress. Use this link: http://" +
|
||||
jsonConfig.serverAdress +
|
||||
"/verify/" +
|
||||
result[0].token;
|
||||
transport.sendMail({
|
||||
from: '"Elevator map " <' + mailConf.username + ">", // sender address
|
||||
to: result[0].targetMail, // list of receivers
|
||||
subject: "[Elevator map] Please verify your Mailadress", // Subject line
|
||||
text: emailContent, // plain text body
|
||||
html: emailContent.replace("\n", "<br>"), // html body
|
||||
});
|
||||
}
|
||||
|
||||
console.log(result);
|
||||
});
|
||||
|
||||
/*
|
||||
let info = await transporter.sendMail({
|
||||
from: '"Elevator map " <' + mysqlData.username + '>', // sender address
|
||||
to: "bar@example.com, baz@example.com", // list of receivers
|
||||
subject: "Hello ✔", // Subject line
|
||||
text: "Hello world?", // plain text body
|
||||
html: "<b>Hello world?</b>", // html body
|
||||
});*/
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
6
routes/debug.route.ts
Normal file
6
routes/debug.route.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = function (app) {
|
||||
app.get("/debug/showSessionInfo", function (req, res) {
|
||||
res.send(JSON.stringify(req.session));
|
||||
});
|
||||
|
||||
}
|
||||
BIN
static/images/elevatormapLogo.png
Normal file
BIN
static/images/elevatormapLogo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 198 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 867 B After Width: | Height: | Size: 9.2 KiB |
267
static/js/createElevator.js
Normal file
267
static/js/createElevator.js
Normal file
@@ -0,0 +1,267 @@
|
||||
|
||||
var lockMap = false;
|
||||
|
||||
function noRestore() {
|
||||
off();
|
||||
Cookies.remove("tempStore")
|
||||
}
|
||||
|
||||
function restoreFunc() {
|
||||
try {
|
||||
dataBlock = JSON.parse(dataBlock)
|
||||
document.getElementById("lat").value = dataBlock["lat"]
|
||||
document.getElementById("lng").value = dataBlock["lng"]
|
||||
document.getElementById("type").value = dataBlock["type"]
|
||||
document.getElementById("visit").value = dataBlock["visit"]
|
||||
document.getElementById("pepl").value = dataBlock["pepl"]
|
||||
document.getElementById("weig").value = dataBlock["weig"]
|
||||
document.getElementById("manuf").value = dataBlock["manuf"]
|
||||
document.getElementById("model").value = dataBlock["model"]
|
||||
document.getElementById("flor").value = dataBlock["flor"]
|
||||
document.getElementById("description").value = dataBlock["description"]
|
||||
} catch (ex) {
|
||||
dataBlock = {}
|
||||
}
|
||||
off()
|
||||
}
|
||||
|
||||
dataBlock = Cookies.get("tempStore");
|
||||
if (dataBlock == undefined) {
|
||||
dataBlock = {};
|
||||
} else {
|
||||
on()
|
||||
}
|
||||
|
||||
var currentPage = 0;
|
||||
function saveValues() {
|
||||
dataBlock["lat"] = document.getElementById("lat").value
|
||||
dataBlock["lng"] = document.getElementById("lng").value
|
||||
dataBlock["type"] = document.getElementById("type").value
|
||||
dataBlock["visit"] = document.getElementById("visit").value
|
||||
dataBlock["pepl"] = document.getElementById("pepl").value
|
||||
dataBlock["weig"] = document.getElementById("weig").value
|
||||
dataBlock["manuf"] = document.getElementById("manuf").value
|
||||
dataBlock["model"] = document.getElementById("model").value
|
||||
dataBlock["flor"] = document.getElementById("flor").value
|
||||
dataBlock["description"] = document.getElementById("description").value
|
||||
Cookies.set('tempStore', JSON.stringify(dataBlock))
|
||||
}
|
||||
|
||||
function submit() {
|
||||
currentPage = 6;
|
||||
updateDialog()
|
||||
saveValues()
|
||||
const options = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({})
|
||||
};
|
||||
|
||||
fetch('/api/saveNewElevatorMeta', options)
|
||||
.then(response => response.json())
|
||||
.then(response => {
|
||||
console.warn("!!!!!!!!!!!!", response)
|
||||
document.getElementById("imageUploadInfo").style.display = 'block';
|
||||
var filesToSend = $('#myFile').prop('files').length;
|
||||
var i = 0;
|
||||
while (i < filesToSend) {
|
||||
document.getElementById("imageUploadInfo").innerHTML = "Uploading image " + String(i) + "/" + String(filesToSend)
|
||||
console.log("Files left to send: ", filesToSend - i)
|
||||
var file_data = $('#myFile').prop('files')[i];
|
||||
var form_data = new FormData();
|
||||
form_data.append('file', file_data);
|
||||
|
||||
console.log(file_data)
|
||||
if (String(file_data.type).includes("image/")) {
|
||||
$.ajax({
|
||||
url: '/api/uploadImage?id=' + response.id,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
data: form_data,
|
||||
type: 'post',
|
||||
success: function (data) {
|
||||
alert(data);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log("Skipping nonimage file")
|
||||
}
|
||||
i++;
|
||||
}
|
||||
console.log("DONE!")
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
function updateDialog() {
|
||||
if (currentPage == 0) {
|
||||
document.getElementById("step1").style.display = 'block';
|
||||
document.getElementById("step2").style.display = 'none';
|
||||
document.getElementById("step3").style.display = 'none';
|
||||
document.getElementById("step4").style.display = 'none';
|
||||
}
|
||||
if (currentPage == 1) {
|
||||
document.getElementById("step1").style.display = 'none';
|
||||
document.getElementById("step2").style.display = 'block';
|
||||
document.getElementById("step3").style.display = 'none';
|
||||
document.getElementById("step4").style.display = 'none';
|
||||
}
|
||||
if (currentPage == 2) {
|
||||
document.getElementById("step1").style.display = 'none';
|
||||
document.getElementById("step2").style.display = 'none';
|
||||
document.getElementById("step3").style.display = 'block';
|
||||
document.getElementById("step4").style.display = 'none';
|
||||
lockMap = false;
|
||||
}
|
||||
if (currentPage == 3) {
|
||||
document.getElementById("step1").style.display = 'none';
|
||||
document.getElementById("step2").style.display = 'none';
|
||||
document.getElementById("step3").style.display = 'none';
|
||||
document.getElementById("step4").style.display = 'block';
|
||||
document.getElementById("step5").style.display = 'none';
|
||||
document.getElementById("missingAlert").style.display = 'none';
|
||||
lockMap = true;
|
||||
}
|
||||
if (currentPage == 4) {
|
||||
document.getElementById("step1").style.display = 'none';
|
||||
document.getElementById("step2").style.display = 'none';
|
||||
document.getElementById("step3").style.display = 'none';
|
||||
document.getElementById("step4").style.display = 'none';
|
||||
|
||||
containsEmpt = false;
|
||||
for (const [key, value] of Object.entries(dataBlock)) {
|
||||
if (value == "" || value == undefined) {
|
||||
console.log("hi")
|
||||
console.log(key, value)
|
||||
containsEmpt = true;
|
||||
document.getElementById("missingAlert").style.display = 'block';
|
||||
}
|
||||
}
|
||||
if (containsEmpt == false) {
|
||||
document.getElementById("missingAlert").style.display = 'none';
|
||||
currentPage = 5;
|
||||
}
|
||||
console.log(containsEmpt);
|
||||
}
|
||||
if (currentPage == 5) {
|
||||
document.getElementById("step1").style.display = 'none';
|
||||
document.getElementById("step2").style.display = 'none';
|
||||
document.getElementById("step3").style.display = 'none';
|
||||
document.getElementById("step4").style.display = 'none';
|
||||
document.getElementById("step5").style.display = 'block';
|
||||
document.getElementById("missingAlert").style.display = 'none';
|
||||
}
|
||||
if (currentPage == 6) {
|
||||
document.getElementById("step1").style.display = 'none';
|
||||
document.getElementById("step2").style.display = 'none';
|
||||
document.getElementById("step3").style.display = 'none';
|
||||
document.getElementById("step4").style.display = 'none';
|
||||
document.getElementById("step5").style.display = 'none';
|
||||
document.getElementById("step6").style.display = 'block';
|
||||
document.getElementById("missingAlert").style.display = 'none';
|
||||
}
|
||||
saveValues();
|
||||
console.log(dataBlock)
|
||||
|
||||
}
|
||||
function nextDialogePage() {
|
||||
currentPage++;
|
||||
updateDialog();
|
||||
}
|
||||
function prevPage() {
|
||||
currentPage--;
|
||||
updateDialog();
|
||||
}
|
||||
|
||||
|
||||
var latElm = document.getElementById("lat");
|
||||
var lngElm = document.getElementById("lng");
|
||||
|
||||
latElm.addEventListener('input', function (evt) {
|
||||
if(!lockMap){
|
||||
markers.clearLayers();
|
||||
console.log(evt.target.value)
|
||||
const lat = evt.target.value;
|
||||
const lng = lngElm.value;
|
||||
var marker = new theMarker([lat, lng])
|
||||
//marker.addTo(mymap)
|
||||
markers.addLayer(marker);
|
||||
markers.addTo(mymap);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
lngElm.addEventListener('input', function (evt) {
|
||||
if(!lockMap){
|
||||
markers.clearLayers();
|
||||
console.log(evt.target.value)
|
||||
const lat = latElm.value;
|
||||
const lng = evt.target.value;
|
||||
var marker = new theMarker([lat, lng])
|
||||
//marker.addTo(mymap)
|
||||
markers.addLayer(marker);
|
||||
markers.addTo(mymap);
|
||||
}
|
||||
});
|
||||
|
||||
var amountOfImages = 0;
|
||||
var markers = L.markerClusterGroup();
|
||||
slideIndex = 1;
|
||||
|
||||
var mymap = L.map("map").setView([51.505, -0.09], 50);
|
||||
|
||||
theMarker = L.Marker.extend({
|
||||
options: {
|
||||
id: "-1",
|
||||
},
|
||||
});
|
||||
|
||||
function showPosition(position) {
|
||||
console.log(position.coords);
|
||||
|
||||
mymap.setView(
|
||||
new L.LatLng(position.coords.latitude, position.coords.longitude),
|
||||
10
|
||||
);
|
||||
// mymap.setView(new L.LatLng(10.737, -73.923), 8);
|
||||
}
|
||||
|
||||
home()
|
||||
|
||||
mymap.on('click', function (e) {
|
||||
if(!lockMap){
|
||||
markers.clearLayers();
|
||||
var coord = e.latlng;
|
||||
var lat = coord.lat;
|
||||
var lng = coord.lng;
|
||||
var marker = new theMarker([lat, lng])
|
||||
//marker.addTo(mymap)
|
||||
markers.addLayer(marker);
|
||||
markers.addTo(mymap);
|
||||
document.getElementById("lat").value = lat
|
||||
document.getElementById("lng").value = lng
|
||||
console.log("You clicked the map at latitude: " + lat + " and longitude: " + lng);
|
||||
}else{
|
||||
console.log("The map is locked.")
|
||||
}
|
||||
});
|
||||
|
||||
function addPin(item, index) {
|
||||
var marker = new theMarker([item.lat, item.lng], {
|
||||
id: item.id,
|
||||
}).on("click", onClick);
|
||||
// var marker = new L.Marker()
|
||||
//marker.addTo(mymap).on('click', onClick);
|
||||
markers.on("clusterclick", function (a) {
|
||||
//alert('cluster ' + a.layer.getAllChildMarkers().length);
|
||||
});
|
||||
markers.addLayer(marker);
|
||||
}
|
||||
|
||||
192
static/js/map.js
Normal file
192
static/js/map.js
Normal file
@@ -0,0 +1,192 @@
|
||||
function createNewElev() {
|
||||
window.location.href = "/createElevator";
|
||||
}
|
||||
|
||||
var amountOfImages = 0;
|
||||
var markers = L.markerClusterGroup();
|
||||
slideIndex = 1;
|
||||
|
||||
|
||||
|
||||
theMarker = L.Marker.extend({
|
||||
options: {
|
||||
id: "-1",
|
||||
},
|
||||
});
|
||||
|
||||
function showPosition(position) {
|
||||
console.log(position.coords);
|
||||
|
||||
mymap.setView(
|
||||
new L.LatLng(position.coords.latitude, position.coords.longitude),
|
||||
10
|
||||
);
|
||||
// mymap.setView(new L.LatLng(10.737, -73.923), 8);
|
||||
}
|
||||
|
||||
function onClick(e) {
|
||||
slideIndex = 1;
|
||||
document.getElementById("inspector").innerHTML =
|
||||
'<br><br><center><div class="lds-ripple"><div></div><div></div></div></center>';
|
||||
res = JSON.parse(httpGet("/api/getElevatorById?id=" + this.options.id));
|
||||
if (res.state == "Ok") {
|
||||
visitStates = [
|
||||
"Test elevator",
|
||||
"Public",
|
||||
"On private property",
|
||||
"Public but locked",
|
||||
];
|
||||
typeStates = [
|
||||
"Hydraulic",
|
||||
"Wiredriven, motor in shaft",
|
||||
"Wiredriven, motor in motorroom",
|
||||
];
|
||||
|
||||
// Prepare the template
|
||||
inspector = httpGet("/templates/inspectorContent.html");
|
||||
inspector = inspector.replace("#MODELL", res.results[0].modell);
|
||||
inspector = inspector.replace("#MANUF", res.results[0].manufacturer);
|
||||
inspector = inspector.replace("#DESC", res.results[0].info);
|
||||
inspector = inspector.replace(
|
||||
"#TYPE",
|
||||
typeStates[res.results[0].technology]
|
||||
);
|
||||
inspector = inspector.replace("#MAXPASS", res.results[0].maxPassangers);
|
||||
inspector = inspector.replace("#MASSWEIGH", res.results[0].maxWeight);
|
||||
inspector = inspector.replace(
|
||||
"#VISIT",
|
||||
visitStates[res.results[0].visitabilty]
|
||||
);
|
||||
try {
|
||||
var username = JSON.parse(
|
||||
httpGet("/api/resolveNameById?id=" + res.results[0].creator)
|
||||
).results[0].username;
|
||||
} catch {
|
||||
username = "Unknown";
|
||||
}
|
||||
|
||||
inspector = inspector.replace("#CREATOR", username);
|
||||
document.getElementById("inspector").innerHTML = inspector;
|
||||
|
||||
// Make gallery
|
||||
document.getElementById("imageGallery").innerHTML =
|
||||
"<div class='slideshow-container'>";
|
||||
imgs = JSON.parse(res.results[0].images);
|
||||
amountOfImages = imgs.images.length;
|
||||
console.log(imgs);
|
||||
var iH = 0;
|
||||
|
||||
while (amountOfImages > iH) {
|
||||
newBox = "<center><div class='mySlides fade'><div class='numbertext'>";
|
||||
newBox += iH + 1;
|
||||
newBox += "/";
|
||||
newBox += amountOfImages;
|
||||
newBox += "</div><img src='";
|
||||
newBox += imgs.images[iH].path;
|
||||
newBox +=
|
||||
"' alt='" +
|
||||
imgs.images[iH].alt +
|
||||
"' class=\"elevatorPhoto\"><div class='text'> </div></div></center>";
|
||||
document.getElementById("imageGallery").innerHTML += newBox;
|
||||
iH++;
|
||||
}
|
||||
document.getElementById("imageGallery").innerHTML +=
|
||||
"<br><a class='prev' onclick='plusSlides(-1)''>❮</a><a class='next' onclick='plusSlides(1)'>❯</a></div><br><div style='text-align:center'></div><br><br><br>";
|
||||
showSlides(1);
|
||||
} else {
|
||||
document.getElementById("inspector").innerHTML =
|
||||
' \
|
||||
<center> \
|
||||
<h1><i style="color: red;" class="fas fa-exclamation-triangle"></i></h1> \
|
||||
<h1>Oh no!</h1> \
|
||||
The website failed to fetch the information about this elevator. It responded with the error code: \
|
||||
<br><code> \
|
||||
' +
|
||||
res.message +
|
||||
"</code><center>";
|
||||
}
|
||||
|
||||
console.log(res);
|
||||
}
|
||||
|
||||
function httpGet(theUrl) {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open("GET", theUrl, false); // false for synchronous request
|
||||
xmlHttp.send(null);
|
||||
return xmlHttp.responseText;
|
||||
}
|
||||
|
||||
function home() {
|
||||
if (navigator.geolocation) {
|
||||
setTimeout(function () {
|
||||
navigator.geolocation.getCurrentPosition(showPosition);
|
||||
}, 200);
|
||||
} else {
|
||||
console.warn("Geolocation of user could not be fetched");
|
||||
}
|
||||
}
|
||||
|
||||
home();
|
||||
|
||||
function addPin(item, index) {
|
||||
var marker = new theMarker([item.lat, item.lng], {
|
||||
id: item.id,
|
||||
}).on("click", onClick);
|
||||
// var marker = new L.Marker()
|
||||
//marker.addTo(mymap).on('click', onClick);
|
||||
markers.on("clusterclick", function (a) {
|
||||
//alert('cluster ' + a.layer.getAllChildMarkers().length);
|
||||
});
|
||||
markers.addLayer(marker);
|
||||
}
|
||||
|
||||
// Start getting the elevators
|
||||
response = httpGet(
|
||||
"/api/getElevatorLocation?lan=" +
|
||||
mymap.getCenter.lng +
|
||||
"&lat=" +
|
||||
mymap.getCenter.lat +
|
||||
"&radius=" +
|
||||
mymap.getZoom()
|
||||
);
|
||||
response = JSON.parse(response);
|
||||
|
||||
if (response.state == "Ok") {
|
||||
response.results.forEach(addPin);
|
||||
mymap.addLayer(markers);
|
||||
} else {
|
||||
// DONT FORGET TO SHOW POPUP OR SOMETHING
|
||||
console.log("Request failed with " + response.message);
|
||||
console.log(response);
|
||||
alert("Loading of the map pins failed");
|
||||
}
|
||||
|
||||
// Next/previous controls
|
||||
function plusSlides(n) {
|
||||
showSlides((slideIndex += n));
|
||||
}
|
||||
|
||||
// Thumbnail image controls
|
||||
function currentSlide(n) {
|
||||
showSlides((slideIndex = n));
|
||||
}
|
||||
|
||||
function showSlides(n) {
|
||||
var i;
|
||||
var slides = document.getElementsByClassName("mySlides");
|
||||
var dots = document.getElementsByClassName("dot");
|
||||
if (n > slides.length) {
|
||||
slideIndex = 1;
|
||||
}
|
||||
if (n < 1) {
|
||||
slideIndex = slides.length;
|
||||
}
|
||||
for (i = 0; i < slides.length; i++) {
|
||||
slides[i].style.display = "none";
|
||||
}
|
||||
for (i = 0; i < dots.length; i++) {
|
||||
dots[i].className = dots[i].className.replace(" active", "");
|
||||
}
|
||||
slides[slideIndex - 1].style.display = "block";
|
||||
dots[slideIndex - 1].className += " active";
|
||||
}
|
||||
60
static/leafletCluster/dist/MarkerCluster.Default.css
vendored
Normal file
60
static/leafletCluster/dist/MarkerCluster.Default.css
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
.marker-cluster-small {
|
||||
background-color: rgba(181, 226, 140, 0.6);
|
||||
}
|
||||
.marker-cluster-small div {
|
||||
background-color: rgba(110, 204, 57, 0.6);
|
||||
}
|
||||
|
||||
.marker-cluster-medium {
|
||||
background-color: rgba(241, 211, 87, 0.6);
|
||||
}
|
||||
.marker-cluster-medium div {
|
||||
background-color: rgba(240, 194, 12, 0.6);
|
||||
}
|
||||
|
||||
.marker-cluster-large {
|
||||
background-color: rgba(253, 156, 115, 0.6);
|
||||
}
|
||||
.marker-cluster-large div {
|
||||
background-color: rgba(241, 128, 23, 0.6);
|
||||
}
|
||||
|
||||
/* IE 6-8 fallback colors */
|
||||
.leaflet-oldie .marker-cluster-small {
|
||||
background-color: rgb(181, 226, 140);
|
||||
}
|
||||
.leaflet-oldie .marker-cluster-small div {
|
||||
background-color: rgb(110, 204, 57);
|
||||
}
|
||||
|
||||
.leaflet-oldie .marker-cluster-medium {
|
||||
background-color: rgb(241, 211, 87);
|
||||
}
|
||||
.leaflet-oldie .marker-cluster-medium div {
|
||||
background-color: rgb(240, 194, 12);
|
||||
}
|
||||
|
||||
.leaflet-oldie .marker-cluster-large {
|
||||
background-color: rgb(253, 156, 115);
|
||||
}
|
||||
.leaflet-oldie .marker-cluster-large div {
|
||||
background-color: rgb(241, 128, 23);
|
||||
}
|
||||
|
||||
.marker-cluster {
|
||||
background-clip: padding-box;
|
||||
border-radius: 20px;
|
||||
}
|
||||
.marker-cluster div {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-left: 5px;
|
||||
margin-top: 5px;
|
||||
|
||||
text-align: center;
|
||||
border-radius: 15px;
|
||||
font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
}
|
||||
.marker-cluster span {
|
||||
line-height: 30px;
|
||||
}
|
||||
14
static/leafletCluster/dist/MarkerCluster.css
vendored
Normal file
14
static/leafletCluster/dist/MarkerCluster.css
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
.leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow {
|
||||
-webkit-transition: -webkit-transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
-moz-transition: -moz-transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
-o-transition: -o-transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
transition: transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
}
|
||||
|
||||
.leaflet-cluster-spider-leg {
|
||||
/* stroke-dashoffset (duration and function) should match with leaflet-marker-icon transform in order to track it exactly */
|
||||
-webkit-transition: -webkit-stroke-dashoffset 0.3s ease-out, -webkit-stroke-opacity 0.3s ease-in;
|
||||
-moz-transition: -moz-stroke-dashoffset 0.3s ease-out, -moz-stroke-opacity 0.3s ease-in;
|
||||
-o-transition: -o-stroke-dashoffset 0.3s ease-out, -o-stroke-opacity 0.3s ease-in;
|
||||
transition: stroke-dashoffset 0.3s ease-out, stroke-opacity 0.3s ease-in;
|
||||
}
|
||||
5
static/leafletCluster/dist/WhereAreTheJavascriptFiles.txt
vendored
Normal file
5
static/leafletCluster/dist/WhereAreTheJavascriptFiles.txt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
We don't ship the .js files in the git master branch.
|
||||
They are only present in version tags and in npm.
|
||||
|
||||
See how to get the JS files here: https://github.com/Leaflet/Leaflet.markercluster#using-the-plugin
|
||||
Or how to build them: https://github.com/Leaflet/Leaflet.markercluster#building-testing-and-linting-scripts
|
||||
2677
static/leafletCluster/dist/leaflet.markercluster-src.js
vendored
Normal file
2677
static/leafletCluster/dist/leaflet.markercluster-src.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7
static/leafletCluster/dist/leaflet.markercluster.js
vendored
Normal file
7
static/leafletCluster/dist/leaflet.markercluster.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -12,5 +12,7 @@
|
||||
|
||||
<b>Type:</b> #TYPE <br>
|
||||
<b>Max. Passerngers:</b> #MAXPASS / #MASSWEIGH (kg) <br>
|
||||
<b>Visitable:</b> #VISIT
|
||||
<b>Visitable:</b> #VISIT <br>
|
||||
|
||||
<i>Created by: #CREATOR</i>
|
||||
</center>
|
||||
@@ -158,221 +158,11 @@
|
||||
<aside>
|
||||
<i style="color: black; cursor: pointer" class="fas fa-map-marker-alt" onclick="home()"></i>
|
||||
</aside>
|
||||
<script type="text/javascript">
|
||||
|
||||
function noRestore() {
|
||||
off();
|
||||
Cookies.remove("tempStore")
|
||||
}
|
||||
|
||||
function restoreFunc() {
|
||||
try {
|
||||
dataBlock = JSON.parse(dataBlock)
|
||||
document.getElementById("lat").value = dataBlock["lat"]
|
||||
document.getElementById("lng").value = dataBlock["lng"]
|
||||
document.getElementById("type").value = dataBlock["type"]
|
||||
document.getElementById("visit").value = dataBlock["visit"]
|
||||
document.getElementById("pepl").value = dataBlock["pepl"]
|
||||
document.getElementById("weig").value = dataBlock["weig"]
|
||||
document.getElementById("manuf").value = dataBlock["manuf"]
|
||||
document.getElementById("model").value = dataBlock["model"]
|
||||
document.getElementById("flor").value = dataBlock["flor"]
|
||||
document.getElementById("description").value = dataBlock["description"]
|
||||
} catch (ex) {
|
||||
dataBlock = {}
|
||||
}
|
||||
off()
|
||||
}
|
||||
|
||||
dataBlock = Cookies.get("tempStore");
|
||||
if (dataBlock == undefined) {
|
||||
dataBlock = {};
|
||||
} else {
|
||||
on()
|
||||
}
|
||||
|
||||
var currentPage = 0;
|
||||
function saveValues() {
|
||||
dataBlock["lat"] = document.getElementById("lat").value
|
||||
dataBlock["lng"] = document.getElementById("lng").value
|
||||
dataBlock["type"] = document.getElementById("type").value
|
||||
dataBlock["visit"] = document.getElementById("visit").value
|
||||
dataBlock["pepl"] = document.getElementById("pepl").value
|
||||
dataBlock["weig"] = document.getElementById("weig").value
|
||||
dataBlock["manuf"] = document.getElementById("manuf").value
|
||||
dataBlock["model"] = document.getElementById("model").value
|
||||
dataBlock["flor"] = document.getElementById("flor").value
|
||||
dataBlock["description"] = document.getElementById("description").value
|
||||
Cookies.set('tempStore', JSON.stringify(dataBlock))
|
||||
}
|
||||
|
||||
function submit() {
|
||||
currentPage = 6;
|
||||
updateDialog()
|
||||
saveValues()
|
||||
const options = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({})
|
||||
};
|
||||
|
||||
fetch('/api/saveNewElevatorMeta', options)
|
||||
.then(response => response.json())
|
||||
.then(response => {
|
||||
console.warn("!!!!!!!!!!!!", response)
|
||||
document.getElementById("imageUploadInfo").style.display = 'block';
|
||||
var filesToSend = $('#myFile').prop('files').length;
|
||||
var i = 0;
|
||||
while (i < filesToSend) {
|
||||
document.getElementById("imageUploadInfo").innerHTML = "Uploading image " + String(i) + "/" + String(filesToSend)
|
||||
console.log("Files left to send: ", filesToSend - i)
|
||||
var file_data = $('#myFile').prop('files')[i];
|
||||
var form_data = new FormData();
|
||||
form_data.append('file', file_data);
|
||||
|
||||
console.log(file_data)
|
||||
if (String(file_data.type).includes("image/")) {
|
||||
$.ajax({
|
||||
url: '/api/uploadImage?id=' + response.id,
|
||||
dataType: 'json',
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
data: form_data,
|
||||
type: 'post',
|
||||
success: function (data) {
|
||||
alert(data);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log("Skipping nonimage file")
|
||||
}
|
||||
i++;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
function updateDialog() {
|
||||
if (currentPage == 0) {
|
||||
document.getElementById("step1").style.display = 'block';
|
||||
document.getElementById("step2").style.display = 'none';
|
||||
document.getElementById("step3").style.display = 'none';
|
||||
document.getElementById("step4").style.display = 'none';
|
||||
}
|
||||
if (currentPage == 1) {
|
||||
document.getElementById("step1").style.display = 'none';
|
||||
document.getElementById("step2").style.display = 'block';
|
||||
document.getElementById("step3").style.display = 'none';
|
||||
document.getElementById("step4").style.display = 'none';
|
||||
}
|
||||
if (currentPage == 2) {
|
||||
document.getElementById("step1").style.display = 'none';
|
||||
document.getElementById("step2").style.display = 'none';
|
||||
document.getElementById("step3").style.display = 'block';
|
||||
document.getElementById("step4").style.display = 'none';
|
||||
}
|
||||
if (currentPage == 3) {
|
||||
document.getElementById("step1").style.display = 'none';
|
||||
document.getElementById("step2").style.display = 'none';
|
||||
document.getElementById("step3").style.display = 'none';
|
||||
document.getElementById("step4").style.display = 'block';
|
||||
document.getElementById("step5").style.display = 'none';
|
||||
document.getElementById("missingAlert").style.display = 'none';
|
||||
}
|
||||
if (currentPage == 4) {
|
||||
document.getElementById("step1").style.display = 'none';
|
||||
document.getElementById("step2").style.display = 'none';
|
||||
document.getElementById("step3").style.display = 'none';
|
||||
document.getElementById("step4").style.display = 'none';
|
||||
|
||||
containsEmpt = false;
|
||||
for (const [key, value] of Object.entries(dataBlock)) {
|
||||
if (value == "" || value == undefined) {
|
||||
console.log("hi")
|
||||
console.log(key, value)
|
||||
containsEmpt = true;
|
||||
document.getElementById("missingAlert").style.display = 'block';
|
||||
}
|
||||
}
|
||||
if (containsEmpt == false) {
|
||||
document.getElementById("missingAlert").style.display = 'none';
|
||||
currentPage = 5;
|
||||
}
|
||||
console.log(containsEmpt);
|
||||
}
|
||||
if (currentPage == 5) {
|
||||
document.getElementById("step1").style.display = 'none';
|
||||
document.getElementById("step2").style.display = 'none';
|
||||
document.getElementById("step3").style.display = 'none';
|
||||
document.getElementById("step4").style.display = 'none';
|
||||
document.getElementById("step5").style.display = 'block';
|
||||
document.getElementById("missingAlert").style.display = 'none';
|
||||
}
|
||||
if (currentPage == 6) {
|
||||
document.getElementById("step1").style.display = 'none';
|
||||
document.getElementById("step2").style.display = 'none';
|
||||
document.getElementById("step3").style.display = 'none';
|
||||
document.getElementById("step4").style.display = 'none';
|
||||
document.getElementById("step5").style.display = 'none';
|
||||
document.getElementById("step6").style.display = 'block';
|
||||
document.getElementById("missingAlert").style.display = 'none';
|
||||
}
|
||||
saveValues();
|
||||
console.log(dataBlock)
|
||||
|
||||
}
|
||||
function nextDialogePage() {
|
||||
currentPage++;
|
||||
updateDialog();
|
||||
}
|
||||
function prevPage() {
|
||||
currentPage--;
|
||||
updateDialog();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<!-- End Document
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<script src="./js/createElevator.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var latElm = document.getElementById("lat");
|
||||
var lngElm = document.getElementById("lng");
|
||||
|
||||
latElm.addEventListener('input', function (evt) {
|
||||
markers.clearLayers();
|
||||
console.log(evt.target.value)
|
||||
const lat = evt.target.value;
|
||||
const lng = lngElm.value;
|
||||
var marker = new theMarker([lat, lng])
|
||||
//marker.addTo(mymap)
|
||||
markers.addLayer(marker);
|
||||
markers.addTo(mymap);
|
||||
});
|
||||
|
||||
lngElm.addEventListener('input', function (evt) {
|
||||
markers.clearLayers();
|
||||
console.log(evt.target.value)
|
||||
const lat = latElm.value;
|
||||
const lng = evt.target.value;
|
||||
var marker = new theMarker([lat, lng])
|
||||
//marker.addTo(mymap)
|
||||
markers.addLayer(marker);
|
||||
markers.addTo(mymap);
|
||||
});
|
||||
|
||||
var amountOfImages = 0;
|
||||
var markers = L.markerClusterGroup();
|
||||
slideIndex = 1;
|
||||
|
||||
var mymap = L.map("map").setView([51.505, -0.09], 50);
|
||||
|
||||
L.tileLayer(
|
||||
"https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=<%= it.mapboxAccessToken %>",
|
||||
{
|
||||
@@ -385,51 +175,6 @@
|
||||
accessToken: "<%= it.mapboxAccessToken %>",
|
||||
}
|
||||
).addTo(mymap);
|
||||
|
||||
theMarker = L.Marker.extend({
|
||||
options: {
|
||||
id: "-1",
|
||||
},
|
||||
});
|
||||
|
||||
function showPosition(position) {
|
||||
console.log(position.coords);
|
||||
|
||||
mymap.setView(
|
||||
new L.LatLng(position.coords.latitude, position.coords.longitude),
|
||||
10
|
||||
);
|
||||
// mymap.setView(new L.LatLng(10.737, -73.923), 8);
|
||||
}
|
||||
|
||||
home()
|
||||
|
||||
mymap.on('click', function (e) {
|
||||
markers.clearLayers();
|
||||
var coord = e.latlng;
|
||||
var lat = coord.lat;
|
||||
var lng = coord.lng;
|
||||
var marker = new theMarker([lat, lng])
|
||||
//marker.addTo(mymap)
|
||||
markers.addLayer(marker);
|
||||
markers.addTo(mymap);
|
||||
document.getElementById("lat").value = lat
|
||||
document.getElementById("lng").value = lng
|
||||
console.log("You clicked the map at latitude: " + lat + " and longitude: " + lng);
|
||||
});
|
||||
|
||||
function addPin(item, index) {
|
||||
var marker = new theMarker([item.lat, item.lng], {
|
||||
id: item.id,
|
||||
}).on("click", onClick);
|
||||
// var marker = new L.Marker()
|
||||
//marker.addTo(mymap).on('click', onClick);
|
||||
markers.on("clusterclick", function (a) {
|
||||
//alert('cluster ' + a.layer.getAllChildMarkers().length);
|
||||
});
|
||||
markers.addLayer(marker);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
<h5>
|
||||
Check it out now <br>
|
||||
<a href= "/map" ><button class="button-primary">Visit the map <i class="fas fa-arrow-right"></i> </button></a>
|
||||
<a href= "/createElevator" ><button class="button-primary">Create a new elevator <i class="fas fa-arrow-right"></i> </button></a>
|
||||
</h5>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
Don’t have an account?
|
||||
</span>
|
||||
|
||||
<a class="txt2" href="#">
|
||||
<a class="txt2" href="/register">
|
||||
Sign Up
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -72,207 +72,28 @@
|
||||
class="fas fa-map-marker-alt"
|
||||
onclick="home()"
|
||||
></i>
|
||||
<i style="color: black; cursor: pointer" class="fas fas fa-plus" onclick="createNewElev()"></i>
|
||||
</aside>
|
||||
|
||||
<!-- End Document
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<script type="text/javascript">
|
||||
var amountOfImages = 0;
|
||||
var markers = L.markerClusterGroup();
|
||||
slideIndex = 1;
|
||||
<script>
|
||||
var mymap = L.map("map").setView([51.505, -0.09], 50);
|
||||
|
||||
var mymap = L.map("map").setView([51.505, -0.09], 50);
|
||||
|
||||
L.tileLayer(
|
||||
"https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=<%= it.mapboxAccessToken %>",
|
||||
{
|
||||
attribution:
|
||||
'Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
|
||||
maxZoom: 18,
|
||||
id: "mapbox/streets-v11",
|
||||
tileSize: 512,
|
||||
zoomOffset: -1,
|
||||
accessToken: "<%= it.mapboxAccessToken %>",
|
||||
}
|
||||
).addTo(mymap);
|
||||
|
||||
theMarker = L.Marker.extend({
|
||||
options: {
|
||||
id: "-1",
|
||||
},
|
||||
});
|
||||
|
||||
function showPosition(position) {
|
||||
console.log(position.coords);
|
||||
|
||||
mymap.setView(
|
||||
new L.LatLng(position.coords.latitude, position.coords.longitude),
|
||||
10
|
||||
);
|
||||
// mymap.setView(new L.LatLng(10.737, -73.923), 8);
|
||||
}
|
||||
|
||||
function onClick(e) {
|
||||
slideIndex = 1;
|
||||
document.getElementById("inspector").innerHTML =
|
||||
'<br><br><center><div class="lds-ripple"><div></div><div></div></div></center>';
|
||||
res = JSON.parse(httpGet("/api/getElevatorById?id=" + this.options.id));
|
||||
if (res.state == "Ok") {
|
||||
visitStates = [
|
||||
"Test elevator",
|
||||
"Public",
|
||||
"On private property",
|
||||
"Public but locked",
|
||||
];
|
||||
typeStates = [
|
||||
"Hydraulic",
|
||||
"Wiredriven, motor in shaft",
|
||||
"Wiredriven, motor in motorroom",
|
||||
];
|
||||
|
||||
// Prepare the template
|
||||
inspector = httpGet("/templates/inspectorContent.html");
|
||||
inspector = inspector.replace("#MODELL", res.results[0].modell);
|
||||
inspector = inspector.replace("#MANUF", res.results[0].manufacturer);
|
||||
inspector = inspector.replace("#DESC", res.results[0].info);
|
||||
inspector = inspector.replace(
|
||||
"#TYPE",
|
||||
typeStates[res.results[0].technology]
|
||||
);
|
||||
inspector = inspector.replace(
|
||||
"#MAXPASS",
|
||||
res.results[0].maxPassangers
|
||||
);
|
||||
inspector = inspector.replace("#MASSWEIGH", res.results[0].maxWeight);
|
||||
inspector = inspector.replace(
|
||||
"#VISIT",
|
||||
visitStates[res.results[0].visitabilty]
|
||||
);
|
||||
document.getElementById("inspector").innerHTML = inspector;
|
||||
|
||||
// Make gallery
|
||||
document.getElementById("imageGallery").innerHTML =
|
||||
"<div class='slideshow-container'>";
|
||||
imgs = JSON.parse(res.results[0].images);
|
||||
amountOfImages = imgs.images.length;
|
||||
console.log(imgs);
|
||||
var iH = 0;
|
||||
|
||||
while (amountOfImages > iH) {
|
||||
newBox =
|
||||
"<center><div class='mySlides fade'><div class='numbertext'>";
|
||||
newBox += iH + 1;
|
||||
newBox += "/";
|
||||
newBox += amountOfImages;
|
||||
newBox += "</div><img src='";
|
||||
newBox += imgs.images[iH].path;
|
||||
newBox +=
|
||||
"' alt='" +
|
||||
imgs.images[iH].alt +
|
||||
"' class=\"elevatorPhoto\"><div class='text'> </div></div></center>";
|
||||
document.getElementById("imageGallery").innerHTML += newBox;
|
||||
iH++;
|
||||
}
|
||||
document.getElementById("imageGallery").innerHTML +=
|
||||
"<br><a class='prev' onclick='plusSlides(-1)''>❮</a><a class='next' onclick='plusSlides(1)'>❯</a></div><br><div style='text-align:center'></div><br><br><br>";
|
||||
showSlides(1);
|
||||
} else {
|
||||
document.getElementById("inspector").innerHTML =
|
||||
' \
|
||||
<center> \
|
||||
<h1><i style="color: red;" class="fas fa-exclamation-triangle"></i></h1> \
|
||||
<h1>Oh no!</h1> \
|
||||
The website failed to fetch the information about this elevator. It responded with the error code: \
|
||||
<br><code> \
|
||||
' +
|
||||
res.message +
|
||||
"</code><center>";
|
||||
}
|
||||
|
||||
console.log(res);
|
||||
}
|
||||
|
||||
function httpGet(theUrl) {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open("GET", theUrl, false); // false for synchronous request
|
||||
xmlHttp.send(null);
|
||||
return xmlHttp.responseText;
|
||||
}
|
||||
|
||||
function home() {
|
||||
if (navigator.geolocation) {
|
||||
setTimeout(function () {
|
||||
navigator.geolocation.getCurrentPosition(showPosition);
|
||||
}, 200);
|
||||
} else {
|
||||
console.warn("Geolocation of user could not be fetched");
|
||||
}
|
||||
}
|
||||
|
||||
home();
|
||||
|
||||
function addPin(item, index) {
|
||||
var marker = new theMarker([item.lat, item.lng], {
|
||||
id: item.id,
|
||||
}).on("click", onClick);
|
||||
// var marker = new L.Marker()
|
||||
//marker.addTo(mymap).on('click', onClick);
|
||||
markers.on("clusterclick", function (a) {
|
||||
//alert('cluster ' + a.layer.getAllChildMarkers().length);
|
||||
});
|
||||
markers.addLayer(marker);
|
||||
}
|
||||
|
||||
// Start getting the elevators
|
||||
response = httpGet(
|
||||
"/api/getElevatorLocation?lan=" +
|
||||
mymap.getCenter.lng +
|
||||
"&lat=" +
|
||||
mymap.getCenter.lat +
|
||||
"&radius=" +
|
||||
mymap.getZoom()
|
||||
);
|
||||
response = JSON.parse(response);
|
||||
|
||||
if (response.state == "Ok") {
|
||||
response.results.forEach(addPin);
|
||||
mymap.addLayer(markers);
|
||||
} else {
|
||||
// DONT FORGET TO SHOW POPUP OR SOMETHING
|
||||
console.log("Request failed with " + response.message);
|
||||
console.log(response);
|
||||
alert("Loading of the map pins failed");
|
||||
}
|
||||
|
||||
// Next/previous controls
|
||||
function plusSlides(n) {
|
||||
showSlides((slideIndex += n));
|
||||
}
|
||||
|
||||
// Thumbnail image controls
|
||||
function currentSlide(n) {
|
||||
showSlides((slideIndex = n));
|
||||
}
|
||||
|
||||
function showSlides(n) {
|
||||
var i;
|
||||
var slides = document.getElementsByClassName("mySlides");
|
||||
var dots = document.getElementsByClassName("dot");
|
||||
if (n > slides.length) {
|
||||
slideIndex = 1;
|
||||
}
|
||||
if (n < 1) {
|
||||
slideIndex = slides.length;
|
||||
}
|
||||
for (i = 0; i < slides.length; i++) {
|
||||
slides[i].style.display = "none";
|
||||
}
|
||||
for (i = 0; i < dots.length; i++) {
|
||||
dots[i].className = dots[i].className.replace(" active", "");
|
||||
}
|
||||
slides[slideIndex - 1].style.display = "block";
|
||||
dots[slideIndex - 1].className += " active";
|
||||
}
|
||||
</script>
|
||||
L.tileLayer(
|
||||
"https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=<%= it.mapboxAccessToken %>",
|
||||
{
|
||||
attribution:
|
||||
'Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
|
||||
maxZoom: 100,
|
||||
minZoom: 2,
|
||||
id: "mapbox/streets-v11",
|
||||
tileSize: 512,
|
||||
zoomOffset: -1,
|
||||
accessToken: "<%= it.mapboxAccessToken %>",
|
||||
}
|
||||
).addTo(mymap);
|
||||
</script>
|
||||
<script src="./js/map.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user