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 package jobs
import ( import (
"sort"
"github.com/aerogo/aero" "github.com/aerogo/aero"
"github.com/animenotifier/notify.moe/components" "github.com/animenotifier/notify.moe/components"
"github.com/animenotifier/notify.moe/utils" "github.com/animenotifier/notify.moe/utils"
) )
var running = map[string]bool{} var jobInfo = map[string]*utils.JobInfo{
var lastRun = map[string]string{} "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. // Overview shows all background jobs.
func Overview(ctx *aero.Context) string { func Overview(ctx *aero.Context) string {
user := utils.GetUser(ctx) 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) EditorTabs(url, user)
h1.editor-list-page-title.mountable Background jobs h1.mountable Background jobs
.buttons .buttons
button.mountable.action(data-action="startJob", data-trigger="click", data-job="twist", disabled=running) each job in jobs
Icon("rocket") button.background-job.mountable.action(data-action="startJob", data-trigger="click", data-job=job.Name, data-running=job.IsRunning())
span twist 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/animeimport"
"github.com/animenotifier/notify.moe/pages/apiview" "github.com/animenotifier/notify.moe/pages/apiview"
"github.com/animenotifier/notify.moe/pages/apiview/apidocs" "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/me"
"github.com/animenotifier/notify.moe/pages/notifications" "github.com/animenotifier/notify.moe/pages/notifications"
"github.com/animenotifier/notify.moe/pages/popular" "github.com/animenotifier/notify.moe/pages/popular"
@ -45,4 +46,7 @@ func Register(l *layout.Layout, app *aero.Application) {
// Import anime // Import anime
app.Post("/api/import/kitsu/anime/:id", animeimport.Kitsu) app.Post("/api/import/kitsu/anime/:id", animeimport.Kitsu)
app.Post("/api/delete/kitsu/anime/:id", animeimport.DeleteKitsu) 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 // Start background job
export async function startJob(arn: AnimeNotifier, button: HTMLButtonElement) { export async function startJob(arn: AnimeNotifier, button: HTMLButtonElement) {
if(button.dataset.running === "true") {
alert("Job is currently running!")
return
}
let jobName = button.dataset.job let jobName = button.dataset.job
if(!confirm(`Are you sure you want to start the "${jobName}" job?`)) { if(!confirm(`Are you sure you want to start the "${jobName}" job?`)) {

View File

@ -1,6 +1,13 @@
package utils 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. // JobInfo gives you information about a background job.
type JobInfo struct { type JobInfo struct {
@ -11,6 +18,30 @@ type JobInfo struct {
// IsRunning tells you whether the given job is running or not. // IsRunning tells you whether the given job is running or not.
func (job *JobInfo) IsRunning() bool { func (job *JobInfo) IsRunning() bool {
now := time.Now() return job.LastStarted.After(job.LastFinished)
return job.LastStarted.After(job.LastFinished) && !now.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
} }