-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
website: start implementing the /admin/songs page
- Loading branch information
Showing
8 changed files
with
260 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{{define "content"}} | ||
<section class="section"> | ||
<div class="container pb-4"> | ||
<form action="/admin/songs" class="control is-flex" hx-boost="true" hx-push-url="true" hx-target="#songs-content" hx-select="#songs-content"> | ||
<input class="input" type="text" name="q" placeholder="Search" value="{{.Query}}" hx-get="/admin/songs" hx-target="#songs-content" hx-select="#songs-content" hx-trigger="keyup changed delay:500ms"> | ||
<button class="button is-info" type="submit">Search</button> | ||
</form> | ||
</div> | ||
<div id="songs-content"> | ||
{{template "pagination" .Page}} | ||
{{range .Forms}} | ||
{{template "form_admin_songs" .}} | ||
{{end}} | ||
{{template "pagination" .Page}} | ||
</div> | ||
</section> | ||
{{end}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
{{define "form_admin_songs"}} | ||
<div class="songs-entry notification {{if .Song.NeedReplacement}}is-warning{{end}}"> | ||
<form method="post" hx-post="/admin/songs" hx-swap="outerHTML swap:1s"> | ||
<input class="is-hidden" type="number" name="id" value="{{.Song.TrackID}}"> | ||
<div class="columns is-gapless"> | ||
<div class="column"> | ||
<div class="field is-horizontal"> | ||
<div class="field-label"> | ||
<label class="label mt-2">Artist</label> | ||
</div> | ||
<div class="field-body"> | ||
<input class="input" name="artist" type="text" value="{{.Song.Artist}}" {{if not .HasEdit}}disabled{{end}}> | ||
</div> | ||
</div> | ||
<div class="field is-horizontal"> | ||
<div class="field-label"> | ||
<label class="label mt-2">Title</label> | ||
</div> | ||
<div class="field-body"> | ||
<input class="input" name="title" type="text" value="{{.Song.Title}}" {{if not .HasEdit}}disabled{{end}}> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="column"> | ||
<div class="field is-horizontal"> | ||
<div class="field-label"> | ||
<label class="label mt-2">Album</label> | ||
</div> | ||
<div class="field-body"> | ||
<input class="input" name="album" type="text" value="{{.Song.Album}}" {{if not .HasEdit}}disabled{{end}}> | ||
</div> | ||
</div> | ||
<div class="field is-horizontal"> | ||
<div class="field-label"> | ||
<label class="label mt-2">Tags</label> | ||
</div> | ||
<div class="field-body"> | ||
<input class="input" name="tags" type="text" value="{{.Song.Tags}}" {{if not .HasEdit}}disabled{{end}}> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="columns is-desktop is-variable is-1"> | ||
<div class="column is-narrow"> | ||
<div class="field is-horizontal"> | ||
<div class="field-label"> | ||
<label class="label mt-2">ID:</label> | ||
</div> | ||
<div class="field-body"> | ||
<span class="mt-2">{{.Song.TrackID}}</span> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="column"> | ||
<div class="field is-horizontal"> | ||
<div class="field-label"> | ||
<label class="label mt-2">Acceptor</label> | ||
</div> | ||
<div class="field-body"> | ||
<span class="mt-2">{{.Song.Acceptor}} ({{.Song.LastEditor}})</span> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="column"> | ||
<div class="field is-horizontal"> | ||
<div class="field-label"> | ||
<label class="label mt-2">LP/LR</label> | ||
</div> | ||
<div class="field-body"> | ||
<span class="mt-2">{{.Song.LastPlayed | Since}} / {{.Song.LastRequested | Since}}</span> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="column is-narrow"> | ||
<div class="field is-horizontal"> | ||
<div class="field-label"> | ||
<label class="label mt-2">Priority</label> | ||
</div> | ||
<div class="field-body"> | ||
<span class="mt-2">{{.Song.Priority}} ({{.Song.RequestCount}})</span> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="column is-flex is-justify-content-end"> | ||
<div class="buttons"> | ||
<button class="button is-success">Download</button> | ||
<button class="button is-info">Play</button> | ||
{{if .HasEdit}} | ||
<button class="button" type="submit" name="action" value="save">Save</button> | ||
{{if .Song.NeedReplacement}} | ||
<button class="button is-white" type="submit" name="action" value="replacement">Unmark Repl</button> | ||
{{else}} | ||
<button class="button is-warning" type="submit" name="action" value="replacement">Mark Repl</button> | ||
{{end}} | ||
{{end}} | ||
{{if .HasDelete}}<button class="button is-danger" type="submit" name="action" value="delete">Delete</button>{{end}} | ||
</div> | ||
</div> | ||
</div> | ||
</form> | ||
</div> | ||
{{end}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package admin | ||
|
||
import ( | ||
"net/http" | ||
|
||
radio "github.com/R-a-dio/valkyrie" | ||
"github.com/R-a-dio/valkyrie/errors" | ||
"github.com/R-a-dio/valkyrie/website/middleware" | ||
"github.com/R-a-dio/valkyrie/website/shared" | ||
"github.com/rs/zerolog/hlog" | ||
) | ||
|
||
const songsPageSize = 20 | ||
|
||
type SongsInput struct { | ||
middleware.Input | ||
|
||
Forms []SongsForm | ||
Query string | ||
Page *shared.Pagination | ||
} | ||
|
||
func (SongsInput) TemplateBundle() string { | ||
return "admin-songs" | ||
} | ||
|
||
type SongsForm struct { | ||
HasDelete bool | ||
HasEdit bool | ||
Song radio.Song | ||
} | ||
|
||
func (SongsForm) TemplateName() string { | ||
return "form_admin_songs" | ||
} | ||
|
||
func (SongsForm) TemplateBundle() string { | ||
return "admin-songs" | ||
} | ||
|
||
func NewSongsInput(s radio.SearchService, r *http.Request) (*SongsInput, error) { | ||
const op errors.Op = "website/admin.NewSongInput" | ||
ctx := r.Context() | ||
|
||
page, offset, err := shared.PageAndOffset(r, songsPageSize) | ||
if err != nil { | ||
return nil, errors.E(op, err) | ||
} | ||
|
||
query := r.FormValue("q") | ||
searchResult, err := s.Search(ctx, query, songsPageSize, offset) | ||
if err != nil { | ||
return nil, errors.E(op, err) | ||
} | ||
|
||
// generate the input we can so far, since we need some data from it | ||
input := &SongsInput{ | ||
Input: middleware.InputFromContext(ctx), | ||
Query: query, | ||
Page: shared.NewPagination( | ||
page, shared.PageCount(int64(searchResult.TotalHits), songsPageSize), | ||
r.URL, | ||
), | ||
} | ||
|
||
forms := make([]SongsForm, len(searchResult.Songs)) | ||
for i := range searchResult.Songs { | ||
forms[i].Song = searchResult.Songs[i] | ||
forms[i].HasDelete = input.User.UserPermissions.Has(radio.PermDatabaseDelete) | ||
forms[i].HasEdit = input.User.UserPermissions.Has(radio.PermDatabaseEdit) | ||
} | ||
|
||
input.Forms = forms | ||
return input, nil | ||
} | ||
|
||
func (s *State) GetSongs(w http.ResponseWriter, r *http.Request) { | ||
input, err := NewSongsInput(s.Search, r) | ||
if err != nil { | ||
hlog.FromRequest(r).Error().Err(err).Msg("input creation failure") | ||
return | ||
} | ||
|
||
err = s.TemplateExecutor.Execute(w, r, input) | ||
if err != nil { | ||
hlog.FromRequest(r).Error().Err(err).Msg("template failure") | ||
return | ||
} | ||
} | ||
|
||
func (s *State) PostSongs(w http.ResponseWriter, r *http.Request) { | ||
|
||
} | ||
|
||
func (s *State) DeleteSongs(w http.ResponseWriter, r *http.Request) { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters