From 653fc133cea5d45ea5b85967ad95616359f290d9 Mon Sep 17 00:00:00 2001 From: 1e99 Date: Sat, 12 Apr 2025 11:31:16 +0200 Subject: [PATCH] show past sessions in UI --- a | 12 --------- index.tmpl | 25 ++++++++++++++++++- main.go | 14 ++++++++++- routes/api.go | 2 +- routes/index.go | 14 ++++++++--- sessions/mem.go | 59 +++++++++++++++++++++++++++++++++++--------- sessions/sessions.go | 21 ++++++++++++---- 7 files changed, 112 insertions(+), 35 deletions(-) delete mode 100644 a diff --git a/a b/a deleted file mode 100644 index deef7a1..0000000 --- a/a +++ /dev/null @@ -1,12 +0,0 @@ -2025/04/12 11:09:47 No "WOLBODGE_ADDRESS" provided, defaulting to ":3000" -2025/04/12 11:09:47 No "WOLBODGE_DEVICE_TYPE" provided, defaulting to "test" -2025/04/12 11:09:47 No "WOLBODGE_STORAGE_TYPE" provided, defaulting to "mem" -2025/04/12 11:09:47 Using device: test -2025/04/12 11:09:47 Using session storage: mem -2025/04/12 11:09:47 Listening on :3000 -2025/04/12 11:09:51 No "WOLBODGE_ADDRESS" provided, defaulting to ":3000" -2025/04/12 11:09:51 No "WOLBODGE_DEVICE_TYPE" provided, defaulting to "test" -2025/04/12 11:09:51 No "WOLBODGE_STORAGE_TYPE" provided, defaulting to "mem" -2025/04/12 11:09:51 Using device: test -2025/04/12 11:09:51 Using session storage: mem -2025/04/12 11:09:51 Listening on :3000 diff --git a/index.tmpl b/index.tmpl index f31a679..be3cfad 100644 --- a/index.tmpl +++ b/index.tmpl @@ -63,7 +63,7 @@ - {{ range $session := .Sessions }} + {{ range $session := .ActiveSessions }} {{ $session.Id }} {{ $session.Description }} @@ -79,6 +79,29 @@ {{ end }} + +

Past sessions

+ + + + + + + + + + + + {{ range $session := .PastSessions }} + + + + + + + {{ end }} + +
IDDescriptionCreated atEnded at
{{ $session.Id }}{{ $session.Description }}{{ $session.CreatedAt.Format "02.01.2006 15:04:05" }}{{ $session.EndedAt.Format "02.01.2006 15:04:05" }}
diff --git a/main.go b/main.go index 0d88413..92b874f 100644 --- a/main.go +++ b/main.go @@ -53,7 +53,19 @@ func Run() error { mux.Handle("DELETE /api/session/{session_id}", routes.APIEndSession(logger, storage)) exit := make(chan bool) - go devices.KeepDeviceInSync(logger, device, storage.HasSessions, exit) + go devices.KeepDeviceInSync( + logger, + device, + func() (bool, error) { + sessions, err := storage.GetActiveSessions() + if err != nil { + return false, err + } + + return len(sessions) != 0, nil + }, + exit, + ) var handler http.Handler = mux if logRequests { diff --git a/routes/api.go b/routes/api.go index ad53d90..3b52ed0 100644 --- a/routes/api.go +++ b/routes/api.go @@ -38,7 +38,7 @@ func APIEndSession(logger *log.Logger, storage sessions.Storage) http.HandlerFun return func(res http.ResponseWriter, req *http.Request) { sessionId := req.PathValue("session_id") - err := storage.EndSession(sessionId) + err := storage.EndSession(sessionId, time.Now()) switch { case err == sessions.ErrUnknownSession: http.Error(res, "", http.StatusNotFound) diff --git a/routes/index.go b/routes/index.go index 1669c49..0dd2c8e 100644 --- a/routes/index.go +++ b/routes/index.go @@ -18,14 +18,20 @@ func GetIndex(device devices.Device, storage sessions.Storage, tmpl *template.Te return } - sessions, err := storage.GetSessions() + activeSessions, err := storage.GetActiveSessions() + if err != nil { + return + } + + pastSessions, err := storage.GetPastSessions() if err != nil { return } tmpl.Execute(res, map[string]any{ - "DeviceStatus": status, - "Sessions": sessions, + "DeviceStatus": status, + "ActiveSessions": activeSessions, + "PastSessions": pastSessions, }) } } @@ -63,7 +69,7 @@ func EndSession(logger *log.Logger, storage sessions.Storage) http.HandlerFunc { } sessionId := req.FormValue("session_id") - err = storage.EndSession(sessionId) + err = storage.EndSession(sessionId, time.Now()) switch { case err == sessions.ErrUnknownSession: http.Error(res, "", http.StatusNotFound) diff --git a/sessions/mem.go b/sessions/mem.go index dd07c7b..5b13c0a 100644 --- a/sessions/mem.go +++ b/sessions/mem.go @@ -21,22 +21,44 @@ type memStorage struct { lock sync.Mutex } -func (s *memStorage) HasSessions() (bool, error) { - s.lock.Lock() - defer s.lock.Unlock() - return len(s.sessions) > 0, nil -} - -func (s *memStorage) GetSessions() ([]Session, error) { +func (s *memStorage) GetAllSessions() ([]Session, error) { s.lock.Lock() defer s.lock.Unlock() sessions := make([]Session, len(s.sessions)) - id := 0 + i := 0 for _, session := range s.sessions { - sessions[id] = session - id += 1 + sessions[i] = session + i += 1 + } + + return sessions, nil +} + +func (s *memStorage) GetActiveSessions() ([]Session, error) { + s.lock.Lock() + defer s.lock.Unlock() + + sessions := make([]Session, 0) + for _, session := range s.sessions { + if session.EndedAt.IsZero() { + sessions = append(sessions, session) + } + } + + return sessions, nil +} + +func (s *memStorage) GetPastSessions() ([]Session, error) { + s.lock.Lock() + defer s.lock.Unlock() + + sessions := make([]Session, 0) + for _, session := range s.sessions { + if !session.EndedAt.IsZero() { + sessions = append(sessions, session) + } } return sessions, nil @@ -54,13 +76,28 @@ func (s *memStorage) StartSession(description string, createdAt time.Time) (Sess Id: id, Description: description, CreatedAt: createdAt, + EndedAt: time.Time{}, // This is the zero time } s.sessions[id] = session return session, nil } -func (s *memStorage) EndSession(id string) error { +func (s *memStorage) EndSession(id string, endedAt time.Time) error { + s.lock.Lock() + defer s.lock.Unlock() + + session, found := s.sessions[id] + if !found { + return ErrUnknownSession + } + + session.EndedAt = endedAt + s.sessions[id] = session + return nil +} + +func (s *memStorage) DeleteSession(id string) error { s.lock.Lock() defer s.lock.Unlock() diff --git a/sessions/sessions.go b/sessions/sessions.go index 78adb0f..9d464f1 100644 --- a/sessions/sessions.go +++ b/sessions/sessions.go @@ -10,6 +10,9 @@ type Session struct { Id string Description string CreatedAt time.Time + + // Should be set to a zero time if the session is still active + EndedAt time.Time } func (s *Session) ExistsFor() time.Duration { @@ -21,18 +24,26 @@ var ( ) type Storage interface { - // Check if the storage contains any sessions. - HasSessions() (bool, error) - // List all sessions. - GetSessions() ([]Session, error) + GetAllSessions() ([]Session, error) + + // List all active sessions. + GetActiveSessions() ([]Session, error) + + // List all past sessions. + GetPastSessions() ([]Session, error) // Start a new session. StartSession(description string, createdAt time.Time) (Session, error) // End an old session. + // Should update a session's [EndedAt] property. // Should return [ErrUnknownSession] if the session couldn't be found. - EndSession(id string) error + EndSession(id string, endedAt time.Time) error + + // Delete a session. + // Should return [ErrUnknownSession] if the session couldn't be found. + DeleteSession(id string) error fmt.Stringer }