UI and better date generation finished
This commit is contained in:
+8
-57
@@ -1,59 +1,10 @@
|
|||||||
import { fileURLToPath } from "url";
|
import mysql from "mysql2/promise";
|
||||||
import { connection } from "./index.js";
|
|
||||||
// Create the connection to database
|
|
||||||
|
|
||||||
// get data for users between 2 dates
|
const connection = await mysql.createConnection({
|
||||||
async function getTopTen() {
|
host: "localhost",
|
||||||
let filteredResults;
|
user: "monty",
|
||||||
let startDate = "2021-01-01";
|
password: "some_pass",
|
||||||
let endDate = "2029-01-01";
|
database: "timelog",
|
||||||
if (req.query.to) startDate = req.query.to;
|
});
|
||||||
if (req.query.from) startDate = req.query.from;
|
|
||||||
try {
|
|
||||||
const [results, fields] = await connection.query(
|
|
||||||
"SELECT t.user,t.time,t.date,t.project \
|
|
||||||
FROM Timelog t\
|
|
||||||
WHERE t.date BETWEEN ? AND ? ;",
|
|
||||||
[startDate, endDate],
|
|
||||||
);
|
|
||||||
filteredResults = results;
|
|
||||||
console.log(filteredResults);
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.query.filterBy) filterBy = req.query.filterBy;
|
export default connection;
|
||||||
// how much time each user has logged during that time period
|
|
||||||
if (filterBy === "user") {
|
|
||||||
let users = {};
|
|
||||||
for (let i = 0; i < filteredResults.length; i++) {
|
|
||||||
if (filteredResults[i].user in users) {
|
|
||||||
users[filteredResults[i].user] += filteredResults[i].time;
|
|
||||||
} else {
|
|
||||||
users[filteredResults[i].user] = filteredResults[i].time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Create items array
|
|
||||||
let items = Object.keys(users).map(function (key) {
|
|
||||||
return [key, users[key]];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Sort the array based on the second element
|
|
||||||
items.sort(function (first, second) {
|
|
||||||
return second[1] - first[1];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create a new array with only the first 10 items
|
|
||||||
return items.slice(0, 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { getTopTen };
|
|
||||||
|
|
||||||
// SELECT u.f_name,u.l_name,u.mail,p.name,t.time,t.date
|
|
||||||
// FROM Timelog t
|
|
||||||
// INNER JOIN Project p ON p.id=t.project
|
|
||||||
// INNER JOIN User u ON u.id=t.user
|
|
||||||
// WHERE User = "100";
|
|
||||||
// ORDER BY time
|
|
||||||
// LIMIT 10 OFFSET 10
|
|
||||||
|
|||||||
+10
-170
@@ -1,179 +1,19 @@
|
|||||||
import express from "express";
|
import express from "express";
|
||||||
import mysql from "mysql2/promise";
|
import getAll from "./routers/getAll.js";
|
||||||
import { getTopTen } from "./db.js";
|
import getUser from "./routers/getUser.js";
|
||||||
import { resourceUsage } from "process";
|
import getTopTen from "./routers/getTopTen.js";
|
||||||
|
import reset from "./routers/reset.js";
|
||||||
export const connection = await mysql.createConnection({
|
|
||||||
host: "localhost",
|
|
||||||
user: "monty",
|
|
||||||
password: "some_pass",
|
|
||||||
database: "timelog",
|
|
||||||
});
|
|
||||||
connection.config.namedPlaceholders = true;
|
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
router.get("/getall", async (req, res) => {
|
|
||||||
let sql =
|
|
||||||
"SELECT u.f_name,u.l_name,u.mail,p.name,t.time,t.date,t.user \
|
|
||||||
FROM Timelog t \
|
|
||||||
INNER JOIN Project p ON p.id=t.project \
|
|
||||||
INNER JOIN User u ON u.id=t.user ";
|
|
||||||
let where = "WHERE t.date BETWEEN ? AND ? ";
|
|
||||||
let order = "ORDER BY ?? ";
|
|
||||||
let offsetSql = "LIMIT 10 OFFSET ?;";
|
|
||||||
let flag = 0;
|
|
||||||
if (req.query.from || req.query.to) {
|
|
||||||
sql = sql + where;
|
|
||||||
flag += 1;
|
|
||||||
}
|
|
||||||
if (req.query.sortby) {
|
|
||||||
sql = sql + order;
|
|
||||||
flag += 2;
|
|
||||||
}
|
|
||||||
sql = sql + offsetSql;
|
|
||||||
let results;
|
|
||||||
let fields;
|
|
||||||
if (flag == 0) {
|
|
||||||
[results, fields] = await connection.query(sql, [
|
|
||||||
parseInt(req.query.offset),
|
|
||||||
]);
|
|
||||||
} else if (flag === 1) {
|
|
||||||
[results, fields] = await connection.query(sql, [
|
|
||||||
req.query.from,
|
|
||||||
req.query.to,
|
|
||||||
parseInt(req.query.offset),
|
|
||||||
]);
|
|
||||||
} else if (flag === 2) {
|
|
||||||
[results, fields] = await connection.query(sql, [
|
|
||||||
req.query.sortby,
|
|
||||||
parseInt(req.query.offset),
|
|
||||||
]);
|
|
||||||
} else if (flag === 3) {
|
|
||||||
[results, fields] = await connection.query(sql, [
|
|
||||||
req.query.from,
|
|
||||||
req.query.to,
|
|
||||||
req.query.sortby,
|
|
||||||
parseInt(req.query.offset),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
res.json(results);
|
|
||||||
});
|
|
||||||
router.get("/gettopten", async (req, res) => {
|
|
||||||
let filteredResults;
|
|
||||||
let results2;
|
|
||||||
let from = "2021-01-01";
|
|
||||||
let to = "2029-01-01";
|
|
||||||
let filterBy = "user";
|
|
||||||
if (req.query.from) from = req.query.from;
|
|
||||||
if (req.query.to) to = req.query.to;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const [results, fields] = await connection.query(
|
|
||||||
"SELECT t.user,t.time,t.date,t.project \
|
|
||||||
FROM Timelog t\
|
|
||||||
WHERE t.date BETWEEN ? AND ? ;",
|
|
||||||
[from, to],
|
|
||||||
);
|
|
||||||
filteredResults = results;
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.query.filterBy) filterBy = req.query.filterBy;
|
|
||||||
// how much time each user has logged during that time period
|
|
||||||
if (filterBy === "user") {
|
|
||||||
let users = {};
|
|
||||||
for (let i = 0; i < filteredResults.length; i++) {
|
|
||||||
if (filteredResults[i].user in users) {
|
|
||||||
users[filteredResults[i].user] += filteredResults[i].time;
|
|
||||||
} else {
|
|
||||||
users[filteredResults[i].user] = filteredResults[i].time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Create items array
|
|
||||||
let items = Object.keys(users).map(function (key) {
|
|
||||||
return [key, users[key]];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Sort the array based on the second element
|
|
||||||
items.sort(function (first, second) {
|
|
||||||
return second[1] - first[1];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create a new array with only the first 10 items
|
|
||||||
results2 = items.slice(0, 10);
|
|
||||||
} else if (filterBy === "project") {
|
|
||||||
let projects = {};
|
|
||||||
for (let i = 0; i < filteredResults.length; i++) {
|
|
||||||
if (filteredResults[i].project in projects) {
|
|
||||||
projects[filteredResults[i].project] += filteredResults[i].time;
|
|
||||||
} else {
|
|
||||||
projects[filteredResults[i].project] = filteredResults[i].time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Create items array
|
|
||||||
let items = Object.keys(projects).map(function (key) {
|
|
||||||
return [key, projects[key]];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Sort the array based on the second element
|
|
||||||
items.sort(function (first, second) {
|
|
||||||
return second[1] - first[1];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create a new array with only the first 10 items
|
|
||||||
results2 = items.slice(0, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
res.json(results2);
|
|
||||||
});
|
|
||||||
router.get("/reset", async (req, res) => {
|
|
||||||
try {
|
|
||||||
const [results, fields] = await connection.query("CALL InitDb;", []);
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
res.status(200).json({ message: "Success" });
|
|
||||||
});
|
|
||||||
router.get("/getUser", async (req, res) => {
|
|
||||||
const userId = req.query.userid;
|
|
||||||
let results, fields;
|
|
||||||
console.log(userId);
|
|
||||||
try {
|
|
||||||
[results, fields] = await connection.query(
|
|
||||||
"SELECT p.name,t.time,t.project \
|
|
||||||
FROM Timelog t \
|
|
||||||
INNER JOIN Project p ON p.id=t.project \
|
|
||||||
INNER JOIN User u ON u.id=t.user \
|
|
||||||
WHERE USER = ? ;",
|
|
||||||
[userId],
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
let projects = {};
|
|
||||||
let projectIdtoName = {};
|
|
||||||
for (let i = 0; i < results.length; i++) {
|
|
||||||
if (results[i].project in projects) {
|
|
||||||
projects[results[i].project] += results[i].time;
|
|
||||||
} else {
|
|
||||||
projects[results[i].project] = results[i].time;
|
|
||||||
projectIdtoName[results[i].project] = results[i].name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// map projectIds to project names before sending the data
|
|
||||||
let respData = {};
|
|
||||||
for (let key in projects) {
|
|
||||||
if (projects.hasOwnProperty(key)) {
|
|
||||||
respData[projectIdtoName[key]] = projects[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.json(respData);
|
|
||||||
});
|
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|
||||||
|
app.use("/api", getAll);
|
||||||
|
app.use("/api", getTopTen);
|
||||||
|
app.use("/api", getUser);
|
||||||
|
app.use("/api", reset);
|
||||||
|
|
||||||
app.use("/api", router);
|
app.use("/api", router);
|
||||||
const PORT = process.env.PORT || 5000;
|
const PORT = process.env.PORT || 5000;
|
||||||
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
|
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import express from "express";
|
||||||
|
import connection from "../db.js";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.get("/getall", async (req, res) => {
|
||||||
|
let sql =
|
||||||
|
"SELECT u.f_name,u.l_name,u.mail,p.name,t.time,t.date,t.user \
|
||||||
|
FROM Timelog t \
|
||||||
|
INNER JOIN Project p ON p.id=t.project \
|
||||||
|
INNER JOIN User u ON u.id=t.user ";
|
||||||
|
const where = "WHERE t.date BETWEEN ? AND ? ";
|
||||||
|
const order = "ORDER BY ?? ";
|
||||||
|
const offsetSql = "LIMIT 10 OFFSET ?;";
|
||||||
|
let flag = 0;
|
||||||
|
// construct the sql statement based on incoming request
|
||||||
|
if (req.query.from || req.query.to) {
|
||||||
|
sql = sql + where;
|
||||||
|
flag += 1;
|
||||||
|
}
|
||||||
|
if (req.query.sortby) {
|
||||||
|
sql = sql + order;
|
||||||
|
flag += 2;
|
||||||
|
}
|
||||||
|
sql = sql + offsetSql;
|
||||||
|
|
||||||
|
let results;
|
||||||
|
let fields;
|
||||||
|
switch (flag) {
|
||||||
|
case 0:
|
||||||
|
[results, fields] = await connection.query(sql, [
|
||||||
|
parseInt(req.query.offset),
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
[results, fields] = await connection.query(sql, [
|
||||||
|
req.query.from,
|
||||||
|
req.query.to,
|
||||||
|
parseInt(req.query.offset),
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
[results, fields] = await connection.query(sql, [
|
||||||
|
req.query.sortby,
|
||||||
|
parseInt(req.query.offset),
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
[results, fields] = await connection.query(sql, [
|
||||||
|
req.query.from,
|
||||||
|
req.query.to,
|
||||||
|
req.query.sortby,
|
||||||
|
parseInt(req.query.offset),
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res.json(results);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import express from "express";
|
||||||
|
import connection from "../db.js";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.get("/gettopten", async (req, res) => {
|
||||||
|
let from = "2020-01-01";
|
||||||
|
let to = "2029-01-01";
|
||||||
|
let filterBy = "user";
|
||||||
|
if (req.query.from) from = req.query.from;
|
||||||
|
if (req.query.to) to = req.query.to;
|
||||||
|
if (req.query.filterBy) filterBy = req.query.filterBy;
|
||||||
|
let results, fields;
|
||||||
|
let filterBySql = filterBy === "user" ? "t.user" : "t.project";
|
||||||
|
try {
|
||||||
|
[results, fields] = await connection.query(
|
||||||
|
"SELECT t.user,t.date,t.project,u.f_name,u.l_name,p.name,SUM(t.time) as total_time \
|
||||||
|
FROM Timelog t \
|
||||||
|
INNER JOIN Project p ON p.id=t.project \
|
||||||
|
INNER JOIN User u ON u.id=t.user \
|
||||||
|
WHERE t.date BETWEEN ? AND ? \
|
||||||
|
GROUP BY ?? \
|
||||||
|
ORDER BY total_time DESC\
|
||||||
|
LIMIT 10;",
|
||||||
|
[from, to, filterBySql],
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
res.status(400).json({ message: "Error" });
|
||||||
|
}
|
||||||
|
// how much time each user has logged during that time period
|
||||||
|
// let items = {};
|
||||||
|
// let itemIdtoName = {};
|
||||||
|
// for (let i = 0; i < results.length; i++) {
|
||||||
|
// if (results[i][filterBy] in items) {
|
||||||
|
// items[results[i][filterBy]] += results[i].time;
|
||||||
|
// } else {
|
||||||
|
// items[results[i][filterBy]] = results[i].time;
|
||||||
|
// if (filterBy === "user")
|
||||||
|
// itemIdtoName[results[i][filterBy]] =
|
||||||
|
// results[i].f_name + " " + results[i].l_name;
|
||||||
|
// else itemIdtoName[results[i][filterBy]] = results[i].name;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// let respData = {};
|
||||||
|
// for (let key in items) {
|
||||||
|
// if (items.hasOwnProperty(key)) {
|
||||||
|
// respData[itemIdtoName[key]] = items[key];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // transform obj to array
|
||||||
|
// respData = Object.keys(items).map(function (key) {
|
||||||
|
// return [key, items[key]];
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// // sort the array based on the second element
|
||||||
|
// respData.sort(function (first, second) {
|
||||||
|
// return second[1] - first[1];
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// // console.log(itemIdtoName);
|
||||||
|
// // console.log(respData);
|
||||||
|
// // Create a new array with only the first 10 items
|
||||||
|
// respData = respData.slice(0, 10);
|
||||||
|
|
||||||
|
res.json(results);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import express from "express";
|
||||||
|
import connection from "../db.js";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.get("/getUser", async (req, res) => {
|
||||||
|
const userId = req.query.userid;
|
||||||
|
let results, fields;
|
||||||
|
try {
|
||||||
|
[results, fields] = await connection.query(
|
||||||
|
"SELECT p.name,t.time,t.project \
|
||||||
|
FROM Timelog t \
|
||||||
|
INNER JOIN Project p ON p.id=t.project \
|
||||||
|
INNER JOIN User u ON u.id=t.user \
|
||||||
|
WHERE USER = ? ;",
|
||||||
|
[userId],
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
res.status(400).json("ERROR");
|
||||||
|
}
|
||||||
|
let projects = {};
|
||||||
|
let projectIdtoName = {};
|
||||||
|
for (let i = 0; i < results.length; i++) {
|
||||||
|
if (results[i].project in projects) {
|
||||||
|
projects[results[i].project] += results[i].time;
|
||||||
|
} else {
|
||||||
|
projects[results[i].project] = results[i].time;
|
||||||
|
projectIdtoName[results[i].project] = results[i].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// map projectIds to project names before sending the data
|
||||||
|
let respData = {};
|
||||||
|
for (let key in projects) {
|
||||||
|
if (projects.hasOwnProperty(key)) {
|
||||||
|
respData[projectIdtoName[key]] = projects[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.json(respData);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import express from "express";
|
||||||
|
import connection from "../db.js";
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.get("/reset", async (req, res) => {
|
||||||
|
try {
|
||||||
|
await connection.query("CALL InitDb;", []);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
res.status(400).json({ message: "Error" });
|
||||||
|
}
|
||||||
|
res.status(200).json({ message: "Success" });
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
@@ -127,3 +127,11 @@ END$$
|
|||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
||||||
|
|
||||||
|
SELECT t.user,t.date,t.project,u.f_name,u.l_name,p.name,SUM(t.time) as total_time
|
||||||
|
FROM Timelog t
|
||||||
|
INNER JOIN Project p ON p.id=t.project
|
||||||
|
INNER JOIN User u ON u.id=t.user
|
||||||
|
GROUP BY t.user
|
||||||
|
ORDER BY total_time DESC
|
||||||
|
LIMIT 10;
|
||||||
|
|
||||||
|
|||||||
+41
-2
@@ -84,14 +84,28 @@ BEGIN
|
|||||||
DECLARE hours FLOAT;
|
DECLARE hours FLOAT;
|
||||||
DECLARE project INT;
|
DECLARE project INT;
|
||||||
DECLARE curDate DATE DEFAULT "2024-11-18";
|
DECLARE curDate DATE DEFAULT "2024-11-18";
|
||||||
|
DECLARE h2 INT;
|
||||||
|
|
||||||
WHILE users <= 100 DO
|
WHILE users <= 100 DO
|
||||||
SET logs = FLOOR(1+(RAND()*20));
|
SET logs = FLOOR(1+(RAND()*20));
|
||||||
SET j=1;
|
SET j=1;
|
||||||
WHILE j <= logs DO
|
WHILE j <= logs DO
|
||||||
SET hours = (RAND() * (8 - 0.25)) + 0.25;
|
|
||||||
SET curDate = DATE_ADD(curDate, INTERVAL 1 DAY);
|
|
||||||
SET project = FLOOR(1+(RAND()*3));
|
SET project = FLOOR(1+(RAND()*3));
|
||||||
|
SET curDate = DATE_ADD('2020-01-01', INTERVAL FLOOR(RAND() * DATEDIFF('2020-02-01', '2020-01-01')) DAY);
|
||||||
|
SET hours = (RAND() * (8 - 0.25)) + 0.25;
|
||||||
|
|
||||||
|
SELECT SUM(time) INTO h2
|
||||||
|
FROM Timelog
|
||||||
|
WHERE date = curdate && user = users ;
|
||||||
|
|
||||||
|
WHILE (h2+hours) > 8 DO
|
||||||
|
SET curDate = DATE_ADD('2020-01-01', INTERVAL FLOOR(RAND() * DATEDIFF('2020-02-01', '2020-01-01')) DAY);
|
||||||
|
|
||||||
|
SELECT SUM(time)INTO h2
|
||||||
|
FROM Timelog
|
||||||
|
WHERE date = curdate && user = users ;
|
||||||
|
|
||||||
|
END WHILE;
|
||||||
INSERT INTO Timelog (user, project, date,time ) VALUES (users,project,curDate,hours);
|
INSERT INTO Timelog (user, project, date,time ) VALUES (users,project,curDate,hours);
|
||||||
SET j=j+1;
|
SET j=j+1;
|
||||||
END WHILE;
|
END WHILE;
|
||||||
@@ -104,3 +118,28 @@ DELIMITER ;
|
|||||||
##
|
##
|
||||||
-- get data
|
-- get data
|
||||||
SELECT t.time,t.date,p.name,u.f_name,u.l_name,u.mail FROM Timelog t INNER JOIN Project p ON p.id=t.project INNER JOIN User u ON u.id=t.user;
|
SELECT t.time,t.date,p.name,u.f_name,u.l_name,u.mail FROM Timelog t INNER JOIN Project p ON p.id=t.project INNER JOIN User u ON u.id=t.user;
|
||||||
|
|
||||||
|
CREATE PROCEDURE fill_timelog ()
|
||||||
|
BEGIN
|
||||||
|
DECLARE j INT DEFAULT 1;
|
||||||
|
DECLARE users INT DEFAULT 1;
|
||||||
|
DECLARE logs INT;
|
||||||
|
DECLARE hours FLOAT;
|
||||||
|
DECLARE project INT;
|
||||||
|
DECLARE curDate DATE DEFAULT "2024-11-18";
|
||||||
|
|
||||||
|
WHILE users <= 100 DO
|
||||||
|
SET logs = FLOOR(1+(RAND()*20));
|
||||||
|
SET j=1;
|
||||||
|
WHILE j <= logs DO
|
||||||
|
SET hours = (RAND() * (8 - 0.25)) + 0.25;
|
||||||
|
SET project = FLOOR(1+(RAND()*3));
|
||||||
|
SET curDate = DATE_ADD(curDate, INTERVAL 1 DAY);
|
||||||
|
INSERT INTO Timelog (user, project, date,time ) VALUES (users,project,curDate,hours);
|
||||||
|
SET j=j+1;
|
||||||
|
END WHILE;
|
||||||
|
SET users=users+1;
|
||||||
|
END WHILE;
|
||||||
|
END$$
|
||||||
|
|
||||||
|
DELIMITER ;
|
||||||
|
|||||||
Generated
+672
-27
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,8 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@emotion/styled": "^11.13.5",
|
||||||
|
"@mui/material": "^6.1.8",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
|||||||
@@ -1,42 +1 @@
|
|||||||
#root {
|
|
||||||
max-width: 1280px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 2rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
height: 6em;
|
|
||||||
padding: 1.5em;
|
|
||||||
will-change: filter;
|
|
||||||
transition: filter 300ms;
|
|
||||||
}
|
|
||||||
.logo:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #646cffaa);
|
|
||||||
}
|
|
||||||
.logo.react:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #61dafbaa);
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes logo-spin {
|
|
||||||
from {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
|
||||||
a:nth-of-type(2) .logo {
|
|
||||||
animation: logo-spin infinite 20s linear;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
padding: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.read-the-docs {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
import "./App.css";
|
import "./App.css";
|
||||||
import LeftSide from "./components/LeftSide";
|
import LeftSide from "./components/LeftSide";
|
||||||
import RightSide from "./components/RightSide";
|
import RightSide from "./components/RightSide";
|
||||||
|
import Grid from "@mui/material/Grid2";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<Grid container spacing={2}>
|
||||||
<LeftSide />
|
<Grid size={6}>
|
||||||
<RightSide />
|
<LeftSide />
|
||||||
</div>
|
</Grid>
|
||||||
|
<Grid size={6}>
|
||||||
|
<RightSide />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,27 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import api from "../utils/api";
|
import api from "../utils/api";
|
||||||
|
import Grid from "@mui/material/Grid2";
|
||||||
|
import {
|
||||||
|
TableRow,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
Table,
|
||||||
|
} from "@mui/material";
|
||||||
|
|
||||||
const LeftSide = () => {
|
const LeftSide = () => {
|
||||||
|
// next prev and sort
|
||||||
const [users, setUsers] = useState();
|
const [users, setUsers] = useState();
|
||||||
const [params, setParams] = useState({ offset: 0, sortby: "f_name" });
|
const [params, setParams] = useState({ offset: 0, sortby: "f_name" });
|
||||||
|
// reset button
|
||||||
const [reset, setReset] = useState(true);
|
const [reset, setReset] = useState(true);
|
||||||
|
|
||||||
// date
|
// date
|
||||||
const [date, setDate] = useState({ from: "2021-01-01", to: "2028-01-01" });
|
const [date, setDate] = useState({ from: "2021-01-01", to: "2028-01-01" });
|
||||||
const [dateToSubmit, setDateToSubmit] = useState({});
|
const [dateToSubmit, setDateToSubmit] = useState({
|
||||||
|
from: "2021-01-01",
|
||||||
|
to: "2028-01-01",
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
@@ -28,13 +40,7 @@ const LeftSide = () => {
|
|||||||
fetchData();
|
fetchData();
|
||||||
}, [reset, params, dateToSubmit]);
|
}, [reset, params, dateToSubmit]);
|
||||||
|
|
||||||
const handleButtonClick = () => {
|
|
||||||
// When the button is clicked, update the dateToShow state and trigger a re-render
|
|
||||||
setDateToSubmit(date);
|
|
||||||
};
|
|
||||||
|
|
||||||
const viewProjectHours = (user) => {
|
const viewProjectHours = (user) => {
|
||||||
console.log(user);
|
|
||||||
async function fetchHours() {
|
async function fetchHours() {
|
||||||
const resp = await api.get("/getUser", {
|
const resp = await api.get("/getUser", {
|
||||||
params: { userid: user },
|
params: { userid: user },
|
||||||
@@ -47,8 +53,8 @@ const LeftSide = () => {
|
|||||||
|
|
||||||
if (!users) return <></>;
|
if (!users) return <></>;
|
||||||
return (
|
return (
|
||||||
<div>
|
<Grid container spacing={2}>
|
||||||
<div>
|
<Grid size={5}>
|
||||||
<label htmlFor="date">From: </label>
|
<label htmlFor="date">From: </label>
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
@@ -65,10 +71,10 @@ const LeftSide = () => {
|
|||||||
value={date.to}
|
value={date.to}
|
||||||
onChange={(event) => setDate({ ...date, to: event.target.value })}
|
onChange={(event) => setDate({ ...date, to: event.target.value })}
|
||||||
/>
|
/>
|
||||||
<button onClick={handleButtonClick}>Submit Date</button>
|
<button onClick={() => setDateToSubmit(date)}>Submit Date</button>
|
||||||
</div>
|
</Grid>
|
||||||
<div>
|
<Grid size={3}>
|
||||||
<h4>Select a sort:</h4>
|
<span>Select a sort:</span>
|
||||||
<select
|
<select
|
||||||
value={params.sortby}
|
value={params.sortby}
|
||||||
onChange={(event) =>
|
onChange={(event) =>
|
||||||
@@ -84,60 +90,68 @@ const LeftSide = () => {
|
|||||||
<option value="date">Date</option>
|
<option value="date">Date</option>
|
||||||
<option value="time">Time</option>
|
<option value="time">Time</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</Grid>
|
||||||
<button
|
<Grid size={4}></Grid>
|
||||||
onClick={() =>
|
<Grid size={4}></Grid>
|
||||||
setParams((prevParams) => {
|
<Grid size={4}>
|
||||||
return { ...prevParams, offset: prevParams.offset + 10 };
|
<button
|
||||||
})
|
onClick={() => {
|
||||||
}
|
if (!params.offset) return;
|
||||||
>
|
setParams((prevParams) => {
|
||||||
Next users
|
return { ...prevParams, offset: prevParams.offset - 10 };
|
||||||
</button>
|
});
|
||||||
<button
|
}}
|
||||||
onClick={() =>
|
>
|
||||||
setParams((prevParams) => {
|
Prev users
|
||||||
return { ...prevParams, offset: prevParams.offset - 10 };
|
</button>
|
||||||
})
|
<button
|
||||||
}
|
onClick={() =>
|
||||||
>
|
setParams((prevParams) => {
|
||||||
Prev users
|
return { ...prevParams, offset: prevParams.offset + 10 };
|
||||||
</button>
|
})
|
||||||
<table>
|
}
|
||||||
<thead>
|
>
|
||||||
<tr>
|
Next users
|
||||||
<th>First Name</th>
|
</button>
|
||||||
<th>Last Name</th>
|
</Grid>
|
||||||
<th>Email</th>
|
<Table>
|
||||||
<th>Project name</th>
|
<TableHead>
|
||||||
<th>Date</th>
|
<TableRow>
|
||||||
<th>Hours</th>
|
<TableCell>First Name</TableCell>
|
||||||
</tr>
|
<TableCell>Last Name</TableCell>
|
||||||
</thead>
|
<TableCell>Email</TableCell>
|
||||||
<tbody>
|
<TableCell>Project name</TableCell>
|
||||||
|
<TableCell>Date</TableCell>
|
||||||
|
<TableCell>Hours</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
{users.length > 0 && Array.isArray(users) ? (
|
{users.length > 0 && Array.isArray(users) ? (
|
||||||
users.map((post, idx) => (
|
users.map((post, idx) => (
|
||||||
<tr key={idx}>
|
<TableRow key={idx}>
|
||||||
<td>{post.f_name} </td>
|
<TableCell>{post.f_name} </TableCell>
|
||||||
<td>{post.l_name} </td>
|
<TableCell>{post.l_name} </TableCell>
|
||||||
<td>{post.mail} </td>
|
<TableCell>{post.mail} </TableCell>
|
||||||
<td>{post.name} </td>
|
<TableCell>{post.name} </TableCell>
|
||||||
<td>{post.date} </td>
|
<TableCell>{post.date.slice(0, 10)} </TableCell>
|
||||||
<td>{post.time} </td>
|
<TableCell>{post.time} </TableCell>
|
||||||
<td>
|
<TableCell>
|
||||||
<button onClick={() => viewProjectHours(post.user)}>
|
<button onClick={() => viewProjectHours(post.user)}>
|
||||||
View Project Hours
|
View Project Hours
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</TableCell>
|
||||||
</tr>
|
</TableRow>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<div>No posts found...</div>
|
<div>No posts found...</div>
|
||||||
)}
|
)}
|
||||||
</tbody>
|
</TableBody>
|
||||||
</table>
|
</Table>
|
||||||
<button onClick={() => setReset(!reset)}>RESET</button>
|
<Grid size={5}></Grid>
|
||||||
</div>
|
<Grid size={6}>
|
||||||
|
<button onClick={() => setReset(!reset)}>RESET</button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,22 +3,39 @@ import api from "../utils/api";
|
|||||||
import { Chart } from "react-google-charts";
|
import { Chart } from "react-google-charts";
|
||||||
|
|
||||||
const RightSide = () => {
|
const RightSide = () => {
|
||||||
const [topten, setTopten] = useState();
|
// graph date
|
||||||
// input field
|
const [topten, setTopten] = useState({
|
||||||
const [date, setDate] = useState({ from: "2021-01-01", to: "2028-01-01" });
|
from: "2000-01-01",
|
||||||
|
to: "2100-01-01",
|
||||||
|
});
|
||||||
|
// date input field
|
||||||
|
const [date, setDate] = useState({ from: "2000-01-01", to: "2100-01-01" });
|
||||||
const [dateToSubmit, setDateToSubmit] = useState({});
|
const [dateToSubmit, setDateToSubmit] = useState({});
|
||||||
// radio
|
// radio button
|
||||||
const [selectedOption, setSelectedOption] = useState("project");
|
const [selectedOption, setSelectedOption] = useState("project");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
const resp = await api.get("/gettopten", {
|
const resp = await api.get("/gettopten", {
|
||||||
params: {
|
params: {
|
||||||
to: dateToSubmit.to,
|
|
||||||
from: dateToSubmit.from,
|
from: dateToSubmit.from,
|
||||||
|
to: dateToSubmit.to,
|
||||||
filterBy: selectedOption,
|
filterBy: selectedOption,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
resp.data.unshift(["User", "Hours"]);
|
resp.data.unshift(["User", "Hours"]);
|
||||||
|
// turn the data into form suitable to charts
|
||||||
|
if (selectedOption === "project")
|
||||||
|
for (let idx = 1; idx < resp.data.length; idx++) {
|
||||||
|
resp.data[idx] = [resp.data[idx].name, resp.data[idx].total_time];
|
||||||
|
}
|
||||||
|
else if (selectedOption === "user")
|
||||||
|
for (let idx = 1; idx < resp.data.length; idx++) {
|
||||||
|
resp.data[idx] = [
|
||||||
|
resp.data[idx].f_name + " " + resp.data[idx].l_name,
|
||||||
|
resp.data[idx].total_time,
|
||||||
|
];
|
||||||
|
}
|
||||||
setTopten(resp.data);
|
setTopten(resp.data);
|
||||||
}
|
}
|
||||||
fetchData();
|
fetchData();
|
||||||
@@ -27,29 +44,21 @@ const RightSide = () => {
|
|||||||
// Chart options
|
// Chart options
|
||||||
const options = {
|
const options = {
|
||||||
title: "Most comitted hours per user",
|
title: "Most comitted hours per user",
|
||||||
chartArea: { width: "50%" },
|
chartArea: { width: "70%" },
|
||||||
hAxis: {
|
hAxis: {
|
||||||
title: "Hours",
|
title: "Hours",
|
||||||
minValue: 0,
|
minValue: 0,
|
||||||
},
|
},
|
||||||
vAxis: {
|
vAxis: {
|
||||||
title: "User",
|
title: selectedOption,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleButtonClick = () => {
|
|
||||||
// When the button is clicked, update the dateToShow state and trigger a re-render
|
|
||||||
setDateToSubmit(date);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle the change when a radio button is selected
|
|
||||||
const handleChange = (event) => {
|
|
||||||
setSelectedOption(event.target.value);
|
|
||||||
};
|
|
||||||
if (!topten) <></>;
|
if (!topten) <></>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div style={{ flex: 1 }}>
|
||||||
<div>
|
<>
|
||||||
<label htmlFor="date">From: </label>
|
<label htmlFor="date">From: </label>
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
@@ -66,30 +75,28 @@ const RightSide = () => {
|
|||||||
value={date.to}
|
value={date.to}
|
||||||
onChange={(event) => setDate({ ...date, to: event.target.value })}
|
onChange={(event) => setDate({ ...date, to: event.target.value })}
|
||||||
/>
|
/>
|
||||||
<button onClick={handleButtonClick}>Submit Date</button>
|
<button onClick={() => setDateToSubmit(date)}>Submit Date</button>
|
||||||
</div>
|
</>
|
||||||
<div>
|
<>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
value="user"
|
value="user"
|
||||||
checked={selectedOption === "user"}
|
checked={selectedOption === "user"}
|
||||||
onChange={handleChange}
|
onChange={(event) => setSelectedOption(event.target.value)}
|
||||||
/>
|
/>
|
||||||
User
|
User
|
||||||
</label>
|
</label>
|
||||||
<br />
|
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
value="project"
|
value="project"
|
||||||
checked={selectedOption === "project"}
|
checked={selectedOption === "project"}
|
||||||
onChange={handleChange}
|
onChange={(event) => setSelectedOption(event.target.value)}
|
||||||
/>
|
/>
|
||||||
Project
|
Project
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</>
|
||||||
<Chart
|
<Chart
|
||||||
chartType="BarChart"
|
chartType="BarChart"
|
||||||
width="100%"
|
width="100%"
|
||||||
|
|||||||
Reference in New Issue
Block a user