Skip to content

NCJ UX with Mode selection#598

Merged
t-anjam merged 47 commits intoncjfrom
ncjPart2
Aug 28, 2017
Merged

NCJ UX with Mode selection#598
t-anjam merged 47 commits intoncjfrom
ncjPart2

Conversation

@t-anjam
Copy link

@t-anjam t-anjam commented Aug 8, 2017

I added mode selection option to the Market feature in BatchLabs. Now users can create pools, job + old pool, job + new pool submissions.
image
image
image
image
image
image

@msftclas
Copy link

msftclas commented Aug 8, 2017

@t-anjam,
Thanks for your contribution as a Microsoft full-time employee or intern. You do not need to sign a CLA.
Thanks,
Microsoft Pull Request Bot

*/
export function tryMultiplePythons(paths: string[]): Promise<string> {
let promise: Promise<string> = Promise.reject(null);
//let promise: Promise<string> = Promise.reject(null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah just remove that line

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -7,13 +7,13 @@

@app.procedure("submit-ncj-job")
def submitNcjJob(request: JsonRpcRequest, template, parameters):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was like that before but should follow python coding style so submit_ncj_job

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return {"what": "it works"}

@app.procedure("get-ncj-pool")
def getNcjPool(request: JsonRpcRequest, template, parameters):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you call that expand_ncj_pool instead(and change at id also to be expand-ncj-pool

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


constructor(private templateService: NcjTemplateService, private route: ActivatedRoute) { }
constructor(private templateService: NcjTemplateService, private route: ActivatedRoute) {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove spaces as it was before

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

this.mode_state = "None";
this.form = new FormGroup({a: new FormControl()});
}
private ngOnInit() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ngOnInit is public

Copy link
Author

@t-anjam t-anjam Aug 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed


public ngOnInit() {
private templateService: NcjTemplateService) {
this.mode_state = "None";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use an enum for this

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

public ngOnInit() {
private templateService: NcjTemplateService) {
this.mode_state = "None";
this.form = new FormGroup({a: new FormControl()});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a: ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed


public createForms() {
let parameterKeys = Object.keys(this.jobTemplate.parameters);
private createForms() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make private methods start with _

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

for (let key of poolParameters) {
if ("defaultValue" in this.poolTemplate.parameters[key]) {
const defaultValue = String(this.poolTemplate.parameters[key].defaultValue);
fg[key] = new FormControl(defaultValue);
Copy link
Member

@timotheeguerin timotheeguerin Aug 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should separate the pool and job properties in 2 different file group.

Form should be

this.jobParams = new FormGroup(jobFg)
this.poolParams = new FormGroup(poolFg)

this.form = formBuilder.group({pool: this.poolParams, job: this.jobParams});

Copy link
Author

@t-anjam t-anjam Aug 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's wait till UX converges to a final design

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be much better that merging all params togther and then trying to figure out which ones are belong to the pool and which ones to the job

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@t-anjam , how will the UX changes affect this? Is there something that we need to discuss in the UX which will affect our decision to keep the job and pool sections of the template separate?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was thinking about corner cases if we decided to add special inputs for the different modes, then which category would they fall into? job or pool? So I tried to kept it general by keeping them all in one form object.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all inputs should belong to one or the other. and in the case it doesn't we can add another root param

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

<bl-file-group-picker [formControlName]="param" [label]="param" class="form-element" [hint]="jobTemplate.parameters[param].metadata.description">
</bl-file-group-picker>
</div>
<div *ngSwitchCase="'file-in-file-group'">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is way to much duplicates here. You should probably create another component called ncj-form-parameter to which you give the param type and it will choose the right value

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's wait till UX converges to a final design

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you mean? you are going to need that either way. This looks way to hacky this way

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking it is better to wait in refactoring code until a finalized design is agreed upon. I predict there might be more changes to the UX in the nearby future.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes but this is completely independent from whatever the UI will looks like. You just make a component that display the right input dependending on the type. This is something we should have either way(even if there was no duplicate).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, will change

</div>
<div *ngSwitchCase="'dropdown'">
{{param}}
<select [formControlName]="param">
Copy link
Member

@timotheeguerin timotheeguerin Aug 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use a md-select here instead of simple select

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

@paselem paselem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added several comments for review. Please take a look.

log.warn("Invalid form param. Not valid json.", params.formParams as any);
}
}
this.templateService.getTemplates(this.applicationId, this.actionId).subscribe((templates) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: why is this 'templates' instead of 'template' (note plural vs. singular')?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't name this method, but it's because it returns both job and pool template.

if (this.poolTemplate && this.poolTemplate.parameters){
poolParameters = Object.keys(this.poolTemplate.parameters);
}
let fg = {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a big fan of abbreviated variables. I assume we can expand to formGroup?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

for (let key of parameterKeys) {

for (let key of jobParameters) {
if ("defaultValue" in this.jobTemplate.parameters[key]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't "defaultValue" be a const?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is actually would not be very useful because we do object.defaultValue after to access it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to if (this.jobTemplate.parameters[key].defaultValue)

for (let key of poolParameters) {
if ("defaultValue" in this.poolTemplate.parameters[key]) {
const defaultValue = String(this.poolTemplate.parameters[key].defaultValue);
fg[key] = new FormControl(defaultValue);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@t-anjam , how will the UX changes affect this? Is there something that we need to discuss in the UX which will affect our decision to keep the job and pool sections of the template separate?

delete expandedPoolTemplate.id;
this.jobTemplate.job.properties.poolInfo = {
autoPoolSpecification: {
autoPoolIdPrefix: "jobname",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should the prefix be the actual job name, not the string "jobname"?

Also, consider what kinds of constraints you will run into here. Batch has limitations on what values are allowed for this. It would be worth taking a look at the Batch docs to know what issues you may run into: https://docs.microsoft.com/en-us/rest/api/batchservice/

</bl-complex-form>
</div>

<div *ngIf="mode_state == 'PoolNJob'">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent spacing around operators throught the file. In some cases you are using

'a==b'

and in others

'a == b'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also an inconsistent use of ' and ".

Is the linter not catching these?

</div>

<button *ngIf="mode_state!='None'" style="width:100px;background-color:#3e81b0;" (click) = "onSubmit()" type="button" md-raised-button>Submit</button>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: lots of empty lines here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


@app.procedure("submit-ncj-job")
def submitNcjJob(request: JsonRpcRequest, template, parameters):
print("Got template", template)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove print statement.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

print("Job is", job)
client.job.add(job)
return job_json
return {"what": "it works"}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this just for debugging? Change it back?

job_json = client.job.expand_template(template, parameters)
print("Job json", job_json)
job = client.job.jobparameter_from_json(job_json)
print("Job is", job)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove print statement.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

import * as inflection from "inflection";
import "./submit-market-application.scss";

enum NcjParameterExtendedType {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This enum was there before you should keep it and add more types

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do

}

class NcjParameterWrapper {
public type: NcjParameterExtendedType;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same this class should still be here instead of the function

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do

return obs;
}

private _redirectToJob(data) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned above, I think we need to pass a parameter back in here.

Regarding this API, I think passing in a 'data' object is a poor design. The method only requires the jobId, and should not need to know about the structure of some random data structure. If the data structure ever changes, then this method would need to get updated with it, which doesn't make sense. The interface should be kept as clean and simple as possible.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I didn't create this function. I removed the data parameter for now till I know where to find the jobID/poolID for all three modes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@paselem
Copy link
Contributor

paselem commented Aug 10, 2017

This is a pretty significant change, and I did not see any unit tests for it. I would be wary about letting this go into master without having unit tests come along with it.

Also, our naming schema for feature branches follows the pattern feature/. Please follow that convention in the future. It helps us identify what kind of work is within the branch.

@timotheeguerin timotheeguerin modified the milestone: NCJ Aug 10, 2017
private _propagateChange: (value: any) => void = null;

constructor() {
console.log("Contructor:", this.parameter, this.type);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this._sub = this.parameterValue.valueChanges.subscribe((value) => {
  if(propage) {propagate(value)};
});

</md-input-container>
</div>
<div *ngFor="let param of poolParametersWrapper">
<bl-parameter-input [formControlName]="param.id" [parameter]="param" [type]="types" [parameterValues]="poolParams.value"> </bl-parameter-input>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't pass this


public ngOnInit(): void {
this.parameterValue.setValue(this.parameter.defaultValue);
// do not need
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this one if not using

import { NcjParameterRawType } from "app/models";
import { BatchApplication, NcjParameterRawType } from "app/models";
import { StorageService } from "app/services";
import { Subject } from "rxjs";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move the library import in the first group above. i.e @angular/... rxjs ...


describe("text parameter type", () => {
let inputEl: DebugElement;
const initialInput: string = "initial input value";
Copy link
Member

@timotheeguerin timotheeguerin Aug 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't define the type here is is a bit too verbose. Only do the type if it is not obvious, on a class attribute or is not assigned right away(Like debugElement above).

Same for all variables below being number or string

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed types for simple variables

});
});

describe("fileinput parameter type", () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for this type you alos want to check the containerId given match what's in the formValues

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

@paselem paselem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, looks pretty good! I have added a few comments to the review to consider. Thanks!

<md-option *ngFor="let opt of parameter.allowedValues" [value]="opt"> {{ opt }} </md-option>
</md-select>
</div>
<div *ngSwitchCase="NcjParameterExtendedType.int">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a specific type for 'bool'?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think bool scenario can be covered under dropdown case with two options: ['true', 'false'].

export enum Modes {
None,
NewPoolAndJob,
OldPoolAndJob,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: "ExistingPoolAndJob" instead of "OldPoolAndJob". Thoughts?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
this.jobParametersWrapper = jobTempWrapper;
const poolParameters = this.poolTemplate.parameters;
const poolTempWrapper: any[] = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be 'let' instead of 'const' if you are going to append to it later?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75

image

Since the array variable is not being reassigned then it's safe to use const. Even though its contents are changing.

defaultValue: 4,
});
expect(parameter.type).toBe(NcjParameterExtendedType.int);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to add a unit test here to check for the value as well (since this is an int which is a different case than what you have above for string).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same goes for cases below.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

<div [ngSwitch]="parameter.type">
<div *ngSwitchCase="NcjParameterExtendedType.string">
<md-input-container class="form-element">
<input mdInput type="text" name="parameter.name" [formControl]="parameterValue" [placeholder]="parameter.name">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the name= attribute here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@t-anjam t-anjam merged commit 581ff55 into ncj Aug 28, 2017
}

public getContainerFromFileGroup(fileGroup: string) {
return fileGroup && `fgrp-${fileGroup}`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is in StorageService.ncjFileGroupPrefix

We could move it into Constants if you like. We shouldn't hard code this anywhere.

@timotheeguerin timotheeguerin deleted the ncjPart2 branch September 5, 2017 23:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants