Compare commits

..

18 Commits

Author SHA1 Message Date
783d59805b Fixed small bug 2024-04-07 19:33:51 +02:00
b5f0fe8985 Added title, link and description to cli args. 2024-04-07 19:29:35 +02:00
d9bf79d5f8 Add space between first and last name 2024-04-07 19:01:21 +02:00
f98ab149a2 Added headings to all templates 2024-04-07 18:57:03 +02:00
822ca2b8ab Use UUID as filename and strip alt off of extension 2024-04-07 18:43:09 +02:00
af65180893 Reflect new cli arg in .air.toml 2024-04-07 11:36:34 +02:00
5615210be5 Add cli arg for domain 2024-04-07 11:32:38 +02:00
b88fb1643c Fixed bug 2024-04-07 11:12:07 +02:00
92189a4a51 Pictures are now handeled correctly 2024-04-07 10:58:07 +02:00
8dc8f02504 Changed rss package to tagged version 2024-04-04 17:17:55 +02:00
e3ce1d7b55 Simply provide RSS feed when GET request is received 2024-04-04 17:13:42 +02:00
532bc6490a Added XML encoding 2024-04-04 17:09:29 +02:00
84fa828b38 Provide RSS feed as file when pressing the button or typing the URL 2024-04-03 21:05:12 +02:00
a3c53b1b20 Changed URL patterns to be more specific 2024-04-03 20:24:54 +02:00
ca70fa6d4d Applied changes also to rework-article.html 2024-04-03 19:52:16 +02:00
972b8cac19 Corrected vertical gap size for tags when wrapping onto the next line 2024-04-03 19:51:27 +02:00
d0605660f7 Made tags wrap onto the next line when overflowing parent container 2024-04-03 19:48:42 +02:00
5d2d841aba Changed tag length to 50 characters 2024-04-03 19:47:27 +02:00
23 changed files with 182 additions and 217 deletions

View File

@ -3,42 +3,52 @@ testdata_dir = "testdata"
tmp_dir = "tmp" tmp_dir = "tmp"
[build] [build]
args_bin = [] args_bin = [
bin = "./tmp/main -key tmp/key.gob -log tmp/cpolis.log -pics tmp/pics -rss tmp/orientexpress_alle.rss -web web" "-desc 'Freiheit, Gleichheit, Brüderlichkeit, Toleranz und Humanität'",
cmd = "go build -o ./tmp/main ./cmd/main.go" "-domain localhost:8080",
delay = 0 "-key tmp/key.gob",
exclude_dir = ["assets", "tmp", "vendor", "testdata"] "-link https://distrikt-ni-st.de",
exclude_file = [] "-log tmp/cpolis.log",
exclude_regex = ["_test.go"] "-pics tmp/pics",
exclude_unchanged = false "-rss tmp/orientexpress_alle.rss",
follow_symlink = false "-title 'Freimaurer Distrikt Niedersachsen und Sachsen-Anhalt'",
full_bin = "" "-web web"
include_dir = [] ]
include_ext = ["go", "tpl", "tmpl", "html", "css"] bin = "./tmp/main"
include_file = [] cmd = "go build -o ./tmp/main ./cmd/main.go"
kill_delay = "0s" delay = 0
log = "build-errors.log" exclude_dir = ["assets", "tmp", "vendor", "testdata"]
poll = false exclude_file = []
poll_interval = 0 exclude_regex = ["_test.go"]
rerun = false exclude_unchanged = false
rerun_delay = 500 follow_symlink = false
send_interrupt = false full_bin = ""
stop_on_error = false include_dir = []
include_ext = ["go", "tpl", "tmpl", "html", "css"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color] [color]
app = "" app = ""
build = "yellow" build = "yellow"
main = "magenta" main = "magenta"
runner = "green" runner = "green"
watcher = "cyan" watcher = "cyan"
[log] [log]
main_only = false main_only = false
time = false time = false
[misc] [misc]
clean_on_exit = false clean_on_exit = false
[screen] [screen]
clear_on_rebuild = false clear_on_rebuild = false
keep_scroll = true keep_scroll = true

View File

@ -7,12 +7,16 @@ import (
) )
type CliArgs struct { type CliArgs struct {
Description string
DBName string DBName string
Domain string
KeyFile string KeyFile string
Link string
LogFile string LogFile string
Port string Port string
PicsDir string PicsDir string
RSSFile string RSSFile string
Title string
WebDir string WebDir string
} }
@ -20,13 +24,17 @@ func HandleCliArgs() (*CliArgs, error) {
var err error var err error
cliArgs := new(CliArgs) cliArgs := new(CliArgs)
flag.StringVar(&cliArgs.DBName, "db", "cpolis", "DB name")
flag.StringVar(&cliArgs.Description, "desc", "Description", "Channel description")
flag.StringVar(&cliArgs.Domain, "domain", "", "domain name")
keyFile := flag.String("key", "/var/www/cpolis/cpolis.key", "key file") keyFile := flag.String("key", "/var/www/cpolis/cpolis.key", "key file")
flag.StringVar(&cliArgs.Link, "link", "Link", "Channel Link")
logFile := flag.String("log", "/var/log/cpolis.log", "log file") logFile := flag.String("log", "/var/log/cpolis.log", "log file")
picsDir := flag.String("pics", "/var/www/cpolis/pics", "pictures directory") flag.StringVar(&cliArgs.PicsDir, "pics", "pics", "pictures directory")
port := flag.Int("port", 8080, "port") port := flag.Int("port", 8080, "port")
rssFile := flag.String("rss", "/var/www/cpolis/cpolis.rss", "RSS file") rssFile := flag.String("rss", "/var/www/cpolis/cpolis.rss", "RSS file")
flag.StringVar(&cliArgs.Title, "title", "Title", "Channel title")
webDir := flag.String("web", "/var/www/cpolis/web", "web directory") webDir := flag.String("web", "/var/www/cpolis/web", "web directory")
flag.StringVar(&cliArgs.DBName, "db", "cpolis", "DB name")
flag.Parse() flag.Parse()
cliArgs.KeyFile, err = filepath.Abs(*keyFile) cliArgs.KeyFile, err = filepath.Abs(*keyFile)
@ -39,7 +47,7 @@ func HandleCliArgs() (*CliArgs, error) {
return nil, fmt.Errorf("error finding absolute path for LogFile: %v", err) return nil, fmt.Errorf("error finding absolute path for LogFile: %v", err)
} }
cliArgs.PicsDir, err = filepath.Abs(*picsDir) _, err = filepath.Abs(cliArgs.PicsDir)
if err != nil { if err != nil {
return nil, fmt.Errorf("error finding absolute path for PicsDir: %v", err) return nil, fmt.Errorf("error finding absolute path for PicsDir: %v", err)
} }

View File

@ -97,7 +97,7 @@ func GenerateRSS(db *model.DB, title, link, desc string) (*string, error) {
channel.Items = append(channel.Items, &rss.Item{ channel.Items = append(channel.Items, &rss.Item{
Title: articleTitle, Title: articleTitle,
Author: user.FirstName + user.LastName, Author: user.FirstName + " " + user.LastName,
PubDate: article.Created.Format(time.RFC1123Z), PubDate: article.Created.Format(time.RFC1123Z),
Description: articleDescription, Description: articleDescription,
Content: &rss.Content{Value: articleContent}, Content: &rss.Content{Value: articleContent},
@ -107,7 +107,7 @@ func GenerateRSS(db *model.DB, title, link, desc string) (*string, error) {
feed := rss.NewFeed() feed := rss.NewFeed()
feed.Channels = append(feed.Channels, channel) feed.Channels = append(feed.Channels, channel)
rss, err := feed.ToXML() rss, err := feed.ToXML("UTF-8")
if err != nil { if err != nil {
return nil, fmt.Errorf("error converting RSS feed to XML: %v", err) return nil, fmt.Errorf("error converting RSS feed to XML: %v", err)
} }

View File

@ -49,36 +49,33 @@ func main() {
http.FileServer(http.Dir(args.WebDir+"/static/")))) http.FileServer(http.Dir(args.WebDir+"/static/"))))
mux.HandleFunc("/", view.HomePage(args, db, store)) mux.HandleFunc("/", view.HomePage(args, db, store))
mux.HandleFunc("GET /create-tag/", view.CreateTag(args)) mux.HandleFunc("GET /create-tag", view.CreateTag(args))
mux.HandleFunc("GET /create-user/", view.CreateUser(args)) mux.HandleFunc("GET /create-user", view.CreateUser(args))
mux.HandleFunc("GET /edit-user/", view.EditUser(args, db, store)) mux.HandleFunc("GET /edit-user", view.EditUser(args, db, store))
mux.HandleFunc("GET /hub/", view.ShowHub(args, db, store)) mux.HandleFunc("GET /hub", view.ShowHub(args, db, store))
mux.HandleFunc("GET /logout/", view.Logout(args, store)) mux.HandleFunc("GET /logout", view.Logout(args, store))
mux.HandleFunc("GET /publish-article/{id}/", view.PublishArticle(args, db, store)) mux.HandleFunc("GET /publish-article/{id}", view.PublishArticle(args, db, store))
mux.HandleFunc("GET /publish-issue/", view.PublishLatestIssue(args, db, store)) mux.HandleFunc("GET /publish-issue", view.PublishLatestIssue(args, db, store))
mux.HandleFunc("GET /reject-article/{id}/", view.RejectArticle(args, db, store)) mux.HandleFunc("GET /reject-article/{id}", view.RejectArticle(args, db, store))
mux.HandleFunc("GET /rejected-articles/", view.ShowRejectedArticles(args, db, store)) mux.HandleFunc("GET /rejected-articles", view.ShowRejectedArticles(args, db, store))
mux.HandleFunc("GET /review-rejected-article/{id}/", view.ReviewRejectedArticle(args, db, store)) mux.HandleFunc("GET /review-rejected-article/{id}", view.ReviewRejectedArticle(args, db, store))
mux.HandleFunc("GET /review-unpublished-article/{id}/", view.ReviewUnpublishedArticle(args, db, store)) mux.HandleFunc("GET /review-unpublished-article/{id}", view.ReviewUnpublishedArticle(args, db, store))
mux.HandleFunc("GET /rss/", view.ShowRSS( mux.HandleFunc("GET /rss", func(w http.ResponseWriter, r *http.Request) {
args, http.ServeFile(w, r, args.RSSFile)
db, })
"Freimaurer Distrikt Niedersachsen und Sachsen-Anhalt", mux.HandleFunc("GET /pics/{pic}", view.ServeImage(args, store))
"https://distrikt-ni-st.de", mux.HandleFunc("GET /this-issue", view.ShowCurrentArticles(args, db))
"Freiheit, Gleichheit, Brüderlichkeit, Toleranz und Humanität", mux.HandleFunc("GET /unpublished-articles", view.ShowUnpublishedArticles(args, db))
)) mux.HandleFunc("GET /write-article", view.WriteArticle(args, db))
mux.HandleFunc("GET /this-issue/", view.ShowCurrentArticles(args, db))
mux.HandleFunc("GET /unpublished-articles/", view.ShowUnpublishedArticles(args, db))
mux.HandleFunc("GET /write-article/", view.WriteArticle(args, db))
mux.HandleFunc("POST /add-first-user/", view.AddFirstUser(args, db, store)) mux.HandleFunc("POST /add-first-user", view.AddFirstUser(args, db, store))
mux.HandleFunc("POST /add-tag/", view.AddTag(args, db, store)) mux.HandleFunc("POST /add-tag", view.AddTag(args, db, store))
mux.HandleFunc("POST /add-user/", view.AddUser(args, db, store)) mux.HandleFunc("POST /add-user", view.AddUser(args, db, store))
mux.HandleFunc("POST /login/", view.Login(args, db, store)) mux.HandleFunc("POST /login", view.Login(args, db, store))
mux.HandleFunc("POST /resubmit-article/{id}/", view.ResubmitArticle(args, db, store)) mux.HandleFunc("POST /resubmit-article/{id}", view.ResubmitArticle(args, db, store))
mux.HandleFunc("POST /submit-article/", view.SubmitArticle(args, db, store)) mux.HandleFunc("POST /submit-article", view.SubmitArticle(args, db, store))
mux.HandleFunc("POST /update-user/", view.UpdateUser(args, db, store)) mux.HandleFunc("POST /update-user", view.UpdateUser(args, db, store))
mux.HandleFunc("POST /upload-image/", view.UploadImage(args)) mux.HandleFunc("POST /upload-image", view.UploadImage(args))
log.Fatalln(http.ListenAndServe(args.Port, mux)) log.Fatalln(http.ListenAndServe(args.Port, mux))
} }

View File

@ -7,9 +7,12 @@ import (
"log" "log"
"net/http" "net/http"
"os" "os"
"path/filepath"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/google/uuid"
"streifling.com/jason/cpolis/cmd/control" "streifling.com/jason/cpolis/cmd/control"
"streifling.com/jason/cpolis/cmd/model" "streifling.com/jason/cpolis/cmd/model"
) )
@ -335,12 +338,7 @@ func PublishArticle(c *control.CliArgs, db *model.DB, s *control.CookieStore) ht
return return
} }
feed, err := control.GenerateRSS( feed, err := control.GenerateRSS(db, c.Title, c.Link, c.Description)
db,
"Freimaurer Distrikt Niedersachsen und Sachsen-Anhalt",
"https://distrikt-ni-st.de",
"Freiheit, Gleichheit, Brüderlichkeit, Toleranz und Humanität",
)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
@ -412,8 +410,17 @@ func UploadImage(c *control.CliArgs) http.HandlerFunc {
} }
defer file.Close() defer file.Close()
filename := fmt.Sprint(c.PicsDir, time.Now().Format("2006-01-02_15:04:05"), "-", header.Filename) nameStrings := strings.Split(header.Filename, ".")
img, err := os.Create(filename) extension := "." + nameStrings[len(nameStrings)-1]
filename := fmt.Sprint(uuid.New(), extension)
absFilepath, err := filepath.Abs(fmt.Sprint(c.PicsDir, "/", filename))
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
img, err := os.Create(absFilepath)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
@ -427,7 +434,9 @@ func UploadImage(c *control.CliArgs) http.HandlerFunc {
return return
} }
alt := strings.Join(nameStrings[0:len(nameStrings)-1], " ")
imgMD := fmt.Sprint("![", alt, "](", c.Domain, "/pics/", filename, ")")
tmpl, err := template.ParseFiles(c.WebDir + "/templates/editor.html") tmpl, err := template.ParseFiles(c.WebDir + "/templates/editor.html")
template.Must(tmpl, err).ExecuteTemplate(w, "editor-images", fmt.Sprint("![", header.Filename, "](", filename, ")")) template.Must(tmpl, err).ExecuteTemplate(w, "editor-images", imgMD)
} }
} }

22
cmd/view/images.go Normal file
View File

@ -0,0 +1,22 @@
package view
import (
"log"
"net/http"
"path/filepath"
"streifling.com/jason/cpolis/cmd/control"
)
func ServeImage(c *control.CliArgs, s *control.CookieStore) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
absFilepath, err := filepath.Abs(c.PicsDir)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.ServeFile(w, r, absFilepath+"/"+r.PathValue("pic"))
}
}

View File

@ -1,95 +0,0 @@
package view
import (
"fmt"
"html/template"
"log"
"net/http"
"time"
"git.streifling.com/jason/rss"
"streifling.com/jason/cpolis/cmd/control"
"streifling.com/jason/cpolis/cmd/model"
)
func ShowRSS(c *control.CliArgs, db *model.DB, title, link, desc string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
channel := &rss.Channel{
Title: title,
Link: link,
Description: desc,
Items: make([]*rss.Item, 0),
}
articles, err := db.GetCertainArticles(true, false)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
for _, article := range articles {
tags, err := db.GetArticleTags(article.ID)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tagNames := make([]string, 0)
for _, tag := range tags {
tagNames = append(tagNames, tag.Name)
}
tagNames = append(tagNames, fmt.Sprint("Orient Express ", article.IssueID))
user, err := db.GetUser(article.AuthorID)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
articleTitle, err := control.ConvertToPlain(article.Title)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
articleDescription, err := control.ConvertToPlain(article.Description)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
articleContent, err := control.ConvertToHTML(article.Content)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
channel.Items = append(channel.Items, &rss.Item{
Title: articleTitle,
Author: user.FirstName + user.LastName,
PubDate: article.Created.Format(time.RFC1123Z),
Description: articleDescription,
Content: &rss.Content{Value: articleContent},
Categories: tagNames,
})
}
feed := rss.NewFeed()
feed.Channels = append(feed.Channels, channel)
rss, err := feed.ToXML()
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
files := []string{c.WebDir + "/templates/index.html", c.WebDir + "/templates/feed.rss"}
tmpl, err := template.ParseFiles(files...)
template.Must(tmpl, err).Execute(w, rss)
}
}

View File

@ -37,7 +37,7 @@ CREATE TABLE articles (
CREATE TABLE tags ( CREATE TABLE tags (
id INT AUTO_INCREMENT, id INT AUTO_INCREMENT,
name VARCHAR(15) NOT NULL UNIQUE, name VARCHAR(50) NOT NULL UNIQUE,
PRIMARY KEY(id) PRIMARY KEY(id)
); );

3
go.mod
View File

@ -3,8 +3,9 @@ module streifling.com/jason/cpolis
go 1.22.0 go 1.22.0
require ( require (
git.streifling.com/jason/rss v0.0.0-20240305164907-524bf9676188 git.streifling.com/jason/rss v0.1.2
github.com/go-sql-driver/mysql v1.7.1 github.com/go-sql-driver/mysql v1.7.1
github.com/google/uuid v1.6.0
github.com/gorilla/sessions v1.2.2 github.com/gorilla/sessions v1.2.2
github.com/microcosm-cc/bluemonday v1.0.26 github.com/microcosm-cc/bluemonday v1.0.26
github.com/yuin/goldmark v1.7.0 github.com/yuin/goldmark v1.7.0

6
go.sum
View File

@ -1,11 +1,13 @@
git.streifling.com/jason/rss v0.0.0-20240305164907-524bf9676188 h1:C8M/j3f+cl5Y7YfGpU/ynb/SC/4tTYMDsyGFt3rswM8= git.streifling.com/jason/rss v0.1.2 h1:UB3UHJXMt5WDDh9y8n0Z6nS1XortbPXjEr7QZTdovY4=
git.streifling.com/jason/rss v0.0.0-20240305164907-524bf9676188/go.mod h1:gpZF0nZbQSstMpyHD9DTAvlQEG7v4pjO5c7aIMWM4Jg= git.streifling.com/jason/rss v0.1.2/go.mod h1:gpZF0nZbQSstMpyHD9DTAvlQEG7v4pjO5c7aIMWM4Jg=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=

View File

@ -4,8 +4,8 @@
<form> <form>
<input required name="tag" placeholder="Tag eingeben" type="text" /> <input required name="tag" placeholder="Tag eingeben" type="text" />
<div class="btn-area"> <div class="btn-area">
<input class="action-btn" type="submit" value="Anlegen" hx-post="/add-tag/" hx-target="#page-content" /> <input class="action-btn" type="submit" value="Anlegen" hx-post="/add-tag" hx-target="#page-content" />
<button class="btn" hx-get="/hub/" hx-target="#page-content">Abbrechen</button> <button class="btn" hx-get="/hub" hx-target="#page-content">Abbrechen</button>
</div> </div>
</form> </form>

View File

@ -1,5 +1,6 @@
{{define "page-content"}} {{define "page-content"}}
<h2>Neuer Benutzer</h2> <h2>Neuer Benutzer</h2>
<form> <form>
<div class="grid grid-cols-3 gap-4"> <div class="grid grid-cols-3 gap-4">
<div> <div>
@ -44,8 +45,8 @@
</div> </div>
<div class="btn-area"> <div class="btn-area">
<input class="action-btn" type="submit" value="Anlegen" hx-post="/add-user/" hx-target="#page-content" /> <input class="action-btn" type="submit" value="Anlegen" hx-post="/add-user" hx-target="#page-content" />
<button class="btn" hx-get="/hub/" hx-target="#page-content">Abbrechen</button> <button class="btn" hx-get="/hub" hx-target="#page-content">Abbrechen</button>
</div> </div>
</form> </form>

View File

@ -1,4 +1,6 @@
{{define "page-content"}} {{define "page-content"}}
<h2>Aktuelle Artikel</h2>
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
{{range .}} {{range .}}
<div class="border px-2 py-1 rounded-md"> <div class="border px-2 py-1 rounded-md">
@ -9,7 +11,7 @@
</div> </div>
<div class="btn-area"> <div class="btn-area">
<button class="action-btn" hx-get="/publish-issue/" hx-target="#page-content">Ausgabe publizieren</button> <button class="action-btn" hx-get="/publish-issue" hx-target="#page-content">Ausgabe publizieren</button>
<button class="btn" hx-get="/hub/" hx-target="#page-content">Abbrechen</button> <button class="btn" hx-get="/hub" hx-target="#page-content">Abbrechen</button>
</div> </div>
{{end}} {{end}}

View File

@ -1,4 +1,6 @@
{{define "page-content"}} {{define "page-content"}}
<h2>Benutzerdaten bearbeiten</h2>
<form> <form>
<div class="grid grid-cols-3 gap-4"> <div class="grid grid-cols-3 gap-4">
<div> <div>
@ -28,9 +30,9 @@
</div> </div>
<div class="btn-area"> <div class="btn-area">
<input class="action-btn" type="submit" value="Aktualisieren" hx-post="/update-user/" <input class="action-btn" type="submit" value="Aktualisieren" hx-post="/update-user"
hx-target="#page-content" /> hx-target="#page-content" />
<button class="btn" hx-get="/hub/" hx-target="#page-content">Abbrechen</button> <button class="btn" hx-get="/hub" hx-target="#page-content">Abbrechen</button>
</div> </div>
</form> </form>
{{end}} {{end}}

View File

@ -1,5 +1,6 @@
{{define "page-content"}} {{define "page-content"}}
<h2>Editor</h2> <h2>Editor</h2>
<form> <form>
<div class="flex flex-col gap-y-1"> <div class="flex flex-col gap-y-1">
<label for="article-title">Titel</label> <label for="article-title">Titel</label>
@ -16,7 +17,7 @@
<div> <div>
<span>Tags</span> <span>Tags</span>
<div class="flex gap-4"> <div class="flex flex-wrap gap-x-4">
{{range .}} {{range .}}
<div> <div>
<input id="{{.Name}}" name="tags" type="checkbox" value="{{.ID}}" /> <input id="{{.Name}}" name="tags" type="checkbox" value="{{.ID}}" />
@ -27,13 +28,13 @@
</div> </div>
<div id="editor-images"> <div id="editor-images">
<input class="mb-2" name="article-image" type="file" hx-encoding="multipart/form-data" hx-post="/upload-image/" <input class="mb-2" name="article-image" type="file" hx-encoding="multipart/form-data" hx-post="/upload-image"
hx-swap="beforeend" hx-target="#editor-images" /> hx-swap="beforeend" hx-target="#editor-images" />
</div> </div>
<div class="btn-area"> <div class="btn-area">
<input class="action-btn" type="submit" value="Senden" hx-post="/submit-article/" hx-target="#page-content" /> <input class="action-btn" type="submit" value="Senden" hx-post="/submit-article" hx-target="#page-content" />
<button class="btn" hx-get="/hub/" hx-target="#page-content">Abbrechen</button> <button class="btn" hx-get="/hub" hx-target="#page-content">Abbrechen</button>
</div> </div>
</form> </form>

View File

@ -1,3 +0,0 @@
{{define "page-content"}}
{{.}}
{{end}}

View File

@ -26,7 +26,7 @@
</div> </div>
<div class="btn-area"> <div class="btn-area">
<input class="action-btn" type="submit" value="Anlegen" hx-post="/add-first-user/" hx-target="#page-content" /> <input class="action-btn" type="submit" value="Anlegen" hx-post="/add-first-user" hx-target="#page-content" />
</div> </div>
</form> </form>

View File

@ -1,14 +1,14 @@
{{define "page-content"}} {{define "page-content"}}
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
<button class="btn" hx-get="/logout/" hx-target="#page-content">Abmelden</button> <button class="btn" hx-get="/logout" hx-target="#page-content">Abmelden</button>
<div class="mb-3"> <div class="mb-3">
<h2>Autor</h2> <h2>Autor</h2>
<div class="grid grid-cols-2 gap-x-4 gap-y-2"> <div class="grid grid-cols-2 gap-x-4 gap-y-2">
<button class="btn" hx-get="/write-article/" hx-target="#page-content">Artikel schreiben</button> <button class="btn" hx-get="/write-article" hx-target="#page-content">Artikel schreiben</button>
<button class="btn" hx-get="/rejected-articles/" hx-target="#page-content">Abgelehnte Artikel</button> <button class="btn" hx-get="/rejected-articles" hx-target="#page-content">Abgelehnte Artikel</button>
<button class="btn" hx-get="/rss/" hx-target="#page-content">RSS Feed</button> <a class="btn text-center" href="/rss">RSS Feed</a>
<button class="btn" hx-get="/edit-user/" hx-target="#page-content">Benutzer bearbeiten</button> <button class="btn" hx-get="/edit-user" hx-target="#page-content">Benutzer bearbeiten</button>
</div> </div>
</div> </div>
@ -16,10 +16,10 @@
<div class="mb-3"> <div class="mb-3">
<h2>Redakteur</h2> <h2>Redakteur</h2>
<div class="grid grid-cols-2 gap-4"> <div class="grid grid-cols-2 gap-4">
<button class="btn" hx-get="/unpublished-articles/" hx-target="#page-content"> <button class="btn" hx-get="/unpublished-articles" hx-target="#page-content">
Unveröffentlichte Artikel Unveröffentlichte Artikel
</button> </button>
<button class="btn" hx-get="/create-tag/" hx-target="#page-content">Neuer Tag</button> <button class="btn" hx-get="/create-tag" hx-target="#page-content">Neuer Tag</button>
</div> </div>
</div> </div>
{{end}} {{end}}
@ -28,7 +28,7 @@
<div class="mb-3"> <div class="mb-3">
<h2>Herausgeber</h2> <h2>Herausgeber</h2>
<div class="grid grid-cols-2 gap-4"> <div class="grid grid-cols-2 gap-4">
<button class="btn" hx-get="/this-issue/" hx-target="#page-content">Diese Ausgabe</button> <button class="btn" hx-get="/this-issue" hx-target="#page-content">Diese Ausgabe</button>
</div> </div>
</div> </div>
{{end}} {{end}}
@ -37,7 +37,7 @@
<div class="mb-3"> <div class="mb-3">
<h2>Administrator</h2> <h2>Administrator</h2>
<div class="grid grid-cols-2 gap-4"> <div class="grid grid-cols-2 gap-4">
<button class="btn" hx-get="/create-user/" hx-target="#page-content">Benutzer hinzufügen</button> <button class="btn" hx-get="/create-user" hx-target="#page-content">Benutzer hinzufügen</button>
</div> </div>
</div> </div>
{{end}} {{end}}

View File

@ -1,11 +1,12 @@
{{define "page-content"}} {{define "page-content"}}
<h2>Anmeldung</h2> <h2>Anmeldung</h2>
<form> <form>
<div class="btn-area"> <div class="btn-area">
<input class="w-full" name="username" placeholder="Benutzername" type="text" /> <input class="w-full" name="username" placeholder="Benutzername" type="text" />
<input class="w-full" name="password" placeholder="Passwort" type="password" /> <input class="w-full" name="password" placeholder="Passwort" type="password" />
</div> </div>
<input class="action-btn" type="submit" value="Anmelden" hx-post="/login/" hx-target="#page-content" /> <input class="action-btn" type="submit" value="Anmelden" hx-post="/login" hx-target="#page-content" />
</form> </form>
{{end}} {{end}}

View File

@ -1,14 +1,16 @@
{{define "page-content"}} {{define "page-content"}}
<h2>Abgelehnte Artikel</h2>
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
{{range .RejectedArticles}} {{range .RejectedArticles}}
{{if index $.MyIDs .ID}} {{if index $.MyIDs .ID}}
<button class="btn" hx-get="/review-rejected-article/{{.ID}}/" hx-target="#page-content"> <button class="btn" hx-get="/review-rejected-article/{{.ID}}" hx-target="#page-content">
<h1 class="font-bold text-2xl">{{.Title}}</h1> <h1 class="font-bold text-2xl">{{.Title}}</h1>
<p>{{.Description}}</p> <p>{{.Description}}</p>
</button> </button>
{{end}} {{end}}
{{end}} {{end}}
<button class="action-btn" hx-get="/hub/" hx-target="#page-content">Zurück</button> <button class="action-btn" hx-get="/hub" hx-target="#page-content">Zurück</button>
</div> </div>
{{end}} {{end}}

View File

@ -1,5 +1,6 @@
{{define "page-content"}} {{define "page-content"}}
<h2>Editor</h2> <h2>Editor</h2>
<form> <form>
<div class="flex flex-col gap-y-1"> <div class="flex flex-col gap-y-1">
<label for="article-title">Titel</label> <label for="article-title">Titel</label>
@ -16,7 +17,7 @@
<div> <div>
<span>Tags</span> <span>Tags</span>
<div class="flex gap-4"> <div class="flex flex-wrap gap-x-4">
{{range .Tags}} {{range .Tags}}
<div> <div>
<input id="tag-{{.Name}}" name="tags" type="checkbox" value="{{.ID}}" {{if index $.Selected <input id="tag-{{.Name}}" name="tags" type="checkbox" value="{{.ID}}" {{if index $.Selected
@ -28,14 +29,14 @@
</div> </div>
<div id="editor-images"> <div id="editor-images">
<input class="mb-2" name="article-image" type="file" hx-encoding="multipart/form-data" hx-post="/upload-image/" <input class="mb-2" name="article-image" type="file" hx-encoding="multipart/form-data" hx-post="/upload-image"
hx-swap="beforeend" hx-target="#editor-images" /> hx-swap="beforeend" hx-target="#editor-images" />
</div> </div>
<div class="btn-area"> <div class="btn-area">
<input class="action-btn" type="submit" value="Senden" hx-post="/resubmit-article/{{.Article.ID}}/" <input class="action-btn" type="submit" value="Senden" hx-post="/resubmit-article/{{.Article.ID}}"
hx-target="#page-content" /> hx-target="#page-content" />
<button class="btn" hx-get="/hub/" hx-target="#page-content">Zurück</button> <button class="btn" hx-get="/hub" hx-target="#page-content">Zurück</button>
</div> </div>
</form> </form>

View File

@ -1,4 +1,6 @@
{{define "page-content"}} {{define "page-content"}}
<h2>Artikel veröffentlichen</h2>
<div> <div>
<span>Titel</span> <span>Titel</span>
<div class="bg-white border mb-3 px-2 py-2 rounded-md w-full"> <div class="bg-white border mb-3 px-2 py-2 rounded-md w-full">
@ -26,10 +28,10 @@
</div> </div>
<div class="btn-area"> <div class="btn-area">
<input class="action-btn" type="submit" value="Veröffentlichen" hx-get="/publish-article/{{.ID}}/" <input class="action-btn" type="submit" value="Veröffentlichen" hx-get="/publish-article/{{.ID}}"
hx-target="#page-content" /> hx-target="#page-content" />
<input class="btn" type="submit" value="Ablehnen" hx-get="/reject-article/{{.ID}}/" hx-target="#page-content" /> <input class="btn" type="submit" value="Ablehnen" hx-get="/reject-article/{{.ID}}" hx-target="#page-content" />
<button class="btn" hx-get="/hub/" hx-target="#page-content">Zurück</button> <button class="btn" hx-get="/hub" hx-target="#page-content">Zurück</button>
</div> </div>
</div> </div>
{{end}} {{end}}

View File

@ -1,11 +1,13 @@
{{define "page-content"}} {{define "page-content"}}
<h2>Unveröffentlichte Artikel</h2>
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
{{range .}} {{range .}}
<button class="btn" hx-get="/review-unpublished-article/{{.ID}}/" hx-target="#page-content"> <button class="btn" hx-get="/review-unpublished-article/{{.ID}}" hx-target="#page-content">
<h1 class="font-bold text-2xl">{{.Title}}</h1> <h1 class="font-bold text-2xl">{{.Title}}</h1>
<p>{{.Description}}</p> <p>{{.Description}}</p>
</button> </button>
{{end}} {{end}}
<button class="action-btn" hx-get="/hub/" hx-target="#page-content">Zurück</button> <button class="action-btn" hx-get="/hub" hx-target="#page-content">Zurück</button>
</div> </div>
{{end}} {{end}}