Skip to content
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

fix(resource-instance-form): disable "next" button when form is not valid (DEV-803) #713

Merged
merged 4 commits into from Apr 13, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -47,8 +47,10 @@
</span>
<span class="fill-remaining-space"></span>
<span>
<!-- check each 'selected' property in addition to the forms validity because the form is actually valid when fetching ontologies and resource classes -->
<button mat-raised-button type="button" color="primary"
[disabled]="!selectResourceForm.valid || this.errorMessage" (click)="nextStep()" class="form-next">
[disabled]="(!selectedProject || !selectedOntology || !selectedResourceClass || !selectResourceForm.valid) || this.errorMessage" (click)="nextStep()" class="form-next">
<app-progress-indicator *ngIf="loading" [status]="0" [color]="'primary'" class="next-progress"></app-progress-indicator>
Next
</button>
</span>
Expand Down
Expand Up @@ -179,6 +179,10 @@ class MockSelectPropertiesComponent {

@Input() parentForm: FormGroup;

@Input() currentOntoIri: string;

@Input() selectedResourceClass: ResourceClassDefinition;

parentResource = new ReadResource();

constructor(private _valueService: ValueService) { }
Expand Down Expand Up @@ -494,22 +498,32 @@ describe('ResourceInstanceFormComponent', () => {
}
);

const nextButton = await loader.getHarness(MatButtonHarness.with({ selector: '.form-next' }));

const selectProjectComp = resourceInstanceFormComponentDe.query(By.directive(MockSelectProjectComponent));

(selectProjectComp.componentInstance as MockSelectProjectComponent).form.controls.projects.setValue('http://rdfh.ch/projects/0001');

testHostComponent.resourceInstanceFormComponent.selectedProject = 'http://rdfh.ch/projects/0001';

testHostComponent.resourceInstanceFormComponent.ontologiesMetadata = MockOntology.mockOntologiesMetadata();

testHostFixture.detectChanges();

expect(nextButton.isDisabled).toBeTruthy();

const selectOntoComp = resourceInstanceFormComponentDe.query(By.directive(MockSelectOntologyComponent));

(selectOntoComp.componentInstance as MockSelectOntologyComponent).form.controls.ontologies.setValue('http://0.0.0.0:3333/ontology/0001/anything/v2');

(selectOntoComp.componentInstance as MockSelectOntologyComponent).ontologySelected.emit('http://0.0.0.0:3333/ontology/0001/anything/v2');

testHostComponent.resourceInstanceFormComponent.selectedOntology = 'http://0.0.0.0:3333/ontology/0001/anything/v2';

testHostFixture.detectChanges();

expect(nextButton.isDisabled).toBeTruthy();

const selectResourceClassComp = resourceInstanceFormComponentDe.query(By.directive(MockSelectResourceClassComponent));

expect(selectResourceClassComp).toBeTruthy();
Expand All @@ -524,8 +538,6 @@ describe('ResourceInstanceFormComponent', () => {

expect(testHostComponent.resourceInstanceFormComponent.selectResourceForm.valid).toBeTruthy();

const nextButton = await loader.getHarness(MatButtonHarness.with({ selector: '.form-next' }));

await nextButton.click();

const selectPropertiesComp = resourceInstanceFormComponentDe.query(By.directive(MockSelectPropertiesComponent));
Expand Down
Expand Up @@ -262,6 +262,8 @@ export class ResourceInstanceFormComponent implements OnInit, OnDestroy {
// assign the selected iri to selectedProject
this.selectedProject = projectIri;

this.loading = true;

this._dspApiConnection.v2.onto.getOntologiesByProjectIri(projectIri).subscribe(
(response: OntologiesMetadata) => {
// filter out system ontologies
Expand All @@ -273,8 +275,11 @@ export class ResourceInstanceFormComponent implements OnInit, OnDestroy {
if (!this.selectOntologyComponent && response.ontologies.length === 0) {
this.errorMessage = 'No data models defined for the select project.';
}

this.loading = false;
},
(error: ApiResponseError) => {
this.loading = false;
this._errorHandler.showMessage(error);
}
);
Expand Down Expand Up @@ -318,6 +323,8 @@ export class ResourceInstanceFormComponent implements OnInit, OnDestroy {

this.selectedOntology = ontologyIri;

this.loading = true;

this._dspApiConnection.v2.onto.getOntology(ontologyIri).subscribe(
(onto: ReadOntology) => {
this.resourceClasses = onto.getClassDefinitionsByType(ResourceClassDefinition);
Expand All @@ -331,8 +338,11 @@ export class ResourceInstanceFormComponent implements OnInit, OnDestroy {
if ((!this.selectResourceClassComponent || this.selectOntologyComponent.form.controls.ontologies.valueChanges) && this.resourceClasses.length === 0) {
this.errorMessage = 'No resources defined for the selected ontology.';
}

this.loading = false;
},
(error: ApiResponseError) => {
this.loading = false;
this._errorHandler.showMessage(error);
}
);
Expand All @@ -348,14 +358,14 @@ export class ResourceInstanceFormComponent implements OnInit, OnDestroy {
* @param resourceClassIri
*/
selectProperties(resourceClassIri: string) {

// reset errorMessage, it will be reassigned in the else clause if needed
this.errorMessage = undefined;

// if the client undoes the selection of a resource class, use the active ontology as a fallback
if (resourceClassIri === null) {
this.selectResourceClasses(this.selectedOntology);
} else if (resourceClassIri) {
this.loading = true;
this._dspApiConnection.v2.ontologyCache.reloadCachedItem(this.selectedOntology).subscribe(
(res: ReadOntology) => {
this._dspApiConnection.v2.ontologyCache.getResourceClassDefinition(resourceClassIri).subscribe(
Expand Down Expand Up @@ -400,16 +410,11 @@ export class ResourceInstanceFormComponent implements OnInit, OnDestroy {
this.errorMessage = 'No properties defined for the selected resource.';
}

if (this.resourceClasses.length > 1 && !this.userWentBack) {
// automatically go to the next step when a resource class is selected
// but not in case the user went back to previous form
this.nextStep();
} else {
// or update the title because the user select another res class
this.updateParent.emit({ title: this.resourceLabel, subtitle: 'Create new resource' });
}
this.loading = false;

},
(error: ApiResponseError) => {
this.loading = false;
this._errorHandler.showMessage(error);
}
);
Expand Down
3 changes: 2 additions & 1 deletion src/assets/style/_elements.scss
Expand Up @@ -576,7 +576,8 @@ $gc-small: $form-width - $gc-large - 4;
}
}

// progress indicator icon on submit button
// progress indicator icon on next and submit buttons
.next-progress,
.submit-progress {
display: inline-block;
margin-right: 6px;
Expand Down