Merge branch 'master' of cloud.ol:oliver/simcompanies-dashboard
This commit is contained in:
161
backend/index.js
161
backend/index.js
@@ -2,30 +2,78 @@ const express = require('express')
|
||||
const app = express();
|
||||
const status = require('http-status');
|
||||
const fetch = require('node-fetch');
|
||||
const cors = require('cors');
|
||||
const bodyParser = require('body-parser');
|
||||
var mysql = require('mysql');
|
||||
var passport = require('passport');
|
||||
var LocalStrategy = require('passport-local').Strategy;
|
||||
var session = require('express-session');
|
||||
var MySQLStore = require('express-mysql-session')(session);
|
||||
const bcrypt = require('bcrypt');
|
||||
const path = require('path');
|
||||
var connection = mysql.createConnection({
|
||||
var connection = mysql.createPool({
|
||||
connectionLimit: 25,
|
||||
host: 'localhost',
|
||||
user: 'simcompanies',
|
||||
password: '',
|
||||
database: 'simcompanies'
|
||||
});
|
||||
var sessionStore = new MySQLStore({
|
||||
clearExpired: false,
|
||||
schema: {
|
||||
tableName: 'sessions',
|
||||
columnNames: {
|
||||
session_id: 'session_id',
|
||||
expires: 'expires',
|
||||
data: 'data'
|
||||
}
|
||||
}
|
||||
}, connection);
|
||||
|
||||
const mockDataDay = require('./mockdata-test/day.json');
|
||||
var resourceList;
|
||||
const saltRounds = 13;
|
||||
|
||||
var serverStartupComplete = false;
|
||||
|
||||
const DEBUG = process.env.NODE_ENV === "debug" ? true : false;
|
||||
|
||||
function twoDigits(d) {
|
||||
if (0 <= d && d < 10) return "0" + d.toString();
|
||||
if (-10 < d && d < 0) return "-0" + (-1 * d).toString();
|
||||
return d.toString();
|
||||
}
|
||||
Date.prototype.toMysqlFormat = function () {
|
||||
return this.getFullYear() + "-" + twoDigits(1 + this.getMonth()) + "-" + twoDigits(this.getDate()) + " " + twoDigits(this.getHours()) + ":" + twoDigits(this.getMinutes()) + ":" + twoDigits(this.getSeconds());
|
||||
};
|
||||
|
||||
|
||||
async function loadData() {
|
||||
var rL = await fetch("https://www.simcompanies.com/api/v3/en/encyclopedia/resources/");
|
||||
resourceList = await rL.json();
|
||||
serverStartupComplete = true;
|
||||
console.log("SERVER STARTUP COMPLETED");
|
||||
}
|
||||
loadData();
|
||||
|
||||
app.use(cors({ credentials: true }));
|
||||
app.use(bodyParser.urlencoded({ extended: true }));
|
||||
app.use(bodyParser.json());
|
||||
app.use(session({
|
||||
secret: "simCoRoxUFocker",
|
||||
saveUninitialized: true,
|
||||
resave: true,
|
||||
store: DEBUG ? undefined : sessionStore,
|
||||
"cookie": {
|
||||
"maxAge": 86400 * 1000
|
||||
}
|
||||
}));
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
|
||||
app.get("*", function (req, res, next) {
|
||||
if (!serverStartupComplete)
|
||||
return res.send("Server is starting...");
|
||||
return res.send("Server is starting... Please try again soon.");
|
||||
else return next();
|
||||
});
|
||||
|
||||
@@ -39,29 +87,116 @@ app.all("/*", function (req, res, next) {
|
||||
if (!/^\/API\/.*/.test(req.url)) {
|
||||
return res.sendFile(path.join(__dirname, 'frontend', 'index.html'));
|
||||
} else return next();
|
||||
})
|
||||
});
|
||||
|
||||
passport.use('local-login', new LocalStrategy({
|
||||
usernameField: "email",
|
||||
passwordField: "password",
|
||||
passReqToCallback: true
|
||||
}, function (req, email, password, done) {
|
||||
if (DEBUG) {
|
||||
if (email === "test" && password === "test") {
|
||||
return done(null, {
|
||||
deactivated: false,
|
||||
email: "test1",
|
||||
id: 0,
|
||||
created: new Date(),
|
||||
password: "test"
|
||||
});
|
||||
} else return done(null, false);
|
||||
}
|
||||
email = mysql.escape(email);
|
||||
connection.query(`SELECT * from user WHERE email = ${email} AND deactivated = 0`, function (err, rows) {
|
||||
if (err) {
|
||||
return res.status(static.INTERNAL_SERVER_ERROR).send("error querying the database - Please contact sys admin");
|
||||
}
|
||||
if (!rows.length) {
|
||||
return done(null, false);
|
||||
}
|
||||
if (!bcrypt.compareSync(password, rows[0].password)) {
|
||||
return done(null, false);
|
||||
}
|
||||
return done(null, rows[0]);
|
||||
})
|
||||
}
|
||||
));
|
||||
|
||||
passport.serializeUser(function (user, done) {
|
||||
done(null, user.id);
|
||||
});
|
||||
|
||||
passport.deserializeUser(function (id, done) {
|
||||
if (!DEBUG)
|
||||
connection.query(`select * from user where id = ${id} AND deactivated = 0`, function (err, rows) {
|
||||
done(err, rows[0]);
|
||||
})
|
||||
else {
|
||||
if (id === 0) {
|
||||
done(null, {
|
||||
deactivated: false,
|
||||
email: "test1",
|
||||
id: 0,
|
||||
created: new Date(),
|
||||
password: "test"
|
||||
});
|
||||
} else return done(null, []);
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/API/user/login", passport.authenticate('local-login'), function (req, res) {
|
||||
res.status(status.OK).send("login success");
|
||||
});
|
||||
|
||||
app.put("/API/user/create", function (req, res) {
|
||||
let { email, password } = req.body;
|
||||
if (email && password) {
|
||||
email = mysql.escape(email);
|
||||
password = mysql.escape(bcrypt.hashSync(password, saltRounds));
|
||||
if (DEBUG) return res.status(status.OK).send();
|
||||
connection.query(`INSERT INTO user (deactivated, email, password) values (1, ${email}, ${password})`, function (err, rows) {
|
||||
if (err)
|
||||
return res.send(status.INTERNAL_SERVER_ERROR).send("the user seems to exist already - if you think this is an error contact the sys admin");
|
||||
return res.status(status.OK).send("account successfully created");
|
||||
});
|
||||
} else {
|
||||
res.status(status.BAD_REQUEST).send("invalid data supplied");
|
||||
}
|
||||
});
|
||||
|
||||
app.all("*", function (req, res, next) {
|
||||
if (req.isAuthenticated()) {
|
||||
return next();
|
||||
}
|
||||
else {
|
||||
res.status(status.UNAUTHORIZED).send("please log in before using this site");
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/API/testlogin", function (req, res) {
|
||||
res.status(status.OK).send(req.user["email"]);
|
||||
});
|
||||
|
||||
app.get('/API/day', function (req, res) {
|
||||
var date = new Date(req.query.date);
|
||||
const kind = parseInt(req.query.kind);
|
||||
if (date instanceof Date && Number.isInteger(kind)) {
|
||||
if (Number.isInteger(kind)) {
|
||||
//Mock Data:
|
||||
if (kind === -1) return res.send(mockDataDay);
|
||||
if (kind === -1 || DEBUG) return res.send(mockDataDay);
|
||||
|
||||
if (!isNaN(date.getTime()) && kind >= 1 && kind <= 113) {
|
||||
const daybegin = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
|
||||
date.setDate(date.getDate() + 1);
|
||||
const dayend = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
|
||||
const querystring = `SELECT time, price FROM market WHERE kind = ${kind} AND time > "${daybegin}" AND time < "${dayend}"`
|
||||
if (kind >= 1 && kind <= 113) {
|
||||
var dayend = new Date().toMysqlFormat();
|
||||
var daybegin = new Date();
|
||||
daybegin.setDate(daybegin.getDate() - 1);
|
||||
daybegin = daybegin.toISOString().slice(0, 19).replace('T', ' ');
|
||||
const querystring = `SELECT time, price, quality FROM marketv2 WHERE kind = ${kind} AND time > "${daybegin}" AND time < "${dayend}" ORDER BY time, quality`;
|
||||
connection.query(querystring, function (error, results, fields) {
|
||||
if (error) {
|
||||
throw error;
|
||||
res.status(status.INTERNAL_SERVER_ERROR).send("database connection failed");
|
||||
}
|
||||
res.send(results);
|
||||
});
|
||||
}
|
||||
else
|
||||
res.status(status.BAD_REQUEST).send("invalid data provided");
|
||||
res.status(status.BAD_REQUEST).send("invalid data range provided");
|
||||
|
||||
}
|
||||
else
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
573
backend/package-lock.json
generated
573
backend/package-lock.json
generated
@@ -48,6 +48,20 @@
|
||||
"picomatch": "^2.0.4"
|
||||
}
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
|
||||
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
|
||||
},
|
||||
"are-we-there-yet": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
|
||||
"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
|
||||
"requires": {
|
||||
"delegates": "^1.0.0",
|
||||
"readable-stream": "^2.0.6"
|
||||
}
|
||||
},
|
||||
"array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
@@ -58,6 +72,15 @@
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"bcrypt": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-4.0.1.tgz",
|
||||
"integrity": "sha512-hSIZHkUxIDS5zA2o00Kf2O5RfVbQ888n54xQoF/eIaquU4uaLxK8vhhBdktd0B3n2MjkcAWzv4mnhogykBKOUQ==",
|
||||
"requires": {
|
||||
"node-addon-api": "^2.0.0",
|
||||
"node-pre-gyp": "0.14.0"
|
||||
}
|
||||
},
|
||||
"bignumber.js": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
|
||||
@@ -156,6 +179,11 @@
|
||||
"readdirp": "~3.3.0"
|
||||
}
|
||||
},
|
||||
"chownr": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
|
||||
},
|
||||
"ci-info": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
|
||||
@@ -166,6 +194,11 @@
|
||||
"resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
|
||||
"integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM="
|
||||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
@@ -197,6 +230,11 @@
|
||||
"xdg-basedir": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
|
||||
},
|
||||
"content-disposition": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
|
||||
@@ -225,6 +263,15 @@
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"cors": {
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
|
||||
"requires": {
|
||||
"object-assign": "^4",
|
||||
"vary": "^1"
|
||||
}
|
||||
},
|
||||
"create-error-class": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
|
||||
@@ -233,6 +280,58 @@
|
||||
"capture-stack-trace": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"cross-env": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.2.tgz",
|
||||
"integrity": "sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "^7.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"cross-spawn": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz",
|
||||
"integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
|
||||
@@ -261,6 +360,11 @@
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
|
||||
},
|
||||
"delegates": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
@@ -271,6 +375,11 @@
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||
},
|
||||
"detect-libc": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
||||
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
|
||||
},
|
||||
"dot-prop": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
|
||||
@@ -360,6 +469,99 @@
|
||||
"vary": "~1.1.2"
|
||||
}
|
||||
},
|
||||
"express-mysql-session": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/express-mysql-session/-/express-mysql-session-2.1.4.tgz",
|
||||
"integrity": "sha512-Fcq168xVI8jtIJLhVHLJvBCvJlHnFWCcPmtt93UrWH38T2YsB919KrMCCh57/YkECkfff/L5zTQ95K1DxfOixg==",
|
||||
"requires": {
|
||||
"debug": "4.1.1",
|
||||
"express-session": "1.17.0",
|
||||
"mysql": "2.18.1",
|
||||
"underscore": "1.9.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||
},
|
||||
"express-session": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.0.tgz",
|
||||
"integrity": "sha512-t4oX2z7uoSqATbMfsxWMbNjAL0T5zpvcJCk3Z9wnPPN7ibddhnmDZXHfEcoBMG2ojKXZoCyPMc5FbtK+G7SoDg==",
|
||||
"requires": {
|
||||
"cookie": "0.4.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~2.0.0",
|
||||
"on-headers": "~1.0.2",
|
||||
"parseurl": "~1.3.3",
|
||||
"safe-buffer": "5.2.0",
|
||||
"uid-safe": "~2.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
|
||||
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"express-session": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz",
|
||||
"integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==",
|
||||
"requires": {
|
||||
"cookie": "0.4.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~2.0.0",
|
||||
"on-headers": "~1.0.2",
|
||||
"parseurl": "~1.3.3",
|
||||
"safe-buffer": "5.2.0",
|
||||
"uid-safe": "~2.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
|
||||
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
@@ -392,17 +594,91 @@
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
|
||||
},
|
||||
"fs-minipass": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
|
||||
"integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
|
||||
"requires": {
|
||||
"minipass": "^2.6.0"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
|
||||
"integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
|
||||
"optional": true
|
||||
},
|
||||
"gauge": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
|
||||
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
|
||||
"requires": {
|
||||
"aproba": "^1.0.3",
|
||||
"console-control-strings": "^1.0.0",
|
||||
"has-unicode": "^2.0.0",
|
||||
"object-assign": "^4.1.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1",
|
||||
"wide-align": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
"strip-ansi": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
|
||||
@@ -447,6 +723,11 @@
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||
},
|
||||
"has-unicode": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
|
||||
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
|
||||
@@ -477,6 +758,14 @@
|
||||
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
|
||||
"integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk="
|
||||
},
|
||||
"ignore-walk": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
|
||||
"integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
|
||||
"requires": {
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"import-lazy": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
|
||||
@@ -487,6 +776,15 @@
|
||||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
@@ -669,6 +967,45 @@
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
|
||||
"integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"minizlib": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
|
||||
"integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
|
||||
"requires": {
|
||||
"minipass": "^2.9.0"
|
||||
}
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
|
||||
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
@@ -685,16 +1022,74 @@
|
||||
"sqlstring": "2.3.1"
|
||||
}
|
||||
},
|
||||
"needle": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/needle/-/needle-2.4.1.tgz",
|
||||
"integrity": "sha512-x/gi6ijr4B7fwl6WYL9FwlCvRQKGlUNvnceho8wxkwXqN8jvVmmmATTmZPRRG7b/yC1eode26C2HO9jl78Du9g==",
|
||||
"requires": {
|
||||
"debug": "^3.2.6",
|
||||
"iconv-lite": "^0.4.4",
|
||||
"sax": "^1.2.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.2.6",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
||||
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
|
||||
},
|
||||
"node-addon-api": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.0.tgz",
|
||||
"integrity": "sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA=="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
|
||||
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
|
||||
},
|
||||
"node-pre-gyp": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz",
|
||||
"integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==",
|
||||
"requires": {
|
||||
"detect-libc": "^1.0.2",
|
||||
"mkdirp": "^0.5.1",
|
||||
"needle": "^2.2.1",
|
||||
"nopt": "^4.0.1",
|
||||
"npm-packlist": "^1.1.6",
|
||||
"npmlog": "^4.0.2",
|
||||
"rc": "^1.2.7",
|
||||
"rimraf": "^2.6.1",
|
||||
"semver": "^5.3.0",
|
||||
"tar": "^4.4.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"nopt": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
|
||||
"integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
|
||||
"requires": {
|
||||
"abbrev": "1",
|
||||
"osenv": "^0.1.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"nodemon": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.2.tgz",
|
||||
@@ -740,6 +1135,29 @@
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
|
||||
},
|
||||
"npm-bundled": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
|
||||
"integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
|
||||
"requires": {
|
||||
"npm-normalize-package-bin": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"npm-normalize-package-bin": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
|
||||
"integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
|
||||
},
|
||||
"npm-packlist": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
|
||||
"integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
|
||||
"requires": {
|
||||
"ignore-walk": "^3.0.1",
|
||||
"npm-bundled": "^1.0.1",
|
||||
"npm-normalize-package-bin": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"npm-run-path": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
|
||||
@@ -748,6 +1166,27 @@
|
||||
"path-key": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"npmlog": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
|
||||
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
|
||||
"requires": {
|
||||
"are-we-there-yet": "~1.1.2",
|
||||
"console-control-strings": "~1.1.0",
|
||||
"gauge": "~2.7.3",
|
||||
"set-blocking": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||
@@ -756,6 +1195,38 @@
|
||||
"ee-first": "1.1.1"
|
||||
}
|
||||
},
|
||||
"on-headers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
|
||||
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"os-homedir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
||||
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
|
||||
},
|
||||
"os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
|
||||
},
|
||||
"osenv": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
|
||||
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
|
||||
"requires": {
|
||||
"os-homedir": "^1.0.0",
|
||||
"os-tmpdir": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"p-finally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||
@@ -777,6 +1248,33 @@
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
|
||||
},
|
||||
"passport": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz",
|
||||
"integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==",
|
||||
"requires": {
|
||||
"passport-strategy": "1.x.x",
|
||||
"pause": "0.0.1"
|
||||
}
|
||||
},
|
||||
"passport-local": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
|
||||
"integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=",
|
||||
"requires": {
|
||||
"passport-strategy": "1.x.x"
|
||||
}
|
||||
},
|
||||
"passport-strategy": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
|
||||
"integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ="
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"path-is-inside": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
|
||||
@@ -792,6 +1290,11 @@
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
|
||||
},
|
||||
"pause": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
|
||||
"integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
|
||||
},
|
||||
"picomatch": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz",
|
||||
@@ -836,6 +1339,11 @@
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
|
||||
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
|
||||
},
|
||||
"random-bytes": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
|
||||
"integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
|
||||
},
|
||||
"range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
@@ -902,6 +1410,14 @@
|
||||
"rc": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
@@ -912,6 +1428,11 @@
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
@@ -963,6 +1484,11 @@
|
||||
"send": "0.17.1"
|
||||
}
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||
@@ -1039,6 +1565,27 @@
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"tar": {
|
||||
"version": "4.4.13",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
|
||||
"integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
|
||||
"requires": {
|
||||
"chownr": "^1.1.1",
|
||||
"fs-minipass": "^1.2.5",
|
||||
"minipass": "^2.8.6",
|
||||
"minizlib": "^1.2.1",
|
||||
"mkdirp": "^0.5.0",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"term-size": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
|
||||
@@ -1082,6 +1629,14 @@
|
||||
"mime-types": "~2.1.24"
|
||||
}
|
||||
},
|
||||
"uid-safe": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
||||
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
|
||||
"requires": {
|
||||
"random-bytes": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"undefsafe": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
|
||||
@@ -1090,6 +1645,11 @@
|
||||
"debug": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.9.2",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.2.tgz",
|
||||
"integrity": "sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ=="
|
||||
},
|
||||
"unique-string": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
|
||||
@@ -1156,6 +1716,14 @@
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"wide-align": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
|
||||
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
|
||||
"requires": {
|
||||
"string-width": "^1.0.2 || 2"
|
||||
}
|
||||
},
|
||||
"widest-line": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz",
|
||||
@@ -1164,6 +1732,11 @@
|
||||
"string-width": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"write-file-atomic": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
|
||||
|
||||
@@ -5,16 +5,26 @@
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"debug": "nodemon index.js",
|
||||
"debug": "cross-env NODE_ENV=debug nodemon index.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Oliver Boehlk",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"bcrypt": "^4.0.1",
|
||||
"body-parser": "^1.19.0",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.17.1",
|
||||
"express-mysql-session": "^2.1.4",
|
||||
"express-session": "^1.17.1",
|
||||
"http-status": "^1.4.2",
|
||||
"mysql": "^2.18.1",
|
||||
"node-fetch": "^2.6.0",
|
||||
"nodemon": "^2.0.2"
|
||||
"nodemon": "^2.0.2",
|
||||
"passport": "^0.4.1",
|
||||
"passport-local": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^7.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
12
frontend/package-lock.json
generated
12
frontend/package-lock.json
generated
@@ -1292,6 +1292,18 @@
|
||||
"@babel/runtime": "^7.4.4"
|
||||
}
|
||||
},
|
||||
"@material-ui/lab": {
|
||||
"version": "4.0.0-alpha.51",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.51.tgz",
|
||||
"integrity": "sha512-X/qv/sZQGhXhKDn83L94gNahGDQj2Rd6r7/9tPpQbSn2A1LAt1+jlTiWD1HUgDXZEPqTsJMajOjWSEmTL7/q7w==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.4.4",
|
||||
"@material-ui/utils": "^4.9.6",
|
||||
"clsx": "^1.0.4",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-is": "^16.8.0"
|
||||
}
|
||||
},
|
||||
"@material-ui/styles": {
|
||||
"version": "4.9.10",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.9.10.tgz",
|
||||
|
||||
@@ -1,41 +1,42 @@
|
||||
{
|
||||
"name": "simcompanies-dashboard",
|
||||
"version": "0.1.0",
|
||||
"homepage": "https://projects.oliver.boehlk.io/simcompanies/",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.9.8",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.4.0",
|
||||
"@testing-library/user-event": "^7.2.1",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-router-dom": "^5.1.2",
|
||||
"react-scripts": "3.4.0",
|
||||
"typeface-roboto": "0.0.75",
|
||||
"recharts": "^1.8.5"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"proxy": "http://127.0.0.1:3001"
|
||||
"name": "simcompanies-dashboard",
|
||||
"version": "0.1.0",
|
||||
"homepage": "https://projects.oliver.boehlk.io/simcompanies/",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.9.8",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "^4.0.0-alpha.51",
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.4.0",
|
||||
"@testing-library/user-event": "^7.2.1",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-router-dom": "^5.1.2",
|
||||
"react-scripts": "3.4.0",
|
||||
"recharts": "^1.8.5",
|
||||
"typeface-roboto": "0.0.75"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"proxy": "http://127.0.0.1:3001"
|
||||
}
|
||||
@@ -9,3 +9,12 @@
|
||||
margin-left: 10px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.loginBackground {
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
margin: auto;
|
||||
min-height: 100vh;
|
||||
background-image: url(./img/loginBackground.png);
|
||||
}
|
||||
@@ -4,12 +4,53 @@ import {
|
||||
} from "react-router-dom";
|
||||
import Navbar from "./components/navigation";
|
||||
import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles';
|
||||
import {
|
||||
Route, Switch
|
||||
} from "react-router-dom";
|
||||
import Login from './components/login/login';
|
||||
|
||||
import CreateAccount from './components/login/createAccount';
|
||||
import "./App.css";
|
||||
import { Redirect } from "react-router-dom";
|
||||
|
||||
class ProtectedRoute extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { auth: null };
|
||||
}
|
||||
|
||||
async componentWillMount() {
|
||||
const url = "/simcompanies/API/testlogin";
|
||||
const response = await fetch(url);
|
||||
if (response.status == "200") {
|
||||
this.setState({
|
||||
auth: true
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
auth: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { component: Component, ...props } = this.props;
|
||||
return (
|
||||
this.state.auth === null ?
|
||||
"Loading..." :
|
||||
<Route
|
||||
{...props}
|
||||
render={props => (
|
||||
this.state.auth ?
|
||||
<Component {...props} /> :
|
||||
<Redirect to='/login' />
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
class App extends Component {
|
||||
|
||||
render() {
|
||||
const theme = createMuiTheme({
|
||||
palette: {
|
||||
@@ -24,11 +65,16 @@ class App extends Component {
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
//change basename in browserrouter if uri changes
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<BrowserRouter basename="/simcompanies">
|
||||
<Navbar></Navbar>
|
||||
<Switch>
|
||||
<Route exact path="/login" component={Login} />
|
||||
<Route exact path="/login/createuser" component={CreateAccount} />
|
||||
<ProtectedRoute path="/*" component={Navbar} />
|
||||
</Switch>
|
||||
</BrowserRouter>
|
||||
</ThemeProvider>
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
import SelectResource from './selectResource';
|
||||
import ResourceChart from './resourcechart/resourcechart';
|
||||
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
root: {
|
||||
flexGrow: 1,
|
||||
@@ -23,7 +24,7 @@ export default function Content() {
|
||||
<div className={classes.root}>
|
||||
<Route exact path="/" component={Overview} />
|
||||
<Route path="/resources" component={SelectResource} />
|
||||
<Route path="/resourcechart/:id" render={() => <ResourceChart day={new Date().toUTCString()}></ResourceChart>} />
|
||||
<Route path="/resourcechart/:id" render={() => <ResourceChart />} />
|
||||
</div>
|
||||
|
||||
);
|
||||
|
||||
187
frontend/src/components/login/createAccount.js
Normal file
187
frontend/src/components/login/createAccount.js
Normal file
@@ -0,0 +1,187 @@
|
||||
import React from 'react';
|
||||
import { Link } from "react-router-dom";
|
||||
import { makeStyles, withStyles } from '@material-ui/core/styles';
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardContent from '@material-ui/core/CardContent';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import Box from '@material-ui/core/Box';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Logo from "../../img/logo.png";
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import { Redirect } from "react-router-dom";
|
||||
import LoginFeedback from './loginfeedback';
|
||||
|
||||
const url = "/simcompanies/API/user/create"
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
card: {
|
||||
backgroundColor: "#0B1929",
|
||||
display: "flex"
|
||||
},
|
||||
logo: {
|
||||
maxWidth: "50%",
|
||||
height: "auto"
|
||||
},
|
||||
input: {
|
||||
color: "#9daac1"
|
||||
},
|
||||
grid: {
|
||||
display: "flex"
|
||||
}
|
||||
}));
|
||||
|
||||
const CssTextField = withStyles({
|
||||
root: {
|
||||
'& label.Mui-focused': {
|
||||
color: '#FFC800',
|
||||
},
|
||||
'&:hover label': {
|
||||
color: '#FFC800',
|
||||
},
|
||||
'& label': {
|
||||
color: 'white',
|
||||
},
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'& input': {
|
||||
color: "white"
|
||||
},
|
||||
'& fieldset': {
|
||||
borderColor: 'white',
|
||||
color: "white"
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
borderColor: "#FFC800",
|
||||
},
|
||||
'&.Mui-focused fieldset': {
|
||||
borderColor: '#FFC800',
|
||||
},
|
||||
},
|
||||
},
|
||||
})(TextField);
|
||||
|
||||
export default function CreateAccount() {
|
||||
const classes = useStyles();
|
||||
const [username, setUsername] = React.useState("");
|
||||
const [password, setPassword] = React.useState("");
|
||||
const [login, setLogin] = React.useState(true);
|
||||
const [status, setStatus] = React.useState(null);
|
||||
const [statusText, setStatusText] = React.useState(null);
|
||||
const [disabled, setDisabled] = React.useState(false);
|
||||
|
||||
const putCreateAccount = async (url, data) => {
|
||||
const response = await fetch(url, {
|
||||
method: 'PUT',
|
||||
mode: 'cors',
|
||||
cache: 'no-cache',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
redirect: 'follow',
|
||||
referrerPolicy: 'no-referrer',
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
const text = await response.text()
|
||||
await setStatusText(text)
|
||||
setStatus(response.status)
|
||||
if (response.status == "200") {
|
||||
setTimeout(() => { setLogin(false) }, 2000)
|
||||
}
|
||||
setDisabled(false)
|
||||
setTimeout(() => { setStatus(null) }, 2000)
|
||||
}
|
||||
const handleClick = (e) => {
|
||||
if (username !== "" && password !== "") {
|
||||
setDisabled(true)
|
||||
putCreateAccount(url, { email: username, password: password })
|
||||
|
||||
setUsername("")
|
||||
setPassword("")
|
||||
}
|
||||
}
|
||||
|
||||
const handleKeyDown = (e) => {
|
||||
if (e.key === "Enter") {
|
||||
if (username !== "" && password !== "") {
|
||||
setDisabled(true)
|
||||
putCreateAccount(url, { email: username, password: password })
|
||||
|
||||
setUsername("")
|
||||
setPassword("")
|
||||
}
|
||||
}
|
||||
}
|
||||
const handleChangeUSR = (e) => {
|
||||
setUsername(e.target.value)
|
||||
}
|
||||
const handleChangePW = (e) => {
|
||||
setPassword(e.target.value)
|
||||
}
|
||||
|
||||
return (
|
||||
login === true ?
|
||||
<Box className="loginBackground" display="flex" justifyContent="center" alignItems="center" m={1} p={1} >
|
||||
<Card className={classes.card} raised>
|
||||
<CardContent>
|
||||
<Box display="flex" justifyContent="center" alignItems="center" m={1} p={1} >
|
||||
<img src={Logo} alt="SC Dashboard Logo" className={classes.logo} />
|
||||
</Box >
|
||||
<form>
|
||||
<Box display="flex" justifyContent="center" alignItems="center" m={1} p={1} >
|
||||
<Grid container spacing={2} >
|
||||
<Grid item xs={12} >
|
||||
<Box display="flex" justifyContent="center" >
|
||||
<Typography variant="h4" color="secondary">
|
||||
Create new Account
|
||||
</Typography>
|
||||
</Box >
|
||||
</Grid>
|
||||
<Grid item xs={12} >
|
||||
<Box display="flex" justifyContent="center" >
|
||||
<CssTextField
|
||||
error={status != null && status != "200"}
|
||||
id="usernameInput"
|
||||
label="Username"
|
||||
variant="outlined"
|
||||
onChange={handleChangeUSR}
|
||||
value={username}
|
||||
className={classes.input}
|
||||
onKeyDown={handleKeyDown}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</Box >
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Box display="flex" justifyContent="center" >
|
||||
<CssTextField
|
||||
error={status != null && status != "200"}
|
||||
id="passwordInput"
|
||||
type="password"
|
||||
label="Password"
|
||||
autoComplete="current-password"
|
||||
variant="outlined"
|
||||
value={password}
|
||||
onChange={handleChangePW}
|
||||
className={classes.input}
|
||||
onKeyDown={handleKeyDown}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</Box >
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Box display="flex" justifyContent="center" >
|
||||
<Button disabled={disabled} variant="contained" color="secondary" onClick={handleClick} >
|
||||
Create Account
|
||||
</Button>
|
||||
</Box >
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box >
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<LoginFeedback login={status} text={statusText}></LoginFeedback>
|
||||
</Box > : <Redirect to={"/login"} />
|
||||
)
|
||||
|
||||
}
|
||||
206
frontend/src/components/login/login.js
Normal file
206
frontend/src/components/login/login.js
Normal file
@@ -0,0 +1,206 @@
|
||||
import React from 'react';
|
||||
import { Link } from "react-router-dom";
|
||||
import { makeStyles, withStyles } from '@material-ui/core/styles';
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardContent from '@material-ui/core/CardContent';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import Box from '@material-ui/core/Box';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Logo from "../../img/logo.png";
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import Link1 from '@material-ui/core/Link';
|
||||
import { Redirect } from "react-router-dom";
|
||||
import LoginFeedback from './loginfeedback';
|
||||
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
card: {
|
||||
backgroundColor: "#0B1929",
|
||||
display: "flex"
|
||||
},
|
||||
logo: {
|
||||
maxWidth: "50%",
|
||||
height: "auto"
|
||||
},
|
||||
input: {
|
||||
color: "#9daac1"
|
||||
},
|
||||
grid: {
|
||||
display: "flex"
|
||||
}
|
||||
}));
|
||||
|
||||
const CssTextField = withStyles({
|
||||
root: {
|
||||
'& label.Mui-focused': {
|
||||
color: "#FFC800",
|
||||
},
|
||||
'&:hover label': {
|
||||
color: '#FFC800',
|
||||
},
|
||||
'& label': {
|
||||
color: 'white',
|
||||
},
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'& input': {
|
||||
color: "white"
|
||||
},
|
||||
'& fieldset': {
|
||||
borderColor: 'white',
|
||||
color: "white"
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
borderColor: "#FFC800",
|
||||
},
|
||||
'&.Mui-focused fieldset': {
|
||||
borderColor: "#FFC800",
|
||||
},
|
||||
},
|
||||
},
|
||||
})(TextField);
|
||||
|
||||
|
||||
export default function Login() {
|
||||
const classes = useStyles();
|
||||
const url = "/simcompanies/API/user/login"
|
||||
const [username, setUsername] = React.useState("");
|
||||
const [password, setPassword] = React.useState("");
|
||||
const [login, setLogin] = React.useState(true);
|
||||
const [status, setStatus] = React.useState(null);
|
||||
const [disabled, setDisabled] = React.useState(false);
|
||||
const [statusText, setStatusText] = React.useState(null);
|
||||
|
||||
const postLogin = async (url, data) => {
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
cache: 'no-cache',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
redirect: 'follow',
|
||||
referrerPolicy: 'no-referrer',
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
const text = await response.text()
|
||||
await setStatusText(text)
|
||||
setStatus(response.status)
|
||||
if (response.status == "200") {
|
||||
setTimeout(() => { setLogin(false) }, 2000)
|
||||
|
||||
}
|
||||
setDisabled(false)
|
||||
setTimeout(() => { setStatus(null) }, 2000)
|
||||
}
|
||||
|
||||
const handleClick = (e) => {
|
||||
|
||||
if (username !== "" && password !== "") {
|
||||
setDisabled(true)
|
||||
postLogin(url, { email: username, password: password })
|
||||
|
||||
setUsername("")
|
||||
setPassword("")
|
||||
}
|
||||
}
|
||||
|
||||
const handleKeyDown = (e) => {
|
||||
if (e.key === "Enter") {
|
||||
if (username !== "" && password !== "") {
|
||||
setDisabled(true)
|
||||
postLogin(url, { email: username, password: password })
|
||||
|
||||
setUsername("")
|
||||
setPassword("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleChangeUSR = (e) => {
|
||||
setUsername(e.target.value)
|
||||
}
|
||||
const handleChangePW = (e) => {
|
||||
setPassword(e.target.value)
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
|
||||
login === true ?
|
||||
< Box className="loginBackground" display="flex" justifyContent="center" alignItems="center" m={1} p={1} >
|
||||
<Card className={classes.card} raised>
|
||||
<CardContent>
|
||||
<Box display="flex" justifyContent="center" alignItems="center" m={1} p={1} >
|
||||
<img src={Logo} alt="SC Dashboard Logo" className={classes.logo} />
|
||||
</Box >
|
||||
<form>
|
||||
<Box display="flex" justifyContent="center" alignItems="center" m={1} p={1} >
|
||||
<Grid container spacing={2} >
|
||||
<Grid item xs={12} >
|
||||
<Box display="flex" justifyContent="center" >
|
||||
<Typography variant="h4" color="secondary">
|
||||
Login
|
||||
</Typography>
|
||||
</Box >
|
||||
</Grid>
|
||||
<Grid item xs={12} >
|
||||
<Box display="flex" justifyContent="center" >
|
||||
<CssTextField
|
||||
error={status != null && status != "200"}
|
||||
id="usernameInput"
|
||||
label="Username"
|
||||
variant="outlined"
|
||||
value={username}
|
||||
onChange={handleChangeUSR}
|
||||
className={classes.input}
|
||||
onKeyDown={handleKeyDown}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</Box >
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Box display="flex" justifyContent="center" >
|
||||
<CssTextField
|
||||
error={status != null && status != "200"}
|
||||
id="passwordInput"
|
||||
type="password"
|
||||
label="Password"
|
||||
autoComplete="current-password"
|
||||
variant="outlined"
|
||||
value={password}
|
||||
onChange={handleChangePW}
|
||||
className={classes.input}
|
||||
onKeyDown={handleKeyDown}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</Box >
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Box display="flex" justifyContent="center" >
|
||||
<Typography variant="subtitle2" >
|
||||
<Link1 to="/login/createuser" component={Link} color="secondary">
|
||||
Create new Account
|
||||
</Link1>
|
||||
</Typography>
|
||||
</Box >
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Box display="flex" justifyContent="center" >
|
||||
<Button disabled={disabled} variant="contained" color="secondary" onClick={handleClick}>
|
||||
Login
|
||||
</Button>
|
||||
</Box >
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box >
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<LoginFeedback login={status} text={statusText}></LoginFeedback>
|
||||
</Box > : <Redirect to='/' />
|
||||
)
|
||||
|
||||
}
|
||||
66
frontend/src/components/login/loginfeedback.js
Normal file
66
frontend/src/components/login/loginfeedback.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import Snackbar from '@material-ui/core/Snackbar';
|
||||
import MuiAlert from '@material-ui/lab/Alert';
|
||||
|
||||
function Alert(props) {
|
||||
return <MuiAlert elevation={6} variant="filled" {...props} />;
|
||||
}
|
||||
|
||||
export default function LoginFeedback(props) {
|
||||
const [login, setLogin] = React.useState(null);
|
||||
const [open, setOpen] = React.useState(true);
|
||||
const [open1, setOpen1] = React.useState(true);
|
||||
const [output, setOutput] = React.useState(null);
|
||||
const [change, setChange] = React.useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (login != props.login) {
|
||||
setChange(true)
|
||||
setOpen(true)
|
||||
setOpen1(true)
|
||||
setLogin(props.login)
|
||||
}
|
||||
}, [login, setLogin, props.login]);
|
||||
|
||||
const handleClose = (event, reason) => {
|
||||
|
||||
setOpen(false);
|
||||
};
|
||||
const handleClose1 = (event, reason) => {
|
||||
setOpen1(false);
|
||||
};
|
||||
|
||||
const snack = (login) => {
|
||||
if (login == "200") {
|
||||
setOutput(
|
||||
<Snackbar open={open} autoHideDuration={2000} onClose={handleClose}>
|
||||
<Alert onClose={handleClose} severity="success">
|
||||
{props.text}
|
||||
</Alert>
|
||||
</Snackbar>)
|
||||
} else if (login != null) {
|
||||
setOutput(
|
||||
<Snackbar open={open1} autoHideDuration={3000} onClose={handleClose1}>
|
||||
<Alert onClose={handleClose1} severity="error">
|
||||
{props.text}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
)
|
||||
} else {
|
||||
setOutput(null)
|
||||
}
|
||||
setChange(false)
|
||||
}
|
||||
|
||||
if (change == true) {
|
||||
snack(login)
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{output}
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
|
||||
}
|
||||
@@ -11,11 +11,15 @@ import CardContent from '@material-ui/core/CardContent';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
display: 'flex',
|
||||
},
|
||||
card: {
|
||||
padding: 20
|
||||
}
|
||||
}));
|
||||
|
||||
const output = (data) => {
|
||||
@@ -38,7 +42,14 @@ const output = (data) => {
|
||||
<YAxis domain={['datamin', 'datamax']} />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Line type="monotone" dataKey="price" stroke="#8884d8" dot={false} />
|
||||
<Line type="monotone" dataKey="q0" stroke="#8884d8" dot={false} />
|
||||
<Line type="monotone" dataKey="q1" stroke="#000000" dot={false} />
|
||||
<Line type="monotone" dataKey="q2" stroke="#82ca9d" dot={false} />
|
||||
<Line type="monotone" dataKey="q3" stroke="#ff0066" dot={false} />
|
||||
<Line type="monotone" dataKey="q4" stroke="#660066" dot={false} />
|
||||
<Line type="monotone" dataKey="q5" stroke="#99cc00" dot={false} />
|
||||
<Line type="monotone" dataKey="q6" stroke="#669999" dot={false} />
|
||||
<Line type="monotone" dataKey="q7" stroke="#996633" dot={false} />
|
||||
</LineChart>
|
||||
)
|
||||
}
|
||||
@@ -49,20 +60,60 @@ export default function ResourceChart(props) {
|
||||
const [data, setData] = React.useState(null);
|
||||
let { id } = useParams();
|
||||
const loadData = async () => {
|
||||
let nextData = await fetch(`/simcompanies/API/day?date=${props["day"]}&kind=${id}`);
|
||||
nextData = await nextData.json();
|
||||
for (let i = 0; i < nextData.length; i++) {
|
||||
nextData[i]["time"] = new Date(nextData[i]["time"]);
|
||||
nextData[i]["time"] = nextData[i]["time"].toLocaleTimeString();
|
||||
let dayData = await fetch(`/simcompanies/API/day?kind=${id}`);
|
||||
let dataWithDate = await dayData.json();
|
||||
let qualitySortedData = [];
|
||||
for (let i = 0; i < dataWithDate.length; i++) {
|
||||
if (i === 0) qualitySortedData.push(dataWithDate[i]);
|
||||
else {
|
||||
if (dataWithDate[i]["time"] === qualitySortedData[qualitySortedData.length - 1]["time"]) {
|
||||
switch (dataWithDate[i].quality) {
|
||||
case 0: break;
|
||||
case 1:
|
||||
qualitySortedData[qualitySortedData.length - 1]["q1"] = dataWithDate[i]["price"];
|
||||
break;
|
||||
case 2:
|
||||
qualitySortedData[qualitySortedData.length - 1]["q2"] = dataWithDate[i]["price"];
|
||||
break;
|
||||
case 3:
|
||||
qualitySortedData[qualitySortedData.length - 1]["q3"] = dataWithDate[i]["price"];
|
||||
break;
|
||||
case 4:
|
||||
qualitySortedData[qualitySortedData.length - 1]["q4"] = dataWithDate[i]["price"];
|
||||
break;
|
||||
case 5:
|
||||
qualitySortedData[qualitySortedData.length - 1]["q5"] = dataWithDate[i]["price"];
|
||||
break;
|
||||
case 6:
|
||||
qualitySortedData[qualitySortedData.length - 1]["q6"] = dataWithDate[i]["price"];
|
||||
break;
|
||||
case 7:
|
||||
qualitySortedData[qualitySortedData.length - 1]["q7"] = dataWithDate[i]["price"];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
qualitySortedData.push(dataWithDate[i]);
|
||||
qualitySortedData[qualitySortedData.length - 1]["q0"] = qualitySortedData[qualitySortedData.length - 1]["price"];
|
||||
}
|
||||
}
|
||||
}
|
||||
setData(nextData)
|
||||
for (let i = 0; i < qualitySortedData.length; i++) {
|
||||
qualitySortedData[i]["time"] = new Date(qualitySortedData[i]["time"]);
|
||||
qualitySortedData[i]["time"] = qualitySortedData[i]["time"].toLocaleTimeString();
|
||||
}
|
||||
console.log(qualitySortedData);
|
||||
setData(qualitySortedData)
|
||||
}
|
||||
|
||||
if (data === null) {
|
||||
loadData();
|
||||
}
|
||||
|
||||
|
||||
const handleClick = (e) => {
|
||||
loadData()
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
@@ -73,16 +124,17 @@ export default function ResourceChart(props) {
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Card>
|
||||
<Card className={classes.card}>
|
||||
<CardContent>
|
||||
{output(data)}
|
||||
</CardContent>
|
||||
<Button variant="contained" color="secondary" onClick={handleClick}>
|
||||
Refresh
|
||||
</Button>
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,37 +2,207 @@ import React from 'react';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import ResourceCard from './resourceCard';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
card: {
|
||||
|
||||
grid: {
|
||||
display: "flex"
|
||||
}
|
||||
}));
|
||||
|
||||
const agri = [66, 3, 4, 5, 6, 7, 8, 9, 40, 72, 106]
|
||||
const construct = [101, 102, 103, 104, 105, 107, 108, 109, 110, 111]
|
||||
const fashion = [41, 46, 60, 61, 62, 63, 64, 65, 70, 71]
|
||||
const energy = [10, 11, 12, 1, 73, 74, 83]
|
||||
const electronics = [20, 21, 22, 23, 24, 25, 26, 27, 28, 79, 98]
|
||||
const auto = [47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 112]
|
||||
const aero = [77, 78, 80, 81, 82, 84, 85, 86, 87, 88, 89]
|
||||
const resource = [2, 13, 14, 15, 16, 17, 18, 19, 42, 43, 44, 45, 68, 69, 75, 76]
|
||||
const research = [29, 30, 31, 32, 33, 34, 35, 58, 59, 100, 113]
|
||||
|
||||
|
||||
export default function SelectResource() {
|
||||
const classes = useStyles();
|
||||
const [resources, setResources] = React.useState(null);
|
||||
const [resources, setResources] = React.useState([]);
|
||||
|
||||
const loadResources = async () => {
|
||||
var resourceJSON = await fetch("/simcompanies/API/resourcelist");
|
||||
resourceJSON = await resourceJSON.json();
|
||||
let rArr = [];
|
||||
let rArr = [[], [], [], [], [], [], [], [], [], []];
|
||||
for (let i = 0; i < resourceJSON.length; i++) {
|
||||
rArr.push(<ResourceCard resource={resourceJSON[i]}></ResourceCard>);
|
||||
if (agri.includes(resourceJSON[i]["db_letter"])) {
|
||||
rArr[0].push(<ResourceCard resource={resourceJSON[i]}></ResourceCard>);
|
||||
} else if (construct.includes(resourceJSON[i]["db_letter"])) {
|
||||
rArr[1].push(<ResourceCard resource={resourceJSON[i]}></ResourceCard>);
|
||||
} else if (fashion.includes(resourceJSON[i]["db_letter"])) {
|
||||
rArr[2].push(<ResourceCard resource={resourceJSON[i]}></ResourceCard>);
|
||||
} else if (energy.includes(resourceJSON[i]["db_letter"])) {
|
||||
rArr[3].push(<ResourceCard resource={resourceJSON[i]}></ResourceCard>);
|
||||
} else if (electronics.includes(resourceJSON[i]["db_letter"])) {
|
||||
rArr[4].push(<ResourceCard resource={resourceJSON[i]}></ResourceCard>);
|
||||
} else if (auto.includes(resourceJSON[i]["db_letter"])) {
|
||||
rArr[5].push(<ResourceCard resource={resourceJSON[i]}></ResourceCard>);
|
||||
} else if (aero.includes(resourceJSON[i]["db_letter"])) {
|
||||
rArr[6].push(<ResourceCard resource={resourceJSON[i]}></ResourceCard>);
|
||||
} else if (resource.includes(resourceJSON[i]["db_letter"])) {
|
||||
rArr[7].push(<ResourceCard resource={resourceJSON[i]}></ResourceCard>);
|
||||
} else if (research.includes(resourceJSON[i]["db_letter"])) {
|
||||
rArr[8].push(<ResourceCard resource={resourceJSON[i]}></ResourceCard>);
|
||||
} else {
|
||||
rArr[9].push(<ResourceCard resource={resourceJSON[i]}></ResourceCard>);
|
||||
}
|
||||
|
||||
}
|
||||
setResources(rArr);
|
||||
}
|
||||
|
||||
if (resources === null)
|
||||
if (resources.length === 0)
|
||||
loadResources();
|
||||
|
||||
return (
|
||||
|
||||
<Grid container spacing={2}>
|
||||
{resources}
|
||||
<Grid container spacing={2} >
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={2} >
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h4">
|
||||
Agriculture & Food
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={1} >
|
||||
{resources[0]}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={2} >
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h4">
|
||||
Construction
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={1} >
|
||||
{resources[1]}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={2} >
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h4">
|
||||
Fashion
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={1} >
|
||||
{resources[2]}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={2} >
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h4">
|
||||
Energy
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={1} >
|
||||
{resources[3]}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={2} >
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h4">
|
||||
Electronics
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={1} >
|
||||
{resources[4]}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={2} >
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h4">
|
||||
Automotive
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={1} >
|
||||
{resources[5]}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={2} >
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h4">
|
||||
Aerospace
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={1} >
|
||||
{resources[6]}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={2} >
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h4">
|
||||
Resources
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={1} >
|
||||
{resources[7]}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={2} >
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h4">
|
||||
Research
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={1} >
|
||||
{resources[8]}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={2} >
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="h4">
|
||||
Others
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.grid}>
|
||||
<Grid container spacing={1} >
|
||||
{resources[9]}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
);
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Link } from 'react-router-dom';
|
||||
import Link1 from '@material-ui/core/Link';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import ListItemText from '@material-ui/core/ListItemText';
|
||||
import CardMedia from '@material-ui/core/CardMedia';
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
@@ -46,7 +46,10 @@ export default function ResourceCard(props) {
|
||||
<Card >
|
||||
<CardContent style={{ padding: 0 }}>
|
||||
<ListItemLink to={"/resourcechart/" + props.resource["db_letter"]} component={Link}>
|
||||
<img src={picture} alt={props.resource["name"]} style={{ width: 50, height: 50 }} />
|
||||
<ListItemIcon>
|
||||
<img src={picture} alt={props.resource["name"]} style={{ width: 50, height: 50 }} />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText primary={props.resource["name"]} />
|
||||
</ListItemLink>
|
||||
</CardContent>
|
||||
|
||||
BIN
frontend/src/img/loginBackground.png
Normal file
BIN
frontend/src/img/loginBackground.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 256 KiB |
Reference in New Issue
Block a user