Move html pages to a package

That way I can separate out HTML for the public-facing report system and
Nidus sync.
This commit is contained in:
Eli Ribble 2026-01-07 15:34:09 +00:00
parent 8c1026a653
commit 4c23eba5d7
51 changed files with 45 additions and 43 deletions

View file

@ -7,7 +7,7 @@ pkgs.buildGoModule rec {
pname = "nidus-sync"; pname = "nidus-sync";
src = ./.; src = ./.;
subPackages = []; subPackages = [];
version = "0.0.7"; version = "0.0.8";
# Needs to be updated after every modification of go.mod/go.sum # Needs to be updated after every modification of go.mod/go.sum
vendorHash = "sha256-JuRB/2pNidonwQm6iCyUXiFxkAwizEXdwieRRjgSBwI="; vendorHash = "sha256-5E5gQJh2cr/XwDg+XRQEdXW7mkObZMoyqQnfToVuZ10=";
} }

View file

@ -11,6 +11,7 @@ import (
"github.com/Gleipnir-Technology/nidus-sync/auth" "github.com/Gleipnir-Technology/nidus-sync/auth"
"github.com/Gleipnir-Technology/nidus-sync/db/models" "github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/Gleipnir-Technology/nidus-sync/htmlpage"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
@ -53,7 +54,7 @@ func getCellDetails(w http.ResponseWriter, r *http.Request, user *models.User) {
respondError(w, "Cannot convert provided cell to uint64", err, http.StatusBadRequest) respondError(w, "Cannot convert provided cell to uint64", err, http.StatusBadRequest)
return return
} }
htmlCell(r.Context(), w, user, cell) htmlpage.Cell(r.Context(), w, user, cell)
} }
func getFavicon(w http.ResponseWriter, r *http.Request) { func getFavicon(w http.ResponseWriter, r *http.Request) {
@ -68,7 +69,7 @@ func getOAuthRefresh(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/?next=/oauth/refresh", http.StatusFound) http.Redirect(w, r, "/?next=/oauth/refresh", http.StatusFound)
return return
} }
htmlOauthPrompt(w, user) htmlpage.OauthPrompt(w, user)
} }
func getQRCodeReport(w http.ResponseWriter, r *http.Request) { func getQRCodeReport(w http.ResponseWriter, r *http.Request) {
@ -145,7 +146,7 @@ func getRoot(w http.ResponseWriter, r *http.Request) {
} }
if user == nil { if user == nil {
errorCode := r.URL.Query().Get("error") errorCode := r.URL.Query().Get("error")
htmlSignin(w, errorCode) htmlpage.Signin(w, errorCode)
return return
} else { } else {
has, err := hasFieldseekerConnection(r.Context(), user) has, err := hasFieldseekerConnection(r.Context(), user)
@ -154,10 +155,10 @@ func getRoot(w http.ResponseWriter, r *http.Request) {
return return
} }
if has { if has {
htmlDashboard(r.Context(), w, user) htmlpage.Dashboard(r.Context(), w, user)
return return
} else { } else {
htmlOauthPrompt(w, user) htmlpage.OauthPrompt(w, user)
return return
} }
} }
@ -167,16 +168,16 @@ func getRoot(w http.ResponseWriter, r *http.Request) {
} }
func getSettings(w http.ResponseWriter, r *http.Request, u *models.User) { func getSettings(w http.ResponseWriter, r *http.Request, u *models.User) {
htmlSettings(w, r, u) htmlpage.Settings(w, r, u)
} }
func getSignin(w http.ResponseWriter, r *http.Request) { func getSignin(w http.ResponseWriter, r *http.Request) {
errorCode := r.URL.Query().Get("error") errorCode := r.URL.Query().Get("error")
htmlSignin(w, errorCode) htmlpage.Signin(w, errorCode)
} }
func getSignup(w http.ResponseWriter, r *http.Request) { func getSignup(w http.ResponseWriter, r *http.Request) {
htmlSignup(w, r.URL.Path) htmlpage.Signup(w, r.URL.Path)
} }
func getSource(w http.ResponseWriter, r *http.Request, u *models.User) { func getSource(w http.ResponseWriter, r *http.Request, u *models.User) {
@ -190,7 +191,7 @@ func getSource(w http.ResponseWriter, r *http.Request, u *models.User) {
respondError(w, "globalid is not a UUID", nil, http.StatusBadRequest) respondError(w, "globalid is not a UUID", nil, http.StatusBadRequest)
return return
} }
htmlSource(w, r, u, globalid) htmlpage.Source(w, r, u, globalid)
} }
func postSMS(w http.ResponseWriter, r *http.Request) { func postSMS(w http.ResponseWriter, r *http.Request) {
@ -324,6 +325,6 @@ func renderMock(templateName string) http.HandlerFunc {
if code == "" { if code == "" {
code = "abc-123" code = "abc-123"
} }
htmlMock(templateName, w, code) htmlpage.Mock(templateName, w, code)
} }
} }

View file

@ -1,15 +0,0 @@
package main
import (
"time"
"github.com/aarondl/opt/null"
)
func fsTimestampToTime(t null.Val[int64]) *time.Time {
if t.IsNull() {
return nil
}
result := time.UnixMilli(t.MustGet())
return &result
}

View file

@ -1,4 +1,4 @@
package main package htmlpage
import ( import (
"fmt" "fmt"

View file

@ -1,4 +1,4 @@
package main package htmlpage
import ( import (
"bytes" "bytes"
@ -30,6 +30,8 @@ import (
//go:embed templates/* //go:embed templates/*
var embeddedFiles embed.FS var embeddedFiles embed.FS
var MapboxToken string
// Authenticated pages // Authenticated pages
var ( var (
cell = newBuiltTemplate("cell", "authenticated") cell = newBuiltTemplate("cell", "authenticated")
@ -251,7 +253,7 @@ func extractInitials(name string) string {
return initials.String() return initials.String()
} }
func htmlCell(ctx context.Context, w http.ResponseWriter, user *models.User, c int64) { func Cell(ctx context.Context, w http.ResponseWriter, user *models.User, c int64) {
org, err := user.Organization().One(ctx, db.PGInstance.BobDB) org, err := user.Organization().One(ctx, db.PGInstance.BobDB)
if err != nil { if err != nil {
respondError(w, "Failed to get org", err, http.StatusInternalServerError) respondError(w, "Failed to get org", err, http.StatusInternalServerError)
@ -312,7 +314,7 @@ func htmlCell(ctx context.Context, w http.ResponseWriter, user *models.User, c i
renderOrError(w, cell, &data) renderOrError(w, cell, &data)
} }
func htmlDashboard(ctx context.Context, w http.ResponseWriter, user *models.User) { func Dashboard(ctx context.Context, w http.ResponseWriter, user *models.User) {
org, err := user.Organization().One(ctx, db.PGInstance.BobDB) org, err := user.Organization().One(ctx, db.PGInstance.BobDB)
if err != nil { if err != nil {
respondError(w, "Failed to get org", err, http.StatusInternalServerError) respondError(w, "Failed to get org", err, http.StatusInternalServerError)
@ -379,7 +381,7 @@ func htmlDashboard(ctx context.Context, w http.ResponseWriter, user *models.User
renderOrError(w, dashboard, data) renderOrError(w, dashboard, data)
} }
func htmlMock(t string, w http.ResponseWriter, code string) { func Mock(t string, w http.ResponseWriter, code string) {
data := ContentMock{ data := ContentMock{
DistrictName: "Delta MVCD", DistrictName: "Delta MVCD",
URLs: ContentMockURLs{ URLs: ContentMockURLs{
@ -409,7 +411,7 @@ func htmlMock(t string, w http.ResponseWriter, code string) {
renderOrError(w, &template, data) renderOrError(w, &template, data)
} }
func htmlOauthPrompt(w http.ResponseWriter, user *models.User) { func OauthPrompt(w http.ResponseWriter, user *models.User) {
dp := user.DisplayName dp := user.DisplayName
data := ContentDashboard{ data := ContentDashboard{
User: User{ User: User{
@ -421,7 +423,7 @@ func htmlOauthPrompt(w http.ResponseWriter, user *models.User) {
renderOrError(w, oauthPrompt, data) renderOrError(w, oauthPrompt, data)
} }
func htmlSettings(w http.ResponseWriter, r *http.Request, user *models.User) { func Settings(w http.ResponseWriter, r *http.Request, user *models.User) {
userContent, err := contentForUser(r.Context(), user) userContent, err := contentForUser(r.Context(), user)
if err != nil { if err != nil {
respondError(w, "Failed to get user content", err, http.StatusInternalServerError) respondError(w, "Failed to get user content", err, http.StatusInternalServerError)
@ -433,19 +435,19 @@ func htmlSettings(w http.ResponseWriter, r *http.Request, user *models.User) {
renderOrError(w, settings, data) renderOrError(w, settings, data)
} }
func htmlSignin(w http.ResponseWriter, errorCode string) { func Signin(w http.ResponseWriter, errorCode string) {
data := ContentSignin{ data := ContentSignin{
InvalidCredentials: errorCode == "invalid-credentials", InvalidCredentials: errorCode == "invalid-credentials",
} }
renderOrError(w, signin, data) renderOrError(w, signin, data)
} }
func htmlSignup(w http.ResponseWriter, path string) { func Signup(w http.ResponseWriter, path string) {
data := ContentSignup{} data := ContentSignup{}
renderOrError(w, signup, data) renderOrError(w, signup, data)
} }
func htmlSource(w http.ResponseWriter, r *http.Request, user *models.User, id uuid.UUID) { func Source(w http.ResponseWriter, r *http.Request, user *models.User, id uuid.UUID) {
org, err := user.Organization().One(r.Context(), db.PGInstance.BobDB) org, err := user.Organization().One(r.Context(), db.PGInstance.BobDB)
if err != nil { if err != nil {
respondError(w, "Failed to get org", err, http.StatusInternalServerError) respondError(w, "Failed to get org", err, http.StatusInternalServerError)

View file

@ -1,4 +1,4 @@
package main package htmlpage
import ( import (
"errors" "errors"

View file

@ -1,4 +1,4 @@
package main package htmlpage
import ( import (
"context" "context"

13
htmlpage/response.go Normal file
View file

@ -0,0 +1,13 @@
package htmlpage
import (
"net/http"
"github.com/rs/zerolog/log"
)
// Respond with an error that is visible to the user
func respondError(w http.ResponseWriter, m string, e error, s int) {
log.Warn().Int("status", s).Err(e).Str("user message", m).Msg("Responding with an error")
http.Error(w, m, s)
}

View file

@ -1,4 +1,4 @@
package main package htmlpage
import ( import (
"sort" "sort"

View file

@ -14,6 +14,7 @@ import (
"github.com/Gleipnir-Technology/nidus-sync/api" "github.com/Gleipnir-Technology/nidus-sync/api"
"github.com/Gleipnir-Technology/nidus-sync/auth" "github.com/Gleipnir-Technology/nidus-sync/auth"
"github.com/Gleipnir-Technology/nidus-sync/db" "github.com/Gleipnir-Technology/nidus-sync/db"
"github.com/Gleipnir-Technology/nidus-sync/htmlpage"
"github.com/Gleipnir-Technology/nidus-sync/queue" "github.com/Gleipnir-Technology/nidus-sync/queue"
"github.com/Gleipnir-Technology/nidus-sync/report" "github.com/Gleipnir-Technology/nidus-sync/report"
"github.com/Gleipnir-Technology/nidus-sync/userfile" "github.com/Gleipnir-Technology/nidus-sync/userfile"
@ -24,7 +25,7 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
var ClientID, ClientSecret, Environment, FieldseekerSchemaDirectory, MapboxToken, URLReport, URLSync string var ClientID, ClientSecret, Environment, FieldseekerSchemaDirectory, URLReport, URLSync string
func main() { func main() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
@ -63,8 +64,8 @@ func main() {
log.Error().Str("ENVIRONMENT", Environment).Msg("ENVIRONMENT should be either DEVELOPMENT or PRODUCTION") log.Error().Str("ENVIRONMENT", Environment).Msg("ENVIRONMENT should be either DEVELOPMENT or PRODUCTION")
os.Exit(2) os.Exit(2)
} }
MapboxToken = os.Getenv("MAPBOX_TOKEN") htmlpage.MapboxToken = os.Getenv("MAPBOX_TOKEN")
if MapboxToken == "" { if htmlpage.MapboxToken == "" {
log.Error().Msg("You must specify a non-empty MAPBOX_TOKEN") log.Error().Msg("You must specify a non-empty MAPBOX_TOKEN")
os.Exit(1) os.Exit(1)
} }