nidus-sync/html/func.go
Eli Ribble 31947c848a
Move static outside HTML. Start work on TypeScript bundle
It's not strictly HTML, so that's just correct.

This is just worth doing while building the new TypeScript bundle
2026-03-21 03:06:59 +00:00

339 lines
7.3 KiB
Go

package html
import (
//"bytes"
"fmt"
"html/template"
//"io/fs"
"math"
//"net/http"
//"os"
"strconv"
"strings"
"time"
"github.com/Gleipnir-Technology/nidus-sync/static"
"github.com/aarondl/opt/null"
"github.com/google/uuid"
"github.com/rs/zerolog/log"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
func addFuncMap(t *template.Template) {
funcMap := template.FuncMap{
"bigNumber": bigNumber,
"bundlePathCSS": bundlePathCSS,
"bundlePathJS": bundlePathJS,
"displayUploadStatus": displayUploadStatus,
"displayUploadType": displayUploadType,
"duration": duration,
"hasPassed": hasPassed,
"html": unescapeHTML,
"iconUploadStatus": iconUploadStatus,
"json": unescapeJS,
"GISStatement": gisStatement,
"latLngDisplay": latLngDisplay,
"publicReportID": publicReportID,
"timeAsRelativeDate": timeAsRelativeDate,
"timeDelta": timeDelta,
"timeElapsed": timeElapsed,
"timeInterval": timeInterval,
"timeRelative": timeRelative,
"timeRelativePtr": timeRelativePtr,
"title": title,
"uuidShort": uuidShort,
}
t.Funcs(funcMap)
}
func bigNumber(n int) string {
// Convert the number to a string
numStr := strconv.FormatInt(int64(n), 10)
// Add commas every three digits from the right
var result strings.Builder
for i, char := range numStr {
if i > 0 && (len(numStr)-i)%3 == 0 {
result.WriteByte(',')
}
result.WriteRune(char)
}
return result.String()
}
func bundlePathCSS() string {
return static.BundlePathCSS
}
func bundlePathJS() string {
return static.BundlePathJS
}
func displayUploadStatus(s string) string {
switch s {
case "committed":
return "Complete"
case "committing":
return "Committing"
case "discarded":
return "Discarded"
case "error":
return "Bad upload"
case "parsed":
return "Waiting for review"
case "uploaded":
return "Processing"
default:
return "Unknown status type"
}
}
func displayUploadType(s string) string {
switch s {
case "PoolList":
return "Green Pool List"
case "Flyover":
return "Flyover"
default:
return "Unknown upload type"
}
}
func duration(d time.Duration) string {
seconds := int(d.Seconds())
if seconds < 60 {
if seconds == 1 {
return "1 second ago"
}
return fmt.Sprintf("%d seconds ago", seconds)
}
minutes := int(d.Minutes())
if minutes < 60 {
if minutes == 1 {
return "1 minute ago"
}
return fmt.Sprintf("%d minutes ago", minutes)
}
hours := int(d.Hours())
if hours < 24 {
if hours == 1 {
return "1 hour ago"
}
return fmt.Sprintf("%d hours ago", hours)
}
days := hours / 24
if days < 30 {
if days == 1 {
return "1 day ago"
}
return fmt.Sprintf("%d days ago", days)
}
months := days / 30
if months < 12 {
if months == 1 {
return "1 month ago"
}
return fmt.Sprintf("%d months ago", months)
}
years := days / 365
if years == 1 {
return "1 year ago"
}
return fmt.Sprintf("%d years ago", years)
}
func publicReportID(s string) string {
if len(s) != 12 {
return s
}
return s[0:4] + "-" + s[4:8] + "-" + s[8:12]
}
func timeAsRelativeDate(d time.Time) string {
return d.Format("01-02")
}
func hasPassed(t time.Time) bool {
return t.Before(time.Now())
}
func iconUploadStatus(s string) string {
switch s {
case "error":
return "bi-exclamation"
case "parsed":
return "bi-check-circle"
case "uploaded":
return "bi-arrow-clockwise"
default:
return "bi-question"
}
}
// FormatTimeDuration returns a human-readable string representing a time.Duration
// as "X units early" or "X units late"
func timeDelta(d time.Duration) string {
suffix := "late"
if d < 0 {
suffix = "early"
d = -d // Make duration positive for calculations
}
const (
day = 24 * time.Hour
week = 7 * day
)
log.Info().Int64("delta", int64(d)).Str("suffix", suffix).Msg("Time delta")
switch {
case d >= week:
weeks := d / week
if weeks == 1 {
return "1 week " + suffix
}
return fmt.Sprintf("%d weeks %s", weeks, suffix)
case d >= day:
days := d / day
if days == 1 {
return "1 day " + suffix
}
return fmt.Sprintf("%d days %s", days, suffix)
case d >= time.Hour:
hours := d / time.Hour
if hours == 1 {
return "1 hour " + suffix
}
return fmt.Sprintf("%d hours %s", hours, suffix)
case d >= time.Minute:
minutes := d / time.Minute
if minutes == 1 {
return "1 minute " + suffix
}
return fmt.Sprintf("%d minutes %s", minutes, suffix)
default:
seconds := d / time.Second
if seconds == 1 {
return "1 second " + suffix
}
return fmt.Sprintf("%d seconds %s", seconds, suffix)
}
}
func timeElapsed(seconds null.Val[float32]) string {
if !seconds.IsValue() {
return "none"
}
s := int(seconds.MustGet())
hours := s / 3600
remainder := s - (hours * 3600)
minutes := remainder / 60
remainder = remainder - (minutes * 60)
if hours > 0 {
return fmt.Sprintf("%02d:%02d:%02d", hours, minutes, remainder)
} else if minutes > 0 {
return fmt.Sprintf("%02d:%02d", minutes, remainder)
} else {
return fmt.Sprintf("%d seconds", remainder)
}
}
func timeInterval(d time.Duration) string {
seconds := d.Seconds()
// Less than 120 seconds -> show in seconds
if seconds < 120 {
return fmt.Sprintf("every %d seconds", int(math.Round(seconds)))
}
minutes := d.Minutes()
// Less than 120 minutes -> show in minutes
if minutes < 120 {
return fmt.Sprintf("every %d minutes", int(math.Round(minutes)))
}
hours := d.Hours()
// Less than 48 hours -> show in hours
if hours < 48 {
return fmt.Sprintf("every %d hours", int(math.Round(hours)))
}
days := hours / 24
// Less than 14 days -> show in days
if days < 14 {
return fmt.Sprintf("every %d days", int(math.Round(days)))
}
weeks := days / 7
// Less than 8 weeks -> show in weeks
if weeks < 8 {
return fmt.Sprintf("every %d weeks", int(math.Round(weeks)))
}
months := days / 30
// Less than 24 months -> show in months
if months < 24 {
return fmt.Sprintf("every %d months", int(math.Round(months)))
}
years := days / 365
return fmt.Sprintf("every %d years", int(math.Round(years)))
}
func timeRelative(t time.Time) string {
now := time.Now()
diff := now.Sub(t)
hours := diff.Hours()
if hours > 0 {
if hours < 1 {
minutes := diff.Minutes()
return fmt.Sprintf("%d minutes ago", int(minutes))
} else if hours < 24 {
return fmt.Sprintf("%d hours ago", int(hours))
} else {
days := hours / 24
return fmt.Sprintf("%d days ago", int(days))
}
} else {
if hours < -24 {
days := hours / 24
return fmt.Sprintf("in %d days", -1*int(days))
} else if hours < -1 {
return fmt.Sprintf("in %d hours", -1*int(hours))
} else {
minutes := diff.Minutes()
if minutes > -1 {
seconds := diff.Seconds()
return fmt.Sprintf("in %d seconds", -1*int(seconds))
}
return fmt.Sprintf("in %d minutes", -1*int(minutes))
}
}
}
func timeRelativePtr(t *time.Time) string {
if t == nil {
return "never"
}
return timeRelative(*t)
}
func title(s string) string {
return cases.Title(language.AmericanEnglish).String(s)
}
func unescapeHTML(s string) template.HTML {
return template.HTML(s)
}
func unescapeJS(s string) template.JS {
return template.JS(s)
}
func uuidShort(uuid uuid.UUID) string {
s := uuid.String()
if len(s) < 7 {
return s // Return as is if too short
}
return s[:3] + "..." + s[len(s)-4:]
}