Add channels to home page

This commit is contained in:
Tim Van Baak 2025-01-31 18:03:30 -08:00
parent e40e2a3245
commit 7b83d01f12
8 changed files with 107 additions and 9 deletions

View File

@ -39,3 +39,29 @@ func GetSourcesInChannel(db DB) (map[string][]string, error) {
} }
return channelSources, nil return channelSources, nil
} }
func GetChannelsAndActiveCounts(db DB) (map[string]int, error) {
rows, err := db.Query(`
select c.name, count(i.id) as count
from channels c
left outer join items i on c.source = i.source and i.active = 1
group by c.name
`)
if err != nil {
return nil, err
}
defer rows.Close()
channelCounts := make(map[string]int)
for rows.Next() {
var name string
var count int
if err := rows.Scan(&name, &count); err != nil {
return nil, err
}
channelCounts[name] = count
}
if err := rows.Err(); err != nil {
return nil, err
}
return channelCounts, nil
}

View File

@ -50,9 +50,17 @@ func TestChannel(t *testing.T) {
}); err != nil { }); err != nil {
t.Fatalf("failed to add items to one: %v", err) t.Fatalf("failed to add items to one: %v", err)
} }
if counts, err := GetChannelsAndActiveCounts(db); counts["channel"] != 2 || err != nil {
t.Fatalf("expected 2 active items in channel, got %d: %v", counts["channel"], err)
}
if _, err := DeactivateItem(db, "one", "a"); err != nil { if _, err := DeactivateItem(db, "one", "a"); err != nil {
t.Fatalf("failed to deactivate item: %v", err) t.Fatalf("failed to deactivate item: %v", err)
} }
if counts, err := GetChannelsAndActiveCounts(db); counts["channel"] != 1 || err != nil {
t.Fatalf("expected 1 active items in channel, got %d: %v", counts["channel"], err)
}
items, err := GetAllItemsForChannel(db, "channel") items, err := GetAllItemsForChannel(db, "channel")
if err != nil { if err != nil {
t.Fatalf("failed to get all items in channel: %v", err) t.Fatalf("failed to get all items in channel: %v", err)

30
web/channel.go Normal file
View File

@ -0,0 +1,30 @@
package web
import (
"net/http"
"github.com/Jaculabilis/intake/core"
"github.com/Jaculabilis/intake/web/html"
)
func (env *Env) getChannel(writer http.ResponseWriter, req *http.Request) {
channel := req.PathValue("channel")
var items []core.Item
var err error
inactive := req.URL.Query().Get("inactive") == "1"
if inactive {
items, err = core.GetAllItemsForChannel(env.db, channel)
} else {
items, err = core.GetActiveItemsForChannel(env.db, channel)
}
if err != nil {
http.Error(writer, err.Error(), 500)
return
}
data := html.FeedData{
Items: items,
}
html.Feed(writer, data)
}

View File

@ -1,6 +1,25 @@
{{ define "title" }}Intake{{ end }} {{ define "title" }}Intake{{ end }}
{{ define "content" -}} {{ define "content" -}}
<article>
<details open>
<summary><span class="item-title">Channels</span></summary>
{{ if .Channels }}
{{ range .Channels }}
<p><a href="/channel/{{ .Name }}">
{{ if .Active }}
{{ .Name }} ({{ .Active }})
{{ else }}
{{ .Name }}
{{ end }}
</a></p>
{{ end }}
{{ else }}
<p>No channels found.</p>
{{ end }}
</details>
</article>
<article> <article>
<details> <details>
<summary><span class="item-title">Sources</span></summary> <summary><span class="item-title">Sources</span></summary>

View File

@ -57,12 +57,18 @@ func load(files ...string) *template.Template {
var home = load("home.html") var home = load("home.html")
type ChannelData struct {
Name string
Active int
}
type SourceData struct { type SourceData struct {
Name string Name string
} }
type HomeData struct { type HomeData struct {
Sources []SourceData Channels []ChannelData
Sources []SourceData
} }
func Home(writer io.Writer, data HomeData) error { func Home(writer io.Writer, data HomeData) error {

View File

@ -31,6 +31,7 @@ func RunServer(db core.DB, addr string, port string) {
handleFunc("GET /style.css", env.getStyle) handleFunc("GET /style.css", env.getStyle)
handleFunc("GET /htmx.org@2.0.4.js", env.getScript) handleFunc("GET /htmx.org@2.0.4.js", env.getScript)
handleFunc("GET /source/{source}", env.getSource) handleFunc("GET /source/{source}", env.getSource)
handleFunc("GET /channel/{channel}", env.getChannel)
handleFunc("GET /item/{source}/{id}", env.getItem) handleFunc("GET /item/{source}/{id}", env.getItem)
handleFunc("DELETE /item/{source}/{id}", env.deleteItem) handleFunc("DELETE /item/{source}/{id}", env.deleteItem)
handleFunc("POST /item/{source}/{id}/action/{action}", env.doAction) handleFunc("POST /item/{source}/{id}/action/{action}", env.doAction)

View File

@ -13,17 +13,27 @@ func (env *Env) getRoot(writer http.ResponseWriter, req *http.Request) {
return return
} }
names, err := core.GetSources(env.db) sources, err := core.GetSources(env.db)
if err != nil { if err != nil {
http.Error(writer, err.Error(), 500) http.Error(writer, err.Error(), 500)
} }
var sourceData []html.SourceData
var sources []html.SourceData for _, name := range sources {
for _, name := range names { sourceData = append(sourceData, html.SourceData{Name: name})
sources = append(sources, html.SourceData{Name: name})
} }
channels, err := core.GetChannelsAndActiveCounts(env.db)
if err != nil {
http.Error(writer, err.Error(), 500)
}
var channelData []html.ChannelData
for name, active := range channels {
channelData = append(channelData, html.ChannelData{Name: name, Active: active})
}
data := html.HomeData{ data := html.HomeData{
Sources: sources, Channels: channelData,
Sources: sourceData,
} }
html.Home(writer, data) html.Home(writer, data)
} }

View File

@ -1,7 +1,6 @@
package web package web
import ( import (
"log"
"net/http" "net/http"
"github.com/Jaculabilis/intake/core" "github.com/Jaculabilis/intake/core"
@ -18,7 +17,6 @@ func (env *Env) getSource(writer http.ResponseWriter, req *http.Request) {
var items []core.Item var items []core.Item
var err error var err error
inactive := req.URL.Query().Get("inactive") == "1" inactive := req.URL.Query().Get("inactive") == "1"
log.Printf("inactive = %t", inactive)
if inactive { if inactive {
items, err = core.GetAllItemsForSource(env.db, source) items, err = core.GetAllItemsForSource(env.db, source)
} else { } else {