Skip to content

Commit

Permalink
feat: shows argument list and highlights changed and invalid fields i…
Browse files Browse the repository at this point in the history
…n menu
  • Loading branch information
Sandi Barr committed Apr 7, 2021
1 parent 4741999 commit 52a9137
Show file tree
Hide file tree
Showing 18 changed files with 166 additions and 43 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div *ngFor="let arg of args">
{{arg}}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
div {
white-space: nowrap;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ArgumentListComponent } from './argument-list.component';

describe('ArgumentListComponent', () => {
let component: ArgumentListComponent;
let fixture: ComponentFixture<ArgumentListComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ArgumentListComponent ]
})
.compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(ArgumentListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Component, Input, ChangeDetectionStrategy } from '@angular/core';

@Component({
selector: 'nx-console-argument-list',
templateUrl: './argument-list.component.html',
styleUrls: ['./argument-list.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ArgumentListComponent {
@Input() args: string[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ nx-console-autocomplete {
margin: 0 0 0.5rem 0;
user-select: text;
white-space: normal;
width: $description-width;
}

.autocomplete-container {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,7 @@ export class AutocompleteComponent
if (this.control) {
this.control.setValue(value);
} else {
this.control = new FormControl(
value,
this.parentFormGroup.controls[this.field.name].validator
);
this.control = this.parentFormGroup.controls[this.field.name] as FormControl;
this.visibleOptions = this._options$.pipe(
switchMap((options) =>
this.control.valueChanges.pipe(
Expand Down Expand Up @@ -178,6 +175,7 @@ export class AutocompleteComponent
this.textInput.nativeElement.blur();
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
registerOnChange(fn: any) {
this.control.valueChanges
.pipe(tap(fn), takeUntil(this.destroying))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ nx-console-checkbox {
margin: 0;
user-select: text;
white-space: normal;
width: $description-width
}

.bool-control {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*ngFor="let field of fields"
(click)="scrollToField(field.name)"
[class.active]="activeFieldName === field.name"
[class.valid]="isFieldValid(field.name)"
[class.error]="isFieldInvalid(field.name)"
[id]="field.name + '-field-tree-item'"
[style.display]="filteredFields.has(field.name) ? 'block' : 'none'"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,11 @@
font-weight: 700;
opacity: 1;
}

&.valid {
color: $modified-text-color;
}
&.error {
color: $error-text-color;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export class FieldTreeComponent implements OnChanges {
@Input() fields: Array<Option>;
@Input() activeFieldName: string;
@Input() filteredFields: Set<string>;
@Input() validFields: {[name: string]: string[] | string | number | boolean};
@Input() invalidFields: {[name: string]: string[] | string | number | boolean};

userSelectedField?: string;

Expand Down Expand Up @@ -73,4 +75,12 @@ export class FieldTreeComponent implements OnChanges {
});
}
}

isFieldValid(fieldName: string): boolean {
return this.validFields && !!this.validFields[fieldName];
}

isFieldInvalid(fieldName: string): boolean {
return this.invalidFields && this.invalidFields[fieldName] !== undefined;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
margin: 0 0 0.5rem 0;
user-select: text;
white-space: normal;
width: $input-width
}

input {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
margin: 0 0 0.5rem 0;
user-select: text;
white-space: normal;
width: $description-width
}

select {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
margin: 0 0 0.5rem 0;
user-select: text;
white-space: normal;
width: $description-width
}

select {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { FieldComponent } from './field/field.component';
import { FieldTreeComponent } from './field-tree/field-tree.component';
import { MultipleSelectComponent } from './multiple-select/multiple-select.component';
import { FormatTaskPipe } from './format-task/format-task.pipe';
import { ArgumentListComponent } from './argument-list/argument-list.component';

@NgModule({
imports: [CommonModule, ReactiveFormsModule],
Expand All @@ -21,6 +22,7 @@ import { FormatTaskPipe } from './format-task/format-task.pipe';
FieldTreeComponent,
MultipleSelectComponent,
FormatTaskPipe,
ArgumentListComponent,
],
exports: [
AutocompleteComponent,
Expand All @@ -31,6 +33,7 @@ import { FormatTaskPipe } from './format-task/format-task.pipe';
FieldTreeComponent,
MultipleSelectComponent,
FormatTaskPipe,
ArgumentListComponent,
],
})
export class VscodeUiComponentsModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
>
<div class="form-header-container" #formHeaderContainer>
<div class="form-header">
<div class="fx-align-start-center fx-row fx-flex">
<div class="filter-container fx-flex fx-align-start-center fx-row">
<div class="fx-align-start-center fx-row">
<div class="filter-container fx-align-start-center fx-flex">
<input
type="text"
placeholder="Search flags"
Expand Down Expand Up @@ -51,10 +51,12 @@
[activeFieldName]="activeFieldName$ | async"
[fields]="taskExecForm.architect.options"
[filteredFields]="filteredFields"
[validFields]="validFields$ | async"
[invalidFields]="invalidFields$ | async"
></vscode-ui-field-tree>
<form class="fields fx-flex" [formGroup]="taskExecForm.form">
<div class="title-container fx-row">
<span class="fx-flex title">
<form class="fields" [formGroup]="taskExecForm.form">
<div class="title-container">
<span class="title">
{{ taskExecForm.architect | formatTask }}
<ng-container
*ngIf="
Expand All @@ -69,41 +71,45 @@
</ng-container>
</span>
</div>
<div class="fx-row">
<div>
<ng-container *ngIf="defaultValues$ | async as defaultValues">
<nx-console-field
[id]="field.name + '-nx-console-field'"
*ngFor="let field of taskExecForm.architect.options"
[class.changed-from-default]="
defaultValues[field.name] !==
taskExecForm.form.value[field.name]
"
[field]="field"
[formControlName]="field.name"
[style.display]="
filteredFields.has(field.name) ? 'block' : 'none'
"
></nx-console-field>
</ng-container>

<ng-container *ngIf="defaultValues$ | async as defaultValues">
<nx-console-field
[id]="field.name + '-nx-console-field'"
*ngFor="let field of taskExecForm.architect.options"
[class.changed-from-default]="
defaultValues[field.name] !==
taskExecForm.form.value[field.name]
"
[field]="field"
[formControlName]="field.name"
[style.display]="
filteredFields.has(field.name) ? 'block' : 'none'
"
></nx-console-field>
</ng-container>

<div
class="filter-flags-message"
*ngIf="filteredFields.size === 0"
#noMatch
>
<div *ngIf="taskExecForm.architect.options.length; else noFlags">
No flags found -
<span
class="clear-search"
(click)="filterFieldsControl.setValue('')"
<div
class="filter-flags-message"
*ngIf="filteredFields.size === 0"
#noMatch
>
Clear search
</span>
</div>
<div *ngIf="taskExecForm.architect.options.length; else noFlags">
No flags found -
<span
class="clear-search"
(click)="filterFieldsControl.setValue('')"
>
Clear search
</span>
</div>

<ng-template #noFlags>
This command has no flags to set
</ng-template>
<ng-template #noFlags>
This command has no flags to set
</ng-template>
</div>
</div>
<nx-console-argument-list [args]="runCommandArguments$ | async"></nx-console-argument-list>
</div>
</form>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ $offset-with-configurations: $offset-without-configurations +
border: $input-border-width solid var(--vscode-settings-textInputBorder);
color: #fff;
text-align: center;
line-height: 30px;
cursor: pointer;
transition: background ease-in-out 0.1s;
margin-left: 1rem;
Expand Down Expand Up @@ -66,7 +65,7 @@ vscode-ui-field-tree {
}

form {
margin-left: 206px;
margin-left: 190px;
padding-right: $host-padding-right - $scrollbar-width;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import {
BehaviorSubject,
combineLatest,
merge,
Observable,
ReplaySubject,
Subscription,
Expand All @@ -32,7 +33,9 @@ import {
tap,
flatMap,
mapTo,
mergeMap,
filter,
withLatestFrom,
} from 'rxjs/operators';

import { TASK_EXECUTION_SCHEMA } from './task-execution-form.schema';
Expand Down Expand Up @@ -160,6 +163,15 @@ export class TaskExecutionFormComponent implements OnInit, AfterViewChecked {
shareReplay()
);

runCommandArguments$ = this.taskExecForm$.pipe(
mergeMap((taskExecForm) => taskExecForm.form.valueChanges.pipe(map(() => taskExecForm))),
map(({ architect, form }) => this.serializeArgs(form.value, architect))
);

validFields$ = this.getValidFields$(true);

invalidFields$ = this.getValidFields$(false);

dryRunSubscription?: Subscription;

constructor(
Expand Down Expand Up @@ -356,7 +368,44 @@ export class TaskExecutionFormComponent implements OnInit, AfterViewChecked {
});
}

getValidFields$(
valid: boolean
): Observable<{ [name: string]: string[] | string | number | boolean }> {
return this.taskExecForm$.pipe(
mergeMap((taskExecForm) =>
merge(
taskExecForm.form.valueChanges,
taskExecForm.form.statusChanges
).pipe(
startWith(taskExecForm),
map(() => taskExecForm)
)
),
withLatestFrom(this.defaultValues$),
map(([{ form, architect }, defaultValues]) => {
return architect.options
.filter((option) => {
const control = form.controls[option.name];
return (
(valid &&
control.valid &&
// touched is not working with checkbox, so ignore touched and just check !== defaultValue
// control.touched &&
control.value !== defaultValues[option.name]) ||
// invalid and touched (checkbox is always valid as true/false)
(!valid && control.touched && control.invalid)
);
})
.reduce((options, option) => ({
...options,
[option.name]: form.controls[option.name].value,
}), {});
})
);
}

private serializeArgs(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: { [p: string]: any },
architect: TaskExecutionSchema,
configurationName?: string
Expand Down
2 changes: 2 additions & 0 deletions libs/vscode-ui/styles/src/lib/_variables.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
$input-border-width: 1px;
$input-border-radius-size: 3px;
$input-width: 320px;
$description-width: 340px;
$input-height: 26px;
$button-primary-color: var(
--vscode-settings-modifiedItemIndicator,
Expand All @@ -12,6 +13,7 @@ $button-primary-color: var(
$scroll-bar-width: 12px;

$primary-text-color: var(--vscode-settings-headerForeground);
$modified-text-color: var(--vscode-gitDecoration-modifiedResourceForeground, #e2c08d);
$error-text-color: var(--vscode-errorForeground, #f00);

$error-border-color: var(--vscode-inputValidation-errorBorder, #f00);

0 comments on commit 52a9137

Please sign in to comment.