Added background jobs UI

This commit is contained in:
Eduard Urbach 2018-04-28 21:17:44 +02:00
parent 59633707c1
commit 262b6018d1
7 changed files with 122 additions and 11 deletions

View File

@ -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))
}

View File

@ -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]

View File

@ -0,0 +1,5 @@
.background-job
[data-running="true"]
&.mounted
opacity 0.5 !important
pointer-events none

View 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"
}

View File

@ -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)
}

View File

@ -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?`)) {

View File

@ -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
}