Update project documentation and improve frontend functionality

- Updated the backend documentation in CONTRIBUTING.md and README.md to reflect changes in application structure and API endpoints.
- Enhanced the frontend components in MapView.vue for better handling of context menu actions.
- Added new types and interfaces in TypeScript for improved type safety in the frontend.
- Introduced new utility classes for managing characters and markers in the map.
- Updated .gitignore to include .vscode directory for better development environment management.
This commit is contained in:
2026-02-24 23:32:50 +03:00
parent 605a31567e
commit 82cb8a13f5
39 changed files with 1788 additions and 2631 deletions

View File

@@ -1,17 +1,13 @@
package app
import (
"encoding/json"
"fmt"
"net/http"
"path/filepath"
"sync"
"time"
"github.com/andyleap/hnh-map/webapp"
"go.etcd.io/bbolt"
"golang.org/x/crypto/bcrypt"
)
// App is the main application (map server) state.
@@ -23,8 +19,6 @@ type App struct {
characters map[string]Character
chmu sync.RWMutex
*webapp.WebApp
gridUpdates topic
mergeUpdates mergeTopic
}
@@ -32,16 +26,11 @@ type App struct {
// NewApp creates an App with the given storage paths and database.
// frontendRoot is the directory for the map SPA (e.g. "frontend").
func NewApp(gridStorage, frontendRoot string, db *bbolt.DB) (*App, error) {
w, err := webapp.New()
if err != nil {
return nil, err
}
return &App{
gridStorage: gridStorage,
frontendRoot: frontendRoot,
db: db,
characters: make(map[string]Character),
WebApp: w,
frontendRoot: frontendRoot,
db: db,
characters: make(map[string]Character),
}, nil
}
@@ -144,110 +133,10 @@ type User struct {
Tokens []string
}
func (a *App) getSession(req *http.Request) *Session {
c, err := req.Cookie("session")
if err != nil {
return nil
}
var s *Session
a.db.View(func(tx *bbolt.Tx) error {
sessions := tx.Bucket([]byte("sessions"))
if sessions == nil {
return nil
}
session := sessions.Get([]byte(c.Value))
if session == nil {
return nil
}
err := json.Unmarshal(session, &s)
if err != nil {
return err
}
if s.TempAdmin {
s.Auths = Auths{AUTH_ADMIN}
return nil
}
users := tx.Bucket([]byte("users"))
if users == nil {
return nil
}
raw := users.Get([]byte(s.Username))
if raw == nil {
s = nil
return nil
}
u := User{}
err = json.Unmarshal(raw, &u)
if err != nil {
s = nil
return err
}
s.Auths = u.Auths
return nil
})
return s
}
func (a *App) deleteSession(s *Session) {
a.db.Update(func(tx *bbolt.Tx) error {
sessions, err := tx.CreateBucketIfNotExists([]byte("sessions"))
if err != nil {
return err
}
return sessions.Delete([]byte(s.ID))
})
}
func (a *App) saveSession(s *Session) {
a.db.Update(func(tx *bbolt.Tx) error {
sessions, err := tx.CreateBucketIfNotExists([]byte("sessions"))
if err != nil {
return err
}
buf, err := json.Marshal(s)
if err != nil {
return err
}
return sessions.Put([]byte(s.ID), buf)
})
}
type Page struct {
Title string `json:"title"`
}
func (a *App) getPage(req *http.Request) Page {
p := Page{}
a.db.View(func(tx *bbolt.Tx) error {
c := tx.Bucket([]byte("config"))
if c == nil {
return nil
}
p.Title = string(c.Get([]byte("title")))
return nil
})
return p
}
func (a *App) getUser(user, pass string) (u *User) {
a.db.View(func(tx *bbolt.Tx) error {
users := tx.Bucket([]byte("users"))
if users == nil {
return nil
}
raw := users.Get([]byte(user))
if raw != nil {
json.Unmarshal(raw, &u)
if bcrypt.CompareHashAndPassword(u.Pass, []byte(pass)) != nil {
u = nil
return nil
}
}
return nil
})
return u
}
// serveMapFrontend serves the map SPA: static files from frontend, fallback to index.html for client-side routes.
func (a *App) serveMapFrontend(rw http.ResponseWriter, req *http.Request) {
path := req.URL.Path
@@ -306,23 +195,10 @@ func (a *App) RegisterRoutes() {
http.HandleFunc("/client/", a.client)
http.HandleFunc("/login", a.redirectLogin)
http.HandleFunc("/logout", a.logout)
http.HandleFunc("/logout", a.redirectLogout)
http.HandleFunc("/admin", a.redirectAdmin)
http.HandleFunc("/admin/", a.redirectAdmin)
http.HandleFunc("/", a.redirectRoot)
http.HandleFunc("/generateToken", a.generateToken)
http.HandleFunc("/password", a.changePassword)
http.HandleFunc("/admin/", a.admin)
http.HandleFunc("/admin/user", a.adminUser)
http.HandleFunc("/admin/deleteUser", a.deleteUser)
http.HandleFunc("/admin/wipe", a.wipe)
http.HandleFunc("/admin/setPrefix", a.setPrefix)
http.HandleFunc("/admin/setDefaultHide", a.setDefaultHide)
http.HandleFunc("/admin/setTitle", a.setTitle)
http.HandleFunc("/admin/rebuildZooms", a.rebuildZooms)
http.HandleFunc("/admin/export", a.export)
http.HandleFunc("/admin/merge", a.merge)
http.HandleFunc("/admin/map", a.adminMap)
http.HandleFunc("/admin/mapic", a.adminICMap)
http.HandleFunc("/map/api/", a.apiRouter)
http.HandleFunc("/map/updates", a.watchGridUpdates)