Commit b780f740 authored by Bryan  BRANCOTTE's avatar Bryan BRANCOTTE

Merge branch 'master' into link-all-ncbi-data

parents 99130d2d 2064ad94
......@@ -15,4 +15,5 @@ empty.xlsx.json.not_needed
VHDB105.xlsx*
VHDB107.xlsx*
.static/
.media/
doc/_build/
......@@ -57,7 +57,6 @@ deploy_prod:
only:
- master
stage: deploy
#when: manual
image: registry-gitlab.pasteur.fr/dsi-tools/docker-images:docker_kubernetes_image
variables:
CI_DEBUG_TRACE: "false"
......@@ -65,6 +64,7 @@ deploy_prod:
PUBLIC_URL: "viralhostrangedb.pasteur.cloud"
STORAGE_SUFFIX: "-${CI_COMMIT_REF_SLUG}"
DEBUG: "True"
DISPOSABLE: "Never"
environment:
name: "viralhostrange-prod/$CI_COMMIT_REF_SLUG"
url: "https://viralhostrangedb.pasteur.cloud"
......@@ -80,7 +80,7 @@ deploy_prod:
- envsubst < k8s/kubernetes-storage.yaml | kubectl apply -n $NAMESPACE -f -
- envsubst < k8s/manifest-postgres.yaml | kubectl apply -n $NAMESPACE -f -
- envsubst < k8s/manifest.yaml | kubectl apply -n $NAMESPACE -f -
- envsubst < k8s/manifest-webhost-autoscale.yaml | kubectl apply -n $NAMESPACE -f -
# - envsubst < k8s/manifest-webhost-autoscale.yaml | kubectl apply -n $NAMESPACE -f -
- envsubst < k8s/kubernetes-cronjob.yaml | kubectl apply -n $NAMESPACE -f -
tags:
- k8s
......@@ -91,7 +91,6 @@ deploy_dev:
except:
- master
stage: deploy
#when: manual
image: registry-gitlab.pasteur.fr/dsi-tools/docker-images:docker_kubernetes_image
variables:
CI_DEBUG_TRACE: "false"
......@@ -99,6 +98,7 @@ deploy_dev:
PUBLIC_URL: "viralhostrangedb-${CI_COMMIT_REF_SLUG}.pasteur.cloud"
STORAGE_SUFFIX: "-${CI_COMMIT_REF_SLUG}"
DEBUG: "True"
DISPOSABLE: "Always"
environment:
name: "viralhostrange-dev/$CI_COMMIT_REF_SLUG"
url: "https://viralhostrangedb-${CI_COMMIT_REF_SLUG}.pasteur.cloud"
......@@ -116,7 +116,7 @@ deploy_dev:
- envsubst < k8s/kubernetes-storage.yaml | kubectl apply -n $NAMESPACE -f -
- envsubst < k8s/manifest-postgres.yaml | kubectl apply -n $NAMESPACE -f -
- envsubst < k8s/manifest.yaml | kubectl apply -n $NAMESPACE -f -
- envsubst < k8s/manifest-webhost-autoscale.yaml | kubectl apply -n $NAMESPACE -f -
# - envsubst < k8s/manifest-webhost-autoscale.yaml | kubectl apply -n $NAMESPACE -f -
- envsubst < k8s/kubernetes-cronjob.yaml | kubectl apply -n $NAMESPACE -f -
tags:
- k8s
......@@ -138,6 +138,7 @@ stop_and_delete_in_dev:
script:
- echo "Removing $CI_COMMIT_REF_SLUG"
- kubectl --namespace=$NAMESPACE --wait=true delete hpa -l branch=branch-$CI_COMMIT_REF_SLUG
- kubectl --namespace=$NAMESPACE --wait=true delete deploy,replicasets -l branch=branch-$CI_COMMIT_REF_SLUG -l role=front
- kubectl --namespace=$NAMESPACE --wait=true delete deploy,replicasets -l branch=branch-$CI_COMMIT_REF_SLUG
- kubectl --namespace=$NAMESPACE --wait=true delete cronjob -l branch=branch-$CI_COMMIT_REF_SLUG
- kubectl --namespace=$NAMESPACE --wait=true delete ing,svc -l branch=branch-$CI_COMMIT_REF_SLUG
......
......@@ -13,3 +13,4 @@ data:
USE_SQLITE_AS_DB: "$USE_SQLITE_AS_DB"
PROJECT_NAME: "viralhostrange"
STATIC_URL: "/static"
MEDIA_URL: "/media"
......@@ -16,6 +16,10 @@ apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: ${CI_ENVIRONMENT_SLUG}-postgres
labels:
branch: branch${STORAGE_SUFFIX}
can-be-killed-without-warning: ${DISPOSABLE}
disposable-by-admin: ${DISPOSABLE}
spec:
template:
metadata:
......@@ -23,6 +27,8 @@ spec:
app: postgres-app
role: backend
branch: branch${STORAGE_SUFFIX}
can-be-killed-without-warning: ${DISPOSABLE}
disposable-by-admin: ${DISPOSABLE}
spec:
containers:
- image: "postgres:10.1"
......
......@@ -5,6 +5,8 @@ metadata:
name: ${CI_ENVIRONMENT_SLUG}-webhost-deployment
labels:
branch: branch${STORAGE_SUFFIX}
can-be-killed-without-warning: ${DISPOSABLE}
disposable-by-admin: ${DISPOSABLE}
spec:
replicas: 1
selector:
......@@ -23,6 +25,8 @@ spec:
app: ${CI_ENVIRONMENT_SLUG} #webhost-app
branch: branch${STORAGE_SUFFIX}
role: front
can-be-killed-without-warning: ${DISPOSABLE}
disposable-by-admin: ${DISPOSABLE}
spec:
containers:
- name: webhost-container
......@@ -39,11 +43,11 @@ spec:
mountPath: /code/persistent_volume
livenessProbe:
httpGet:
path: /about/
path: /probe_alive/
port: 8086
readinessProbe:
httpGet:
path: /about/
path: /probe_ready/
port: 8086
resources:
requests:
......
......@@ -61,8 +61,6 @@ COPY . /code
ARG CI_COMMIT_SHORT_SHA
ARG CI_COMMIT_REF_SLUG
RUN if [ "$CI_COMMIT_REF_SLUG" != "master" ]; then envsubst < ./viralhostrangedb/templates/viralhostrangedb/pre_content_page_title.example.html > ./viralhostrangedb/templates/viralhostrangedb/pre_content_page_title.html; fi
RUN echo "Version $CI_COMMIT_SHORT_SHA $CI_COMMIT_REF_SLUG on $(date +'%Y-%m-%d %H:%M %Z')" > /code/viralhostrangedb/templates/viralhostrangedb/last_update.html && adduser --disabled-password --gecos '' kiwi && chown -R kiwi:kiwi /code
RUN if [ "$CI_COMMIT_REF_SLUG" != "master" ]; then export WHEN="$(date +'%Y-%m-%d %H:%M %Z')"; envsubst < ./viralhostrangedb/templates/viralhostrangedb/pre_content_page_title.example.html > ./viralhostrangedb/templates/viralhostrangedb/pre_content_page_title.html; fi && echo "Version $CI_COMMIT_SHORT_SHA $CI_COMMIT_REF_SLUG on $(date +'%Y-%m-%d %H:%M %Z')" > /code/viralhostrangedb/templates/viralhostrangedb/last_update.html && adduser --disabled-password --gecos '' kiwi && chown -R kiwi:kiwi /code
USER kiwi
\ No newline at end of file
......@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-11-04 15:28+0100\n"
"POT-Creation-Date: 2019-11-13 11:35+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
......@@ -53,7 +53,7 @@ msgid "The file to upload."
msgstr ""
msgid "new_allowed_users__label"
msgstr "Users you want to grant permission to see the data source"
msgstr "List of users allowed to see the data source:"
msgid "new_allowed_users__help_text"
msgstr ""
......@@ -333,7 +333,10 @@ msgstr ""
"or:\n"
"T4\tid_of_t4\n"
"Virus_2\tNC_001416\n"
"Virus 3\t&lt;blank&gt;"
"\n"
"or:\n"
"T4;id of t4\n"
"Virus_2;NC_001416"
msgid "host_placeholder_in_form"
msgstr ""
......@@ -349,6 +352,9 @@ msgid "delimiter_not_found_please_specify_it"
msgstr ""
"We were not able to guess to separator, you should consider providing it."
msgid "Recommended responses scheme"
msgstr ""
msgid "ContactOwnerForm__recipient"
msgstr "Recipient"
......@@ -418,7 +424,9 @@ msgid "public__verbose_name"
msgstr "Public"
msgid "public__help_text"
msgstr "Is the data source publicly readable"
msgstr ""
"Is the data source publicly readable ? Otherwise you can allow specific "
"users."
msgid "data_source__name__verbose_name"
msgstr "Name"
......@@ -687,6 +695,15 @@ msgstr ""
msgid "Sort hosts on their infection ratio"
msgstr ""
msgid "L'Institut Pasteur"
msgstr ""
msgid "Bioinformatics and Biostatistics HUB"
msgstr ""
msgid "Interactions Bacteriophages Bacteria in Animals"
msgstr ""
msgid "Browse it"
msgstr "Explore it"
......@@ -811,7 +828,8 @@ msgstr ""
msgid "ViralHostRangeDB_main_title"
msgstr ""
"Viral Host Range database, a resource for virus-host interactions&nbsp;studies"
"Viral Host Range database, a resource for virus-host interactions&nbsp;"
"studies"
#, python-format
msgid ""
......@@ -840,24 +858,27 @@ msgstr ""
msgid "hosts responses to viruses"
msgstr ""
msgid "Search"
msgstr ""
msgid "in viruses, hosts and data sources"
msgstr "viruses, hosts and data sources"
msgid "Contribute"
msgstr ""
msgid "with your data"
msgstr ""
msgid "Search"
msgstr ""
msgid "in viruses, hosts and data sources"
msgstr "viruses, hosts and data sources"
msgid "title_subset_of_data_source"
msgstr "Recently updated data sources"
msgid "From"
msgstr ""
msgid "Open"
msgstr ""
msgid "access_to_virus_host_and_data_source"
msgstr "Direct access to the content of the database"
......@@ -1064,8 +1085,26 @@ msgstr ""
msgid "Contribution"
msgstr ""
msgid "Provide a new data source"
msgstr ""
msgid "DataSourceWizard.title.Information"
msgstr "Provide a new data source: General information"
msgid "DataSourceWizard.title.Visibility"
msgstr "Provide a new data source: Adjusting its visibility"
msgid "DataSourceWizard.title.Description"
msgstr "Provide a new data source: Description"
msgid "DataSourceWizard.title.UploadOrLiveInput"
msgstr "Provide a new data source: Way to provide it"
msgid "DataSourceWizard.title.Upload"
msgstr "Provide a new data source: Upload a file"
msgid "DataSourceWizard.title.LiveInput"
msgstr "Provide a new data source: Preparing the template"
msgid "DataSourceWizard.title.UploadTemplate"
msgstr "Provide a new data source: Uploading the template"
msgid "Proceed"
msgstr ""
......@@ -1101,8 +1140,8 @@ msgstr "_"
msgid "step_message_Visibility"
msgstr ""
"As your data source is not public, you can allow specific users to visualize "
"your data source."
"As your data source is <b>not public</b>, you can allow specific users to "
"visualize your data source."
msgid "step_message_UploadOrLiveInput"
msgstr "_"
......@@ -1123,15 +1162,45 @@ msgstr ""
"\" href=\"http://hub.pages.pasteur.fr/12765-viralhostrangedb/compatible_file."
"html\">documentation</a>.</p>"
msgid "step_message_LiveInput"
msgid "step_message_LiveInput when is_bound"
msgstr ""
"You can now provide the list of viruses and hosts you want to add to your "
"data source. <br/>If there is more than one element per line, we will try to "
"guess what is the separator between <code title=\"tabulation\">\\t</code>, "
"<code title=\"comma\">,</code> or <code title=\"semicolon\">;</code>.<br/>If "
"you have your elements along with their identifiers, you can copy/paste them "
"in a format with two column where the first column is the name, and the "
"second column is the identifier."
"data source. <br/>If you have your elements along with their identifiers, "
"you can copy/paste them from a spreadsheet in a format with two column where "
"the first column is the name, and the second column is the identifier. <br/"
">If there is more than one element per line, we will try to guess what is "
"the separator between <code title=\"tabulation\">\\t</code>, <code title="
"\"comma\">,</code> or <code title=\"semicolon\">;</code>. If not we will ask "
"you."
#. Translators : when data is provided i.e: when we were not able to guess what is the separator,
#. so give more details
msgid "step_message_LiveInput when not is_bound"
msgstr ""
"You can now provide the list of viruses and hosts you want to add to your "
"data source. <br/>If you have your elements along with their identifiers, "
"you can copy/paste them from a spreadsheet in a format with two column where "
"the first column is the name, and the second column is the identifier."
#, python-format
msgid "step_message_UploadTemplate%(scheme)s%(template_file_url)s"
msgstr ""
"<p>A template have been generated, and a sample is displayed on the right. "
"You now have to download the template <a href=\"%(template_file_url)s\" "
"target=\"_blank\">(<i class=\"fa fa-download\"> link)</i></a>, fill it with "
"responses, and upload the filled template here bellow.</p><p>Note that a "
"response is entered as a number and the recommended values to use are: "
"%(scheme)s. <b>NCBI identifiers</b> of host and virus can still be provided "
"within the spreadsheet file between parenthesis after the name of host or "
"virus : <code class=\"p-2 d-inline-block\"><span title=\"Name\" class="
"\"border border-secondary\">Virus 1</span> (<span title=\"Identifier\" class="
"\"border border-secondary\">id of Virus 1</span>)</code></p>"
msgid "Fig 1: A (subset of) your template<br/>"
msgstr ""
msgid "download complete template"
msgstr ""
msgid "and"
msgstr ""
......@@ -1226,6 +1295,3 @@ msgstr ""
"You can contact a data source owner with this form. We will send on your "
"behalf the email you are about to write. The owner will get the email you "
"wrote, your name and email address, alloing him/her to answer you directly."
#~ msgid "SearchForm.owner.label"
#~ msgstr "Narrow your search to data shared by only some users."
......@@ -18,7 +18,7 @@ ErrorLog "|/usr/bin/rotatelogs /code/persistent_volume/apache.%Y-%m-%d-%H_%M_%S.
WSGIProcessGroup ${PROJECT_NAME}
Alias ${STATIC_URL}/ /code/.static/
#Alias ${MEDIA_URL}/ /code/.media/
Alias ${MEDIA_URL}/ /code/.media/
Alias /favicon.ico /code/.static/favicon.ico
Alias /robots.txt /code/.static/robots.txt
Redirect permanent "/apple-touch-icon-precomposed.png" "${STATIC_URL}/favicon-256.png"
......
......@@ -8,6 +8,11 @@ if [ "$1" == "test" ]; then
msg_info "Running tests"
pip install coverage
cp viralhostrange/settings.example.ini viralhostrange/settings.ini || exit 2
MEDIA_ROOT_DIR=$(python manage.py shell -c "from django.conf import settings; print(settings.MEDIA_ROOT)" | grep -v django.db.backends)
mkdir -p $MEDIA_ROOT_DIR
chmod 777 $MEDIA_ROOT_DIR
python manage.py collectstatic --noinput
python manage.py compilemessages || exit 6
coverage run --source='.' manage.py test || exit 3
......@@ -78,7 +83,7 @@ else
msg_warning "csscompressor missing, passed"
fi
MEDIA_ROOT_DIR=$(python manage.py shell -c "from django.conf import settings; print(settings.MEDIA_ROOT)")
MEDIA_ROOT_DIR=$(python manage.py shell -c "from django.conf import settings; print(settings.MEDIA_ROOT)" | grep -v django.db.backends)
msg_info "Creating media root at $MEDIA_ROOT_DIR"
if [ "$MEDIA_ROOT_DIR" != "" ]; then
mkdir -p $MEDIA_ROOT_DIR
......@@ -87,11 +92,15 @@ else
msg_warning "settings.MEDIA_ROOT missing, passed"
fi
sudo /usr/sbin/service cron start
msg_info "Adding cron task to dump db every day"
cat <(crontab -l) <(echo "") <(echo "* * * * * find $MEDIA_ROOT_DIR/ -type f -name 'Template*.xlsx' -mtime +1 -exec rm {} \; >> /code/persistent_volume/django-crontab.log 2>> /code/persistent_volume/django-crontab.err") | crontab -
# Setting up cron tasks
msg_info "Registering cron tasks"
if [ "$(pip freeze | grep django-crontab | wc -l )" == "1" ]; then
python manage.py crontab add
sudo /usr/sbin/service cron start
#sudo /usr/sbin/service cron start
grep = /code/resources/default.ini /code/resources/local.ini -h | sed "s/^\(.*\)$/export \1/g" > /home/kiwi/env.sh
echo "export ALLOWED_HOSTS=$ALLOWED_HOSTS" >> /home/kiwi/env.sh
echo "export DEBUG=$DEBUG" >> /home/kiwi/env.sh
......@@ -100,6 +109,8 @@ else
msg_warning "django-crontab missing, passed"
fi
crontab -l
if [ "$1" == "do_not_start" ]; then
msg_info "Entrypoint have been run successfully, we are not starting the project as requested"
elif [ "$1" == "django" ]; then
......
{
"C1 (HG738867.1)": {
"r1 (NC_001416)": "1"
},
"C2 (HGC2738867.3)": {
"r1 (NC_001416)": "2"
}
}
\ No newline at end of file
......@@ -156,6 +156,7 @@ USE_TZ = True
STATIC_ROOT = os.path.join(BASE_DIR, '.static')
STATIC_URL = config('STATIC_URL', default='/static') + '/'
MEDIA_ROOT = os.path.join(BASE_DIR, '.media')
MEDIA_URL = config('MEDIA_URL', default='/media') + '/'
################################################################################
# LOGGING
......@@ -166,6 +167,14 @@ ADMINS = [
MAIL_ADMINS_ON_ERROR = config('MAIL_ADMINS_ON_ERROR', default="auto") in ["True", "true", "1"] \
or config('MAIL_ADMINS_ON_ERROR', default="auto") == "auto" \
and not config('USE_SQLITE_AS_DB', default=False, cast=bool)
def skip_probe(record):
if record and record.request and record.request.path == "/probe_ready/":
return False
return True
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
......@@ -175,6 +184,12 @@ LOGGING = {
'style': '{',
},
},
'filters': {
'skip_probes': {
'()': 'django.utils.log.CallbackFilter',
'callback': skip_probe,
}
},
'handlers': {
'console': {
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
......@@ -186,6 +201,7 @@ LOGGING = {
'formatter': 'simple',
'class': 'django.utils.log.AdminEmailHandler',
'include_html': True,
'filters': ['skip_probes'],
}
},
'loggers': {
......
......@@ -35,3 +35,6 @@ if not settings.DEBUG:
urlpatterns.append(
url(r'^static/(?P<path>.*)$', serve, {'document_root': settings.STATIC_ROOT})
)
urlpatterns.append(
url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT})
)
......@@ -357,24 +357,6 @@ def import_file(*, data_source, file, importation_observer: ImportationObserver
return data_source
def merge_entries(entry_to_keep, entry_to_merge):
if type(entry_to_keep) != type(entry_to_merge):
raise ValueError("Can't merge entries with different type")
if isinstance(entry_to_keep, models.Host):
key = "host"
elif isinstance(entry_to_keep, models.Virus):
key = "virus"
else:
raise ValueError("Can't merge entries of type %s" % type(entry_to_keep))
for o in entry_to_merge.responseindatasource.all():
setattr(o, key, entry_to_keep)
o.save()
for o in entry_to_merge.data_source.all():
entry_to_keep.data_source.add(o)
entry_to_merge.delete()
return entry_to_keep
def reset_mapping(queryset):
not_mapped_yet = models.GlobalViralHostResponseValue.get_not_mapped_yet()
for o in queryset:
......
import csv
import io
import os
import random
import string
import pandas as pd
from basetheme_bootstrap.user_preferences import get_user_preferences_for_user
from crispy_forms import helper as crispy_forms_helper
from crispy_forms import layout as crispy_forms_layout
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Layout, Row, Column
from django import forms
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import transaction
from django.db.models import Q, Min, Max
from django.forms import widgets
from django.utils import timezone
from django.utils.datastructures import MultiValueDictKeyError
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _, ugettext
from viralhostrangedb import models, business_process
from viralhostrangedb.business_process import ImportationObserver
from viralhostrangedb.business_process import ImportationObserver, explicit_item
from viralhostrangedb.mixins import only_public_or_granted_or_owned_queryset_filter
......@@ -105,7 +110,7 @@ class DataSourceUserCreateOrUpdateForm(forms.ModelForm):
new_allowed_users = forms.CharField(
label=_("new_allowed_users__label"),
help_text=_("new_allowed_users__help_text"),
widget=widgets.Textarea(),
widget=widgets.Textarea(attrs={'rows': '4'}),
required=False,
)
allowed_users = ByLastFirstNameModelMultipleChoiceField(
......@@ -120,7 +125,7 @@ class DataSourceUserCreateOrUpdateForm(forms.ModelForm):
model = models.DataSource
fields = (
'name',
'experiment_date',
# 'experiment_date',
'publication_url',
'life_domain',
'description',
......@@ -129,7 +134,7 @@ class DataSourceUserCreateOrUpdateForm(forms.ModelForm):
)
widgets = dict(
raw_name=widgets.TextInput(),
experiment_date=DateInput,
# experiment_date=DateInput,
)
def __init__(self, owner=None, data=None, *args, **kwargs):
......@@ -137,7 +142,7 @@ class DataSourceUserCreateOrUpdateForm(forms.ModelForm):
super().__init__(data=data, *args, **kwargs)
if self.instance and data and "public" in data and data["public"]:
self.fields["description"].required = True
self.fields["experiment_date"].required = True
# self.fields["experiment_date"].required = True
if self.instance and self.instance.pk is not None:
self.fields["allowed_users"].queryset = self.instance.allowed_users.order_by("last_name", "first_name")
......@@ -986,7 +991,7 @@ class DataSourceDescriptionModelForm(forms.ModelForm):
class Meta:
model = models.DataSource
fields = (
'experiment_date',
# 'experiment_date',
'description',
'publication_url',
)
......@@ -997,7 +1002,7 @@ class DataSourceDescriptionModelForm(forms.ModelForm):
def __init__(self, required, msg=None, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["description"].required = required
self.fields["experiment_date"].required = required
# self.fields["experiment_date"].required = required
# Translators: The text displayed in the form field when it is empty.
self.fields["description"].widget.attrs["placeholder"] = _("description_placeholder_in_form")
self.helper = crispy_forms_helper.FormHelper()
......@@ -1009,7 +1014,7 @@ class DataSourceDescriptionModelForm(forms.ModelForm):
css_class='col-md-6 mb-0',
),
crispy_forms_layout.Column(
'experiment_date',
# 'experiment_date',
'description',
'publication_url',
css_class='col-md-6 mb-0',
......@@ -1042,6 +1047,7 @@ class UploadOrLiveInput(forms.Form):
label=_("upload_or_live_input__label"),
choices=(
("upload", _("UploadOrLiveInput__upload__choice")),
# ("template", _("UploadOrLiveInput__template__choice")),
("live", _("UploadOrLiveInput__live_input__choice")),
),
required=True,
......@@ -1071,6 +1077,7 @@ DELIMITER_CHOICES = [
(',', mark_safe(ugettext("delimiter__comma"))),
(';', mark_safe(ugettext("delimiter__semicolon"))),
('two_col\t', mark_safe(ugettext("delimiter__two_col_tabulation_format"))),
('two_col ', mark_safe(ugettext("delimiter__two_col_tabulation_format"))),
('two_col,', mark_safe(ugettext("delimiter__two_col_comma_format"))),
('two_col;', mark_safe(ugettext("delimiter__two_col_semicolon_format"))),
# (' ', mark_safe(ugettext("delimiter__space"))),
......@@ -1082,7 +1089,7 @@ class LiveInputVirusHostForm(forms.Form):
label=_("Virus"),
help_text=_("LiveVirusHostInput__Virus__help_text"),
required=True,
widget=forms.widgets.Textarea()
widget=forms.widgets.Textarea({'rows': '8'})
)
virus_delimiter = forms.ChoiceField(
label=_("LiveVirusHostInput__virus_delimiter__label"),
......@@ -1096,7 +1103,7 @@ class LiveInputVirusHostForm(forms.Form):
label=_("Host"),
help_text=_("LiveVirusHostInput__Host__help_text"),
required=True,
widget=forms.widgets.Textarea()
widget=forms.widgets.Textarea({'rows': '8'})
)
host_delimiter = forms.ChoiceField(
label=_("LiveVirusHostInput__host_delimiter__label"),
......@@ -1107,8 +1114,8 @@ class LiveInputVirusHostForm(forms.Form):
widget=forms.Select,
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def __init__(self, data=None, *args, **kwargs):
super().__init__(data=data, *args, **kwargs)
self.fields["virus"].widget.attrs["placeholder"] = mark_safe(_("virus_placeholder_in_form"))
self.fields["host"].widget.attrs["placeholder"] = _("host_placeholder_in_form")
self.helper = crispy_forms_helper.FormHelper()
......@@ -1128,6 +1135,9 @@ class LiveInputVirusHostForm(forms.Form):
),
)
self.helper.form_tag = False
if not data:
self.fields["host_delimiter"].widget = forms.HiddenInput()
self.fields["virus_delimiter"].widget = forms.HiddenInput()
def get_as_list(self, key):
f = io.StringIO(self.cleaned_data[key])
......@@ -1176,19 +1186,63 @@ class LiveInputVirusHostForm(forms.Form):
if self.cleaned_data[delimiter_key] is None:
self.add_error(key, _("delimiter_not_found_please_check_input"))
self.add_error(delimiter_key, _("delimiter_not_found_please_specify_it"))
# else:
# self.add_error(key, "eee")
def get_template_files(self):
col_header = [explicit_item(n, i) for n, i in self.get_as_list('host')]
row_header = [explicit_item(n, i) for n, i in self.get_as_list('virus')]
# Prepare the legend
mapping = models.GlobalViralHostResponseValue.objects_mappable().order_by('value')
legend_name = []
legend_value = []
legend = []
for m in models.GlobalViralHostResponseValue.objects_mappable().order_by('value'):
legend_name.append([m.name])
legend_value.append(m.value)
legend.append([m.name, m.value])
df_legend = pd.DataFrame(legend_name, columns=[str(_("Recommended responses scheme"))], index=legend_value)