feat(display-attendies): split list

Split up suiter list in attendies and suiterWaitingList

and added localization with goi18n, btw
This commit is contained in:
nikurasu 2024-03-03 22:55:50 +01:00
parent a914d6a328
commit 0965f9e115
Signed by: Nikurasu
GPG key ID: 9E7F14C03EF1F271
21 changed files with 345 additions and 17 deletions

4
.vscode/launch.json vendored
View file

@ -8,8 +8,8 @@
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "src/main.go"
"mode": "debug",
"program": "src/main.go",
}
]
}

View file

@ -2,9 +2,9 @@ FROM golang:alpine3.17 AS build
WORKDIR /build
COPY ./src ./src
WORKDIR /build/src
RUN ls
RUN apk add gcc libc-dev
RUN go get .
RUN go build -o /build/pretix-proxy
RUN CGO_ENABLED=1 go build -o /build/pretix-proxy
FROM alpine:3.17 AS final
COPY --from=build /build/pretix-proxy /bin/pretix-proxy

View file

@ -1,6 +0,0 @@
DOMAIN="reg.ulmer-furs.de"
API_KEY="NeedForEep"
DEBUG="true"
DATABASE_PATH="/home/tamaki/Documents/coding/pretix-proxy/main.db"
API_KEY_PRETIX="ktb7ahh2dzkultyk2vqkafkd7s06fj25lie55a9tx9g2is682an55v1wx8zsh4ij"
SECRET="dfdsfdsfdsfsdfsf"

View file

@ -2,9 +2,15 @@ package controller
import (
"fmt"
"sort"
"github.com/gofiber/fiber/v2"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/text/language"
"ulmer-furs.de/pretix-proxy/v2/app/service"
"ulmer-furs.de/pretix-proxy/v2/app/util"
"ulmer-furs.de/pretix-proxy/v2/config"
"ulmer-furs.de/pretix-proxy/v2/entities"
)
// @Description Get the attendies of an event by the name
@ -23,6 +29,13 @@ func GetAttendiesByEventPublic(c *fiber.Ctx) error {
}
func GetAttendiesByEventPublicTable(c *fiber.Ctx) error {
siteLang := c.Query("lang")
var localizer *i18n.Localizer
if siteLang == "de-DE" {
localizer = i18n.NewLocalizer(config.LocaleBundle, language.German.String())
} else {
localizer = i18n.NewLocalizer(config.LocaleBundle)
}
name := c.Params("name")
event, err := service.Get_db_event_by_event(name)
if err != nil {
@ -32,8 +45,37 @@ func GetAttendiesByEventPublicTable(c *fiber.Ctx) error {
if err != nil {
return c.Status(fiber.ErrNotFound.Code).SendString("attendies not found")
}
localizations := map[string]string{
"Attendie": localizer.MustLocalize(&i18n.LocalizeConfig{
MessageID: "Attendie",
PluralCount: 2,
}),
"HelloWorld": localizer.MustLocalize(&i18n.LocalizeConfig{
MessageID: "HelloWorld",
}),
"Role": localizer.MustLocalize(&i18n.LocalizeConfig{
MessageID: "Role",
PluralCount: 1,
}),
"Name": localizer.MustLocalize(&i18n.LocalizeConfig{
MessageID: "Name",
PluralCount: 1,
}),
}
sort.Sort(entities.ByRegistrationTime(attendies))
roleSuiter, _ := service.GetRoleByName("Suiter")
roleSpotter, _ := service.GetRoleByName("Spotter")
suiterWaitingList := util.CreateSuiterWaitingList(
&attendies,
event.SuiterPerSpotter,
&roleSuiter,
&roleSpotter,
)
fmt.Printf("len(attendies): %v\n", len(attendies))
return c.Render("app/views/index", fiber.Map{
"Title": fmt.Sprintf("%s Attendies", *event.Event),
"Attendies": attendies,
"Event Name": event.Name,
"Attendies": attendies,
"SuiterWaitingList": suiterWaitingList,
"Locals": localizations,
})
}

View file

@ -44,7 +44,7 @@ func GetAttendiesByEvent(event entities.Db_Event) ([]entities.Db_Attendies, erro
return attendies, nil
}
func GetAttendiesByEventPrivacy(event entities.Db_Event, privacy bool) ([]entities.Db_Attendies, error) {
func GetAttendiesByEventPrivacy(event entities.Db_Event, privacy bool) (entities.AttendiesList, error) {
var attendies []entities.Db_Attendies
result := config.Database.Model(&entities.Db_Attendies{}).Preload("Event").Preload("Role").Where("event_id = ?", event.ID).Where("privacy = ?", privacy).Find(&attendies)
if result.Error != nil {

View file

@ -0,0 +1,28 @@
package util
import (
"fmt"
"ulmer-furs.de/pretix-proxy/v2/entities"
)
func CreateSuiterWaitingList(attendiesList *entities.AttendiesList, suiterPerSpotter *int, suiter, spotter *entities.Role) entities.AttendiesList {
spotterCount := attendiesList.CountByRole(*spotter)
suiterCount := spotterCount * *suiterPerSpotter
var suiterCounter int
var suiterWatinglist entities.AttendiesList
var i int
for i < len(*attendiesList) {
if (*attendiesList)[i].Role == *suiter {
suiterCounter++
}
if suiterCounter > suiterCount && (*attendiesList)[i].Role == *suiter {
suiterWatinglist = append(suiterWatinglist, (*attendiesList)[i])
*attendiesList = append((*attendiesList)[:i], (*attendiesList)[i+1:]...)
} else {
i++
}
}
fmt.Printf("len(a): %v\n", len(*attendiesList))
return suiterWatinglist
}

View file

@ -41,6 +41,7 @@ func GetAttendieListFromPretixJson(pretixEvent entities.Pretix_Event, event enti
var name string
for _, order := range pretixEvent.Results {
indexParticipation := slices.IndexFunc(order.Positions, func(p entities.Pretix_Position) bool { return p.Item == *event.ItemIdParticipation })
indexBadge := slices.IndexFunc(order.Positions, func(p entities.Pretix_Position) bool { return p.Item == *event.ItemIdBadge })
indexRestaurant := slices.IndexFunc(order.Positions, func(p entities.Pretix_Position) bool { return p.Item == *event.ItemIdRestaurant })
@ -125,6 +126,8 @@ func GetAttendiesFromPretixJsonWithRoleQuestion(pretixEvent *entities.Pretix_Eve
return attendies, err
}
attendie.RegistrationTime = order.Datetime
attendies = append(attendies, attendie)
}
return attendies, nil

View file

@ -10,6 +10,8 @@
<main>
<h1>{{.Title}}</h1>
{{template "table" .}}
<p>Test:</p>
<p>{{.Locals.HelloWorld}}</p>
</main>
</body>
</html>

View file

@ -1,9 +1,12 @@
{{define "table"}}
<h1>{{ index . "Event Name" }} {{ .Locals.Attendie }}</h1>
<h2></h2>
<table>
<thead>
<tr class="tableHeading">
<th>Name</th>
<th>Role</th>
<th>{{ .Locals.Name }}</th>
<th>{{ .Locals.Role }}</th>
<th>Time</th>
</tr>
</thead>
<tbody>
@ -11,6 +14,7 @@
<tr>
<td>{{.Nickname}}</td>
<td>{{.Role.Name}}</td>
<td>{{.RegistrationTime}}</td>
</tr>
{{end}}
</tbody>

View file

@ -0,0 +1,79 @@
package config
import (
"embed"
"encoding/json"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/text/language"
)
var LocaleBundle *i18n.Bundle
func SetupLocalization(locaizationFS *embed.FS) {
LocaleBundle = i18n.NewBundle(language.English)
for _, message := range defaultMessages {
LocaleBundle.AddMessages(language.English, &message)
}
LocaleBundle.RegisterUnmarshalFunc("json", json.Unmarshal)
LocaleBundle.LoadMessageFileFS(locaizationFS, "localization/active.de.json")
}
var defaultMessages = []i18n.Message{
{
ID: "HelloWorld",
Other: "Hello newer World",
},
{
ID: "Attendie",
One: "Attendie",
Other: "Attendies",
},
{
ID: "Role",
One: "Role",
Other: "Roles",
},
{
ID: "Name",
One: "Name",
Other: "Names",
},
{
ID: "Registered",
Other: "Registered",
},
{
ID: "SuiterWatinglist",
Other: "Suiter Watinglist",
},
{
ID: "WatinglistDesc",
Other: "We set a ratio of Suiters per Spotter for each event in order to keep the count of suiters manageble for them. If you are listed here we sadly don't have enough spotters yet.",
},
{
ID: "Suiter",
One: "Suiter",
Other: "Suiters",
},
{
ID: "Guest",
One: "Guest",
Other: "Guets",
},
{
ID: "Spotter",
One: "Spotter",
Other: "Spotters",
},
{
ID: "Photographer",
One: "Photographer",
Other: "Photographers",
},
{
ID: "SpecialAnimal",
One: "#SpecialAnimal",
Other: "#SpecialAnimals",
},
}

View file

@ -0,0 +1,13 @@
package entities
type AttendiesList []Db_Attendies
func (a AttendiesList) CountByRole(role Role) int {
var count int
for _, attendie := range a {
if attendie.Role == role {
count++
}
}
return count
}

View file

@ -1,9 +1,25 @@
package entities
import (
"time"
"gorm.io/gorm"
)
type ByRegistrationTime AttendiesList
func (a ByRegistrationTime) Len() int {
return len(a)
}
func (a ByRegistrationTime) Less(i, j int) bool {
return a[i].RegistrationTime.Unix() < a[j].RegistrationTime.Unix()
}
func (a ByRegistrationTime) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
type Db_Attendies struct {
gorm.Model
Nickname string `gorm:"column:nickname;not null"`
@ -11,6 +27,7 @@ type Db_Attendies struct {
Event Db_Event
RoleID int `gorm:"not null"`
Role Role
AttendsRestaurant bool `gorm:"column:attends_restaurant;not null"`
Privacy bool `gorm:"column:privacy;not null"`
AttendsRestaurant bool `gorm:"column:attends_restaurant;not null"`
Privacy bool `gorm:"column:privacy;not null"`
RegistrationTime time.Time `gorm:"column:registration_time;not null;default:CURRENT_TIMESTAMP"`
}

View file

@ -27,6 +27,7 @@ type Db_Event struct {
VariationIdPhotograph *int `gorm:"variation_id_photograph"`
VariationIdSpecialAnimal *int `gorm:"variation_id_special_animal"`
EventType *string `gorm:"cloumn:event_type;not null" validate:"required"`
SuiterPerSpotter *int `gorm:"column:suiter_per_spotter;not null;default:5" validate:"required"`
}
type Db_Event_Public struct {

View file

@ -1,5 +1,7 @@
package entities
import "time"
type Pretix_Event struct {
Count int `json:"count"`
Results []Pretix_Result `json:"results"`
@ -8,6 +10,7 @@ type Pretix_Event struct {
type Pretix_Result struct {
Status string `json:"status"`
Positions []Pretix_Position `json:"positions"`
Datetime time.Time `json:"datetime"`
}
type Pretix_Position struct {

View file

@ -20,6 +20,7 @@ require (
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/nicksnyder/go-i18n/v2 v2.4.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/text v0.14.0 // indirect
)

View file

@ -0,0 +1,21 @@
{
"Attendie": {
"hash": "sha1-4c29d6c952ccd2b114d1792c7b18fa7f7052ebed",
"one": "Teilnehmer*in",
"other": "Teilnehmende"
},
"HelloWorld": {
"hash": "sha1-6225ffc638ce81e53cdf7868fe0c7435594f11e4",
"other": "Hallo neuere Welt"
},
"Name": {
"hash": "sha1-2b7c08c3ab75f37e2da656c1aab228f5f3a793b1",
"one": "Name",
"other": "Namen"
},
"Role": {
"hash": "sha1-47dcc27d6e87ece8baebe7e3877a261a5467093d",
"one": "Rolle",
"other": "Rollen"
}
}

View file

@ -0,0 +1,38 @@
{
"Attendie": {
"one": "Attendie",
"other": "Attendies"
},
"Guest": {
"one": "Guest",
"other": "Guets"
},
"HelloWorld": "Hello newer World",
"Name": {
"one": "Name",
"other": "Names"
},
"Photographer": {
"one": "Photographer",
"other": "Photographers"
},
"Registered": "Registered",
"Role": {
"one": "Role",
"other": "Roles"
},
"SpecialAnimal": {
"one": "#SpecialAnimal",
"other": "#SpecialAnimals"
},
"Spotter": {
"one": "Spotter",
"other": "Spotters"
},
"Suiter": {
"one": "Suiter",
"other": "Suiters"
},
"SuiterWatinglist": "Suiter Watinglist",
"WatinglistDesc": "We set a ratio of Suiters per Spotter for each event in order to keep the count of suiters manageble for them. If you are listed here we sadly don't have enough spotters yet."
}

View file

@ -0,0 +1,39 @@
{
"Guest": {
"hash": "sha1-7b7f214bbd4af36f25668b0ddade965422d342fd",
"one": "Guest",
"other": "Guets"
},
"Photographer": {
"hash": "sha1-dc41992cfe878fe6744f94c3a3fc5843d9f1bc11",
"one": "Photographer",
"other": "Photographers"
},
"Registered": {
"hash": "sha1-a844fcf834e7d026e7936e042c0ce2777b7fb4d9",
"other": "Registered"
},
"SpecialAnimal": {
"hash": "sha1-7f937e9e4906c8f52977132faa76b81f3a331e45",
"one": "#SpecialAnimal",
"other": "#SpecialAnimals"
},
"Spotter": {
"hash": "sha1-6f53dff03ced62b694851ffe37aab682b4b2b227",
"one": "Spotter",
"other": "Spotters"
},
"Suiter": {
"hash": "sha1-eb6248e60da77b4df76de9b35efe44178ee34ead",
"one": "Suiter",
"other": "Suiters"
},
"SuiterWatinglist": {
"hash": "sha1-a5d3dc94fc4f3f0604f0cc5e077c0c9eb43340d4",
"other": "Suiter Watinglist"
},
"WatinglistDesc": {
"hash": "sha1-aadc433a212fca8d927e9134520f5a10aa7e4263",
"other": "We set a ratio of Suiters per Spotter for each event in order to keep the count of suiters manageble for them. If you are listed here we sadly don't have enough spotters yet."
}
}

View file

@ -15,6 +15,9 @@ var viewFS embed.FS
//go:embed app/static/*
var staticFS embed.FS
//go:embed localization/active.*.json
var locaizationFS embed.FS
func main() {
config.LoadEnv()
config.Connect()
@ -23,6 +26,7 @@ func main() {
config.SetupFiber(viewFS, staticFS)
config.SetupCors()
config.SetupHttp()
config.SetupLocalization(&locaizationFS)
if config.Env.Debug {
config.App.Use(cors.New(cors.Config{

21
src/translate.de.json Normal file
View file

@ -0,0 +1,21 @@
{
"Attendie": {
"hash": "sha1-4c29d6c952ccd2b114d1792c7b18fa7f7052ebed",
"one": "Attendie",
"other": "Attendies"
},
"HelloWorld": {
"hash": "sha1-6225ffc638ce81e53cdf7868fe0c7435594f11e4",
"other": "Hello newer World"
},
"Name": {
"hash": "sha1-2b7c08c3ab75f37e2da656c1aab228f5f3a793b1",
"one": "Name",
"other": "Names"
},
"Role": {
"hash": "sha1-47dcc27d6e87ece8baebe7e3877a261a5467093d",
"one": "Role",
"other": "Roles"
}
}

18
src/translate.de.toml Normal file
View file

@ -0,0 +1,18 @@
[Attendie]
hash = "sha1-4c29d6c952ccd2b114d1792c7b18fa7f7052ebed"
one = "Attendie"
other = "Attendies"
[HelloWorld]
hash = "sha1-6225ffc638ce81e53cdf7868fe0c7435594f11e4"
other = "Hello newer World"
[Name]
hash = "sha1-2b7c08c3ab75f37e2da656c1aab228f5f3a793b1"
one = "Name"
other = "Names"
[Role]
hash = "sha1-47dcc27d6e87ece8baebe7e3877a261a5467093d"
one = "Role"
other = "Roles"