Manager: show worker tag in job details
Show the worker tag name (and its description in a tooltip) in the job details. When no worker tag is assigned, "All Workers" is shown in a more dimmed colour. This also renames the "Type" field to "Job Type". "Tag" and "Type" could be confused, and now they're displayed as "Worker Tag" and "Job Type". The UI in the add-on's submission interface is also updated for this, so that that also shows "Worker Tag" (instead of just "Tag").
This commit is contained in:
parent
e8438bb645
commit
df4f94c642
@ -51,7 +51,7 @@ class FLAMENCO_PT_job_submission(bpy.types.Panel):
|
|||||||
)
|
)
|
||||||
if not job_types.are_job_types_available():
|
if not job_types.are_job_types_available():
|
||||||
return
|
return
|
||||||
col.prop(context.scene, "flamenco_worker_tag", text="Tag")
|
col.prop(context.scene, "flamenco_worker_tag", text="Worker Tag")
|
||||||
|
|
||||||
# Job properties:
|
# Job properties:
|
||||||
job_col = layout.column(align=True)
|
job_col = layout.column(align=True)
|
||||||
|
@ -687,7 +687,7 @@ func jobDBtoAPI(dbJob *persistence.Job) api.Job {
|
|||||||
apiJob.DeleteRequestedAt = &dbJob.DeleteRequestedAt.Time
|
apiJob.DeleteRequestedAt = &dbJob.DeleteRequestedAt.Time
|
||||||
}
|
}
|
||||||
if dbJob.WorkerTag != nil {
|
if dbJob.WorkerTag != nil {
|
||||||
apiJob.WorkerTag = &dbJob.WorkerTag.UUID
|
apiJob.WorkerTag = workerTagDBtoAPI(dbJob.WorkerTag)
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiJob
|
return apiJob
|
||||||
|
@ -89,6 +89,60 @@ func TestQueryJobs(t *testing.T) {
|
|||||||
assertResponseJSON(t, echoCtx, http.StatusOK, expectedJobs)
|
assertResponseJSON(t, echoCtx, http.StatusOK, expectedJobs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFetchJob(t *testing.T) {
|
||||||
|
mockCtrl := gomock.NewController(t)
|
||||||
|
defer mockCtrl.Finish()
|
||||||
|
|
||||||
|
mf := newMockedFlamenco(mockCtrl)
|
||||||
|
|
||||||
|
dbJob := persistence.Job{
|
||||||
|
UUID: "afc47568-bd9d-4368-8016-e91d945db36d",
|
||||||
|
Name: "работа",
|
||||||
|
JobType: "test",
|
||||||
|
Priority: 50,
|
||||||
|
Status: api.JobStatusActive,
|
||||||
|
Settings: persistence.StringInterfaceMap{
|
||||||
|
"result": "/render/frames/exploding.kittens",
|
||||||
|
},
|
||||||
|
Metadata: persistence.StringStringMap{
|
||||||
|
"project": "/projects/exploding-kittens",
|
||||||
|
},
|
||||||
|
WorkerTag: &persistence.WorkerTag{
|
||||||
|
UUID: "d86e1b84-5ee2-4784-a178-65963eeb484b",
|
||||||
|
Name: "Tikkie terug Kees!",
|
||||||
|
Description: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
echoCtx := mf.prepareMockedRequest(nil)
|
||||||
|
mf.persistence.EXPECT().FetchJob(gomock.Any(), dbJob.UUID).Return(&dbJob, nil)
|
||||||
|
|
||||||
|
require.NoError(t, mf.flamenco.FetchJob(echoCtx, dbJob.UUID))
|
||||||
|
|
||||||
|
expectedJob := api.Job{
|
||||||
|
SubmittedJob: api.SubmittedJob{
|
||||||
|
Name: "работа",
|
||||||
|
Type: "test",
|
||||||
|
Priority: 50,
|
||||||
|
Settings: &api.JobSettings{AdditionalProperties: map[string]interface{}{
|
||||||
|
"result": "/render/frames/exploding.kittens",
|
||||||
|
}},
|
||||||
|
Metadata: &api.JobMetadata{AdditionalProperties: map[string]string{
|
||||||
|
"project": "/projects/exploding-kittens",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
Id: "afc47568-bd9d-4368-8016-e91d945db36d",
|
||||||
|
Status: api.JobStatusActive,
|
||||||
|
WorkerTag: &api.WorkerTag{
|
||||||
|
Id: ptr("d86e1b84-5ee2-4784-a178-65963eeb484b"),
|
||||||
|
Name: "Tikkie terug Kees!",
|
||||||
|
Description: nil, // Empty description should just be excluded from the JSON.
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assertResponseJSON(t, echoCtx, http.StatusOK, expectedJob)
|
||||||
|
}
|
||||||
|
|
||||||
func TestFetchTask(t *testing.T) {
|
func TestFetchTask(t *testing.T) {
|
||||||
mockCtrl := gomock.NewController(t)
|
mockCtrl := gomock.NewController(t)
|
||||||
defer mockCtrl.Finish()
|
defer mockCtrl.Finish()
|
||||||
|
@ -415,6 +415,11 @@ func TestSubmitJobWithWorkerTag(t *testing.T) {
|
|||||||
DeleteRequestedAt: nil,
|
DeleteRequestedAt: nil,
|
||||||
Activity: "",
|
Activity: "",
|
||||||
Status: api.JobStatusQueued,
|
Status: api.JobStatusQueued,
|
||||||
|
WorkerTag: &api.WorkerTag{
|
||||||
|
Id: ptr(workerTagUUID),
|
||||||
|
Name: "first tag",
|
||||||
|
Description: ptr("my first tag"),
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,8 +313,11 @@ func (f *Flamenco) FetchWorkerTag(e echo.Context, tagUUID string) error {
|
|||||||
logger.Error().Err(err).Msg("fetching worker tag")
|
logger.Error().Err(err).Msg("fetching worker tag")
|
||||||
return sendAPIError(e, http.StatusInternalServerError, "error fetching worker tag: %v", err)
|
return sendAPIError(e, http.StatusInternalServerError, "error fetching worker tag: %v", err)
|
||||||
}
|
}
|
||||||
|
if tag == nil {
|
||||||
|
panic("Could fetch a worker tag without error, but then the returned tag was still nil")
|
||||||
|
}
|
||||||
|
|
||||||
return e.JSON(http.StatusOK, workerTagDBtoAPI(*tag))
|
return e.JSON(http.StatusOK, workerTagDBtoAPI(tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Flamenco) UpdateWorkerTag(e echo.Context, tagUUID string) error {
|
func (f *Flamenco) UpdateWorkerTag(e echo.Context, tagUUID string) error {
|
||||||
@ -387,8 +390,8 @@ func (f *Flamenco) FetchWorkerTags(e echo.Context) error {
|
|||||||
|
|
||||||
apiTags := []api.WorkerTag{}
|
apiTags := []api.WorkerTag{}
|
||||||
for _, dbTag := range dbTags {
|
for _, dbTag := range dbTags {
|
||||||
apiTag := workerTagDBtoAPI(*dbTag)
|
apiTag := workerTagDBtoAPI(dbTag)
|
||||||
apiTags = append(apiTags, apiTag)
|
apiTags = append(apiTags, *apiTag)
|
||||||
}
|
}
|
||||||
|
|
||||||
tagList := api.WorkerTagList{
|
tagList := api.WorkerTagList{
|
||||||
@ -443,7 +446,7 @@ func (f *Flamenco) CreateWorkerTag(e echo.Context) error {
|
|||||||
sioUpdate := eventbus.NewWorkerTagUpdate(&dbTag)
|
sioUpdate := eventbus.NewWorkerTagUpdate(&dbTag)
|
||||||
f.broadcaster.BroadcastNewWorkerTag(sioUpdate)
|
f.broadcaster.BroadcastNewWorkerTag(sioUpdate)
|
||||||
|
|
||||||
return e.JSON(http.StatusOK, workerTagDBtoAPI(dbTag))
|
return e.JSON(http.StatusOK, workerTagDBtoAPI(&dbTag))
|
||||||
}
|
}
|
||||||
|
|
||||||
func workerSummary(w persistence.Worker) api.WorkerSummary {
|
func workerSummary(w persistence.Worker) api.WorkerSummary {
|
||||||
@ -479,7 +482,7 @@ func workerDBtoAPI(w persistence.Worker) api.Worker {
|
|||||||
if len(w.Tags) > 0 {
|
if len(w.Tags) > 0 {
|
||||||
tags := []api.WorkerTag{}
|
tags := []api.WorkerTag{}
|
||||||
for i := range w.Tags {
|
for i := range w.Tags {
|
||||||
tags = append(tags, workerTagDBtoAPI(*w.Tags[i]))
|
tags = append(tags, *workerTagDBtoAPI(w.Tags[i]))
|
||||||
}
|
}
|
||||||
apiWorker.Tags = &tags
|
apiWorker.Tags = &tags
|
||||||
}
|
}
|
||||||
@ -487,7 +490,11 @@ func workerDBtoAPI(w persistence.Worker) api.Worker {
|
|||||||
return apiWorker
|
return apiWorker
|
||||||
}
|
}
|
||||||
|
|
||||||
func workerTagDBtoAPI(wc persistence.WorkerTag) api.WorkerTag {
|
func workerTagDBtoAPI(wc *persistence.WorkerTag) *api.WorkerTag {
|
||||||
|
if wc == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
uuid := wc.UUID // Take a copy for safety.
|
uuid := wc.UUID // Take a copy for safety.
|
||||||
|
|
||||||
apiTag := api.WorkerTag{
|
apiTag := api.WorkerTag{
|
||||||
@ -497,5 +504,5 @@ func workerTagDBtoAPI(wc persistence.WorkerTag) api.WorkerTag {
|
|||||||
if len(wc.Description) > 0 {
|
if len(wc.Description) > 0 {
|
||||||
apiTag.Description = &wc.Description
|
apiTag.Description = &wc.Description
|
||||||
}
|
}
|
||||||
return apiTag
|
return &apiTag
|
||||||
}
|
}
|
||||||
|
@ -359,6 +359,18 @@ func (db *DB) FetchJob(ctx context.Context, jobUUID string) (*Job, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sqlcJob.WorkerTagID.Valid {
|
||||||
|
workerTag, err := fetchWorkerTagByID(db.gormDB, uint(sqlcJob.WorkerTagID.Int64))
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, sql.ErrNoRows):
|
||||||
|
return nil, ErrWorkerTagNotFound
|
||||||
|
case err != nil:
|
||||||
|
return nil, workerTagError(err, "fetching worker tag of job")
|
||||||
|
}
|
||||||
|
gormJob.WorkerTag = workerTag
|
||||||
|
}
|
||||||
|
|
||||||
return &gormJob, nil
|
return &gormJob, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,38 @@ func TestStoreAuthoredJobWithShamanCheckoutID(t *testing.T) {
|
|||||||
assert.Equal(t, job.Storage.ShamanCheckoutID, fetchedJob.Storage.ShamanCheckoutID)
|
assert.Equal(t, job.Storage.ShamanCheckoutID, fetchedJob.Storage.ShamanCheckoutID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStoreAuthoredJobWithWorkerTag(t *testing.T) {
|
||||||
|
ctx, cancel, db := persistenceTestFixtures(1 * time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
workerTagUUID := "daa811ac-6861-4004-8748-7700aebc244c"
|
||||||
|
require.NoError(t, db.CreateWorkerTag(ctx, &WorkerTag{
|
||||||
|
UUID: workerTagUUID,
|
||||||
|
Name: "🐈",
|
||||||
|
Description: "Mrieuw",
|
||||||
|
}))
|
||||||
|
workerTag, err := db.FetchWorkerTag(ctx, workerTagUUID)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
job := createTestAuthoredJobWithTasks()
|
||||||
|
job.WorkerTagUUID = workerTagUUID
|
||||||
|
|
||||||
|
err = db.StoreAuthoredJob(ctx, job)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
fetchedJob, err := db.FetchJob(ctx, job.JobID)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, fetchedJob)
|
||||||
|
|
||||||
|
require.NotNil(t, fetchedJob.WorkerTagID)
|
||||||
|
assert.Equal(t, *fetchedJob.WorkerTagID, workerTag.ID)
|
||||||
|
|
||||||
|
require.NotNil(t, fetchedJob.WorkerTag)
|
||||||
|
assert.Equal(t, fetchedJob.WorkerTag.Name, workerTag.Name)
|
||||||
|
assert.Equal(t, fetchedJob.WorkerTag.Description, workerTag.Description)
|
||||||
|
assert.Equal(t, fetchedJob.WorkerTag.UUID, workerTagUUID)
|
||||||
|
}
|
||||||
|
|
||||||
func TestFetchTaskJobUUID(t *testing.T) {
|
func TestFetchTaskJobUUID(t *testing.T) {
|
||||||
ctx, cancel, db := persistenceTestFixtures(1 * time.Second)
|
ctx, cancel, db := persistenceTestFixtures(1 * time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -53,6 +53,16 @@ func fetchWorkerTag(gormDB *gorm.DB, uuid string) (*WorkerTag, error) {
|
|||||||
return &w, nil
|
return &w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fetchWorkerTagByID fetches the worker tag using the given database instance.
|
||||||
|
func fetchWorkerTagByID(gormDB *gorm.DB, id uint) (*WorkerTag, error) {
|
||||||
|
w := WorkerTag{}
|
||||||
|
tx := gormDB.First(&w, "id = ?", id)
|
||||||
|
if tx.Error != nil {
|
||||||
|
return nil, workerTagError(tx.Error, "fetching worker tag")
|
||||||
|
}
|
||||||
|
return &w, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (db *DB) SaveWorkerTag(ctx context.Context, tag *WorkerTag) error {
|
func (db *DB) SaveWorkerTag(ctx context.Context, tag *WorkerTag) error {
|
||||||
if err := db.gormDB.WithContext(ctx).Save(tag).Error; err != nil {
|
if err := db.gormDB.WithContext(ctx).Save(tag).Error; err != nil {
|
||||||
return workerTagError(err, "saving worker tag")
|
return workerTagError(err, "saving worker tag")
|
||||||
|
@ -52,9 +52,15 @@
|
|||||||
{{ jobData.status }}
|
{{ jobData.status }}
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt class="field-type" title="Type">Type</dt>
|
<dt class="field-type" title="Job Type">Job Type</dt>
|
||||||
<dd>{{ jobType ? jobType.label : jobData.type }}</dd>
|
<dd>{{ jobType ? jobType.label : jobData.type }}</dd>
|
||||||
|
|
||||||
|
<dt class="field-worker-tag" title="Worker Tag">Worker Tag</dt>
|
||||||
|
<dd v-if="jobData.worker_tag" :title="jobData.worker_tag.description">
|
||||||
|
{{ jobData.worker_tag.name }}
|
||||||
|
</dd>
|
||||||
|
<dd v-else class="no-worker-tag">All Workers</dd>
|
||||||
|
|
||||||
<dt class="field-priority" title="Priority">Priority</dt>
|
<dt class="field-priority" title="Priority">Priority</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<PopoverEditableJobPriority :jobId="jobData.id" :priority="jobData.priority" />
|
<PopoverEditableJobPriority :jobId="jobData.id" :priority="jobData.priority" />
|
||||||
@ -289,4 +295,8 @@ export default {
|
|||||||
color: var(--indicator-color);
|
color: var(--indicator-color);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dd.no-worker-tag {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user