Added background jobs UI
This commit is contained in:
parent
59633707c1
commit
262b6018d1
@ -1,17 +1,39 @@
|
||||
package jobs
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/aerogo/aero"
|
||||
"github.com/animenotifier/notify.moe/components"
|
||||
"github.com/animenotifier/notify.moe/utils"
|
||||
)
|
||||
|
||||
var running = map[string]bool{}
|
||||
var lastRun = map[string]string{}
|
||||
var jobInfo = map[string]*utils.JobInfo{
|
||||
"anime-ratings": &utils.JobInfo{
|
||||
Name: "anime-ratings",
|
||||
},
|
||||
"twist": &utils.JobInfo{
|
||||
Name: "twist",
|
||||
},
|
||||
"refresh-osu": &utils.JobInfo{
|
||||
Name: "refresh-osu",
|
||||
},
|
||||
}
|
||||
|
||||
var jobLogs = []string{}
|
||||
|
||||
// Overview shows all background jobs.
|
||||
func Overview(ctx *aero.Context) string {
|
||||
user := utils.GetUser(ctx)
|
||||
jobs := []*utils.JobInfo{}
|
||||
|
||||
return ctx.HTML(components.EditorJobs(running, lastRun, ctx.URI(), user))
|
||||
for _, job := range jobInfo {
|
||||
jobs = append(jobs, job)
|
||||
}
|
||||
|
||||
sort.Slice(jobs, func(i, j int) bool {
|
||||
return jobs[i].Name < jobs[j].Name
|
||||
})
|
||||
|
||||
return ctx.HTML(components.EditorJobs(jobs, jobLogs, ctx.URI(), user))
|
||||
}
|
||||
|
@ -1,9 +1,18 @@
|
||||
component EditorJobs(running bool, url string, user *arn.User)
|
||||
component EditorJobs(jobs []*utils.JobInfo, jobLogs []string, url string, user *arn.User)
|
||||
EditorTabs(url, user)
|
||||
|
||||
h1.editor-list-page-title.mountable Background jobs
|
||||
h1.mountable Background jobs
|
||||
|
||||
.buttons
|
||||
button.mountable.action(data-action="startJob", data-trigger="click", data-job="twist", disabled=running)
|
||||
Icon("rocket")
|
||||
span twist
|
||||
each job in jobs
|
||||
button.background-job.mountable.action(data-action="startJob", data-trigger="click", data-job=job.Name, data-running=job.IsRunning())
|
||||
if job.IsRunning()
|
||||
Icon("hourglass-start")
|
||||
else
|
||||
Icon("rocket")
|
||||
|
||||
span= job.Name
|
||||
|
||||
footer.footer
|
||||
for i := 0; i < len(jobLogs); i++
|
||||
p.mountable= jobLogs[len(jobLogs) - 1 - i]
|
5
pages/editor/jobs/jobs.scarlet
Normal file
5
pages/editor/jobs/jobs.scarlet
Normal file
@ -0,0 +1,5 @@
|
||||
.background-job
|
||||
[data-running="true"]
|
||||
&.mounted
|
||||
opacity 0.5 !important
|
||||
pointer-events none
|
35
pages/editor/jobs/start.go
Normal file
35
pages/editor/jobs/start.go
Normal file
@ -0,0 +1,35 @@
|
||||
package jobs
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/animenotifier/arn"
|
||||
|
||||
"github.com/aerogo/aero"
|
||||
"github.com/animenotifier/notify.moe/utils"
|
||||
)
|
||||
|
||||
// Start will start the specified background job.
|
||||
func Start(ctx *aero.Context) string {
|
||||
user := utils.GetUser(ctx)
|
||||
|
||||
if user == nil || (user.Role != "editor" && user.Role != "admin") {
|
||||
return ctx.Error(http.StatusUnauthorized, "Not authorized", nil)
|
||||
}
|
||||
|
||||
jobName := ctx.Get("job")
|
||||
job := jobInfo[jobName]
|
||||
|
||||
if job == nil {
|
||||
return ctx.Error(http.StatusBadRequest, "Job not available", nil)
|
||||
}
|
||||
|
||||
if job.IsRunning() {
|
||||
return ctx.Error(http.StatusBadRequest, "Job is currently running!", nil)
|
||||
}
|
||||
|
||||
job.Start()
|
||||
jobLogs = append(jobLogs, user.Nick+" started "+job.Name+" job ("+arn.DateTimeUTC()+").")
|
||||
|
||||
return "ok"
|
||||
}
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/animenotifier/notify.moe/pages/animeimport"
|
||||
"github.com/animenotifier/notify.moe/pages/apiview"
|
||||
"github.com/animenotifier/notify.moe/pages/apiview/apidocs"
|
||||
"github.com/animenotifier/notify.moe/pages/editor/jobs"
|
||||
"github.com/animenotifier/notify.moe/pages/me"
|
||||
"github.com/animenotifier/notify.moe/pages/notifications"
|
||||
"github.com/animenotifier/notify.moe/pages/popular"
|
||||
@ -45,4 +46,7 @@ func Register(l *layout.Layout, app *aero.Application) {
|
||||
// Import anime
|
||||
app.Post("/api/import/kitsu/anime/:id", animeimport.Kitsu)
|
||||
app.Post("/api/delete/kitsu/anime/:id", animeimport.DeleteKitsu)
|
||||
|
||||
// Jobs
|
||||
app.Post("/api/job/:job/start", jobs.Start)
|
||||
}
|
||||
|
@ -75,6 +75,11 @@ export async function multiSearchAnime(arn: AnimeNotifier, textarea: HTMLTextAre
|
||||
|
||||
// Start background job
|
||||
export async function startJob(arn: AnimeNotifier, button: HTMLButtonElement) {
|
||||
if(button.dataset.running === "true") {
|
||||
alert("Job is currently running!")
|
||||
return
|
||||
}
|
||||
|
||||
let jobName = button.dataset.job
|
||||
|
||||
if(!confirm(`Are you sure you want to start the "${jobName}" job?`)) {
|
||||
|
@ -1,6 +1,13 @@
|
||||
package utils
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"os/exec"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/animenotifier/arn"
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
// JobInfo gives you information about a background job.
|
||||
type JobInfo struct {
|
||||
@ -11,6 +18,30 @@ type JobInfo struct {
|
||||
|
||||
// IsRunning tells you whether the given job is running or not.
|
||||
func (job *JobInfo) IsRunning() bool {
|
||||
now := time.Now()
|
||||
return job.LastStarted.After(job.LastFinished) && !now.After(job.LastFinished)
|
||||
return job.LastStarted.After(job.LastFinished)
|
||||
}
|
||||
|
||||
// Start will start the job.
|
||||
func (job *JobInfo) Start() error {
|
||||
cmd := exec.Command(path.Join(arn.Root, "jobs", job.Name, job.Name))
|
||||
err := cmd.Start()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
job.LastStarted = time.Now()
|
||||
|
||||
// Wait for job finish in another goroutine
|
||||
go func() {
|
||||
err := cmd.Wait()
|
||||
|
||||
if err != nil {
|
||||
color.Red("Job '%s' encountered an error: %s", job.Name, err.Error())
|
||||
}
|
||||
|
||||
job.LastFinished = time.Now()
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user