-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UI: Specialized Job Detail Pages #3829
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks really good! 🎉 I clicked around the UI locally and it all worked nicely. Didn't try too hard to break anything. (Wow, the dev Mirage server sure takes a while to start up, huh?)
I really like the multi-component structure. It's much clearer than the multiple-nested-if alternative. Test coverage seems great too.
Left a few questions & comments while reading through the code, but nothing important.
import { computed } from '@ember/object'; | ||
import DistributionBar from './distribution-bar'; | ||
|
||
export default DistributionBar.extend({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be misreading this, but would it be possible to use composition instead of inheritance here? That is, have this component (and the other subclass) render {{distribution-bar data=data}}
?
It would mean rendering another component, but it might be clearer to understand the code that way. It took me a while to figure out how this subclass interacted with the parent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I definitely agree it would be clearer and more idiomatic. I just still have a gut aversion to making extra components. Especially when those components are in lists.
There are no lists in Nomad long enough to cause component allocation to drag the app though, so I shouldn't prematurely optimize.
args: ['jobs.job', job], | ||
}, | ||
]; | ||
}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again wondering if composition is an option here. All of the templates have the same breadcrumbs markup, so if this logic was pulled into a component, there might be no need for an abstract parent class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactoring all of breadcrumbs is in my top three things to do. I'd prefer to leave this the way it is, understanding full well that it is strange and out of place, and clean it up when I refactor all of breadcrumbs.
@@ -49,6 +108,12 @@ export default Model.extend({ | |||
runningChildren: attr('number'), | |||
deadChildren: attr('number'), | |||
|
|||
childrenList: collect('pendingChildren', 'runningChildren', 'deadChildren'), | |||
|
|||
totalChildren: sum('childrenList'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fancy! 💅
hash.ParentID = JSON.stringify([hash.ParentID, hash.NamespaceID || 'default']); | ||
} | ||
|
||
// Periodic is a boolean on list and an object on single |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😬
ui/mirage/factories/job.js
Outdated
Enabled: true, | ||
ProhibitOverlap: true, | ||
Spec: '*/5 * * * * *', | ||
SpecType: 'ctron', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not important, but should this be 'cron'
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lol, yes.
const sum = (list, key) => list.reduce((sum, item) => sum + get(item, key), 0); | ||
moduleForJob('Acceptance | job detail (batch)', () => server.create('job', { type: 'batch' })); | ||
moduleForJob('Acceptance | job detail (system)', () => server.create('job', { type: 'system' })); | ||
moduleForJob('Acceptance | job detail (periodic)', () => server.create('job', 'periodic')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a really interesting way to test very similar pages! Will be stealing this for some upcoming TFE tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It works, but I'd prefer something that is a little more qunit-y. I sorta fell back into my mocha comfort zone when writing this and nested related tests in the moduleForJob
function rather than setting some global context with moduleForJob
and calling the tests right below it.
onClick=(action gotoTaskGroup row.model)}} | ||
{{/t.body}} | ||
{{/list-table}} | ||
{{/list-pagination}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any pagination controls being rendered for this list-pagination
instance. Why is it being used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good eyes. I must have copied this from the children component which does actually have pagination.
.filterBy('method', 'POST') | ||
.find(req => req.url === `/v1/job/${id}/periodic/force?namespace=${namespace}`), | ||
'POST request was made' | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I often prefer asserting about the state of the Mirage DB over looking at logged requests. It helps me be more sure that the request body was correct (and that my Mirage handler was exercised). For example, in this case I think you could assert that a periodicChild
record was created for the job.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call! This is the first POST in the UI, so I haven't had to write a test like this with Mirage yet.
Paths now start from package.json location, not project root.
This is a composite of scheduler type, batch variations, and children v. template
832d6d2
to
2414f48
Compare
This is to later compose job detail page variations
2414f48
to
e818757
Compare
I addressed everything I said I would, @alisdair. I'm not sure if I like using composition over inheritance for the chart components now that I've gone through the exercise of writing it. It ends up being pretty repetitive and burdened by its own gotchas (e.g., plumbing the class and any other attributes down to the inner Those changes are all in the last commit if you want to exam it directly. |
Yeah, agreed, I'm not sure the composition approach is much cleaner. I didn't notice you were conditionally rendering the legend or yielding, that makes it much more difficult. I don't have any ideas for improving it further. Sorry the suggestion wasn't useful! |
I'm glad you brought it up! It was worth trying despite it not panning out. |
e818757
to
9e606f3
Compare
I'm going to lock this pull request because it has been closed for 120 days ⏳. This helps our maintainers find and focus on the active contributions. |
Tailored job detail pages based on the type of job. Features include:
Closes #3510