Web ad-hoc items

This commit is contained in:
Tim Van Baak 2025-02-07 15:49:22 -08:00
parent bc19b0a70f
commit f5e9a0faec
7 changed files with 111 additions and 2 deletions

View File

@ -103,7 +103,7 @@ Parity features
* [ ] set a working directory for item actions
* [ ] crontab integration
* [ ] source batching
* [ ] add item from web
* [x] add item from web
* [ ] Nix build
* [ ] NixOS module
* [ ] NixOS vm demo

View File

@ -42,4 +42,36 @@
{{ end }}
</details>
</article>
<article>
<details open>
<summary><span class="feed-controls">Add item</span></summary>
<form action="/item" method="post">
<p>
<input type="text" name="title" class="wide" placeholder="Title">
</p>
<p>
<input type="url" name="link" class="wide" placeholder="Link">
</p>
<p>
<textarea name="body" class="wide" placeholder="Body"></textarea>
</p>
<p>
<label for="ttl">TTL:</label>
<input type="datetime-local" name="ttl">
</p>
<p>
<label for="ttd">TTD:</label>
<input type="datetime-local" name="ttd">
</p>
<p>
<label for="tts">TTS:</label>
<input type="datetime-local" name="tts">
</p>
<p>
<input type="submit" value="Add">
</p>
</form>
</details>
</article>
{{- end }}

View File

@ -133,7 +133,6 @@ var item = load("itemPage.html", "item.html")
type ItemData struct {
Item core.Item
Open bool
}
func Item(writer io.Writer, data ItemData) {

View File

@ -71,6 +71,7 @@ summary:focus {
.wide {
width: 100%;
resize: vertical;
box-sizing: border-box;
}
.fade > * {
opacity: 0.2;

View File

@ -1,5 +1,11 @@
{{ define "title" }}{{ if .Item.Title }}{{ .Item.Title }}{{ else }}{{ .Item.Source }}/{{ .Item.Id }}{{ end }} - Intake [{{ .Item.Source }}]{{ end }}
{{ define "content" -}}
<article class="center">
<span class="feed-controls">
<a href="/">Home</a>
</span>
</article>
{{ template "item" .Item }}
{{- end }}

View File

@ -1,6 +1,8 @@
package web
import (
"crypto/rand"
"encoding/hex"
"fmt"
"log"
"net/http"
@ -135,3 +137,71 @@ func (env *Env) massDeactivate(writer http.ResponseWriter, req *http.Request) {
writer.Header()["HX-Refresh"] = []string{"true"}
http.Error(writer, "ok", http.StatusNoContent)
}
func (env *Env) addItem(writer http.ResponseWriter, req *http.Request) {
if err := req.ParseForm(); err != nil {
log.Printf("error parsing form data: %v", err)
http.Error(writer, "", http.StatusBadRequest)
return
}
exists, err := core.SourceExists(env.db, "default")
if err != nil {
http.Error(writer, fmt.Sprintf("error: failed to check for source: %v", err), 500)
return
}
if !exists {
if err := core.AddSource(env.db, "default"); err != nil {
http.Error(writer, fmt.Sprintf("error: failed to add source: %v", err), 500)
return
}
}
bytes := make([]byte, 16)
if _, err := rand.Read(bytes); err != nil {
http.Error(writer, fmt.Sprintf("error: failed to generate id: %v", err), 500)
}
id := hex.EncodeToString(bytes)
title := req.PostForm.Get("title")
link := req.PostForm.Get("link")
body := req.PostForm.Get("body")
item := core.Item{
Source: "default",
Id: id,
Title: title,
Link: link,
Body: body,
}
now := time.Now().Unix()
if ttl := req.PostForm.Get("ttl"); ttl != "" {
ttl, _ := time.Parse("2006-01-02T15:04", ttl)
item.Ttl = int(ttl.Unix() - now)
}
if ttd := req.PostForm.Get("ttd"); ttd != "" {
ttd, _ := time.Parse("2006-01-02T15:04", ttd)
item.Ttd = int(ttd.Unix() - now)
}
if tts := req.PostForm.Get("tts"); tts != "" {
tts, _ := time.Parse("2006-01-02T15:04", tts)
item.Tts = int(tts.Unix() - now)
}
if err := core.AddItems(env.db, []core.Item{item}); err != nil {
http.Error(writer, fmt.Sprintf("error: failed to add item: %s", err), 500)
return
}
item, err = core.GetItem(env.db, "default", id)
if err != nil {
http.Error(writer, err.Error(), 500)
return
}
data := html.ItemData{
Item: item,
}
html.Item(writer, data)
}

View File

@ -42,6 +42,7 @@ func RunServer(db core.DB, addr string, port string) {
handleFunc("GET /source/{source}", env.getSource, env.authed, logged)
handleFunc("POST /source/{source}/fetch", env.fetchSource, env.authed, logged)
handleFunc("GET /channel/{channel}", env.getChannel, env.authed, logged)
handleFunc("POST /item", env.addItem, env.authed, logged)
handleFunc("GET /item/{source}/{id}", env.getItem, env.authed, logged)
handleFunc("DELETE /item/{source}/{id}", env.deleteItem, env.authed, logged)
handleFunc("POST /item/{source}/{id}/action/{action}", env.doAction, env.authed, logged)