feat: Add web view to display notes in HTML
All checks were successful
/ pre-commit (push) Successful in 2m59s
All checks were successful
/ pre-commit (push) Successful in 2m59s
Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
parent
a5ebf7607c
commit
8edaebfad6
3 changed files with 159 additions and 2 deletions
|
@ -192,6 +192,7 @@ type PageData struct {
|
||||||
Languages []string
|
Languages []string
|
||||||
Err error
|
Err error
|
||||||
URL string
|
URL string
|
||||||
|
Note *Note
|
||||||
}
|
}
|
||||||
|
|
||||||
type HomeHandler struct {
|
type HomeHandler struct {
|
||||||
|
@ -316,6 +317,81 @@ func (h *CreateNoteWithFormHandler) ServeHTTP(w http.ResponseWriter, r *http.Req
|
||||||
h.Templates.ExecuteTemplate(w, "create", h.PageData)
|
h.Templates.ExecuteTemplate(w, "create", h.PageData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetWebNoteHandler struct {
|
||||||
|
Templates *template.Template
|
||||||
|
PageData PageData
|
||||||
|
logger *slog.Logger
|
||||||
|
db *Database
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *GetWebNoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
h.PageData.Err = nil
|
||||||
|
templateName := "note"
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
id := vars["id"]
|
||||||
|
|
||||||
|
note, err := h.db.Get(id)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
h.PageData.Err = fmt.Errorf("could not find note: %v", err)
|
||||||
|
h.Templates.ExecuteTemplate(w, templateName, h.PageData)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if note.Encrypted {
|
||||||
|
h.PageData.Err = fmt.Errorf("note is encrypted")
|
||||||
|
h.Templates.ExecuteTemplate(w, templateName, h.PageData)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
h.PageData.Err = fmt.Errorf("jriou")
|
||||||
|
h.Templates.ExecuteTemplate(w, templateName, h.PageData)
|
||||||
|
|
||||||
|
h.PageData.Note = note
|
||||||
|
|
||||||
|
h.logger.Debug("rendering note web page")
|
||||||
|
h.Templates.ExecuteTemplate(w, "note", h.PageData)
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetProtectedWebNoteHandler struct {
|
||||||
|
Templates *template.Template
|
||||||
|
PageData PageData
|
||||||
|
logger *slog.Logger
|
||||||
|
db *Database
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *GetProtectedWebNoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
h.PageData.Err = nil
|
||||||
|
templateName := "note"
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
id := vars["id"]
|
||||||
|
password := vars["password"]
|
||||||
|
|
||||||
|
note, err := h.db.Get(id)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
h.PageData.Err = fmt.Errorf("could not find note: %v", err)
|
||||||
|
h.Templates.ExecuteTemplate(w, templateName, h.PageData)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if password != "" && note.Encrypted {
|
||||||
|
note.Content, err = internal.Decrypt(note.Content, password)
|
||||||
|
if err != nil {
|
||||||
|
h.PageData.Err = fmt.Errorf("could not decrypt note: %v", err)
|
||||||
|
h.Templates.ExecuteTemplate(w, templateName, h.PageData)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h.PageData.Note = note
|
||||||
|
|
||||||
|
h.logger.Debug("rendering protected note web page")
|
||||||
|
h.Templates.ExecuteTemplate(w, "note", h.PageData)
|
||||||
|
}
|
||||||
|
|
||||||
//go:embed templates/*
|
//go:embed templates/*
|
||||||
var templatesFS embed.FS
|
var templatesFS embed.FS
|
||||||
|
|
||||||
|
@ -339,6 +415,7 @@ func (s *Server) Start() error {
|
||||||
funcs := template.FuncMap{
|
funcs := template.FuncMap{
|
||||||
"HumanDuration": internal.HumanDuration,
|
"HumanDuration": internal.HumanDuration,
|
||||||
"lower": strings.ToLower,
|
"lower": strings.ToLower,
|
||||||
|
"string": func(b []byte) string { return string(b) },
|
||||||
}
|
}
|
||||||
p := PageData{
|
p := PageData{
|
||||||
Title: s.config.Title,
|
Title: s.config.Title,
|
||||||
|
@ -363,6 +440,22 @@ func (s *Server) Start() error {
|
||||||
}
|
}
|
||||||
r.Path("/create").Handler(createNoteWithFormHandler).Methods("POST")
|
r.Path("/create").Handler(createNoteWithFormHandler).Methods("POST")
|
||||||
|
|
||||||
|
protectedWebNoteHandler := &GetProtectedWebNoteHandler{
|
||||||
|
Templates: templates,
|
||||||
|
PageData: p,
|
||||||
|
logger: s.logger,
|
||||||
|
db: s.db,
|
||||||
|
}
|
||||||
|
r.Path("/{id:[a-zA-Z0-9]+}/{password:[a-zA-Z0-9]+}.html").Handler(protectedWebNoteHandler).Methods("GET")
|
||||||
|
|
||||||
|
webNoteHandler := &GetWebNoteHandler{
|
||||||
|
Templates: templates,
|
||||||
|
PageData: p,
|
||||||
|
logger: s.logger,
|
||||||
|
db: s.db,
|
||||||
|
}
|
||||||
|
r.Path("/{id:[a-zA-Z0-9]+}.html").Handler(webNoteHandler).Methods("GET")
|
||||||
|
|
||||||
r.Path("/").Handler(&HomeHandler{Templates: templates, PageData: p}).Methods("GET")
|
r.Path("/").Handler(&HomeHandler{Templates: templates, PageData: p}).Methods("GET")
|
||||||
|
|
||||||
addr := fmt.Sprintf("%s:%d", s.config.ListenAddress, s.config.ListenPort)
|
addr := fmt.Sprintf("%s:%d", s.config.ListenAddress, s.config.ListenPort)
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<div class="alert alert-success" role="alert">
|
<div class="alert alert-success" role="alert">
|
||||||
<p>Note created successfully</p>
|
<p>Note created successfully</p>
|
||||||
<p>
|
<p>
|
||||||
<a href="{{.URL}}">{{.URL}}</a>
|
<a href="{{.URL}}.html">{{.URL}}.html</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
@ -20,8 +20,8 @@
|
||||||
<p>Could not create note</p>
|
<p>Could not create note</p>
|
||||||
<p><strong>{{.Err}}</strong></p>
|
<p><strong>{{.Err}}</strong></p>
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{block "footer" .}}{{end}}
|
{{block "footer" .}}{{end}}
|
||||||
</body>
|
</body>
|
||||||
|
|
64
src/server/templates/note.html
Normal file
64
src/server/templates/note.html
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
{{define "note"}}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" data-bs-theme="light">
|
||||||
|
|
||||||
|
{{block "head" .}}{{end}}
|
||||||
|
|
||||||
|
<body>
|
||||||
|
{{block "header" .}}{{end}}
|
||||||
|
|
||||||
|
{{if ne .Err nil}}
|
||||||
|
<div class="container mb-4 text-center">
|
||||||
|
<div class="alert alert-danger" role="alert">
|
||||||
|
<p>Could not show note</p>
|
||||||
|
<p><strong>{{.Err}}</strong></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="container mb-4">
|
||||||
|
<div class="d-flex flex-wrap py-2">
|
||||||
|
<span class="fs-4 d-flex mb-3 mb-md-0 me-md-auto text-decoration-none">Note {{.Note.ID}}</span>
|
||||||
|
<ul class="nav nav-pills align-items-center">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="" id="rawURL">raw</a>
|
||||||
|
<script>document.getElementById("rawURL").href = window.location.href.replace(".html", "");</script>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item px-2">
|
||||||
|
{{.Note.Language}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div id="editor" name="editor" class="form-control"
|
||||||
|
style="height: 300px; resize: vertical; overflow: auto;"></div>
|
||||||
|
</div>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.52.2/min/vs/loader.min.js"></script>
|
||||||
|
<script>
|
||||||
|
require.config({ paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.52.2/min/vs' } });
|
||||||
|
|
||||||
|
require(['vs/editor/editor.main'], function () {
|
||||||
|
var editor = monaco.editor.create(document.getElementById('editor'), {
|
||||||
|
theme: document.documentElement.getAttribute('data-bs-theme') == 'light' ? "vs" : "vs-dark",
|
||||||
|
language: "{{.Note.Language}}",
|
||||||
|
readOnly: true,
|
||||||
|
value: "{{string .Note.Content}}"
|
||||||
|
});
|
||||||
|
|
||||||
|
// Dark mode
|
||||||
|
document.getElementById("lightSwitch").addEventListener("click", () => {
|
||||||
|
if (document.documentElement.getAttribute('data-bs-theme') == 'light') {
|
||||||
|
monaco.editor.setTheme("vs")
|
||||||
|
} else if (document.documentElement.getAttribute('data-bs-theme') == 'dark') {
|
||||||
|
monaco.editor.setTheme("vs-dark")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{block "footer" .}}{{end}}
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
{{end}}
|
Loading…
Add table
Add a link
Reference in a new issue