Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Voor en achter #27

Merged
merged 56 commits into from
Jul 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
3f4d7c7
vinvoor: init
Topvennie Jun 11, 2024
0328a81
zess: development docker
Topvennie Jun 11, 2024
f230190
vingo: customizable redirect
Topvennie Jun 16, 2024
2a795d8
zess: add -c option
Topvennie Jun 16, 2024
ee1567e
vinvoor: add login
Topvennie Jun 16, 2024
ec72885
vingo: add cors
Topvennie Jun 21, 2024
3747e67
vingo: add json serialization
Topvennie Jun 21, 2024
f9d81c7
vinvoor: add login and logout
Topvennie Jun 21, 2024
4b9d47f
vinvoor: add a cards page
Topvennie Jun 21, 2024
9e861d3
zess: add development instructions
Topvennie Jun 21, 2024
ddf3e91
vinvoor: add a theme
Topvennie Jun 21, 2024
ffb934b
vinvoor: refactor
Topvennie Jun 21, 2024
874ccc8
vinvoor: add support for dark and light mode
Topvennie Jun 21, 2024
0b9ef39
vinvoor: move url's to .env
Topvennie Jun 21, 2024
66ff7cf
zess: start vinvoor as non root user
Topvennie Jun 21, 2024
ec0b38d
vinvoor: add a cards overview
Topvennie Jun 21, 2024
98c1bf4
vingo: more serialization
Topvennie Jun 22, 2024
506895d
vinvoor: refactor the cards page
Topvennie Jun 22, 2024
d7e9ec4
vinvoor: change to camelCase
Topvennie Jun 22, 2024
71e942a
vinvoor: add a leaderboard
Topvennie Jun 22, 2024
221bd9a
vinvoor: add a welcome page
Topvennie Jun 22, 2024
5fbf7d9
zess: change env var to export in dev script
hannes-dev Jun 25, 2024
4b8372d
vingo: add database migrations
hannes-dev Jun 25, 2024
7762f73
vingo: fix api returning null when no results
hannes-dev Jun 25, 2024
9bed987
vingo: add card register via api
hannes-dev Jun 25, 2024
52df507
vingo: add card id and name
hannes-dev Jun 25, 2024
632bfb0
vinvoor: add a github activity style overview
Topvennie Jun 28, 2024
060ac73
vinvoor: merge branch 'main' into vinvoor-heatmap
Topvennie Jun 28, 2024
f13d543
vinvoor: support adding new cards
Topvennie Jul 6, 2024
5b5a3a6
vinvoor: merge vinvoor-heatmap into voor-en-achter
Topvennie Jul 6, 2024
7c0519b
vinvoor: show current checkin status
Topvennie Jul 6, 2024
ed6d70a
vinvoor: show current streak days
Topvennie Jul 6, 2024
41e16cc
vinvoor: show the user's most common days
Topvennie Jul 6, 2024
dc2ef3d
vinvoor: simple overview page
Topvennie Jul 16, 2024
5d0f872
vinvoor: fix crash when no scans are registered
Topvennie Jul 16, 2024
bb8a855
vinvoor: center graphs in the overview
Topvennie Jul 16, 2024
3ab6c3d
vinvoor: add support for new comers
Topvennie Jul 16, 2024
c4bf180
vingo: move to gorm
hannes-dev Jul 16, 2024
c42c99e
vingo: go get -u && go mod tidy
hannes-dev Jul 16, 2024
371b89f
vingo: card register status endpoint
hannes-dev Jul 16, 2024
2f3737c
vingo: ability to add name to card
hannes-dev Jul 16, 2024
c295ae8
vingo: return if last register was success
hannes-dev Jul 16, 2024
40b24a3
vingo: return extra stats for cards
hannes-dev Jul 16, 2024
3735c44
vingo: time remaining on card status endpoint
hannes-dev Jul 16, 2024
1864bdc
vinvoor: support new card features
Topvennie Jul 17, 2024
2ac3951
vingo: add leaderboard position change
hannes-dev Jul 17, 2024
0deb98a
vingo: pieter post pieter post pieter post verdient de kost (met zijn…
hannes-dev Jul 17, 2024
77e6dac
vinvoor: pieter post deed ambetant
Topvennie Jul 17, 2024
21cf2e5
vinvoor: show position changes in the leaderboard
Topvennie Jul 17, 2024
9a208e3
vinvoor: show a scan overview
Topvennie Jul 17, 2024
db96f94
vingo: fix scans
hannes-dev Jul 18, 2024
e403886
vingo: card handlers to receivers
hannes-dev Jul 18, 2024
db59fd5
vingo: settings endpoint
hannes-dev Jul 18, 2024
61aa8fc
vingo: cleanup
hannes-dev Jul 18, 2024
656a329
vinvoor: add a new zess logo
Topvennie Jul 18, 2024
f70fb2f
vinvoor: scans
Topvennie Jul 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 20 additions & 28 deletions vingo/database/cards.go
Original file line number Diff line number Diff line change
@@ -1,43 +1,35 @@
package database

import "time"

type Card struct {
Serial string `json:"serial"`
CreatedAt time.Time `json:"createdAt"`
}

var (
cardsCreateStmt = `
CREATE TABLE IF NOT EXISTS cards (
serial TEXT NOT NULL PRIMARY KEY UNIQUE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
user_id INTEGER NOT NULL REFERENCES users(id)
);
`
)

func CreateCard(serial string, user_id int) error {
_, err := db.Exec("INSERT INTO cards (serial, user_id) VALUES ($1, $2);", serial, user_id)
return err
return gorm_db.Create(&Card{Serial: serial, UserId: user_id}).Error
}

func GetCardsForUser(user_id int) ([]Card, error) {
rows, err := db.Query("SELECT serial, created_at FROM cards WHERE user_id = $1;", user_id)
var cards []Card
result := gorm_db.Where("user_id = ?", user_id).Find(&cards)
return cards, result.Error
}

func GetCardsAndStatsForUser(user_id int) ([]CardAPI, error) {
rows, err := db.Query(`
SELECT cards.id, cards.created_at, serial, name, COUNT(scans.id), (select MAX(scan_time) from scans where card_serial = cards.serial) from cards LEFT JOIN scans on scans.card_serial = serial WHERE
user_id = $1 GROUP BY cards.id;
`, user_id)

if err != nil {
return nil, err
}
defer rows.Close()

cards := make([]Card, 0)
cards := []CardAPI{}
for rows.Next() {
var card Card
err := rows.Scan(&card.Serial, &card.CreatedAt)
if err != nil {
return nil, err
}
cards = append(cards, card)
var item CardAPI
_ = rows.Scan(&item.Id, &item.CreatedAt, &item.Serial, &item.Name, &item.AmountUsed, &item.LastUsed)
cards = append(cards, item)
}

return cards, nil
}

func UpdateCardName(id int, name string, user_id int) error {
return gorm_db.Model(&Card{}).Where("id = ? AND user_id = ?", id, user_id).Update("name", name).Error
}
9 changes: 0 additions & 9 deletions vingo/database/days.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,6 @@ type Day struct {
Date time.Time
}

var (
daysCreateStmt = `
CREATE TABLE IF NOT EXISTS days (
id SERIAL NOT NULL PRIMARY KEY,
date DATE NOT NULL UNIQUE
);
`
)

func CreateDays(first_day time.Time, last_day time.Time) error {
tx, err := db.Begin()
if err != nil {
Expand Down
41 changes: 23 additions & 18 deletions vingo/database/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,39 @@ package database
import (
"database/sql"
"log"

"gorm.io/driver/postgres"
"gorm.io/gorm"
)

var (
db *sql.DB
db *sql.DB
gorm_db *gorm.DB
)

func createTables() {
// Tables to create
createStmts := []string{usersCreateStmt, settingsCreateStmt, cardsCreateStmt, scansCreateStmt, daysCreateStmt}
for _, stmt := range createStmts {
_, err := db.Exec(stmt)
if err != nil {
log.Println("Error creating table with query: \n", stmt)
log.Fatal(err)
}
}
}

func Get() *sql.DB {
return db
}

func OpenDatabase(conn string) {
new_db, err := sql.Open("postgres", conn)
func OpenDatabase(db_string string) {
new_db, err := gorm.Open(postgres.Open(db_string), &gorm.Config{})
if err != nil {
log.Panicln("Error opening database connection")
log.Println("Error opening database connection")
log.Fatal(err)
}
db = new_db
createTables()

err = new_db.AutoMigrate()
if err != nil {
log.Println("Error migrating database")
log.Fatal(err)
}

err = new_db.AutoMigrate(&User{}, &Card{}, &Scan{}, &Day{}, &Settings{}, &Season{})
if err != nil {
log.Println("Error migrating database")
log.Fatal(err)
}

gorm_db = new_db
db, _ = new_db.DB()
}
70 changes: 70 additions & 0 deletions vingo/database/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package database

import (
"time"

"gorm.io/gorm"
)

type BaseModel struct {
Id int `json:"id" gorm:"primarykey"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
}

type User struct {
BaseModel
Username string `json:"username"`
Admin bool `json:"admin"`
SettingsId int
Settings Settings `json:"settings"`
Cards []Card `json:"-" gorm:"foreignKey:UserId;references:Id"`
}

type Settings struct {
BaseModel
ScanInOut bool `json:"scanInOut"`
Leaderboard bool `json:"leaderboard"`
Public bool `json:"public"`
}

type Card struct {
BaseModel
Serial string `gorm:"uniqueIndex"`
Name string
UserId int
User User
Scans []Scan `gorm:"foreignKey:CardSerial;references:Serial"`
}

func Card_to_API(card Card) CardAPI {
var lastUsed time.Time = card.CreatedAt
if len(card.Scans) != 0 {
lastUsed = card.Scans[len(card.Scans)-1].ScanTime
}

return CardAPI{
Id: card.Id,
Serial: card.Serial,
Name: card.Name,
LastUsed: lastUsed,
AmountUsed: len(card.Scans),
}
}

type CardAPI struct {
Id int `json:"id"`
CreatedAt time.Time `json:"createdAt"`
Serial string `json:"serial"`
Name string `json:"name"`
LastUsed time.Time `json:"lastUsed"`
AmountUsed int `json:"amountUsed"`
}

type Scan struct {
BaseModel
ScanTime time.Time `json:"scanTime"`
CardSerial string `json:"cardSerial" gorm:"index"`
Card Card `json:"-" gorm:"foreignKey:CardSerial;references:Serial"`
}
65 changes: 24 additions & 41 deletions vingo/database/scans.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package database

import "time"

type Scan struct {
ScanTime time.Time `json:"scanTime"`
Card string `json:"card"`
}
import (
"time"
)

type Present struct {
Date time.Time
Expand All @@ -14,42 +11,27 @@ type Present struct {
}

type LeaderboardItem struct {
Position int `json:"position"`
Username string `json:"username"`
TotalDays int `json:"totalDays"`
Position int `json:"position"`
UserId int `json:"userId"`
Username string `json:"username"`
TotalDays int `json:"totalDays"`
PositionChange int `json:"positionChange"`
}

var (
scansCreateStmt = `
CREATE TABLE IF NOT EXISTS scans (
id SERIAL NOT NULL PRIMARY KEY,
scan_time TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,
scan_in BOOLEAN,
card_serial TEXT NOT NULL REFERENCES cards(serial)
);
`
)

func CreateScan(card_serial string) error {
_, err := db.Exec("INSERT INTO scans (card_serial) VALUES ($1);", card_serial)
return err
return gorm_db.Create(&Scan{ScanTime: time.Now(), CardSerial: card_serial}).Error
}

func GetScansForUser(user_id int) ([]Scan, error) {
scans_rows, err := db.Query("SELECT scan_time, card_serial FROM scans WHERE card_serial IN (SELECT serial FROM cards WHERE user_id = $1) ORDER BY scan_time DESC;", user_id)
if err != nil {
return nil, err
}
var user User
result := gorm_db.Preload("Cards.Scans").First(&user, user_id)

var scans []Scan

for scans_rows.Next() {
var scan Scan
_ = scans_rows.Scan(&scan.ScanTime, &scan.Card)

scans = append(scans, scan)
for _, card := range user.Cards {
scans = append(scans, card.Scans...)
}
return scans, nil

return scans, result.Error
}

func GetPresenceHistory(user_id int) ([]Present, error) {
Expand Down Expand Up @@ -78,7 +60,7 @@ func GetPresenceHistory(user_id int) ([]Present, error) {
return nil, err
}

var presences []Present
presences := []Present{}
for rows.Next() {
var present Present
_ = rows.Scan(&present.Date, &present.Present, &present.StreakDay)
Expand All @@ -89,24 +71,25 @@ func GetPresenceHistory(user_id int) ([]Present, error) {
return presences, nil
}

func TotalDaysPerUser() ([]LeaderboardItem, error) {
func TotalDaysPerUser(before_time time.Time) ([]LeaderboardItem, error) {
rows, err := db.Query(`
SELECT count, username, RANK() OVER (ORDER BY count desc) AS position
FROM (SELECT COUNT(DISTINCT ((scan_time - INTERVAL '4 hours') AT TIME ZONE 'Europe/Brussels')::date), username
SELECT user_id, count, username, RANK() OVER (ORDER BY count desc) AS position
FROM (SELECT COUNT(DISTINCT ((scan_time - INTERVAL '4 hours') AT TIME ZONE 'Europe/Brussels')::date), username, users.id as user_id
FROM scans
LEFT JOIN cards ON card_serial = serial
LEFT JOIN users ON user_id = users.id
GROUP BY username);
`)
WHERE scan_time < $1
GROUP BY username, users.id);
`, before_time)

if err != nil {
return nil, err
}

var leaderboard []LeaderboardItem
leaderboard := []LeaderboardItem{}
for rows.Next() {
var item LeaderboardItem
_ = rows.Scan(&item.TotalDays, &item.Username, &item.Position)
_ = rows.Scan(&item.UserId, &item.TotalDays, &item.Username, &item.Position)

leaderboard = append(leaderboard, item)
}
Expand Down
24 changes: 3 additions & 21 deletions vingo/database/settings.go
Original file line number Diff line number Diff line change
@@ -1,32 +1,14 @@
package database

type Settings struct {
ScanInOut bool `json:"scanInOut"`
Leaderboard bool `json:"leaderboard"`
Public bool `json:"public"`
}

var (
settingsCreateStmt = `
CREATE TABLE IF NOT EXISTS settings (
user_id INT NOT NULL PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
public BOOLEAN NOT NULL DEFAULT FALSE,
scan_in_out BOOLEAN NOT NULL DEFAULT FALSE,
leaderboard BOOLEAN NOT NULL DEFAULT TRUE
);
`
)

func CreateSettings(user_id int) error {
_, err := db.Exec("INSERT INTO settings (user_id) VALUES ($1) ON CONFLICT DO NOTHING;", user_id)
return err
}

func GetSettings(user_id int) (*Settings, error) {
row := db.QueryRow("SELECT scan_in_out, leaderboard, public FROM settings WHERE user_id = $1;", user_id)
settings := new(Settings)
err := row.Scan(&settings.ScanInOut, &settings.Leaderboard, &settings.Public)
return settings, err
var settings Settings
result := gorm_db.First(&settings, "user_id = ?", user_id)
return &settings, result.Error
}

func UpdateSettings(user_id int, settings Settings) error {
Expand Down
Loading