This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

Add uuid formatter

nagee (Jun 6, 2026, 8:23 PM -0700) 12a025d1 fb15febe

+430 -186
+1
go.mod
··· 13 13 github.com/cli/browser v1.3.0 // indirect 14 14 github.com/fatih/color v1.16.0 // indirect 15 15 github.com/fsnotify/fsnotify v1.7.0 // indirect 16 + github.com/google/uuid v1.6.0 16 17 github.com/mattn/go-colorable v0.1.13 // indirect 17 18 github.com/mattn/go-isatty v0.0.20 // indirect 18 19 github.com/natefinch/atomic v1.0.1 // indirect
+2
go.sum
··· 16 16 github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= 17 17 github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 18 18 github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 19 + github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 20 + github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 19 21 github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 20 22 github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 21 23 github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+14 -8
main.go
··· 3 3 import ( 4 4 "embed" 5 5 "fmt" 6 - "git.nagee.dev/isthisnagee/toolbox/src/handlers" 7 - "git.nagee.dev/isthisnagee/toolbox/src/services" 6 + "git.nagee.dev/isthisnagee/toolbox/src/ui/templates" 7 + "git.nagee.dev/isthisnagee/toolbox/src/uuidtool" 8 + "git.nagee.dev/isthisnagee/toolbox/src/uuidtool/handler" 8 9 "log/slog" 9 10 "net/http" 10 11 "os" ··· 34 35 port = "8080" 35 36 } 36 37 37 - ms := services.NewMath(logger) 38 - toolboxHandler := handlers.New(logger, ms) 38 + uuidFormatter := uuidtool.NewUuidFormatter(logger) 39 + uuidToolHandler := handler.New(logger, uuidFormatter) 39 40 40 41 mux := http.NewServeMux() 41 42 ··· 44 45 mux.Handle("/static/", fileServer) 45 46 46 47 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 48 + templates.IndexPage().Render(r.Context(), w) 49 + }) 50 + mux.HandleFunc("/uuid/{uuid}", uuidToolHandler.Index) 51 + mux.HandleFunc("/uuid/", func(w http.ResponseWriter, r *http.Request) { 47 52 if r.Method == http.MethodPost { 48 - toolboxHandler.Increment(w, r) 53 + uuidToolHandler.Format(w, r) 54 + } else { 55 + uuidToolHandler.Index(w, r) 49 56 } 50 - toolboxHandler.Index(w, r) 51 57 }) 52 58 mux.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {}) // no favicon 53 59 54 60 // Wrap with logging middleware 55 61 logged := loggingMiddleware(mux, logger) 56 62 57 - logger.Info("Server started at port", port) 63 + logger.Info("Server started at", "port", port) 58 64 addr := ":" + port 59 65 if err := http.ListenAndServe(addr, logged); err != nil { 60 - logger.Error("could not start server: %v", err) 66 + logger.Error("could not start server", "err", err) 61 67 } 62 68 } 63 69
-59
src/handlers/default.go
··· 1 - package handlers 2 - 3 - import ( 4 - "context" 5 - "log/slog" 6 - "net/http" 7 - "strconv" 8 - 9 - "git.nagee.dev/isthisnagee/toolbox/src/models" 10 - "git.nagee.dev/isthisnagee/toolbox/src/ui" 11 - "git.nagee.dev/isthisnagee/toolbox/src/ui/templates" 12 - ) 13 - 14 - type ToolboxHandler struct { 15 - Log *slog.Logger 16 - CountService CountService 17 - } 18 - 19 - func New(log *slog.Logger, cs CountService) *ToolboxHandler { 20 - return &ToolboxHandler{ 21 - Log: log, 22 - CountService: cs, 23 - } 24 - } 25 - 26 - type CountService interface { 27 - Add(ctx context.Context, a, b int) (result models.AddResult, err error) 28 - } 29 - 30 - func (h *ToolboxHandler) Index(w http.ResponseWriter, r *http.Request) { 31 - h.Log.Info("Index page") 32 - result := models.AddResult{N: 10} 33 - uiResult := ui.ToUiAddResult(result) 34 - pageData := ui.IndexPageData{Result: uiResult} 35 - templates.IndexPage(pageData).Render(r.Context(), w) 36 - } 37 - 38 - func (h *ToolboxHandler) Increment(w http.ResponseWriter, r *http.Request) { 39 - h.Log.Info("Add method") 40 - 41 - valueStr := r.FormValue("increment") 42 - value, err := strconv.Atoi(valueStr) 43 - if err != nil { 44 - http.Error(w, "invalid increment", http.StatusBadRequest) 45 - return 46 - } 47 - 48 - result, err := h.CountService.Add(r.Context(), value, 1) 49 - if err != nil { 50 - h.Log.Error("Failed to add", err) 51 - http.Error(w, "failed to add", http.StatusInternalServerError) 52 - return 53 - } 54 - pageData := ui.IndexPageData{ 55 - Result: ui.ToUiAddResult(result), 56 - } 57 - 58 - templates.IndexPage(pageData).Render(r.Context(), w) 59 - }
-5
src/models/models.go
··· 1 - package models 2 - 3 - type AddResult struct { 4 - N int 5 - }
-20
src/services/services.go
··· 1 - package services 2 - 3 - import ( 4 - "log/slog" 5 - "context" 6 - "git.nagee.dev/isthisnagee/toolbox/src/models" 7 - ) 8 - 9 - type Math struct { 10 - Log *slog.Logger 11 - } 12 - 13 - func NewMath(log *slog.Logger) Math { 14 - return Math{Log: log} 15 - } 16 - 17 - func (ms Math) Add(ctx context.Context, a, b int) (result models.AddResult, err error) { 18 - ms.Log.Info("Adding some numbers", a, b) 19 - return models.AddResult{N: a + b}, nil 20 - }
+40 -9
src/ui/models.go
··· 1 1 package ui 2 2 3 3 import ( 4 - "git.nagee.dev/isthisnagee/toolbox/src/models" 4 + "fmt" 5 + "git.nagee.dev/isthisnagee/toolbox/src/uuidtool" 5 6 ) 6 7 7 - type UiAddResult struct { 8 - N int 8 + // Uuid Formatter 9 + 10 + type UiUuidFormatResult struct { 11 + FormatType string 12 + Result string 13 + } 14 + 15 + func toUuidFormatString(uuidFmt uuidtool.UuidFormat) string { 16 + switch uuidFmt { 17 + case uuidtool.Braces: 18 + return "braces" 19 + case uuidtool.HexLiteral: 20 + return "hex literal" 21 + case uuidtool.Spec: 22 + return "spec" 23 + case uuidtool.UrnPrefix: 24 + return "urn prefix" 25 + default: 26 + panic(fmt.Sprintf("unexpected uuidtool.UuidFormat: %#v", uuidFmt)) 27 + } 28 + } 29 + 30 + func ToUiUuidFormatResult(result uuidtool.UuidFormatResult) UiUuidFormatResult { 31 + return UiUuidFormatResult{ 32 + FormatType: toUuidFormatString(result.Format), 33 + Result: result.Result, 34 + } 9 35 } 10 36 11 - func ToUiAddResult(result models.AddResult) UiAddResult { 12 - return UiAddResult{ 13 - N: result.N, 37 + func ToUiUuidFormatResults(results []uuidtool.UuidFormatResult) []UiUuidFormatResult { 38 + uiResults := make([]UiUuidFormatResult, 0, len(results)) 39 + 40 + for _, result := range results { 41 + uiResults = append(uiResults, ToUiUuidFormatResult(result)) 14 42 } 15 - } 16 43 44 + return uiResults 45 + } 17 46 18 - type IndexPageData struct { 19 - Result UiAddResult 47 + type UuidFormatPageData struct { 48 + Formatted []UiUuidFormatResult 49 + Input string 50 + Error string 20 51 }
+5 -13
src/ui/templates/index.templ
··· 1 1 package templates 2 2 3 - import "git.nagee.dev/isthisnagee/toolbox/src/ui" 4 - 5 - templ form(result ui.UiAddResult) { 6 - <form action="/" method="POST"> 7 - <div><button type="submit" name="increment" value={ result.N }>Increment { result.N }</button></div> 8 - </form> 9 - } 10 - 11 - // TODO: Add increment button 12 - templ IndexPage(data ui.IndexPageData) { 3 + templ IndexPage() { 13 4 @Page("home") { 14 - <div> 15 - @form(data.Result) 16 - </div> 5 + <div>Hello!</div> 6 + <ul> 7 + <li><a href="/uuid">uuid formatter</a></li> 8 + </ul> 17 9 } 18 10 }
+4 -70
src/ui/templates/index_templ.go
··· 8 8 import "github.com/a-h/templ" 9 9 import templruntime "github.com/a-h/templ/runtime" 10 10 11 - import "git.nagee.dev/isthisnagee/toolbox/src/ui" 12 - 13 - func form(result ui.UiAddResult) templ.Component { 11 + func IndexPage() templ.Component { 14 12 return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 15 13 templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 16 14 if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { ··· 31 29 templ_7745c5c3_Var1 = templ.NopComponent 32 30 } 33 31 ctx = templ.ClearChildren(ctx) 34 - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<form action=\"/\" method=\"POST\"><div><button type=\"submit\" name=\"increment\" value=\"") 35 - if templ_7745c5c3_Err != nil { 36 - return templ_7745c5c3_Err 37 - } 38 - var templ_7745c5c3_Var2 string 39 - templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.ResolveAttributeValue(result.N) 40 - if templ_7745c5c3_Err != nil { 41 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/ui/templates/index.templ`, Line: 7, Col: 62} 42 - } 43 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var2) 44 - if templ_7745c5c3_Err != nil { 45 - return templ_7745c5c3_Err 46 - } 47 - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\">Increment ") 48 - if templ_7745c5c3_Err != nil { 49 - return templ_7745c5c3_Err 50 - } 51 - var templ_7745c5c3_Var3 string 52 - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(result.N) 53 - if templ_7745c5c3_Err != nil { 54 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/ui/templates/index.templ`, Line: 7, Col: 85} 55 - } 56 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 57 - if templ_7745c5c3_Err != nil { 58 - return templ_7745c5c3_Err 59 - } 60 - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</button></div></form>") 61 - if templ_7745c5c3_Err != nil { 62 - return templ_7745c5c3_Err 63 - } 64 - return nil 65 - }) 66 - } 67 - 68 - // TODO: Add increment button 69 - func IndexPage(data ui.IndexPageData) templ.Component { 70 - return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 71 - templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 72 - if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 73 - return templ_7745c5c3_CtxErr 74 - } 75 - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 76 - if !templ_7745c5c3_IsBuffer { 77 - defer func() { 78 - templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 79 - if templ_7745c5c3_Err == nil { 80 - templ_7745c5c3_Err = templ_7745c5c3_BufErr 81 - } 82 - }() 83 - } 84 - ctx = templ.InitializeContext(ctx) 85 - templ_7745c5c3_Var4 := templ.GetChildren(ctx) 86 - if templ_7745c5c3_Var4 == nil { 87 - templ_7745c5c3_Var4 = templ.NopComponent 88 - } 89 - ctx = templ.ClearChildren(ctx) 90 - templ_7745c5c3_Var5 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 32 + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 91 33 templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 92 34 templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 93 35 if !templ_7745c5c3_IsBuffer { ··· 99 41 }() 100 42 } 101 43 ctx = templ.InitializeContext(ctx) 102 - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div>") 103 - if templ_7745c5c3_Err != nil { 104 - return templ_7745c5c3_Err 105 - } 106 - templ_7745c5c3_Err = form(data.Result).Render(ctx, templ_7745c5c3_Buffer) 107 - if templ_7745c5c3_Err != nil { 108 - return templ_7745c5c3_Err 109 - } 110 - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div>") 44 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div>Hello!</div><ul><li><a href=\"/uuid\">uuid formatter</a></li></ul>") 111 45 if templ_7745c5c3_Err != nil { 112 46 return templ_7745c5c3_Err 113 47 } 114 48 return nil 115 49 }) 116 - templ_7745c5c3_Err = Page("home").Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer) 50 + templ_7745c5c3_Err = Page("home").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) 117 51 if templ_7745c5c3_Err != nil { 118 52 return templ_7745c5c3_Err 119 53 }
+1 -1
src/ui/templates/page.templ
··· 4 4 5 5 templ Page(title string) { 6 6 <!DOCTYPE html> 7 - <html lang="en"> 7 + <html lang="en" data-font-family="sans-serif"> 8 8 <head> 9 9 <meta charset="UTF-8"/> 10 10 <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
+1 -1
src/ui/templates/page_templ.go
··· 31 31 templ_7745c5c3_Var1 = templ.NopComponent 32 32 } 33 33 ctx = templ.ClearChildren(ctx) 34 - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>") 34 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\" data-font-family=\"sans-serif\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>") 35 35 if templ_7745c5c3_Err != nil { 36 36 return templ_7745c5c3_Err 37 37 }
+31
src/ui/templates/uuidtool.templ
··· 1 + package templates 2 + 3 + import "git.nagee.dev/isthisnagee/toolbox/src/ui" 4 + 5 + templ uuidForm(uuidVal string) { 6 + <form action="/uuid/" method="POST"> 7 + <div> 8 + <label for="uuid">Enter a uuid: </label> 9 + <input type="text" name="uuid" id="uuid" value={ uuidVal } required/> 10 + </div> 11 + <div> 12 + <input type="submit"/> 13 + </div> 14 + </form> 15 + } 16 + 17 + templ UuidFormatPage(data ui.UuidFormatPageData) { 18 + @Page("uuidtool") { 19 + <div> 20 + { data.Error } 21 + @uuidForm(data.Input) 22 + </div> 23 + <div> 24 + <ul> 25 + for _, uuidFmt := range data.Formatted { 26 + <li>{ uuidFmt.FormatType } - <code class="selectall">{ uuidFmt.Result }</code></li> 27 + } 28 + </ul> 29 + </div> 30 + } 31 + }
+155
src/ui/templates/uuidtool_templ.go
··· 1 + // Code generated by templ - DO NOT EDIT. 2 + 3 + // templ: version: v0.3.1020 4 + package templates 5 + 6 + //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 + 8 + import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 + 11 + import "git.nagee.dev/isthisnagee/toolbox/src/ui" 12 + 13 + func uuidForm(uuidVal string) templ.Component { 14 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 15 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 16 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 17 + return templ_7745c5c3_CtxErr 18 + } 19 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 20 + if !templ_7745c5c3_IsBuffer { 21 + defer func() { 22 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 23 + if templ_7745c5c3_Err == nil { 24 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 25 + } 26 + }() 27 + } 28 + ctx = templ.InitializeContext(ctx) 29 + templ_7745c5c3_Var1 := templ.GetChildren(ctx) 30 + if templ_7745c5c3_Var1 == nil { 31 + templ_7745c5c3_Var1 = templ.NopComponent 32 + } 33 + ctx = templ.ClearChildren(ctx) 34 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<form action=\"/uuid/\" method=\"POST\"><div><label for=\"uuid\">Enter a uuid: </label> <input type=\"text\" name=\"uuid\" id=\"uuid\" value=\"") 35 + if templ_7745c5c3_Err != nil { 36 + return templ_7745c5c3_Err 37 + } 38 + var templ_7745c5c3_Var2 string 39 + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.ResolveAttributeValue(uuidVal) 40 + if templ_7745c5c3_Err != nil { 41 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/ui/templates/uuidtool.templ`, Line: 9, Col: 67} 42 + } 43 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var2) 44 + if templ_7745c5c3_Err != nil { 45 + return templ_7745c5c3_Err 46 + } 47 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" required></div><div><input type=\"submit\"></div></form>") 48 + if templ_7745c5c3_Err != nil { 49 + return templ_7745c5c3_Err 50 + } 51 + return nil 52 + }) 53 + } 54 + 55 + func UuidFormatPage(data ui.UuidFormatPageData) templ.Component { 56 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 57 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 58 + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { 59 + return templ_7745c5c3_CtxErr 60 + } 61 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 62 + if !templ_7745c5c3_IsBuffer { 63 + defer func() { 64 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 65 + if templ_7745c5c3_Err == nil { 66 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 67 + } 68 + }() 69 + } 70 + ctx = templ.InitializeContext(ctx) 71 + templ_7745c5c3_Var3 := templ.GetChildren(ctx) 72 + if templ_7745c5c3_Var3 == nil { 73 + templ_7745c5c3_Var3 = templ.NopComponent 74 + } 75 + ctx = templ.ClearChildren(ctx) 76 + templ_7745c5c3_Var4 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 77 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 78 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 79 + if !templ_7745c5c3_IsBuffer { 80 + defer func() { 81 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 82 + if templ_7745c5c3_Err == nil { 83 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 84 + } 85 + }() 86 + } 87 + ctx = templ.InitializeContext(ctx) 88 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<div>") 89 + if templ_7745c5c3_Err != nil { 90 + return templ_7745c5c3_Err 91 + } 92 + var templ_7745c5c3_Var5 string 93 + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(data.Error) 94 + if templ_7745c5c3_Err != nil { 95 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/ui/templates/uuidtool.templ`, Line: 20, Col: 23} 96 + } 97 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 98 + if templ_7745c5c3_Err != nil { 99 + return templ_7745c5c3_Err 100 + } 101 + templ_7745c5c3_Err = uuidForm(data.Input).Render(ctx, templ_7745c5c3_Buffer) 102 + if templ_7745c5c3_Err != nil { 103 + return templ_7745c5c3_Err 104 + } 105 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</div><div><ul>") 106 + if templ_7745c5c3_Err != nil { 107 + return templ_7745c5c3_Err 108 + } 109 + for _, uuidFmt := range data.Formatted { 110 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<li>") 111 + if templ_7745c5c3_Err != nil { 112 + return templ_7745c5c3_Err 113 + } 114 + var templ_7745c5c3_Var6 string 115 + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(uuidFmt.FormatType) 116 + if templ_7745c5c3_Err != nil { 117 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/ui/templates/uuidtool.templ`, Line: 26, Col: 44} 118 + } 119 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 120 + if templ_7745c5c3_Err != nil { 121 + return templ_7745c5c3_Err 122 + } 123 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, " - <code class=\"selectall\">") 124 + if templ_7745c5c3_Err != nil { 125 + return templ_7745c5c3_Err 126 + } 127 + var templ_7745c5c3_Var7 string 128 + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(uuidFmt.Result) 129 + if templ_7745c5c3_Err != nil { 130 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `src/ui/templates/uuidtool.templ`, Line: 26, Col: 89} 131 + } 132 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 133 + if templ_7745c5c3_Err != nil { 134 + return templ_7745c5c3_Err 135 + } 136 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</code></li>") 137 + if templ_7745c5c3_Err != nil { 138 + return templ_7745c5c3_Err 139 + } 140 + } 141 + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</ul></div>") 142 + if templ_7745c5c3_Err != nil { 143 + return templ_7745c5c3_Err 144 + } 145 + return nil 146 + }) 147 + templ_7745c5c3_Err = Page("uuidtool").Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer) 148 + if templ_7745c5c3_Err != nil { 149 + return templ_7745c5c3_Err 150 + } 151 + return nil 152 + }) 153 + } 154 + 155 + var _ = templruntime.GeneratedTemplate
+78
src/uuidtool/handler/handler.go
··· 1 + package handler 2 + 3 + import ( 4 + "context" 5 + "log/slog" 6 + "net/http" 7 + "git.nagee.dev/isthisnagee/toolbox/src/ui/templates" 8 + "git.nagee.dev/isthisnagee/toolbox/src/ui" 9 + "git.nagee.dev/isthisnagee/toolbox/src/uuidtool" 10 + ) 11 + 12 + type Handler struct { 13 + Log *slog.Logger 14 + UuidToolService UuidToolService 15 + } 16 + 17 + func New(log *slog.Logger, us UuidToolService) *Handler { 18 + return &Handler{ 19 + Log: log, 20 + UuidToolService: us, 21 + } 22 + } 23 + 24 + 25 + type UuidToolService interface { 26 + CanFormat(ctx context.Context, val string) (err error) 27 + Format(ctx context.Context, val string, uuidFmt uuidtool.UuidFormat) (result uuidtool.UuidFormatResult, err error) 28 + Formats(ctx context.Context, val string, uuidFmts []uuidtool.UuidFormat) (result []uuidtool.UuidFormatResult, err error) 29 + } 30 + 31 + // Declare the formats so we always have the same order...might be a good idea to lift this 32 + var uuidFormatOrder []uuidtool.UuidFormat = []uuidtool.UuidFormat{ 33 + uuidtool.Spec, 34 + uuidtool.HexLiteral, 35 + uuidtool.Braces, 36 + uuidtool.UrnPrefix, 37 + } 38 + 39 + 40 + func (h *Handler) Index(w http.ResponseWriter, r *http.Request) { 41 + h.Log.Info("uuid fmt") 42 + 43 + var pageData ui.UuidFormatPageData 44 + 45 + input := r.PathValue("uuid") 46 + pageData.Input = input 47 + 48 + if input != "" { 49 + err := h.UuidToolService.CanFormat(r.Context(), input) 50 + if err != nil { 51 + pageData.Error = err.Error() 52 + templates.UuidFormatPage(pageData).Render(r.Context(), w) 53 + return 54 + } 55 + formatResults, err := h.UuidToolService.Formats(r.Context(), input, uuidFormatOrder) 56 + if err != nil { 57 + pageData.Error = err.Error() 58 + templates.UuidFormatPage(pageData).Render(r.Context(), w) 59 + return 60 + } 61 + h.Log.Info("Formatted", "results", formatResults) 62 + pageData.Formatted = ui.ToUiUuidFormatResults(formatResults) 63 + } 64 + 65 + templates.UuidFormatPage(pageData).Render(r.Context(), w) 66 + } 67 + 68 + func (h *Handler) Format(w http.ResponseWriter, r *http.Request) { 69 + h.Log.Info("Formatting Handler") 70 + if err := r.ParseForm(); err != nil { 71 + http.Error(w, "invalid form", http.StatusBadRequest) 72 + return 73 + } 74 + 75 + uuid := r.FormValue("uuid") 76 + 77 + http.Redirect(w, r, r.URL.JoinPath(uuid).Path, http.StatusSeeOther) 78 + }
+16
src/uuidtool/model.go
··· 1 + package uuidtool 2 + 3 + type UuidFormat int 4 + 5 + const ( 6 + Spec UuidFormat = iota 7 + UrnPrefix 8 + Braces 9 + HexLiteral 10 + ) 11 + 12 + type UuidFormatResult struct { 13 + Format UuidFormat 14 + Result string 15 + } 16 +
+76
src/uuidtool/service.go
··· 1 + package uuidtool 2 + 3 + import ( 4 + "log/slog" 5 + "context" 6 + "github.com/google/uuid" 7 + "fmt" 8 + ) 9 + 10 + type UuidFormatter struct { 11 + Log *slog.Logger 12 + } 13 + 14 + func NewUuidFormatter(log *slog.Logger) UuidFormatter { 15 + return UuidFormatter{Log: log} 16 + } 17 + 18 + func (uf UuidFormatter) CanFormat(ctx context.Context, val string) error { 19 + return uuid.Validate(val) 20 + } 21 + 22 + func (uf UuidFormatter) Format(ctx context.Context, val string, uuidFmt UuidFormat) (r UuidFormatResult, err error) { 23 + err = uf.CanFormat(ctx, val) 24 + if err != nil { 25 + uf.Log.Error("Cannot format value", "val", val) 26 + return UuidFormatResult{}, err 27 + } 28 + 29 + id, err := uuid.Parse(val) 30 + if err != nil { 31 + uf.Log.ErrorContext(ctx, "failed to parse uuid", 32 + "value", val, 33 + "error", err, 34 + ) 35 + 36 + return UuidFormatResult{}, err 37 + } 38 + 39 + var result string 40 + 41 + switch uuidFmt { 42 + case Spec: 43 + result = id.String() 44 + 45 + case UrnPrefix: 46 + result = "urn:uuid:" + id.String() 47 + 48 + case Braces: 49 + result = "{" + id.String() + "}" 50 + 51 + case HexLiteral: 52 + result = fmt.Sprintf("x'%032x'", [16]byte(id)) 53 + 54 + default: 55 + result = id.String() 56 + } 57 + 58 + return UuidFormatResult{ 59 + Format: uuidFmt, 60 + Result: result, 61 + }, nil 62 + } 63 + 64 + func (uf UuidFormatter) Formats(ctx context.Context, val string, uuidFmts []UuidFormat) (r []UuidFormatResult, err error) { 65 + r = make([]UuidFormatResult, 0, len(uuidFmts)) 66 + 67 + for _, uuidFmt := range uuidFmts { 68 + fmtResult, err := uf.Format(ctx, val, uuidFmt) 69 + if err != nil { 70 + return r, err 71 + } 72 + r = append(r, fmtResult) 73 + } 74 + 75 + return r, nil 76 + }
+6
static/css/styles.css
··· 284 284 form:not(.exclude) label:not(input:is([type="checkbox"], [type="radio"]) + label) { 285 285 font-weight: bold; 286 286 } 287 + 288 + .selectall { 289 + -moz-user-select: all; 290 + -webkit-user-select: all; 291 + -ms-user-select: all; 292 + }