add blog index to admin dashboard

This commit is contained in:
ari melody 2025-11-07 01:04:10 +00:00
parent ee8bf6543e
commit 65366032fd
Signed by: ari
GPG key ID: CF99829C92678188
10 changed files with 603 additions and 91 deletions

View file

@ -0,0 +1,33 @@
{{define "head"}}
<title>Blog - ari melody 💫</title>
<link rel="shortcut icon" href="/img/favicon.png" type="image/x-icon">
<link rel="stylesheet" href="/admin/static/blog.css">
{{end}}
{{define "content"}}
<main>
<header>
<h1>Blog Posts <small>({{.TotalPosts}} total)</small></h2>
<a class="button new" id="create-post">Create New</a>
</header>
{{if .Collections}}
<div class="blog-group">
{{range .Collections}}
{{if .Posts}}
<div class="blog-collection">
<h2>{{.Year}}</h2>
{{range .Posts}}
{{block "blogpost" .}}{{end}}
{{end}}
</div>
{{end}}
{{end}}
</div>
{{else}}
<p>There are no blog posts.</p>
{{end}}
</main>
<script type="module" src="/admin/static/blog.js"></script>
{{end}}

View file

@ -0,0 +1,14 @@
{{define "blogpost"}}
<div class="blogpost">
<h3 class="title"><a href="/admin/blogs/{{.ID}}">{{.Title}}</a>{{if not .Visible}} <small>(Not published)</small>{{end}}</h3>
<p class="meta">
<span class="author"><img src="/img/favicon.png" alt="{{.Author.Username}}'s avatar" width="32" height="32"/> {{.Author.Username}}</span>
<span class="date">&bull; {{.PrintDate}}</span>
</p>
<p class="description">{{.Description}}</p>
<div class="actions">
<a href="/admin/blogs/{{.ID}}">Edit</a>
<a href="/blog/{{.ID}}">View</a>
</div>
</div>
{{end}}

View file

@ -27,7 +27,9 @@
<div class="nav-item{{if eq .Path "/logs"}} active{{end}}">
<a href="/admin/logs">logs</a>
</div>
<hr>
<p class="section-label">music</p>
<div class="nav-item{{if hasPrefix .Path "/releases"}} active{{end}}">
<a href="/admin/music/releases/">releases</a>
@ -38,6 +40,13 @@
<div class="nav-item{{if hasPrefix .Path "/tracks"}} active{{end}}">
<a href="/admin/music/tracks/">tracks</a>
</div>
<hr>
<p class="section-label">blog</p>
<div class="nav-item{{if hasPrefix .Path "/blogs"}} active{{end}}">
<a href="/admin/blogs/">blog</a>
</div>
{{end}}
<div class="flex-fill"></div>

View file

@ -17,63 +17,9 @@ var prideflagHTML string
//go:embed "html/index.html"
var indexHTML string
//go:embed "html/register.html"
var registerHTML string
//go:embed "html/login.html"
var loginHTML string
//go:embed "html/login-totp.html"
var loginTotpHTML string
//go:embed "html/totp-confirm.html"
var totpConfirmHTML string
//go:embed "html/totp-setup.html"
var totpSetupHTML string
//go:embed "html/logout.html"
var logoutHTML string
//go:embed "html/logs.html"
var logsHTML string
//go:embed "html/edit-account.html"
var editAccountHTML string
//go:embed "html/releases.html"
var releasesHTML string
//go:embed "html/artists.html"
var artistsHTML string
//go:embed "html/tracks.html"
var tracksHTML string
//go:embed "html/edit-release.html"
var editReleaseHTML string
//go:embed "html/edit-artist.html"
var editArtistHTML string
//go:embed "html/edit-track.html"
var editTrackHTML string
//go:embed "html/components/credit/newcredit.html"
var componentNewCreditHTML string
//go:embed "html/components/credit/addcredit.html"
var componentAddCreditHTML string
//go:embed "html/components/credit/editcredits.html"
var componentEditCreditsHTML string
//go:embed "html/components/link/editlinks.html"
var componentEditLinksHTML string
//go:embed "html/components/release/release.html"
var componentReleaseHTML string
//go:embed "html/components/artist/artist.html"
var componentArtistHTML string
//go:embed "html/components/track/track.html"
var componentTrackHTML string
//go:embed "html/components/track/newtrack.html"
var componentNewTrackHTML string
//go:embed "html/components/track/addtrack.html"
var componentAddTrackHTML string
//go:embed "html/components/track/edittracks.html"
var componentEditTracksHTML string
var BaseTemplate = template.Must(
template.New("base").Funcs(
template.FuncMap{
@ -84,6 +30,13 @@ var BaseTemplate = template.Must(
prideflagHTML,
}, "\n")))
//go:embed "html/components/release/release.html"
var componentReleaseHTML string
//go:embed "html/components/artist/artist.html"
var componentArtistHTML string
//go:embed "html/components/track/track.html"
var componentTrackHTML string
var IndexTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(
strings.Join([]string{
indexHTML,
@ -95,37 +48,83 @@ var IndexTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(
//go:embed "html/login.html"
var loginHTML string
var LoginTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(loginHTML))
//go:embed "html/login-totp.html"
var loginTotpHTML string
var LoginTOTPTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(loginTotpHTML))
//go:embed "html/register.html"
var registerHTML string
var RegisterTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(registerHTML))
//go:embed "html/logout.html"
var logoutHTML string
var LogoutTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(logoutHTML))
//go:embed "html/edit-account.html"
var editAccountHTML string
var AccountTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(editAccountHTML))
//go:embed "html/totp-setup.html"
var totpSetupHTML string
var TOTPSetupTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(totpSetupHTML))
//go:embed "html/totp-confirm.html"
var totpConfirmHTML string
var TOTPConfirmTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(totpConfirmHTML))
var LogsTemplate = template.Must(template.Must(BaseTemplate.Clone()).Funcs(template.FuncMap{
"parseLevel": parseLevel,
"titleCase": titleCase,
"toLower": toLower,
"prettyTime": prettyTime,
"parseLevel": func (level log.LogLevel) string {
switch level {
case log.LEVEL_INFO:
return "INFO"
case log.LEVEL_WARN:
return "WARN"
}
return fmt.Sprintf("%d?", level)
},
"titleCase": func (logType string) string {
runes := []rune(logType)
for i, r := range runes {
if (i == 0 || runes[i - 1] == ' ') && r >= 'a' && r <= 'z' {
runes[i] = r + ('A' - 'a')
}
}
return string(runes)
},
"toLower": func (str string) string {
return strings.ToLower(str)
},
"prettyTime": func (t time.Time) string {
return t.Format("02 Jan 2006, 15:04:05")
},
}).Parse(logsHTML))
//go:embed "html/releases.html"
var releasesHTML string
var ReleasesTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(
strings.Join([]string{
releasesHTML,
componentReleaseHTML,
}, "\n"),
))
//go:embed "html/artists.html"
var artistsHTML string
var ArtistsTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(
strings.Join([]string{
artistsHTML,
componentArtistHTML,
}, "\n"),
))
//go:embed "html/tracks.html"
var tracksHTML string
var TracksTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(
strings.Join([]string{
tracksHTML,
@ -135,13 +134,21 @@ var TracksTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(
//go:embed "html/edit-release.html"
var editReleaseHTML string
var EditReleaseTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(
strings.Join([]string{
editReleaseHTML,
componentTrackHTML,
}, "\n"),
))
//go:embed "html/edit-artist.html"
var editArtistHTML string
var EditArtistTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(editArtistHTML))
//go:embed "html/edit-track.html"
var editTrackHTML string
var EditTrackTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(
strings.Join([]string{
editTrackHTML,
@ -151,41 +158,45 @@ var EditTrackTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(
//go:embed "html/components/credit/newcredit.html"
var componentNewCreditHTML string
var EditCreditsTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(componentEditCreditsHTML))
//go:embed "html/components/credit/addcredit.html"
var componentAddCreditHTML string
var AddCreditTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(componentAddCreditHTML))
//go:embed "html/components/credit/editcredits.html"
var componentEditCreditsHTML string
var NewCreditTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(componentNewCreditHTML))
//go:embed "html/components/link/editlinks.html"
var componentEditLinksHTML string
var EditLinksTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(componentEditLinksHTML))
//go:embed "html/components/track/newtrack.html"
var componentNewTrackHTML string
var EditTracksTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(componentEditTracksHTML))
//go:embed "html/components/track/addtrack.html"
var componentAddTrackHTML string
var AddTrackTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(componentAddTrackHTML))
//go:embed "html/components/track/edittracks.html"
var componentEditTracksHTML string
var NewTrackTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(componentNewTrackHTML))
func parseLevel(level log.LogLevel) string {
switch level {
case log.LEVEL_INFO:
return "INFO"
case log.LEVEL_WARN:
return "WARN"
}
return fmt.Sprintf("%d?", level)
}
func titleCase(logType string) string {
runes := []rune(logType)
for i, r := range runes {
if (i == 0 || runes[i - 1] == ' ') && r >= 'a' && r <= 'z' {
runes[i] = r + ('A' - 'a')
}
}
return string(runes)
}
func toLower(str string) string {
return strings.ToLower(str)
}
func prettyTime(t time.Time) string {
// return t.Format("2006-01-02 15:04:05")
// return t.Format("15:04:05, 2 Jan 2006")
return t.Format("02 Jan 2006, 15:04:05")
}
//go:embed "html/blogs.html"
var blogsHTML string
//go:embed "html/components/blog/blogpost.html"
var componentBlogPostHTML string
var BlogsTemplate = template.Must(template.Must(BaseTemplate.Clone()).Parse(
strings.Join([]string{
blogsHTML,
componentBlogPostHTML,
}, "\n"),
))