Compare commits
17 Commits
4a375149f6
...
3110d315e6
| Author | SHA1 | Date | |
|---|---|---|---|
|
3110d315e6
|
|||
|
507f6c932b
|
|||
|
58eda6d1ea
|
|||
|
e82adbe5e4
|
|||
|
01b3b7b429
|
|||
|
38f2f627a8
|
|||
|
feef4c7800
|
|||
|
1d04006335
|
|||
|
80e3d270c8
|
|||
|
58b3dfe28a
|
|||
|
758c87652c
|
|||
|
0bdaac368c
|
|||
|
31913d0b94
|
|||
|
fb9e3130e0
|
|||
|
2aaa448331
|
|||
|
fa8e4486f3
|
|||
|
20da46a8d7
|
BIN
database/data.db
BIN
database/data.db
Binary file not shown.
@@ -16,7 +16,6 @@
|
|||||||
height: 85%;
|
height: 85%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 5%;
|
padding: 5%;
|
||||||
overflow: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#menu {
|
#menu {
|
||||||
@@ -40,4 +39,25 @@
|
|||||||
|
|
||||||
#taskButton {
|
#taskButton {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#historyContent {
|
||||||
|
height: 75%;
|
||||||
|
overflow: scroll;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#stats {
|
||||||
|
height: 25%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tasks {
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
padding: 0;
|
||||||
|
background: white;
|
||||||
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,17 @@
|
|||||||
<div id="mainPage" style="display: none;">
|
<div id="mainPage" style="display: none;">
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<div id="tasks" class="screen flex two demo" style=""></div>
|
<div id="tasks" class="screen flex two demo" style=""></div>
|
||||||
<div id="history" class="screen" style="display: none;"></div>
|
<div id="history" class="screen" style="display: none;">
|
||||||
|
<div id="stats">
|
||||||
|
<article class="card">
|
||||||
|
<header>
|
||||||
|
<h1>Stats</h1>
|
||||||
|
<pre id="statData"></pre>
|
||||||
|
</header>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
<div id="historyContent"></div>
|
||||||
|
</div>
|
||||||
<div id="addTask" class="screen" style="display: none;">Add Task</div>
|
<div id="addTask" class="screen" style="display: none;">Add Task</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="menu" class="flex three demo">
|
<div id="menu" class="flex three demo">
|
||||||
|
|||||||
@@ -54,22 +54,43 @@ async function populateScreen() {
|
|||||||
let tasks = tasksRaw.tasks;
|
let tasks = tasksRaw.tasks;
|
||||||
|
|
||||||
// get historical data
|
// get historical data
|
||||||
let historyPage = document.getElementById("history");
|
let historyPage = document.getElementById("historyContent");
|
||||||
historyPage.innerHTML = "";
|
historyPage.innerHTML = "";
|
||||||
response = await fetch("/getHistory");
|
response = await fetch("/getHistory");
|
||||||
let historyRaw = await response.json();
|
let historyRaw = await response.json();
|
||||||
let history = historyRaw.history;
|
let history = historyRaw.history;
|
||||||
|
|
||||||
|
// get points data
|
||||||
|
let statsPage = document.getElementById("statData");
|
||||||
|
statsPage.innerText = "";
|
||||||
|
response = await fetch("/getUserPoints");
|
||||||
|
let statsRaw = await response.json();
|
||||||
|
let stats = statsRaw.userPoints;
|
||||||
|
|
||||||
for (let i = 0; i < tasks.length; i++) {
|
// if it is a user make the tasks add points
|
||||||
taskPage.innerHTML += `
|
// or if admin make it do nothing
|
||||||
<div id="${tasks[i].tid}" class="half" style="height: fit-content">
|
if (sessionStorage.getItem("role") === "user") {
|
||||||
<div class="button" onclick="completeTask(${tasks[i].tid})">
|
for (let i = 0; i < tasks.length; i++) {
|
||||||
<p id="taskName">${tasks[i].name}</p>
|
taskPage.innerHTML += `
|
||||||
<p id="${tasks[i].tid}-p">${tasks[i].points} points</p>
|
<div id="${tasks[i].tid}" class="half" style="height: fit-content">
|
||||||
</div>
|
<div class="button" onclick="completeTask(${tasks[i].tid})">
|
||||||
</div>`
|
<p id="taskName">${tasks[i].name}</p>
|
||||||
|
<p id="${tasks[i].tid}-p">${tasks[i].points} points</p>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
|
} else if (sessionStorage.getItem("role") === "admin") {
|
||||||
|
for (let i = 0; i < tasks.length; i++) {
|
||||||
|
taskPage.innerHTML += `
|
||||||
|
<div id="${tasks[i].tid}" class="half" style="height: fit-content">
|
||||||
|
<div class="button" disabled data-tooltip="Admins can't get points">
|
||||||
|
<p id="taskName">${tasks[i].name}</p>
|
||||||
|
<p id="${tasks[i].tid}-p">${tasks[i].points} points</p>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = (history.length -1); i >= 0; i-=1) {
|
for (let i = (history.length -1); i >= 0; i-=1) {
|
||||||
historyPage.innerHTML += `
|
historyPage.innerHTML += `
|
||||||
<div class="full">
|
<div class="full">
|
||||||
@@ -83,13 +104,17 @@ async function populateScreen() {
|
|||||||
</article>
|
</article>
|
||||||
</div>`
|
</div>`
|
||||||
}
|
}
|
||||||
|
for (let i = 0; i < stats.length; i++) {
|
||||||
|
// put user points in box
|
||||||
|
statsPage.innerText += `${stats[i].name}: ${stats[i].points} \n`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function completeTask(taskID) {
|
async function completeTask(taskID) {
|
||||||
let points = document.getElementById(`${taskID}-p`).innerText;
|
let points = document.getElementById(`${taskID}-p`).innerText.split(" ")[0];
|
||||||
let time = new Date().toISOString().split(".")[0];
|
let time = new Date().toISOString().split(".")[0];
|
||||||
let uid = sessionStorage.getItem("uid");
|
let uid = sessionStorage.getItem("uid");
|
||||||
let response = await fetch("/completeTask", {
|
await fetch("/completeTask", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|||||||
95
main.go
95
main.go
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"flag"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -17,11 +18,12 @@ type loginInput struct {
|
|||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type loginOutput struct {
|
type userData struct {
|
||||||
UID int `json:"uid"`
|
UID int `json:"uid"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Role string `json:"role"`
|
Role string `json:"role"`
|
||||||
|
Points int `json:"points"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type task struct {
|
type task struct {
|
||||||
@@ -34,14 +36,14 @@ type taskArray struct {
|
|||||||
Tasks []task `json:"tasks"`
|
Tasks []task `json:"tasks"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type historyReqData struct {
|
type newHistoryData struct {
|
||||||
UID int `json:"uid"`
|
UID int `json:"uid"`
|
||||||
TID int `json:"tid"`
|
TID int `json:"tid"`
|
||||||
Time string `json:"time"`
|
Time string `json:"time"`
|
||||||
PointsGained int `json:"pointsGained"`
|
PointsGained int `json:"pointsGained"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type historyResData struct {
|
type historyData struct {
|
||||||
User string `json:"user"`
|
User string `json:"user"`
|
||||||
Task string `json:"task"`
|
Task string `json:"task"`
|
||||||
Time string `json:"time"`
|
Time string `json:"time"`
|
||||||
@@ -49,32 +51,41 @@ type historyResData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type historyArray struct {
|
type historyArray struct {
|
||||||
History []historyResData `json:"history"`
|
History []historyData `json:"history"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type userPointsData struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Points int `json:"points"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type userPointsArray struct {
|
||||||
|
UserPoints []userPointsData `json:"userPoints"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// log the user into their account
|
// log the user into their account
|
||||||
func login(c *gin.Context) {
|
func login(c *gin.Context) {
|
||||||
// get the username and password from the request
|
// get the username and password from the request
|
||||||
var userData loginInput
|
var requestedUser loginInput
|
||||||
if err := c.BindJSON(&userData); err != nil {
|
if err := c.BindJSON(&requestedUser); err != nil {
|
||||||
c.IndentedJSON(http.StatusBadRequest, userData)
|
c.IndentedJSON(http.StatusBadRequest, requestedUser)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// check for user using given credentials
|
// check for user using given credentials
|
||||||
stmt, err := db.Prepare("SELECT * FROM users WHERE name=?")
|
stmt, err := db.Prepare("SELECT * FROM users WHERE name=?")
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
defer stmt.Close()
|
defer stmt.Close()
|
||||||
var user loginOutput
|
var user userData
|
||||||
err = stmt.QueryRow(userData.Name).Scan(&user.UID, &user.Name, &user.Password, &user.Role)
|
err = stmt.QueryRow(requestedUser.Name).Scan(&user.UID, &user.Name, &user.Password, &user.Role, &user.Points)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// search failed user not real
|
// search failed user not real
|
||||||
c.IndentedJSON(http.StatusNotFound, userData)
|
c.IndentedJSON(http.StatusNotFound, requestedUser)
|
||||||
panic(err)
|
panic(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if user.Password != userData.Password {
|
if user.Password != requestedUser.Password {
|
||||||
// user not real
|
// user not real
|
||||||
c.IndentedJSON(http.StatusNotFound, userData)
|
c.IndentedJSON(http.StatusNotFound, requestedUser)
|
||||||
panic(err)
|
panic(err)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
@@ -107,7 +118,7 @@ func getTasks(c *gin.Context) {
|
|||||||
|
|
||||||
func completeTask(c *gin.Context) {
|
func completeTask(c *gin.Context) {
|
||||||
// get the task data from the request
|
// get the task data from the request
|
||||||
var completedTask historyReqData
|
var completedTask newHistoryData
|
||||||
if err := c.BindJSON(&completedTask); err != nil {
|
if err := c.BindJSON(&completedTask); err != nil {
|
||||||
c.IndentedJSON(http.StatusBadRequest, completedTask)
|
c.IndentedJSON(http.StatusBadRequest, completedTask)
|
||||||
return
|
return
|
||||||
@@ -123,17 +134,30 @@ func completeTask(c *gin.Context) {
|
|||||||
c.IndentedJSON(http.StatusNotModified, completedTask)
|
c.IndentedJSON(http.StatusNotModified, completedTask)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add points to user table
|
||||||
|
stmt, err = db.Prepare("UPDATE users SET points = points + ? WHERE uid=?")
|
||||||
|
if err != nil {
|
||||||
|
c.IndentedJSON(http.StatusNotModified, completedTask)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = stmt.Exec(completedTask.PointsGained, completedTask.UID)
|
||||||
|
if err != nil {
|
||||||
|
c.IndentedJSON(http.StatusNotModified, completedTask)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.IndentedJSON(http.StatusOK, completedTask)
|
c.IndentedJSON(http.StatusOK, completedTask)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHistory(c *gin.Context) {
|
func getHistory(c *gin.Context) {
|
||||||
// get the log of past points gained
|
// get the log of past points gained
|
||||||
var history []historyReqData
|
var history []newHistoryData
|
||||||
// get array of all historyReqData
|
// get array of all history Data
|
||||||
rows, err := db.Query("SELECT * FROM history")
|
rows, err := db.Query("SELECT * FROM history")
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var tempHistoryData historyReqData
|
var tempHistoryData newHistoryData
|
||||||
err = rows.Scan(&tempHistoryData.UID, &tempHistoryData.TID, &tempHistoryData.Time, &tempHistoryData.PointsGained)
|
err = rows.Scan(&tempHistoryData.UID, &tempHistoryData.TID, &tempHistoryData.Time, &tempHistoryData.PointsGained)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.IndentedJSON(http.StatusNotFound, history)
|
c.IndentedJSON(http.StatusNotFound, history)
|
||||||
@@ -143,15 +167,15 @@ func getHistory(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
rows.Close()
|
rows.Close()
|
||||||
|
|
||||||
var historyRes []historyResData
|
var historyRes []historyData
|
||||||
// make the data human-readable
|
// make the data human-readable
|
||||||
for i := 0; i < len(history); i++ {
|
for i := 0; i < len(history); i++ {
|
||||||
var tempHistory historyResData
|
var tempHistory historyData
|
||||||
// get the username
|
// get the username
|
||||||
var tempUser loginOutput
|
var tempUser userData
|
||||||
stmt, err := db.Prepare("SELECT * FROM users WHERE uid=?")
|
stmt, err := db.Prepare("SELECT * FROM users WHERE uid=?")
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
err = stmt.QueryRow(history[i].UID).Scan(&tempUser.UID, &tempUser.Name, &tempUser.Password, &tempUser.Role)
|
err = stmt.QueryRow(history[i].UID).Scan(&tempUser.UID, &tempUser.Name, &tempUser.Password, &tempUser.Role, &tempUser.Points)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
tempHistory.User = tempUser.Name
|
tempHistory.User = tempUser.Name
|
||||||
stmt.Close()
|
stmt.Close()
|
||||||
@@ -197,7 +221,35 @@ func addTask(c *gin.Context) {
|
|||||||
c.IndentedJSON(http.StatusOK, newTask)
|
c.IndentedJSON(http.StatusOK, newTask)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getUserPoints(c *gin.Context) {
|
||||||
|
// get the names of all users
|
||||||
|
var allUsers []userPointsData
|
||||||
|
|
||||||
|
rows, err := db.Query("SELECT name, points FROM users WHERE role='user'")
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
|
// put them in an array of users
|
||||||
|
for rows.Next() {
|
||||||
|
var tempUser userPointsData
|
||||||
|
err = rows.Scan(&tempUser.Name, &tempUser.Points)
|
||||||
|
if err != nil {
|
||||||
|
c.IndentedJSON(http.StatusNotFound, allUsers)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
allUsers = append(allUsers, tempUser)
|
||||||
|
}
|
||||||
|
rows.Close()
|
||||||
|
|
||||||
|
// return to the requester
|
||||||
|
var jsonUserPoints userPointsArray
|
||||||
|
jsonUserPoints.UserPoints = allUsers
|
||||||
|
c.IndentedJSON(http.StatusOK, jsonUserPoints)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
var port string
|
||||||
|
flag.StringVar(&port, "port", "localhost:8080", "define the port you want the program to use to serve")
|
||||||
|
flag.Parse()
|
||||||
//release mode
|
//release mode
|
||||||
//gin.SetMode(gin.ReleaseMode)
|
//gin.SetMode(gin.ReleaseMode)
|
||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
@@ -208,6 +260,7 @@ func main() {
|
|||||||
router.POST("/addTask", addTask)
|
router.POST("/addTask", addTask)
|
||||||
router.GET("/getTasks", getTasks)
|
router.GET("/getTasks", getTasks)
|
||||||
router.GET("/getHistory", getHistory)
|
router.GET("/getHistory", getHistory)
|
||||||
|
router.GET("/getUserPoints", getUserPoints)
|
||||||
|
|
||||||
// page routes
|
// page routes
|
||||||
router.LoadHTMLGlob("frontend/*")
|
router.LoadHTMLGlob("frontend/*")
|
||||||
@@ -216,7 +269,7 @@ func main() {
|
|||||||
})
|
})
|
||||||
router.Static("/frontend", "./frontend")
|
router.Static("/frontend", "./frontend")
|
||||||
|
|
||||||
router.Run("localhost:8080")
|
router.Run(port)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkErr(err error) {
|
func checkErr(err error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user