Commit 83d1d3d7 authored by rajkumar's avatar rajkumar
Browse files

Adding Sample Registration code

parent 83035544
......@@ -4,7 +4,7 @@
<div class="mat-h3 mat-tittle">Account Management</div>
</div>
<mat-divider></mat-divider>
<form (ngSubmit)="submitAccount(f)" #f="ngForm" [appMatchPassword]="['webinPassword', 'confirmPassword']">
<form (ngSubmit)="submitAccount(f)" #f="ngForm" [appMatchPassword]="['webinPassword', 'confirmPassword']" autocomplete="false">
<div class="container">
<mat-card>
......@@ -16,14 +16,19 @@
</mat-form-field>
<mat-form-field class="app-field-padding">
<input name="centerName" matInput placeholder="Center Name" required [(ngModel)]="centerName">
<mat-hint *ngIf="editMode">
Changing Center Name will not affect existing submissions
</mat-hint>
</mat-form-field>
<mat-form-field class="app-field-padding">
<input matInput placeholder="Laboratory Name" [(ngModel)]="laboratoryName" name="laboratoryName">
</mat-form-field>
<mat-form-field class="app-field-padding">
<input matInput placeholder="Address" required [(ngModel)]="address" name="address">
</mat-form-field>
<mat-form-field class="app-field-padding">
<mat-form-field class="app-field-padding">
<input matInput placeholder="Country" [matAutocomplete]="auto" name="country" #countryVal="ngModel" [(ngModel)]="country" (ngModelChange)="getCountries(country)">
</mat-form-field>
<mat-autocomplete #auto="matAutocomplete">
......@@ -36,13 +41,13 @@
</div>
<div class="column" *ngIf="!editMode">
<mat-form-field class="app-field-padding">
<input matInput [disabled]="editMode" type="password" placeholder="Password" required [(ngModel)]="webinPassword" name="webinPassword">
<input matInput [disabled]="editMode" type="password" placeholder="Password" required [(ngModel)]="webinPassword" name="webinPassword" autocomplete="new-password">
</mat-form-field>
<mat-form-field class="app-field-padding">
<input matInput [disabled]="editMode" type="password" placeholder="Confirm Password" required [(ngModel)]="confirmPassword" name="confirmPassword">
<input matInput [disabled]="editMode" type="password" placeholder="Confirm Password" required [(ngModel)]="confirmPassword" name="confirmPassword" autocomplete="new-password">
<mat-error *ngIf="f.controls['confirmPassword']?.errors?.passwordMismatch">
Password and Confirm password dose not match
Passwords do not match
</mat-error>
</mat-form-field>
</div>
......@@ -56,7 +61,7 @@
<mat-card class="mat-body">
<mat-card-subtitle>Contact Information</mat-card-subtitle>
<a (click)="openDialog('Add',{'submissionAccountId':id})">Add new contact <mat-icon>add_circle</mat-icon></a>
<a (click)="openDialog('Add',{'submissionAccountId':id})">Add At Least One Contact<mat-icon>add_circle</mat-icon></a>
<table mat-table *ngIf="dataSource" #table [dataSource]="dataSource" class="mat-elevation-z8">
......@@ -98,9 +103,9 @@
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-error *ngIf="mainContact <= 0 ">
<!--<mat-error *ngIf="mainContact <= 0 ">
Please enter atlease one primary contact to save the account.
</mat-error>
</mat-error>-->
</mat-card>
</div>
......
......@@ -16,6 +16,7 @@ import { MatTableDataSource } from '@angular/material';
import { UtilService } from '../util/Util-services'
import { getLocaleDayNames } from '@angular/common';
import { mergeMap, catchError } from 'rxjs/operators';
import { Router } from '@angular/router';
import { WebinAuthenticationService } from '../webin-authentication.service';
import { Compiler } from '@angular/core';
import { ResetPasswordRequestDialogComponent } from '../reset-password-request-dialog/reset-password-request-dialog.component'
......@@ -47,7 +48,7 @@ export class AccountInfoComponent {
editMode=false;
constructor(public dialog: MatDialog,private util: UtilService,private _webinAuthenticationService: WebinAuthenticationService,private _compiler: Compiler) {
constructor(private _router: Router,public dialog: MatDialog,private util: UtilService,private _webinAuthenticationService: WebinAuthenticationService,private _compiler: Compiler) {
_compiler.clearCache();
this.mainContact=0;
if(_webinAuthenticationService.authenticated){
......@@ -90,6 +91,14 @@ export class AccountInfoComponent {
this.deleteContactRow(contactObj);
}
if(result.event==='CloseSuccess'){
if(!this.editMode){
this._router.navigateByUrl('');
} else{
this._router.navigateByUrl('/accountInfo');
}
}
this.updateMainContact(contactObj)
this.dataSource = new MatTableDataSource<any>(this.contactArray);
......
......@@ -52,6 +52,8 @@ import { StudyManagementComponent } from './study-management/study-management.co
import { PopupMessageComponent } from './popup-message/popup-message.component';
import { FormsModule } from '@angular/forms';
import { MatIconModule, MatCardSubtitle } from '@angular/material';
import { FileInputValueAccessor } from './directives/file-input.accessor.directive';
import { DiableAutofillDirective } from './directives/app-disable-autofill.directive';
const appRoutes: Routes = [
{
......@@ -157,6 +159,8 @@ const appRoutes: Routes = [
ResetPasswordPageComponent,
StudyManagementComponent,
PopupMessageComponent,
FileInputValueAccessor,
DiableAutofillDirective,
],
bootstrap: [
......
......@@ -6,6 +6,10 @@
padding: 10px 0px 0px 0px;
}
mat-card{
margin:10px;
}
.checklist-restriction {
color: black;
background-color: #F5F5F5;
......@@ -37,4 +41,10 @@
float: left;
padding-top: 2px;
cursor: pointer;
}
.centred{
position: fixed; /* or absolute */
top: 50%;
left: 50%;
}
\ No newline at end of file
<div class="body">
<div>
<div class="back-div" ><mat-icon matTooltip="Back" routerLink="">arrow_back_ios</mat-icon></div>
<div class="mat-h3 mat-tittle">Download spreadsheet template for annotated sequences</div>
<div *ngIf="checklistType === ChecklistType.sample" class="mat-h3 mat-tittle">Register Samples using spreadsheet template</div>
<div *ngIf="checklistType === ChecklistType.sequence" class="mat-h3 mat-tittle">Spreadsheet templates for Annoted sequences</div>
</div>
<mat-divider></mat-divider>
<div class="container">
<mat-card class="mat-body">
<mat-accordion>
<mat-expansion-panel (opened)="panelOpenState = true" (closed)="panelOpenState = false" class="mat-body">
<mat-expansion-panel-header>
<mat-panel-title>
<b *ngIf="checklistType === ChecklistType.sequence">Download spreadsheet template for annotated sequences</b>
<b *ngIf="checklistType === ChecklistType.sample">Download spreadsheet to register samples</b>
</mat-panel-title>
</mat-expansion-panel-header>
<div *ngIf="!checklistGroupDataSource && !init" class="mat-body">
<p *ngIf="checklistType === ChecklistType.sample">
......@@ -49,7 +58,9 @@
{{dataError}}
</div>
</div>
<mat-vertical-stepper #stepper *ngIf="checklistGroupDataSource">
<mat-step label="Select checklist group">
<p>Please select a checklist group first.</p>
......@@ -119,7 +130,7 @@
<mat-expansion-panel *ngFor="let fieldGroup of selectedChecklist.fieldGroups">
<mat-expansion-panel-header>
<mat-panel-title>
{{fieldGroup.name}}<span fxHide fxShow.gt-sm> {{getSelectedFieldsDisplayText(fieldGroup)}}</span>
{{fieldGroup.name}}<span fxHide fxShow.gt-sm> {{getSelectedFieldsDisplayText(fieldGroup)}}</span>
</mat-panel-title>
</mat-expansion-panel-header>
......@@ -211,9 +222,32 @@
</mat-step>
</mat-vertical-stepper>
</mat-card>
</mat-expansion-panel>
<mat-expansion-panel *ngIf="checklistType === ChecklistType.sample" (opened)="panelOpenState = true"
(closed)="panelOpenState = false">
<mat-expansion-panel-header>
<mat-panel-title>
<b>Upload filled spreadsheet to register samples</b>
</mat-panel-title>
</mat-expansion-panel-header>
<form (ngSubmit)="uploadFile(form)" #form="ngForm">
<div>
<p>If you have downloaded and filled a template spreadsheet please upload it using the <b>Submit Completed Spreadsheet</b> button.</p>
<br>
<p>Please note that only spreadsheets in tab-delimited text format are supported (with either .tsv or .txt or .tab extensions). If you edited the spreadsheet in Microsoft Excel (or equivalent) please save the spreadsheet as Text (Tab delimited). To do this please see <a href="https://support.office.com/en-us/article/Import-or-export-text-txt-or-csv-runs-5250ac4c-663c-47ce-937b-339e391393ba?ui=en-US&amp;rs=en-US&amp;ad=US#bmexport" target="_blank">these instructions</a>.</p></div>
<input type="file" required name="spreadSheet" [(ngModel)]="form.spreadSheet" observeFiles />
<button mat-raised-button color="accent" [disabled]="form.invalid ">Submit Completed Spreadsheet</button>
</form>
</mat-expansion-panel>
</mat-accordion>
<div class="centred" *ngIf="showLoadingFlag" style="height:70px;">
<mat-spinner [diameter]="50" [strokeWidth]="5" style="margin:0 auto;">
</mat-spinner>
</div>
</div>
</div>
......@@ -11,7 +11,7 @@
import { Component, Input, ViewEncapsulation, OnInit } from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http';
import { MatTableDataSource } from '@angular/material';
import { MatTableDataSource, MatDialog } from '@angular/material';
import { saveAs } from 'file-saver';
import { retry, mergeMap, map } from 'rxjs/operators';
import { ChecklistType } from '../checklist-type.enum';
......@@ -21,7 +21,10 @@ import { ChecklistFieldGroupInterface } from '../checklist-field-group.interface
import { ChecklistFieldInterface } from '../checklist-field.interface';
import { WebinAuthenticationService } from '../webin-authentication.service';
import { WebinReportService } from '../webin-report.service';
import { WebinRestService } from '../webin-rest.service';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { PopupMessageComponent } from '../popup-message/popup-message.component';
interface BooleanFieldInterface {
[key: string]: boolean;
......@@ -51,11 +54,15 @@ export class ChecklistComponent implements OnInit {
mandatoryFields: BooleanFieldInterface;
active: boolean;
dataError: string;
spreadSheet: File;
showLoadingFlag=false;
constructor(
private _webinAuthenticationService: WebinAuthenticationService,
private _webinReportService: WebinReportService,
private _webinRestService: WebinRestService,
private _route: ActivatedRoute,
public dialog: MatDialog,
private activatedRoute: ActivatedRoute) {
if (_route) {
switch (_route.snapshot.data.checklistType) {
......@@ -378,4 +385,81 @@ export class ChecklistComponent implements OnInit {
const blob = new Blob([this.getSequenceSpreadsheetText()], { type: 'text/plain;charset=utf-8' });
saveAs(blob, 'Sequence-' + this.selectedChecklist.id + '-' + dateText + '.tsv');
}
uploadFile(form){
this.showLoading();
const formData: FormData = new FormData();
const observable: Observable<string> =
this._webinRestService.submitXml(
null,
null,
null,
form.spreadSheet,
null,
null,
null,
null,
null,
null);
this.handleServerResponse(observable);
}
handleServerResponse(observable){
if (observable) {
observable.pipe(
retry(3)
).subscribe(
data => {
let result = this._webinRestService.parseResult(data);
if (result.isError) {
console.log(result.errors)
let message=result.errors[0]["error"];
this.showErrorPopup(message)
} else {
console.log(result.accessions);
let message="Successfully subimited project with project identification : "+result.accessions[0]["accession"];
this.showSuccessPopup(message);
}
this.hideLoading();
},
(err: HttpErrorResponse) => {
console.error('** Webin submission service failed **', err);
const message = 'Webin submission service failed. Please try again later. If the problem persists please contact the helpdesk.';
this.showErrorPopup(message);
this.hideLoading();
}
);
}
}
showLoading(){
this.showLoadingFlag=true;
}
hideLoading(){
this.showLoadingFlag=false;
}
showSuccessPopup(message){
const dialogRef = this.dialog.open(PopupMessageComponent, {
width: '500px',
backdropClass: 'custom-dialog-backdrop-class',
panelClass: 'custom-dialog-panel-class',
data: {'action':'Success','message':message,'title':'Study Submission'}
});
}
showErrorPopup(message){
const dialogRef = this.dialog.open(PopupMessageComponent, {
width: '500px',
backdropClass: 'custom-dialog-backdrop-class',
panelClass: 'custom-dialog-panel-class',
data: {'action':'Error','message':message,'title':'Study Redistration Error'}
});
}
}
......@@ -54,7 +54,7 @@
<button type="button" mat-raised-button style="margin-left: 5px;" (click)="closePopup()">Ok</button>
</div>
<div style="text-align:center" *ngIf="action==='Success'">
<button type="button" mat-raised-button style="margin-left: 5px;" (click)="closePopup()" routerLink="">Ok</button>
<button type="button" mat-raised-button style="margin-left: 5px;" (click)="closeSuccessPopup()" >Ok</button>
</div>
</form>
\ No newline at end of file
......@@ -53,6 +53,10 @@ export class ContactDialogModalComponent implements OnInit {
this.dialogRef.close({event: 'close'});
}
closeSuccessPopup(){
this.dialogRef.close({event: 'CloseSuccess'});
}
updateName(contact){
var name= contact["firstName"] + " " + (contact["middleInitials"] || "") + " "+ contact["surname"];
if(contact["consortiumContact"]){
......
......@@ -43,10 +43,14 @@
<mat-card>
<mat-card-subtitle>Spreadsheet Templates</mat-card-subtitle>
<div class="cat-element">
<span [routerLink]="['/app-checklist','sample',true]">
<mat-icon class="system_update_alt">system_update_alt</mat-icon>
<p class="mat-small mat-caption">Register samples</p>
</span>
<span [routerLink]="['/app-checklist','sequence',true]">
<mat-icon class="system_update_alt">system_update_alt</mat-icon>
<p class="mat-small mat-caption">Annotated Sequences</p>
</span>
<mat-icon class="system_update_alt">system_update_alt</mat-icon>
<p class="mat-small mat-caption">Annotated Sequences</p>
</span>
</div>
</mat-card>
......
import { AppDisableAutofillDirective } from './app-disable-autofill.directive';
describe('AppDisableAutofillDirective', () => {
it('should create an instance', () => {
const directive = new AppDisableAutofillDirective();
expect(directive).toBeTruthy();
});
});
import { Directive, ElementRef, Renderer2, AfterViewInit } from '@angular/core';
@Directive({
selector: '[appDisableAutofill]'
})
export class DiableAutofillDirective implements AfterViewInit {
constructor(private readonly el: ElementRef, private readonly renderer: Renderer2) { }
ngAfterViewInit() {
const randomString = Math.random().toString(36).slice(-6);
this.renderer.setAttribute(this.el.nativeElement, 'name', randomString);
this.renderer.setAttribute(this.el.nativeElement, 'autocomplete', randomString);
}
}
\ No newline at end of file
import { FileInput.AccessorDirective } from './file-input.accessor.directive';
describe('FileInput.AccessorDirective', () => {
it('should create an instance', () => {
const directive = new FileInput.AccessorDirective();
expect(directive).toBeTruthy();
});
});
// Import the core angular services.
import { ControlValueAccessor } from "@angular/forms";
import { Directive } from "@angular/core";
import { ElementRef } from "@angular/core";
import { NG_VALUE_ACCESSOR } from "@angular/forms";
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
var noop = () => {
// ...
};
@Directive({
selector: "input[type=file][ngModel][observeFiles]",
host: {
"(blur)": "onTouchedCallback()",
"(change)": "handleChange( $event.target.files )"
},
// By overriding the NG_VALUE_ACCESSOR dependency-injection token at this level of
// the component tree / hierarchical injectors, we are effectively replacing the
// DefaultValueAccessor for this Input Element context. As such, when Angular looks
// for a ControlValueAccessor implementation in the local dependency-injection
// container, it will only find this one - the one that looks at the "FileList"
// property, not the "value" property.
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: FileInputValueAccessor,
multi: true
// NOTE: I _believe_ that because I am using Ahead-of-Time (AoT) compiling in
// this demo, I don't need to use the forwardRef() wrapper to reference the
// Class that hasn't been defined yet.
}
]
})
export class FileInputValueAccessor implements ControlValueAccessor {
private elementRef: ElementRef;
private onChangeCallback: Function;
private onTouchedCallback: Function;
// I initialize the file-input value accessor service.
constructor( elementRef: ElementRef ) {
this.elementRef = elementRef;
// CAUTION: These will be called by Angular when rendering the View.
this.onChangeCallback = noop;
this.onTouchedCallback = noop;
}
// ---
// PUBLIC METHODS.
// ---
// I handle changes to the file input element value made by the user. Instead of
// pushing the "value," I push the underlying File or File[] references to the
// calling context.
public handleChange( files: FileList ) : void {
// If the input is set to allow MULTIPLE files, then always push an ARRAY of
// files through to the calling context (even if it is empty).
// --
// NOTE: We are using Array.from() in order to create a proper Array from the
// Array-like FileList collection.
if ( this.elementRef.nativeElement.multiple ) {
this.onChangeCallback( Array.from( files ) );
// If the input is set to allow only a SINGLE file, then let's only push the
// first file in the collection (or NULL if no file is available).
} else {
this.onChangeCallback( files.length ? files[ 0 ] : null );
}
}
// I register the callback to be invoked when the value of the file input element
// has been changed by the user.
public registerOnChange( callback: Function ) : void {
this.onChangeCallback = callback;
}
// I register the callback to be invoked when the file input element has been
// "touched" by the user.
public registerOnTouched( callback: Function ) : void {
this.onTouchedCallback = callback;
}
// I set the disabled property of the file input element.
public setDisabledState( isDisabled: boolean ) : void {
this.elementRef.nativeElement.disabled = isDisabled;
}
// I set the value property of the file input element.
// --
// CAUTION: Only a limited set of values can be used on file inputs.
public writeValue( value: any ) : void {
if ( value instanceof FileList ) {
this.elementRef.nativeElement.files = value;
} else if ( Array.isArray( value ) && ! value.length ) {
this.elementRef.nativeElement.files = null;
} else if ( value === null ) {
this.elementRef.nativeElement.files = null;
} else {
// Since we cannot manually construct a FileList instance, we have to ignore
// any attempt to push a non-FileList instance into the input.
if ( console && console.warn && console.log ) {
console.warn( "Ignoring attempt to assign non-FileList to input[type=file]." );
console.log( "Value:", value );
}
}
}
}
\ No newline at end of file
<div class="mat-h3 mat-tittle">Reset Password</div>
<form (ngSubmit)="doAction(rpf)" #rpf="ngForm" >
<p class="mat-body">Enter details and you will be emailed a link to allow you to choose a new password</p>
<div *ngIf="action!='Success' && action!='Error' && action!='Reset-Password-Success' && action!='Reset-Password-Error'">
<div *ngIf="loggedIn" >
......
......@@ -23,20 +23,23 @@
<mat-form-field class="app-field-padding">
<input matInput placeholder="Study Name" [(ngModel)]="studyName" name="studyName">
</mat-form-field>
<!-- <mat-checkbox matInput name="provideGenomeAnnotation" [(ngModel)]="provideGenomeAnnotation" >Will you provide functional genome annotation</mat-checkbox> -->
<mat-checkbox matInput name="provideGenomeAnnotation" (click)="setGenomeAnotation($event)" [(ngModel)]="provideGenomeAnnotation" >Will you provide functional genome annotation</mat-checkbox>
</div>
<div class="column" *ngIf="!editMode">
<mat-form-field class="app-field-padding">
<input matInput placeholder="Short descriptive study title" required [(ngModel)]="studyTitle" name="studyTitle">
</mat-form-field>
<mat-form-field class="app-field-padding">
<input matInput placeholder="Detailed study abstract" required [(ngModel)]="description" name="description">
<textarea rows="6" matInput placeholder="Detailed study abstract" required [(ngModel)]="description" name="description"></textarea>
</mat-form-field>
</div>
</div>