index endpoint start

This commit is contained in:
Simon Martens
2024-11-16 02:30:20 +01:00
parent d4feb20f07
commit 527fbfa000
14 changed files with 230 additions and 25 deletions

51
.air.toml Normal file
View File

@@ -0,0 +1,51 @@
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./tmp/main"
cmd = "go build -tags=\"dev\" -o ./tmp/main ."
delay = 1000
exclude_dir = ["assets", "views", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
post_cmd = []
pre_cmd = []
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
main_only = false
time = false
[misc]
clean_on_exit = false
[proxy]
app_port = 0
enabled = false
proxy_port = 0
[screen]
clear_on_rebuild = false
keep_scroll = true

View File

@@ -1,4 +1,4 @@
package controller
package controllers
import (
"net/http"

21
controllers/years.go Normal file
View File

@@ -0,0 +1,21 @@
package controllers
import (
"github.com/Theodor-Springmann-Stiftung/kgpz_web/app"
"github.com/gofiber/fiber/v2"
)
func GetYear(kgpz *app.KGPZ) fiber.Handler {
return func(c *fiber.Ctx) error {
y := c.Params("year", "1764")
if len(y) != 4 {
return c.SendStatus(fiber.StatusBadRequest)
}
issues := kgpz.Library.Issues.GetYear(y)
if len(issues.Issues) == 0 {
return c.SendStatus(fiber.StatusNotFound)
}
return c.Render("/", fiber.Map{"model": issues})
}
}

View File

@@ -31,7 +31,6 @@ type FileWatcher struct {
}
func NewFileWatcher() (*FileWatcher, error) {
fw := &FileWatcher{mu: sync.Mutex{}}
fw.Watch()
return fw, nil
@@ -96,8 +95,8 @@ func (fw *FileWatcher) Watch() error {
if !ok {
return
}
log.Println("event:", event)
if !event.Has(fsnotify.Chmod) {
log.Println("event:", event)
fw.mu.Lock()
for _, wf := range fw.wf {
wf(event.Name)

View File

@@ -37,7 +37,7 @@ func main() {
kgpz := app.NewKGPZ(cfg)
kgpz.Init()
server := server.Start(kgpz, cfg)
server := server.Create(kgpz, cfg)
Start(kgpz, server)
}

View File

@@ -1,5 +0,0 @@
# Notes on xml reading
The models expect certain files and a certain file XML structure and throw quite often if the structure is not as expected.
This is by design, as the models are supposed to be used in a controlled environment. Changes in the XML schema should be reflected in the models.
All collections in the models should be kept thread-safe.

View File

@@ -11,7 +11,31 @@ type IssueProvider struct {
type Issues struct {
XMLName xml.Name `xml:"stuecke"`
Issue []Issue `xml:"stueck"`
Issues []Issue `xml:"stueck"`
}
func (i *IssueProvider) GetYear(year string) YearViewModel {
res := YearViewModel{Year: year}
last := ""
for _, issue := range i.Items.Issues {
if len(issue.Datum.When) < 4 {
continue
}
date := issue.Datum.When[0:4]
if date != last {
res.PushAvailable(date)
last = date
}
if date == year {
res.PushIssue(issue)
}
}
res.SortAvailableYears()
return res
}
type Issue struct {
@@ -39,13 +63,13 @@ type Additional struct {
}
func (i Issues) Append(data Issues) Issues {
i.Issue = append(i.Issue, data.Issue...)
i.Issues = append(i.Issues, data.Issues...)
return i
}
func (i Issues) String() string {
var res []string
for _, issue := range i.Issue {
for _, issue := range i.Issues {
res = append(res, issue.String())
}

View File

@@ -81,5 +81,5 @@ type Reference struct {
}
type Value struct {
Value string `xml:",chardata"`
Chardata string `xml:",chardata"`
}

84
providers/year.go Normal file
View File

@@ -0,0 +1,84 @@
package providers
import (
"slices"
"strconv"
"time"
)
const TLAYOUT = "2006-01-02"
var TRANSLM = map[string][]string{
"January": {"Januar", "Jan"},
"February": {"Februar", "Feb"},
"March": {"März", "Mär"},
"April": {"April", "Apr"},
"May": {"Mai", "Mai"},
"June": {"Juni", "Jun"},
"July": {"Juli", "Jul"},
"August": {"August", "Aug"},
"September": {"September", "Sep"},
"October": {"Oktober", "Okt"},
"November": {"November", "Nov"},
"December": {"Dezember", "Dez"},
}
var TRANSLD = map[string][]string{
"Monday": {"Montag", "Mo"},
"Tuesday": {"Dienstag", "Di"},
"Wednesday": {"Mittwoch", "Mi"},
"Thursday": {"Donnerstag", "Do"},
"Friday": {"Freitag", "Fr"},
"Saturday": {"Samstag", "Sa"},
"Sunday": {"Sonntag", "So"},
}
type IssueViewModel struct {
Issue
Weekday []string
Day int
Month []string
}
func NewIssueView(i Issue) (IssueViewModel, error) {
t, err := time.Parse(TLAYOUT, i.Datum.When)
if err != nil {
return IssueViewModel{}, err
}
return IssueViewModel{
Issue: i,
Weekday: append(TRANSLD[t.Weekday().String()], t.Weekday().String()),
Day: t.Day(),
Month: append(TRANSLM[t.Month().String()], i.Datum.When[5:7]),
}, nil
}
type YearViewModel struct {
Year string
AvailableYears []int
Issues []IssueViewModel
}
func (y *YearViewModel) PushIssue(i Issue) {
iv, err := NewIssueView(i)
if err != nil {
return
}
y.Issues = append(y.Issues, iv)
}
func (y *YearViewModel) PushAvailable(s string) {
i, err := strconv.Atoi(s)
if err != nil {
return
}
if !slices.Contains(y.AvailableYears, i) {
y.AvailableYears = append(y.AvailableYears, i)
}
}
func (y *YearViewModel) SortAvailableYears() {
slices.Sort(y.AvailableYears)
}

View File

@@ -7,6 +7,7 @@ import (
"time"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/app"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/controllers"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/providers"
"github.com/Theodor-Springmann-Stiftung/kgpz_web/templating"
@@ -40,27 +41,45 @@ const (
// - we invalidate all caches if data is valid
// - we reload all clients
// - if data validity catastrophically fails, we restart the router to map error pages.
// TODO: Use fiber
type Server struct {
Config *providers.ConfigProvider
running chan bool
shutdown *sync.WaitGroup
cache *memory.Storage
mu sync.Mutex
watcher *helpers.FileWatcher
kgpz *app.KGPZ
}
func Start(k *app.KGPZ, c *providers.ConfigProvider) *Server {
func Create(k *app.KGPZ, c *providers.ConfigProvider) *Server {
if c == nil || k == nil {
log.Println("Error creating server")
return nil
}
return &Server{
Config: c,
kgpz: k,
}
}
// INFO: hot reloading for poor people
// BUG: unable to close the old file watcher here, since the process gets aborted in the middle of creating the new one.
func (s *Server) Watcher() error {
s.mu.Lock()
defer s.mu.Unlock()
watcher, err := helpers.NewFileWatcher()
if err != nil {
return err
}
s.watcher = watcher
s.watcher.Append(func(path string) {
log.Println("Restarting server")
time.Sleep(200 * time.Millisecond)
s.Restart()
})
@@ -111,6 +130,7 @@ func (s *Server) Start() {
srv.Use(recover.New())
// TODO: Dont cache static assets, bc storage gets huge
// INFO: Maybe fiber does this already?
if s.Config.Debug {
srv.Use(cache.New(cache.Config{
Next: func(c *fiber.Ctx) bool {
@@ -133,16 +153,15 @@ func (s *Server) Start() {
srv.Use(STATIC_PREFIX, static(&views.StaticFS))
srv.Get("/", func(c *fiber.Ctx) error {
return c.Render("/", fiber.Map{})
})
srv.Get("/:year?", controllers.GetYear(s.kgpz))
s.runner(srv)
if s.Config.Debug {
err := s.Watcher()
if err != nil {
fmt.Println(err)
log.Println("Error watching files")
log.Println(err)
}
}
}
@@ -194,8 +213,6 @@ func (s *Server) runner(srv *fiber.App) {
defer cleanup.Done()
clean := <-s.running
srv.Server().CloseOnShutdown = true
if clean {
if err := srv.ShutdownWithTimeout(SERVER_TIMEOUT); err != nil {
fmt.Println(err)

View File

@@ -73,9 +73,6 @@
- Was ist "Link auf seite teilen"? -> Permalink
## Überarbeiten
- Undifferenzierte Angabe von "Akteur" von Werken in der Kurzangabe, Differenzieren
- Jahr
- Kurztitel, Titel
- Sekundärüberlieferung in Stück/Beitrag
- Fehlende Daten in Stück/Beitrag
- Kurzinformation Überlieferung

1
tmp/build-errors.log Normal file
View File

@@ -0,0 +1 @@
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1

BIN
tmp/main Executable file

Binary file not shown.

View File

@@ -1,3 +1,19 @@
{{ define "body" }}
<p>Change! Hello from body</p>
{{ range $year := .model.AvailableYears }}
<a href="/{{ $year }}">{{ $year }}</a>
{{ end }}
{{ range $issue := .model.Issues }}
<div>
<div>
{{ $issue.Number.Chardata }}
</div>
<div>
{{ index $issue.Month 1 }}
</div>
<div>
{{ index $issue.Weekday 1 }}
</div>
<div>{{ $issue.Day }}.{{ index $issue.Month 2 }}.</div>
</div>
{{ end }}
{{ end }}