Commit d9050574 authored by Ryan Herbert's avatar Ryan Herbert

save space in forms

replaces fieldsets with divs and removes many legends in order to save
space by eliminating the border of the fieldset.
also removes some labels and displays form elements inline.
parent 6ef972ba
......@@ -647,7 +647,7 @@ Database.prototype = {
var pre_process = $('#pre_process');
pre_process.prop('disabled', disable);
pre_process.closest("fieldset").prop('hidden', disable);
pre_process.closest("div").prop('hidden', disable);
},
toggle_jstree: function(){
......
......@@ -89,11 +89,12 @@ FormBuilder.prototype.build_textarea = function(id, className, name, set_type, p
return t;
}
FormBuilder.prototype.build_fieldset = function(type) {
var f = document.createElement('fieldset');
f.name = type + this.index;
f.appendChild(this.build_legend(capitalise(type) + " " + (this.index+1)));
return f;
FormBuilder.prototype.build_div = function(type) {
var d = document.createElement('div');
var s = document.createElement('div');
s.innerText = capitalise(type) + " " + (this.index+1);
d.appendChild(s);
return d;
}
FormBuilder.prototype.build_legend = function(text) {
......@@ -159,16 +160,16 @@ PatientFormBuilder.prototype = Object.create(SetFormBuilder.prototype);
PatientFormBuilder.prototype.build = function(index) {
this.index = index;
var fieldset = this.build_fieldset(this.type);
fieldset.appendChild(this.createCloseButton());
fieldset.appendChild(this.build_input('id', 'text', 'id', 'hidden', this.type));
fieldset.appendChild(this.build_input('sample_set_id', 'text', 'sample_set_id', 'hidden', this.type));
fieldset.appendChild(this.set_id());
fieldset.appendChild(this.build_field('first_name', undefined, undefined, true));
fieldset.appendChild(this.build_field('last_name', undefined, undefined, true));
fieldset.appendChild(this.build_date('birth'));
fieldset.appendChild(this.build_info(this.type, [$('#group_select option:selected').val()]));
return fieldset;
var div = this.build_div(this.type);
div.appendChild(this.createCloseButton());
div.appendChild(this.build_input('id', 'text', 'id', 'hidden', this.type));
div.appendChild(this.build_input('sample_set_id', 'text', 'sample_set_id', 'hidden', this.type));
div.appendChild(this.set_id());
div.appendChild(this.build_field('first_name', undefined, undefined, true));
div.appendChild(this.build_field('last_name', undefined, undefined, true));
div.appendChild(this.build_date('birth'));
div.appendChild(this.build_info(this.type, [$('#group_select option:selected').val()]));
return div;
};
function RunFormBuilder() {
......@@ -180,17 +181,17 @@ RunFormBuilder.prototype = Object.create(SetFormBuilder.prototype);
RunFormBuilder.prototype.build = function(index) {
this.index = index;
var fieldset = this.build_fieldset(this.type);
fieldset.appendChild(this.createCloseButton());
fieldset.appendChild(this.build_input('id', 'text', 'id', 'hidden', this.type));
fieldset.appendChild(this.build_input('sample_set_id', 'text', 'sample_set_id', 'hidden', this.type));
fieldset.appendChild(this.set_id());
fieldset.appendChild(this.build_field('name', undefined, undefined, true));
fieldset.appendChild(this.build_date('run_date', 'run_date', 'Date'));
fieldset.appendChild(this.build_info(this.type, [$('#group_select option:selected').val()]));
fieldset.appendChild(this.build_field('sequencer'));
fieldset.appendChild(this.build_field('pcr', 'pcr', 'PCR'));
return fieldset;
var div = this.build_div(this.type);
div.appendChild(this.createCloseButton());
div.appendChild(this.build_input('id', 'text', 'id', 'hidden', this.type));
div.appendChild(this.build_input('sample_set_id', 'text', 'sample_set_id', 'hidden', this.type));
div.appendChild(this.set_id());
div.appendChild(this.build_field('name', undefined, undefined, true));
div.appendChild(this.build_date('run_date', 'run_date', 'Date'));
div.appendChild(this.build_info(this.type, [$('#group_select option:selected').val()]));
div.appendChild(this.build_field('sequencer'));
div.appendChild(this.build_field('pcr', 'pcr', 'PCR'));
return div;
};
function GenericFormBuilder() {
......@@ -202,13 +203,13 @@ GenericFormBuilder.prototype = Object.create(SetFormBuilder.prototype);
GenericFormBuilder.prototype.build = function(index) {
this.index = index;
var fieldset = this.build_fieldset('set');
fieldset.appendChild(this.createCloseButton());
fieldset.appendChild(this.build_input('id', 'text', 'id', 'hidden', this.type));
fieldset.appendChild(this.build_input('sample_set_id', 'text', 'sample_set_id', 'hidden', this.type));
fieldset.appendChild(this.build_field('name', undefined, undefined, true));
fieldset.appendChild(this.build_info(this.type, [$('#group_select option:selected').val()]));
return fieldset;
var div = this.build_div(this.type);
div.appendChild(this.createCloseButton());
div.appendChild(this.build_input('id', 'text', 'id', 'hidden', this.type));
div.appendChild(this.build_input('sample_set_id', 'text', 'sample_set_id', 'hidden', this.type));
div.appendChild(this.build_field('name', undefined, undefined, true));
div.appendChild(this.build_info(this.type, [$('#group_select option:selected').val()]));
return div;
}
function FileFormBuilder(group_ids, source, num_files) {
......@@ -223,32 +224,30 @@ FileFormBuilder.prototype = Object.create(FormBuilder.prototype);
FileFormBuilder.prototype.build = function(index) {
this.index = index;
var fieldset = this.build_fieldset('sample');
fieldset.appendChild(this.createCloseButton());
fieldset.appendChild(this.build_hidden_fields());
fieldset.appendChild(this.build_file_fieldset());
fieldset.appendChild(this.build_set_fieldset());
fieldset.appendChild(this.build_info_fieldset());
return fieldset;
var div = this.build_div('file');
div.appendChild(this.createCloseButton());
div.appendChild(this.build_hidden_fields());
div.appendChild(this.build_file_div());
div.appendChild(this.build_set_div());
div.appendChild(this.build_date('sampling_date', 'file'));
div.appendChild(this.build_info('file', this.group_ids));
return div;
}
FileFormBuilder.prototype.build_file_fieldset = function() {
FileFormBuilder.prototype.build_file_div = function() {
var self = this;
var hide_second = this.source || this.num_files < 2;
var f = document.createElement('fieldset');
f.appendChild(this.build_legend('sequence file(s)'));
var s = document.createElement('div');
s.innerText = "(.fa, .fastq, .fa.gz, .fastq.gz, .clntab)";
f.appendChild(s);
var d = document.createElement('div');
d.className="field_div";
var file1 = this.build_file_field(1, this.source);
var file_input = file1.getElementsByTagName('input')[0];
file_input.onchange = function() {
db.upload_file_onChange('file_filename_' + self.index, this.value);
}
f.appendChild(file1);
f.appendChild(this.build_file_field(2, hide_second));
f.appendChild(this.build_jstree(!this.source));
return f;
d.appendChild(file1);
d.appendChild(this.build_file_field(2, hide_second));
d.appendChild(this.build_jstree(!this.source));
return d;
}
FileFormBuilder.prototype.build_hidden_fields = function() {
......@@ -264,14 +263,10 @@ FileFormBuilder.prototype.build_hidden_fields = function() {
return d;
}
FileFormBuilder.prototype.build_set_fieldset = function() {
FileFormBuilder.prototype.build_set_div = function() {
var self = this;
var f = document.createElement('fieldset');
f.appendChild(this.build_legend('set selection'));
var txt = document.createElement('div');
txt.innerHTML = "You must associate this sample with at least one patient, run or set.<br>You can also associate it with any combination of the three.";
f.appendChild(txt);
var f = document.createElement('div');
f.className = "field_div"
f.appendChild(this.build_label('sets', 'file', 'set_ids'));
var d = document.createElement('div');
......@@ -309,25 +304,17 @@ FileFormBuilder.prototype.build_set_fieldset = function() {
return f;
}
FileFormBuilder.prototype.build_info_fieldset = function() {
var f = document.createElement('fieldset');
f.appendChild(this.build_legend('sample information'));
f.appendChild(this.build_date('sampling_date', 'file'));
f.appendChild(this.build_info('file', this.group_ids));
return f;
}
FileFormBuilder.prototype.build_file_field = function(id, hidden) {
var d = this.build_wrapper();
d.className += " file_" + id;
if (this.source || hidden) {
d.hidden = true;
}
d.appendChild(this.build_label('file ' + id, 'file', 'file'));
var i = this.build_input('upload_' + id, 'upload_field', 'file'+id, 'file', 'file');
if (this.source) {
i.disabled = true;
}
i.title = "(.fa, .fastq, .fa.gz, .fastq.gz, .clntab)";
d.appendChild(i);
return d;
}
......
......@@ -6,17 +6,13 @@
<form id="upload_form" action="DB_ADDRESS/file/submit" enctype="multipart/form-data" method="post">
{{ if source_module_active: }}
<fieldset name="file_source">
<legend>file source</legend>
<span>file source</span>
<label for="source_computer">my computer</label>
<input type="radio" id="source_computer" name="source" value="computer" onchange="db.toggle_file_source()"/>
<label for="source_nfs">network</label>
<input type="radio" id="source_nfs" name="source" value="nfs" onchange="db.toggle_file_source()" checked="checked" />
</fieldset>
{{pass}}
<fieldset {{if source_module_active:}} hidden {{pass}}>
<legend>Pre process</legend>
<label for="pre_process" id="pre_process__label">pre-process scenario: </label>
<div {{if source_module_active:}} hidden {{pass}}>
<select id="pre_process" name="pre_process" onChange="db.pre_process_onChange(this)" {{if source_module_active:}} disabled {{pass}}>
<option required_files="1" value="0">no pre-process (1 file)</option>
{{for row in pre_process_list :}}
......@@ -26,47 +22,43 @@
</option>
{{pass}}
</select>
</fieldset>
<fieldset>
<legend>set selection</legend>
<div>
You must associate this sample with at least one patient, run or set.<br>You can also associate it with any combination of the three.
</div>
<div class="field_div">
{{ if len(errors) > 0: }}
<div class="error">{{=", ".join(errors)}}</div>
{{ pass }}
<label for="set_ids" id="set_ids__label">sets: </label>
<div class="token_div form-control" onclick="$('#token_input').focus()">
<input
hidden
id="file_set_list"
name="set_ids"
type="text"
value="{{=",".join([set['id'] for set in sets])}}">
<div id="set_div" class="token_container">
{{ for set in sets: }}
<span class="set_token {{=set['type']}}_token" data-set-id="{{=set['id']}}">
<i class="icon-cancel" onclick="new Tokeniser(document.getElementById('set_div'), document.getElementById('file_set_list')).removeToken(this.parentNode);"></i>
{{=set['id'][3:]}}
</span>
{{pass}}
</div>
<input
id="token_input"
class="token_input"
autocomplete="off"
onfocus="new VidjilAutoComplete().setupSamples(this);
new Tokeniser(document.getElementById('set_div'), document.getElementById('file_set_list'));"
data-needs-atwho="true"
data-needs-tokeniser="true"
data-group-ids="{{=upload_group_ids}}"
data-keys='["generic", "patient", "run"]'
type="text">
</div>
<div>
You must associate this sample with at least one patient, run or set.<br>You can also associate it with any combination of the three.
</div>
<div class="field_div">
{{ if len(errors) > 0: }}
<div class="error">{{=", ".join(errors)}}</div>
{{ pass }}
<label for="set_ids" id="set_ids__label">sets: </label>
<div class="token_div form-control" onclick="$('#token_input').focus()">
<input
hidden
id="file_set_list"
name="set_ids"
type="text"
value="{{=",".join([set['id'] for set in sets])}}">
<div id="set_div" class="token_container">
{{ for set in sets: }}
<span class="set_token {{=set['type']}}_token" data-set-id="{{=set['id']}}">
<i class="icon-cancel" onclick="new Tokeniser(document.getElementById('set_div'), document.getElementById('file_set_list')).removeToken(this.parentNode);"></i>
{{=set['id'][3:]}}
</span>
{{pass}}
</div>
<input
id="token_input"
class="token_input"
autocomplete="off"
onfocus="new VidjilAutoComplete().setupSamples(this);
new Tokeniser(document.getElementById('set_div'), document.getElementById('file_set_list'));"
data-needs-atwho="true"
data-needs-tokeniser="true"
data-group-ids="{{=upload_group_ids}}"
data-keys='["generic", "patient", "run"]'
type="text">
</div>
</fieldset>
</div>
<div id="fieldset_container">
{{ for i, file in enumerate(files): }}
{{ include 'partial/file/form.html' }}
......
<fieldset name="file{{=i}}">
<legend>Sample {{=i+1}}</legend>
<div>
<div>File {{=i+1}}</div>
{{ if file is not None and 'error' in file and len(file['error']) > 0: }}
<div class="error">error: {{=", ".join(file['error'])}}</div>
{{ pass }}
......@@ -13,24 +13,23 @@
<input type="hidden" id="sample_set_id" name="sample_set_id" value="{{if "sample_set_id" in request.vars:}}{{=request.vars["sample_set_id"]}}{{pass}}" >
<input type="hidden" id="sample_type" name="sample_type" value="{{=sample_type}}" />
</div>
<fieldset name="sequence_file">
<legend>sequence file(s)</legend>
<div>(.fa, .fastq, .fa.gz, .fastq.gz, .clntab)</div>
<div class="field_div">
<div id="file_field_1_{{=i}}" class="field_div file_1" {{if source_module_active:}} hidden {{pass}}>
<label for="file_upload_1_{{=i}}" id="file__label_{{=i}}"> file 1 :</label>
<input class="upload_field form-control" id="file_upload_1_{{=i}}" type="file"
{{if source_module_active:}}
disabled
{{pass}}
onchange="db.upload_file_onChange('file_filename_{{=i}}', this.value)"
title="(.fa, .fastq, .fa.gz, .fastq.gz, .clntab)"
>
</div>
<div id="file_2_{{=i}}" class="field_div file_2" hidden>
<label for="file_upload_2_{{=i}}" id="file2__label_{{=i}}"> file 2 :</label>
<input class="upload_field form-control" id="file_upload_2_{{=i}}" type="file"
{{if source_module_active:}}
disabled
{{pass}}
title="(.fa, .fastq, .fa.gz, .fastq.gz, .clntab)"
>
</div>
<div class="jstree_container" {{if not source_module_active:}} hidden {{pass}}>
......@@ -46,59 +45,50 @@
<div id="jstree_{{=i}}" data-index="{{=i}}"></div>
</div>
</div>
</fieldset>
<fieldset>
<legend>set selection</legend>
<div>
You must associate this sample with at least one patient, run or set.<br>You can also associate it with any combination of the three.
</div>
<div class="field_div">
<label for="file_set_ids_{{=i}}" id="file_set_ids__label_{{=i}}">sets: </label>
<div class="token_div form-control" onclick="$('#token_input_{{=i}}').focus()">
<input
hidden
id="file_set_list_{{=i}}"
name="file[{{=i}}][set_ids]"
type="text"
value="{{=",".join([set['id'] for set in sets])}}">
<div id="file_set_div_{{=i}}" class="token_container">
{{ for set in file['sets']: }}
<span class="set_token {{=set['type']}}_token" data-set-id="{{=set['id']}}">
<i class="icon-cancel" onclick="new Tokeniser(document.getElementById('file_set_div_{{=i}}'), document.getElementById('file_set_list_{{=i}}')).removeToken(this.parentNode);"></i>
{{=set['id'][3:]}}
</span>
{{pass}}
</div>
<input
id="token_input_{{=i}}"
class="token_input"
autocomplete="off"
onfocus="new VidjilAutoComplete().setupSamples(this);
new Tokeniser(document.getElementById('file_set_div_{{=i}}'), document.getElementById('file_set_list_{{=i}}'));"
data-needs-atwho="true"
data-needs-tokeniser="true"
data-group-ids="{{=upload_group_ids}}"
data-keys='["generic", "patient", "run"]'
type="text">
</div>
<div class="field_div">
<label for="file_set_ids_{{=i}}" id="file_set_ids__label_{{=i}}">sets: </label>
<div class="token_div form-control" onclick="$('#token_input_{{=i}}').focus()">
<input
hidden
id="file_set_list_{{=i}}"
name="file[{{=i}}][set_ids]"
type="text"
value="{{=",".join([set['id'] for set in file['sets']])}}">
<div id="file_set_div_{{=i}}" class="token_container">
{{ for set in file['sets']: }}
<span class="set_token {{=set['type']}}_token" data-set-id="{{=set['id']}}">
<i class="icon-cancel" onclick="new Tokeniser(document.getElementById('file_set_div_{{=i}}'), document.getElementById('file_set_list_{{=i}}')).removeToken(this.parentNode);"></i>
{{=set['id'][3:]}}
</span>
{{pass}}
</div>
</div>
</fieldset>
<fieldset>
<legend>sample information</legend>
<div class="field_div">
<input class="date form-control" id="sampling_date_{{=i}}" name="file[{{=i}}][sampling_date]" type="text"
value="{{if 'sampling_date' in file and file['sampling_date'] is not None:}}{{=file['sampling_date']}}{{pass}}"
placeholder="Sampling Date (yyyy-mm-dd)" pattern="(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))">
</div>
<div class="field_div">
<textarea id="file_info_{{=i}}"
onfocus="new VidjilAutoComplete().setupTags(this);"
<input
id="token_input_{{=i}}"
class="token_input"
autocomplete="off"
onfocus="new VidjilAutoComplete().setupSamples(this);
new Tokeniser(document.getElementById('file_set_div_{{=i}}'), document.getElementById('file_set_list_{{=i}}'));"
data-needs-atwho="true"
data-keys="{{=group_ids}}"
class="text form-control"
name="file[{{=i}}][info]"
rows="1"
placeholder="Info">{{if 'info' in file and file['info'] is not None:}}{{=file['info']}}{{pass}}</textarea>
data-needs-tokeniser="true"
data-group-ids="{{=upload_group_ids}}"
data-keys='["generic", "patient", "run"]'
type="text">
</div>
</fieldset>
</fieldset>
</div>
<div class="field_div">
<input class="date form-control" id="sampling_date_{{=i}}" name="file[{{=i}}][sampling_date]" type="text"
value="{{if 'sampling_date' in file and file['sampling_date'] is not None:}}{{=file['sampling_date']}}{{pass}}"
placeholder="Sampling Date (yyyy-mm-dd)" pattern="(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))">
</div>
<div class="field_div">
<textarea id="file_info_{{=i}}"
onfocus="new VidjilAutoComplete().setupTags(this);"
data-needs-atwho="true"
data-keys="{{=group_ids}}"
class="text form-control"
name="file[{{=i}}][info]"
rows="1"
placeholder="Info">{{if 'info' in file and file['info'] is not None:}}{{=file['info']}}{{pass}}</textarea>
</div>
</div>
<fieldset name="generic{{=i}}">
<legend>Set {{=i+1}}</legend>
<input type="hidden" id="generic_id_{{=i}}" name="generic[{{=i}}][id]" value="{{if set is not None:}}{{=set['id']}}{{pass}}">
<input type="hidden" sample_set_id="generic_sample_set_id_{{=i}}" name="generic[{{=i}}][sample_set_id]" value="{{if set is not None:}}{{=set['sample_set_id']}}{{pass}}">
{{ if set is not None and 'error' in set and len(set['error']) > 0: }}
<div class="error">error: {{=", ".join(set['error'])}}</div>
{{pass}}
{{ if set is not None and 'message' in set and len(set['message']) > 0: }}
<div>{{=", ".join(set['message'])}}</div>
{{ pass }}
<div class="field_div">
<input id="sample_set_name_{{=i}}" name="generic[{{=i}}][name]" type="text" class="string form-control"
value="{{if set is not None:}}{{=set['name']}}{{pass}}" required placeholder="Name">
</div>
<div class="field_div">
<textarea
onfocus="$(this).data('group-ids', [$('#group_select option:selected').val()]);
new VidjilAutoComplete().setupAtWho(this);"
data-needs-atwho="true"
class="text form-control"
id="sample_set_info_{{=i}}"
name="generic[{{=i}}][info]"
rows="1"
placeholder="Info">{{if set is not None and set['info'] is not None:}}{{=set['info']}}{{pass}}</textarea>
</div>
</fieldset>
<div>Set {{=i+1}}</div>
<input type="hidden" id="generic_id_{{=i}}" name="generic[{{=i}}][id]" value="{{if set is not None:}}{{=set['id']}}{{pass}}">
<input type="hidden" sample_set_id="generic_sample_set_id_{{=i}}" name="generic[{{=i}}][sample_set_id]" value="{{if set is not None:}}{{=set['sample_set_id']}}{{pass}}">
{{ if set is not None and 'error' in set and len(set['error']) > 0: }}
<div class="error">error: {{=", ".join(set['error'])}}</div>
{{pass}}
{{ if set is not None and 'message' in set and len(set['message']) > 0: }}
<div>{{=", ".join(set['message'])}}</div>
{{ pass }}
<div class="field_div">
<input id="sample_set_name_{{=i}}" name="generic[{{=i}}][name]" type="text" class="string form-control"
value="{{if set is not None:}}{{=set['name']}}{{pass}}" required placeholder="Name">
</div>
<div class="field_div">
<textarea
onfocus="$(this).data('group-ids', [$('#group_select option:selected').val()]);
new VidjilAutoComplete().setupAtWho(this);"
data-needs-atwho="true"
class="text form-control"
id="sample_set_info_{{=i}}"
name="generic[{{=i}}][info]"
rows="1"
placeholder="Info">{{if set is not None and set['info'] is not None:}}{{=set['info']}}{{pass}}</textarea>
</div>
<fieldset name="patient{{=i}}">
<legend>Patient {{=i+1}}</legend>
<input type="hidden" id="patient_id_{{=i}}" name="patient[{{=i}}][id]" value="{{if set is not None:}}{{=set['id']}}{{pass}}">
<input type="hidden" sample_set_id="patient_sample_set_id_{{=i}}" name="patient[{{=i}}][sample_set_id]" value="{{if set is not None:}}{{=set['sample_set_id']}}{{pass}}">
{{ if set is not None and 'error' in set and len(set['error']) > 0: }}
<div class="error">error: {{=", ".join(set['error'])}}</div>
{{ pass }}
{{ if set is not None and 'message' in set and len(set['message']) > 0: }}
<div>{{=", ".join(set['message'])}}</div>
{{ pass }}
<div class="field_div">
<input class="date form-control" id="patient_id_label_{{=i}}" name="patient[{{=i}}][id_label]" type="text"
value="{{if set is not None and set['id_label'] is not None:}}{{=set['id_label']}}{{pass}}" placeholder="Patient ID">
</div>
<div class="field_div">
<input class="string form-control" id="patient_first_name_{{=i}}" name="patient[{{=i}}][first_name]" type="text"
value="{{if set is not None:}}{{=set['first_name']}}{{pass}}" required placeholder="First Name">
</div>
<div class="field_div">
<input class="string form-control" id="patient_last_name_{{=i}}" name="patient[{{=i}}][last_name]" type="text"
value="{{if set is not None:}}{{=set['last_name']}}{{pass}}" required placeholder="Last Name">
</div>
<div class="field_div">
<input class="date form-control" id="patient_birth_{{=i}}" name="patient[{{=i}}][birth]" type="text"
value="{{if set is not None and set['birth'] is not None:}}{{=set['birth']}}{{pass}}"
title="yyyy-mm-dd" pattern="(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))" placeholder="Birth (yyyy-mm-dd)">
</div>
<div class="field_div">
<textarea
onfocus="$(this).data('keys', [$('#group_select option:selected').val()]);
new VidjilAutoComplete().setupTags(this);"
data-needs-atwho="true"
class="text form-control"
id="patient_info_{{=i}}"
name="patient[{{=i}}][info]"
rows="1"
placeholder="Info">{{if set is not None and set['info'] is not None:}}{{=set['info']}}{{pass}}</textarea>
</div>
</fieldset>
<div>Patient {{=i+1}}</div>
<input type="hidden" id="patient_id_{{=i}}" name="patient[{{=i}}][id]" value="{{if set is not None:}}{{=set['id']}}{{pass}}">
<input type="hidden" sample_set_id="patient_sample_set_id_{{=i}}" name="patient[{{=i}}][sample_set_id]" value="{{if set is not None:}}{{=set['sample_set_id']}}{{pass}}">
{{ if set is not None and 'error' in set and len(set['error']) > 0: }}
<div class="error">error: {{=", ".join(set['error'])}}</div>
{{ pass }}
{{ if set is not None and 'message' in set and len(set['message']) > 0: }}
<div>{{=", ".join(set['message'])}}</div>
{{ pass }}
<div class="field_div">
<input class="date form-control" id="patient_id_label_{{=i}}" name="patient[{{=i}}][id_label]" type="text"
value="{{if set is not None and set['id_label'] is not None:}}{{=set['id_label']}}{{pass}}" placeholder="Patient ID">
</div>
<div class="field_div">
<input class="string form-control" id="patient_first_name_{{=i}}" name="patient[{{=i}}][first_name]" type="text"
value="{{if set is not None:}}{{=set['first_name']}}{{pass}}" required placeholder="First Name">
</div>
<div class="field_div">
<input class="string form-control" id="patient_last_name_{{=i}}" name="patient[{{=i}}][last_name]" type="text"
value="{{if set is not None:}}{{=set['last_name']}}{{pass}}" required placeholder="Last Name">
</div>
<div class="field_div">
<input class="date form-control" id="patient_birth_{{=i}}" name="patient[{{=i}}][birth]" type="text"
value="{{if set is not None and set['birth'] is not None:}}{{=set['birth']}}{{pass}}"
title="yyyy-mm-dd" pattern="(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))" placeholder="Birth (yyyy-mm-dd)">
</div>
<div class="field_div">
<textarea
onfocus="$(this).data('keys', [$('#group_select option:selected').val()]);
new VidjilAutoComplete().setupTags(this);"
data-needs-atwho="true"
class="text form-control"
id="patient_info_{{=i}}"
name="patient[{{=i}}][info]"
rows="1"
placeholder="Info">{{if set is not None and set['info'] is not None:}}{{=set['info']}}{{pass}}</textarea>
</div>
<fieldset name="run{{=i}}">
<legend>Run {{=i+1}}</legend>
<input type="hidden" id="run_id_{{=i}}" name="run[{{=i}}][id]" value="{{if set is not None:}}{{=set['id']}}{{pass}}">
<input type="hidden" sample_set_id="run_sample_set_id_{{=i}}" name="run[{{=i}}][sample_set_id]" value="{{if set is not None:}}{{=set['sample_set_id']}}{{pass}}">
{{ if set is not None and 'error' in set and len(set['error']) > 0: }}
<div class="error">error: {{=", ".join(set['error'])}}</div>
{{ pass }}
{{ if set is not None and 'message' in set and len(set['message']) > 0: }}
<div>{{=", ".join(set['message'])}}</div>
{{ pass }}
<div class="field_div">
<input class="date" id="run_id_label_{{=i}}" name="run[{{=i}}][id_label]" type="text"
value="{{if set is not None and set['id_label'] is not None:}}{{=set['id_label']}}{{pass}}" placeholder="Run ID"><span></span>
</div>
<div class="field_div">
<input class="string form-control" id="run_name_{{=i}}" name="run[{{=i}}][name]" type="text"
value="{{if set is not None:}}{{=set['name']}}{{pass}}" required placeholder="Name">
</div>
<div class="field_div">
<input id="run_date_{{=i}}" name="run[{{=i}}][run_date]" type="text" class="date form-control"
value="{{if set is not None and set['run_date'] is not None:}}{{=set['run_date']}}{{pass}}"
placeholder="Date (yyyy-mm-dd)" title="yyyy-mm-dd" pattern="(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))">
</div>
<div class="field_div">
<textarea
onfocus="$(this).data('group-ids', [$('#group_select option:selected').val()]);
new VidjilAutoComplete().setupAtWho(this);"
data-needs-atwho="true"
class="text form-control"
id="run_info_{{=i}}"
name="run[{{=i}}][info]"
rows="1"
placeholder="Info">{{if set is not None and set['info'] is not None:}}{{=set['info']}}{{pass}}</textarea>
</div>
<div class="field_div">
<input id="run_sequencer_{{=i}}" name="run[{{=i}}][sequencer]" type="text" class="form-control"