Skip to content

Commit

Permalink
Merge pull request #29 from moleculemaker/feat/add-validation
Browse files Browse the repository at this point in the history
Feat/add validation
  • Loading branch information
ckouder authored May 14, 2024
2 parents ed6b9e4 + 39d63c1 commit 029863e
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 151 deletions.
2 changes: 1 addition & 1 deletion openapi/mmli-backend.openapi.json

Large diffs are not rendered by default.

66 changes: 66 additions & 0 deletions src/app/api/mmli-backend/v1/api/novostoic.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export class NovostoicService {

/**
* Get Chemical Auto Complete
* Returns a list of chemicals that match the search string limited to 20 results.
* @param search
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
Expand Down Expand Up @@ -438,4 +439,69 @@ export class NovostoicService {
);
}

/**
* Validate Chemical
* @param search
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public validateChemicalChemicalValidateGet(search: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<ChemicalAutoCompleteResponse>;
public validateChemicalChemicalValidateGet(search: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<ChemicalAutoCompleteResponse>>;
public validateChemicalChemicalValidateGet(search: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<ChemicalAutoCompleteResponse>>;
public validateChemicalChemicalValidateGet(search: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
if (search === null || search === undefined) {
throw new Error('Required parameter search was null or undefined when calling validateChemicalChemicalValidateGet.');
}

let localVarQueryParameters = new HttpParams({encoder: this.encoder});
if (search !== undefined && search !== null) {
localVarQueryParameters = this.addToHttpParams(localVarQueryParameters,
<any>search, 'search');
}

let localVarHeaders = this.defaultHeaders;

let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
if (localVarHttpHeaderAcceptSelected === undefined) {
// to determine the Accept header
const httpHeaderAccepts: string[] = [
'application/json'
];
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
}
if (localVarHttpHeaderAcceptSelected !== undefined) {
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
}

let localVarHttpContext: HttpContext | undefined = options && options.context;
if (localVarHttpContext === undefined) {
localVarHttpContext = new HttpContext();
}


let responseType_: 'text' | 'json' | 'blob' = 'json';
if (localVarHttpHeaderAcceptSelected) {
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
responseType_ = 'text';
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
responseType_ = 'json';
} else {
responseType_ = 'blob';
}
}

let localVarPath = `/chemical/validate`;
return this.httpClient.request<ChemicalAutoCompleteResponse>('get', `${this.configuration.basePath}${localVarPath}`,
{
context: localVarHttpContext,
params: localVarQueryParameters,
responseType: <any>responseType_,
withCredentials: this.configuration.withCredentials,
headers: localVarHeaders,
observe: observe,
reportProgress: reportProgress
}
);
}

}
8 changes: 5 additions & 3 deletions src/app/components/novostoic/enz-rank/enz-rank.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ <h2 class="mb-2">Input Enzyme Sequence</h2>
></span
>
</div>
<app-marvinjs-input placeholder="CC(=O)C(=O)O"
[smiles]="request.form.controls['primaryPrecursor'].value || ''"
(smilesChange)="request.form.controls['primaryPrecursor'].setValue($event)"
<app-marvinjs-input
formControlName="primaryPrecursor"
placeholder="CC(=O)C(=O)O"
[errors]="request.form.controls['primaryPrecursor'].errors"
[dirty]="request.form.controls['primaryPrecursor'].dirty"
></app-marvinjs-input>

<!-- Enzyme Sequence Input -->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
<div class="marvin-filter-container">
<div class="marvin-filter-container"
[class.invalid]="errors && dirty"
>
<div class="p-inputgroup">
<input
title="Input your molecule"
pInputText
type="text"
class="border-0"
[placeholder]="placeholder"
[ngModel]="smiles"
(ngModelChange)="smilesChange.emit($event)"
[(ngModel)]="value"
(blur)="onTouched()"
/>
<button
pButton
Expand All @@ -20,6 +23,11 @@
</div>
</div>

<div class="text-[--status-error-color] text-xs my-1" *ngIf="errors && dirty">
<div *ngIf="errors['required']">This field is required</div>
<div *ngIf="errors['chemicalNotSupported']">Chemical not supported</div>
</div>

<p-dialog
*ngIf="showDialog$.value"
class="marvin-editor-container"
Expand All @@ -31,8 +39,7 @@
>
<app-marvin-js-editor
class="marvin-editor"
[smiles]="smiles"
(smilesChange)="smilesChange.emit($event)"
[(smiles)]="smiles"
></app-marvin-js-editor>
<ng-template pTemplate="footer">
<p-button
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
.marvin-filter-container{
.marvin-filter-container {
padding: 5px;
border: #CED4DA;
border-style: solid;
border-width: 1px;
border-radius: 6px;

&.invalid {
border-color: var(--status-error-color);
}

.p-inputgroup{
input{
border-width: 0px;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,100 @@
import { Component, EventEmitter, Input, Output } from "@angular/core";
import { BehaviorSubject } from "rxjs";
import { Component, EventEmitter, Input, Output, forwardRef } from "@angular/core";
import { AbstractControl, AsyncValidator, ControlValueAccessor, NG_ASYNC_VALIDATORS, NG_VALUE_ACCESSOR, ValidationErrors, Validator } from "@angular/forms";
import { BehaviorSubject, Observable, debounce, debounceTime, filter, map, switchMap, take } from "rxjs";
import { NovostoicService } from "~/app/services/novostoic.service";

@Component({
selector: "app-marvinjs-input",
templateUrl: "./marvinjs-input.component.html",
styleUrls: ["./marvinjs-input.component.scss"],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MarvinjsInputComponent),
multi: true
},
{
provide: NG_ASYNC_VALIDATORS,
useExisting: forwardRef(() => MarvinjsInputComponent),
multi: true
}
]
})
export class MarvinjsInputComponent {
export class MarvinjsInputComponent implements ControlValueAccessor, AsyncValidator {
@Input() placeholder: string = "";
@Input() smiles: string = "";
@Output() smilesChange = new EventEmitter();
@Input() errors: ValidationErrors | null;
@Input() dirty: boolean = false;

_value = "";
get value() {
return this._value;
}
set value(value: string) {
this._value = value;
this.onChange(value);
this.onTouched();
}

_smiles = "";
get smiles() {
return this._smiles;
}

set smiles(value: string) {
this._smiles = value;
if (this.value !== value) {
this.value = value;
}
}

showDialog$ = new BehaviorSubject(false);

constructor(private novostoicService: NovostoicService) {}

/* -------------------------------------------------------------------------- */
/* Control Value Accessor Interface */
/* -------------------------------------------------------------------------- */
disabled = false;
onChange = (value: string) => {};
onTouched = () => {};

writeValue(obj: string): void {
this.value = obj;
}

registerOnChange(fn: any): void {
this.onChange = fn;
}

registerOnTouched(fn: any): void {
this.onTouched = fn;
}

setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}

/* -------------------------------------------------------------------------- */
/* Async Validator Interface */
/* -------------------------------------------------------------------------- */
onValidatorChange = () => {};

validate(control: AbstractControl<any, any>): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
return control.valueChanges.pipe(
debounceTime(500),
switchMap((v) => this.novostoicService.validateChemical(v)),
map((chemical) => {
if (chemical) {
this.smiles = chemical.smiles;
return null;
}
return { chemicalNotSupported: true };
}),
take(1),
);
}

registerOnValidatorChange?(fn: () => void): void {
this.onValidatorChange = fn;
}
}
Loading

0 comments on commit 029863e

Please sign in to comment.