File
Implements
Index
Properties
|
|
Methods
|
|
Outputs
|
|
Outputs
uploadForm
|
Type : EventEmitter
|
|
Methods
atLeastOnePhoneRequired
|
atLeastOnePhoneRequired(group: FormGroup)
|
|
Parameters :
Name |
Type |
Optional |
group |
FormGroup
|
No
|
Returns : literal type | null
|
checkLinkFormat
|
checkLinkFormat(url: string)
|
|
Parameters :
Name |
Type |
Optional |
url |
string
|
No
|
Returns : { sheetID: any; gid: any; csvUrl: string; }
|
upload
|
upload(fileFormDataEvent: FormData)
|
|
Parameters :
Name |
Type |
Optional |
fileFormDataEvent |
FormData
|
No
|
|
formGroup
|
Type : FormGroup
|
|
formValid
|
Default value : true
|
|
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
import { UploadForm } from '../../models/sheet.model';
@Component({
selector: 'app-upload',
templateUrl: './upload.component.html',
styleUrls: ['./upload.component.scss'],
})
export class UploadComponent implements OnInit {
@Output() uploadForm = new EventEmitter<UploadForm>();
formGroup!: FormGroup;
formValid = true;
constructor(public fb: FormBuilder) {}
ngOnInit(): void {
this.formGroup = new FormGroup(
{
link: new FormControl('', [
Validators.required,
Validators.compose([Validators.pattern(/\/([\w-_]{15,})\/(.*?gid=(\d+))?|\w*csv$/)]) as ValidatorFn,
]),
formData: new FormControl(''),
fileName: new FormControl(''),
},
{ validators: [this.atLeastOnePhoneRequired as ValidatorFn] },
);
this.formGroup.valueChanges.subscribe((x) => {
if (!(x.fileName === null || x.fileName === '')) {
this.formGroup.get('link')?.clearValidators();
this.formGroup.get('link')?.updateValueAndValidity({ emitEvent: false });
}
this.formValid = this.formGroup.status === 'VALID';
});
}
atLeastOnePhoneRequired(group: FormGroup): { [s: string]: boolean } | null {
if (group) {
if (group.controls['link'].value || group.controls['fileName'].value) {
return null;
}
}
return { error: true };
}
upload(fileFormDataEvent: FormData) {
this.formGroup.patchValue({ formData: fileFormDataEvent });
}
submitData() {
this.formValid = this.formGroup.status === 'VALID';
if (this.formGroup.status !== 'VALID') {
return;
}
const sheet = this.formGroup.value;
const sheetId = this.checkLinkFormat(sheet.link)?.sheetID ?? '';
const data: UploadForm = {
link: sheet.link,
formData: sheet.formData,
fileName: sheet.fileName,
sheetId,
gid: this.checkLinkFormat(sheet.link)?.gid ?? '',
csvUrl: this.checkLinkFormat(sheet.link)?.csvUrl ?? '',
};
// ga call handled in the playground module component
this.uploadForm.emit(data);
}
checkLinkFormat(url: string) {
if (url.startsWith('https://docs.google.com/spreadsheets/d/')) {
const splitUrl = url.split('/');
if (splitUrl.length === 7) {
return {
sheetID: splitUrl[5],
gid: splitUrl[6].split('=')[1],
csvUrl: '',
};
}
}
return {
sheetID: '0',
gid: '0',
csvUrl: url,
};
}
}
<div class="">
<mat-expansion-panel [expanded]="true">
<mat-expansion-panel-header>
<mat-panel-title>
<div class="instruction-title">Instructions</div>
</mat-panel-title>
</mat-expansion-panel-header>
<div class="mt-1 text-muted">
<ul class="pl-3">
<li class="text-justify">
Through this feature, you can upload your own data (ASCT+B to ASCT+B, ASCT+B to experimental data, or ASCT+B
to OMAP) by pasting the Browser URL address for the Google sheet of your data in the fields mentioned below.
</li>
<li class="text-justify">
In order to successfully link your sheet, make sure the sheet has public access by selecting Share --> Get
link --> selecting "Anyone with the link" option and "Viewer" privileges, select "Done" to save.
</li>
<li class="text-justify">
Please make sure your data follows the appropriate data format:
<ul class="pl-3">
<li class="text-justify">
<a
href="https://docs.google.com/spreadsheets/d/1smQ8_3F-KSRlY7bmozsoM1EonQL4ahNaXP7zeQFf3Ko/edit#gid=0"
target="_blank"
>ASCT+B Table template</a
>
</li>
<li class="text-justify">
<a
href="https://docs.google.com/spreadsheets/d/1DE4Bh2PI7mgaMciMOky2OTduNwYNRU-DyYQPT8szJ-Y/edit#gid=0"
target="_blank"
>OMAP compare template</a
>
</li>
</ul>
</li>
</ul>
</div>
<hr />
<div class="optional-info">
<div class="rounded-blob">New</div>
<div>Organ Mapping Antibody Panel files (CSV) are now supported!</div>
</div>
</mat-expansion-panel>
</div>
<div class="content">
<span class="required-field-disclaimer">* required field</span>
<form [formGroup]="formGroup" class="mt-4 px-2">
<div class="data-upload-title">
Data
<p class="required">* </p>
<span class="data-disclaimer-text"> (Add a link to data or upload a CSV/XLSX file)</span>
</div>
<div class="w-100 sheet-link-container">
<div class="w-100 flex-container">
<p>
<mat-form-field appearance="fill" class="w-75">
<mat-label>Google Sheet (or CSV) Link</mat-label>
<input class="w-100" matInput placeholder="Enter link..." formControlName="link" />
<mat-hint>Enter Browser URL address for your public Google Sheet (or CSV)</mat-hint>
</mat-form-field>
</p>
</div>
<div class="title-sheet-sub-container">
<div class="w-100">
<p>
<app-file-upload formControlName="fileName" (fileFormDataEvent)="upload($event)"></app-file-upload>
</p>
</div>
</div>
</div>
<hr />
</form>
</div>
<div footer class="footer">
<div class="mt-2" class="button-container">
<button
mat-flat-button
color="primary"
(click)="submitData()"
class="submit-button"
[ngClass]="{ 'submit-button-color': !formValid }"
>
Submit
</button>
</div>
</div>
:host {
border-style: solid;
border-width: 0.03rem;
border: #e4e4e4;
width: 100%;
background-color: white;
margin-left: 1rem;
font-size: 0.85rem;
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.link-input-field {
width: 100%;
}
input[type='color'] {
border: none;
outline: none;
}
::ng-deep input[type='color']::-webkit-color-swatch-wrapper {
padding: 0;
}
input[type='color']::-webkit-color-swatch {
border: none;
}
.content {
flex: 1 1;
overflow: auto;
}
.mat-expansion-panel:not([class*='mat-elevation-z']) {
box-shadow: none;
}
.mat-expansion-panel-header:not(.compare) {
background: rgb(228, 228, 228) !important;
}
::ng-deep mat-expansion-panel-header {
background: rgb(228, 228, 228);
}
.mat-expansion-panel-header:hover {
opacity: 0.85 !important;
}
.instruction-title {
font-weight: 600;
font-size: 10pt;
}
.required-field-disclaimer {
font-size: 0.625rem;
color: #f44336;
padding-left: 1.5rem;
}
.title-sheet-container {
display: flex;
align-items: center;
justify-content: space-between;
}
.title-sheet-sub-container {
display: flex;
align-items: center;
justify-content: space-between;
flex: 0.5;
font-size: medium;
}
.flex-container {
flex: 0.5;
background-color: white;
mat-hint {
color: #757575;
margin-left: -0.8rem;
}
::ng-deep .mdc-text-field--filled {
background-color: white;
}
}
.file-upload {
color: #757575;
}
.sheet-link-container {
display: flex;
align-items: center;
justify-content: space-between;
padding-left: 1rem;
}
.button-container {
margin-left: 1.4rem;
}
.submit-button {
border-radius: 0.5rem !important;
}
.submit-button-color {
background-color: #f44336 !important;
}
.required {
color: red;
display: inline;
}
.data-upload-title {
margin-top: 1.5rem !important;
color: #444a65;
padding-left: 1rem;
.data-disclaimer-text {
font-size: 0.625rem;
color: #757575;
}
}
.optional-info {
display: flex;
flex-direction: row;
justify-content: flex-start;
grid-gap: 0.625rem;
}
.rounded-blob {
align-items: center;
height: 1.5rem;
width: 2.5rem;
background-color: #c2cae5;
border-radius: 6.25rem;
text-align: center;
}
.footer {
height: 3rem;
}
}
Legend
Html element with directive