Add owner field to experiment fixes #327
This commit is contained in:
Родитель
3bd9383ece
Коммит
b9c5464b62
|
@ -100,6 +100,14 @@ class ExperimentConstants(object):
|
|||
'Does this study affect a large number of Release users?')
|
||||
|
||||
# Help texts
|
||||
OWNER_HELP_TEXT = """
|
||||
<p>
|
||||
The owner of the experiment is the person responsible for ensuring
|
||||
that it is run in its entirety and is the primary stake holder in
|
||||
its analysis.
|
||||
</p>
|
||||
"""
|
||||
|
||||
PROJECT_HELP_TEXT = format_lazy("""
|
||||
<p>
|
||||
Choose which project this experiment belongs to.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import json
|
||||
|
||||
from django import forms
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.utils.text import slugify
|
||||
|
||||
from experimenter.projects.forms import AutoNameSlugFormMixin
|
||||
|
@ -36,6 +37,7 @@ class NameSlugMixin(object):
|
|||
|
||||
|
||||
class ControlVariantForm(NameSlugMixin, forms.ModelForm):
|
||||
|
||||
description = forms.CharField(
|
||||
label='Description',
|
||||
help_text=Experiment.CONTROL_DESCRIPTION_HELP_TEXT,
|
||||
|
@ -84,6 +86,7 @@ class ControlVariantForm(NameSlugMixin, forms.ModelForm):
|
|||
|
||||
|
||||
class ExperimentalVariantForm(NameSlugMixin, forms.ModelForm):
|
||||
|
||||
slug = forms.CharField(required=False)
|
||||
experiment = forms.ModelChoiceField(
|
||||
required=False, queryset=Experiment.objects.all())
|
||||
|
@ -152,6 +155,14 @@ class ChangeLogMixin(object):
|
|||
|
||||
class ExperimentOverviewForm(
|
||||
AutoNameSlugFormMixin, ChangeLogMixin, forms.ModelForm):
|
||||
|
||||
owner = forms.ModelChoiceField(
|
||||
required=False,
|
||||
label='Owner',
|
||||
help_text=Experiment.OWNER_HELP_TEXT,
|
||||
queryset=get_user_model().objects.all(),
|
||||
widget=forms.Select(attrs={'class': 'form-control'}),
|
||||
)
|
||||
project = forms.ModelChoiceField(
|
||||
required=False,
|
||||
label='Project',
|
||||
|
@ -206,6 +217,7 @@ class ExperimentOverviewForm(
|
|||
class Meta:
|
||||
model = Experiment
|
||||
fields = [
|
||||
'owner',
|
||||
'project',
|
||||
'name',
|
||||
'slug',
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11 on 2018-05-08 19:15
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('experiments', '0008_auto_20180503_1747'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='experiment',
|
||||
name='owner',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
|
@ -22,6 +22,7 @@ class ExperimentManager(models.Manager):
|
|||
|
||||
|
||||
class Experiment(ExperimentConstants, models.Model):
|
||||
owner = models.ForeignKey(get_user_model(), blank=True, null=True)
|
||||
project = models.ForeignKey(
|
||||
'projects.Project',
|
||||
blank=True,
|
||||
|
|
|
@ -16,6 +16,7 @@ faker = FakerFactory.create()
|
|||
|
||||
|
||||
class ExperimentFactory(factory.django.DjangoModelFactory):
|
||||
owner = factory.SubFactory(UserFactory)
|
||||
project = factory.SubFactory(ProjectFactory)
|
||||
name = factory.LazyAttribute(lambda o: faker.catch_phrase())
|
||||
slug = factory.LazyAttribute(lambda o: slugify(o.name))
|
||||
|
|
|
@ -198,6 +198,7 @@ class TestExperimentOverviewForm(MockRequestMixin, TestCase):
|
|||
self.project = ProjectFactory.create()
|
||||
|
||||
self.data = {
|
||||
'owner': self.user.id,
|
||||
'project': self.project.id,
|
||||
'name': 'A new experiment!',
|
||||
'short_description': 'Let us learn new things',
|
||||
|
@ -215,6 +216,7 @@ class TestExperimentOverviewForm(MockRequestMixin, TestCase):
|
|||
self.assertTrue(form.is_valid())
|
||||
experiment = form.save()
|
||||
|
||||
self.assertEqual(experiment.owner, self.user)
|
||||
self.assertEqual(experiment.project, self.project)
|
||||
self.assertEqual(experiment.status, experiment.STATUS_DRAFT)
|
||||
self.assertEqual(experiment.name, self.data['name'])
|
||||
|
|
|
@ -110,6 +110,8 @@ class ExperimentCreateView(ExperimentFormMixin, CreateView):
|
|||
if 'project' in self.request.GET:
|
||||
initial['project'] = self.request.GET['project']
|
||||
|
||||
initial['owner'] = self.request.user.id
|
||||
|
||||
return initial
|
||||
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
<footer>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">
|
||||
<div class="col-md-12 md-mb-20 text-center">
|
||||
<hr/>
|
||||
© Mozilla Corporation 2018
|
||||
</div>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
<div class="col-md-9">
|
||||
<a class="noanchorstyle spaced-text" href="{% url "experiments-detail" slug=experiment.slug %}">
|
||||
{{ object.name }}
|
||||
{{ experiment.name }}
|
||||
</a>
|
||||
<span class="badge status-color-{{ experiment.status }}">{{ experiment.status }}</span>
|
||||
</div>
|
||||
|
@ -29,30 +29,31 @@
|
|||
|
||||
{% if experiment.is_draft %}
|
||||
<div class="col-md-4 text-right">
|
||||
<a class="noanchorstyle" href="{% url "experiments-overview-update" slug=object.slug %}"><h5><span class="glyphicon glyphicon-pencil"></span> Edit</h5></a>
|
||||
<a class="noanchorstyle" href="{% url "experiments-overview-update" slug=experiment.slug %}"><h5><span class="glyphicon glyphicon-pencil"></span> Edit</h5></a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="row card md-pt-15 md-pb-10">
|
||||
{% if object.is_launched %}
|
||||
<iframe style="display:block" scrolling="no" frameBorder="0" width="100%" height="450px" src="{{ object.enrollment_dashboard_url }}" ></iframe>
|
||||
{% if experiment.is_launched %}
|
||||
<iframe style="display:block" scrolling="no" frameBorder="0" width="100%" height="450px" src="{{ experiment.enrollment_dashboard_url }}" ></iframe>
|
||||
{% else %}
|
||||
<div class="col-md-6">
|
||||
<p><strong>{{ object.proposed_start_date }} - {{ object.proposed_end_date }}</strong></p>
|
||||
<div class="col-md-8">
|
||||
<p><strong>Owner: {{ experiment.owner }}</strong></p>
|
||||
</div>
|
||||
<div class="col-md-6 text-right">
|
||||
<h4 class="md-mt-0">{{ object.population }}</h4>
|
||||
<div class="col-md-4 text-right">
|
||||
<h4 class="md-mt-0">{{ experiment.population }}</h4>
|
||||
<p><strong>{{ experiment.proposed_start_date }} - {{ experiment.proposed_end_date }}</strong></p>
|
||||
</div>
|
||||
<div class="col-md-12 md-mt-10">
|
||||
{{ object.short_description|linebreaks }}
|
||||
<div class="col-md-12">
|
||||
{{ experiment.short_description|linebreaks }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="row md-mt-20">
|
||||
<h4 class="col-md-8">
|
||||
{% if not object.completed_variants %}
|
||||
{% if not experiment.completed_variants %}
|
||||
<span class="icon-warning glyphicon glyphicon-exclamation-sign"></span>
|
||||
{% endif %}
|
||||
Firefox Pref & Branches
|
||||
|
@ -60,31 +61,31 @@
|
|||
|
||||
{% if experiment.is_draft %}
|
||||
<div class="col-md-4 text-right">
|
||||
<a class="noanchorstyle" href="{% url "experiments-variants-update" slug=object.slug %}"><h5><span class="glyphicon glyphicon-pencil"></span> Edit</h5></a>
|
||||
<a class="noanchorstyle" href="{% url "experiments-variants-update" slug=experiment.slug %}"><h5><span class="glyphicon glyphicon-pencil"></span> Edit</h5></a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="row card md-pt-15 md-pb-10">
|
||||
{% if object.variants.all %}
|
||||
{% for variant in object.variants.all %}
|
||||
{% if experiment.variants.all %}
|
||||
{% for variant in experiment.variants.all %}
|
||||
<div class="col-md-12 {% if not forloop.last %}md-mb-15{% endif %}">
|
||||
<h4 class="md-mt-0">{{ variant.ratio }}% {{ variant.name }}</h4>
|
||||
<p><strong>{{ object.pref_key }} = <span class="text-info">{{ variant.value }}</span></strong></p>
|
||||
<p><strong>{{ experiment.pref_key }} = <span class="text-info">{{ variant.value }}</span></strong></p>
|
||||
<p>{{ variant.description }}</p>
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
|
||||
<p class="col-md-12">You must <a href="{% url "experiments-variants-update" slug=object.slug %}">define your branches</a> before you can launch your experiment.</p>
|
||||
<p class="col-md-12">You must <a href="{% url "experiments-variants-update" slug=experiment.slug %}">define your branches</a> before you can launch your experiment.</p>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row md-mt-20">
|
||||
<h4 class="col-md-8">
|
||||
{% if not object.completed_objectives %}
|
||||
{% if not experiment.completed_objectives %}
|
||||
<span class="icon-warning glyphicon glyphicon-exclamation-sign"></span>
|
||||
{% endif %}
|
||||
Objectives
|
||||
|
@ -92,24 +93,24 @@
|
|||
|
||||
{% if experiment.is_draft %}
|
||||
<div class="col-md-4 text-right">
|
||||
<a class="noanchorstyle" href="{% url "experiments-objectives-update" slug=object.slug %}"><h5><span class="glyphicon glyphicon-pencil"></span> Edit</h5></a>
|
||||
<a class="noanchorstyle" href="{% url "experiments-objectives-update" slug=experiment.slug %}"><h5><span class="glyphicon glyphicon-pencil"></span> Edit</h5></a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="row card md-pt-15 md-pb-10">
|
||||
<div class="col-md-12">
|
||||
{% if object.completed_objectives %}
|
||||
{{ object.objectives|linebreaks }}
|
||||
{% if experiment.completed_objectives %}
|
||||
{{ experiment.objectives|linebreaks }}
|
||||
{% else %}
|
||||
<p>You must <a href="{% url "experiments-objectives-update" slug=object.slug %}">define the objectives</a> before you can launch your experiment.</p>
|
||||
<p>You must <a href="{% url "experiments-objectives-update" slug=experiment.slug %}">define the objectives</a> before you can launch your experiment.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row md-mt-20">
|
||||
<h4 class="col-md-8">
|
||||
{% if not object.completed_objectives %}
|
||||
{% if not experiment.completed_objectives %}
|
||||
<span class="icon-warning glyphicon glyphicon-exclamation-sign"></span>
|
||||
{% endif %}
|
||||
Analysis
|
||||
|
@ -117,25 +118,25 @@
|
|||
|
||||
{% if experiment.is_draft %}
|
||||
<div class="col-md-4 text-right">
|
||||
<a class="noanchorstyle" href="{% url "experiments-objectives-update" slug=object.slug %}"><h5><span class="glyphicon glyphicon-pencil"></span> Edit</h5></a>
|
||||
<a class="noanchorstyle" href="{% url "experiments-objectives-update" slug=experiment.slug %}"><h5><span class="glyphicon glyphicon-pencil"></span> Edit</h5></a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="row card md-pt-15 md-pb-10">
|
||||
<div class="col-md-12">
|
||||
{% if object.completed_objectives %}
|
||||
{{ object.analysis|linebreaks }}
|
||||
{% if experiment.completed_objectives %}
|
||||
{{ experiment.analysis|linebreaks }}
|
||||
{% else %}
|
||||
|
||||
<p>You must <a href="{% url "experiments-objectives-update" slug=object.slug %}">define the analysis plan</a> before you can launch your experiment.</p>
|
||||
<p>You must <a href="{% url "experiments-objectives-update" slug=experiment.slug %}">define the analysis plan</a> before you can launch your experiment.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row md-mt-20">
|
||||
<h4 class="col-md-8">
|
||||
{% if not object.completed_risks %}
|
||||
{% if not experiment.completed_risks %}
|
||||
<span class="icon-warning glyphicon glyphicon-exclamation-sign"></span>
|
||||
{% endif %}
|
||||
Risk Assessment
|
||||
|
@ -143,42 +144,42 @@
|
|||
|
||||
{% if experiment.is_draft %}
|
||||
<div class="col-md-4 text-right">
|
||||
<a class="noanchorstyle" href="{% url "experiments-risks-update" slug=object.slug %}"><h5><span class="glyphicon glyphicon-pencil"></span> Edit</h5></a>
|
||||
<a class="noanchorstyle" href="{% url "experiments-risks-update" slug=experiment.slug %}"><h5><span class="glyphicon glyphicon-pencil"></span> Edit</h5></a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="row card md-pt-15 md-pb-10">
|
||||
<div class="col-md-12">
|
||||
{% if object.completed_risks %}
|
||||
<p><strong>{{ object.RISK_PARTNER_RELATED_LABEL }}</strong></p>
|
||||
<p>{{ object.risk_partner_related|yesno:"Yes,No" }}</p>
|
||||
{% if experiment.completed_risks %}
|
||||
<p><strong>{{ experiment.RISK_PARTNER_RELATED_LABEL }}</strong></p>
|
||||
<p>{{ experiment.risk_partner_related|yesno:"Yes,No" }}</p>
|
||||
|
||||
<p><strong>{{ object.RISK_BRAND_LABEL }}</strong></p>
|
||||
<p>{{ object.risk_brand|yesno:"Yes,No" }}</p>
|
||||
<p><strong>{{ experiment.RISK_BRAND_LABEL }}</strong></p>
|
||||
<p>{{ experiment.risk_brand|yesno:"Yes,No" }}</p>
|
||||
|
||||
<p><strong>{{ object.RISK_FAST_SHIPPED_LABEL }}</strong></p>
|
||||
<p>{{ object.risk_fast_shipped|yesno:"Yes,No" }}</p>
|
||||
<p><strong>{{ experiment.RISK_FAST_SHIPPED_LABEL }}</strong></p>
|
||||
<p>{{ experiment.risk_fast_shipped|yesno:"Yes,No" }}</p>
|
||||
|
||||
<p><strong>{{ object.RISK_CONFIDENTIAL_LABEL }}</strong></p>
|
||||
<p>{{ object.risk_confidential|yesno:"Yes,No" }}</p>
|
||||
<p><strong>{{ experiment.RISK_CONFIDENTIAL_LABEL }}</strong></p>
|
||||
<p>{{ experiment.risk_confidential|yesno:"Yes,No" }}</p>
|
||||
|
||||
<p><strong>{{ object.RISK_RELEASE_POPULATION_LABEL }}</strong></p>
|
||||
<p>{{ object.risk_release_population|yesno:"Yes,No" }}</p>
|
||||
<p><strong>{{ experiment.RISK_RELEASE_POPULATION_LABEL }}</strong></p>
|
||||
<p>{{ experiment.risk_release_population|yesno:"Yes,No" }}</p>
|
||||
|
||||
{% if object.is_high_risk %}
|
||||
{% if experiment.is_high_risk %}
|
||||
<h5>RASCI Owners and Deliverables</h5>
|
||||
{{ object.risks|linebreaks }}
|
||||
{{ experiment.risks|linebreaks }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p>You must <a href="{% url "experiments-risks-update" slug=object.slug %}">define the risks</a> before you can launch your experiment.</p>
|
||||
<p>You must <a href="{% url "experiments-risks-update" slug=experiment.slug %}">define the risks</a> before you can launch your experiment.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row md-mt-20">
|
||||
<h4 class="col-md-8">
|
||||
{% if not object.completed_risks %}
|
||||
{% if not experiment.completed_risks %}
|
||||
<span class="icon-warning glyphicon glyphicon-exclamation-sign"></span>
|
||||
{% endif %}
|
||||
Testing Plan
|
||||
|
@ -186,17 +187,17 @@
|
|||
|
||||
{% if experiment.is_draft %}
|
||||
<div class="col-md-4 text-right">
|
||||
<a class="noanchorstyle" href="{% url "experiments-risks-update" slug=object.slug %}"><h5><span class="glyphicon glyphicon-pencil"></span> Edit</h5></a>
|
||||
<a class="noanchorstyle" href="{% url "experiments-risks-update" slug=experiment.slug %}"><h5><span class="glyphicon glyphicon-pencil"></span> Edit</h5></a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="row card md-pt-15 md-pb-10">
|
||||
<div class="col-md-12">
|
||||
{% if object.completed_risks %}
|
||||
{{ object.testing|linebreaks }}
|
||||
{% if experiment.completed_risks %}
|
||||
{{ experiment.testing|linebreaks }}
|
||||
{% else %}
|
||||
<p>You must <a href="{% url "experiments-risks-update" slug=object.slug %}">define the QA plan</a> before you can launch your experiment.</p>
|
||||
<p>You must <a href="{% url "experiments-risks-update" slug=experiment.slug %}">define the QA plan</a> before you can launch your experiment.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -206,7 +207,7 @@
|
|||
<div class="col-md-3">
|
||||
|
||||
{% if experiment.is_draft %}
|
||||
{% if object.is_ready_for_review %}
|
||||
{% if experiment.is_ready_for_review %}
|
||||
<form
|
||||
action="{% url "experiments-status-update" slug=experiment.slug %}"
|
||||
method="POST"
|
||||
|
@ -253,7 +254,7 @@
|
|||
{% endif %}
|
||||
|
||||
<h5>History</h5>
|
||||
{% for change in object.changes.all reversed %}
|
||||
{% for change in experiment.changes.all reversed %}
|
||||
<div class="row help-block">
|
||||
<div class="col-md-12">
|
||||
<p>{{ change.changed_on.date }}</p>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "experiments/edit_base.html" %}
|
||||
|
||||
{% load static %}
|
||||
|
||||
|
||||
{% block edit_title %}
|
||||
{% if object %}
|
||||
Edit {{ object.name }}
|
||||
|
@ -15,22 +15,24 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block edit_form %}
|
||||
<form
|
||||
class="form-horizontal"
|
||||
method="POST"
|
||||
<form
|
||||
class="form-horizontal"
|
||||
method="POST"
|
||||
enctype='multipart/form-data'
|
||||
>
|
||||
{% csrf_token %}
|
||||
|
||||
{% include "experiments/field_inline.html" with field=form.owner %}
|
||||
|
||||
{% include "experiments/field_inline.html" with field=form.name %}
|
||||
|
||||
|
||||
{% include "experiments/field_inline.html" with field=form.short_description %}
|
||||
|
||||
<div class="form-group">
|
||||
<div class="{% if form.errors.population_percent %}has-error{% endif %}">
|
||||
<label class="col-md-3 control-label" for="{{ form.population_percent.id_for_label }}">{{ form.population_percent.label }}</label>
|
||||
<div class="col-md-2 ">
|
||||
{{ form.population_percent }}
|
||||
{{ form.population_percent }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
|
@ -45,7 +47,7 @@
|
|||
{% if form.errors.population_percent %}
|
||||
<div class="col-md-9 col-md-offset-3 has-error text-right">
|
||||
{% for error in form.errors.population_percent %}
|
||||
<label for="{{ form.population_percent.id_for_label }}" class="control-label">{{ error }}</label>
|
||||
<label for="{{ form.population_percent.id_for_label }}" class="control-label">{{ error }}</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -58,9 +60,9 @@
|
|||
</div>
|
||||
|
||||
{% include "experiments/field_inline.html" with field=form.client_matching %}
|
||||
|
||||
|
||||
{% include "experiments/field_inline.html" with field=form.proposed_start_date %}
|
||||
|
||||
|
||||
{% include "experiments/field_inline.html" with field=form.proposed_end_date %}
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -79,7 +81,7 @@
|
|||
{% block edit_info %}
|
||||
<h4><span class="glyphicon glyphicon-info-sign"></span> Getting Started</h4>
|
||||
<p>
|
||||
Your experiment will start as a draft.
|
||||
Your experiment will start as a draft.
|
||||
</p>
|
||||
<p>
|
||||
Fill out the information on this page to save your draft.
|
||||
|
@ -89,7 +91,7 @@
|
|||
now or later.
|
||||
</p>
|
||||
<p>
|
||||
When all of the sections are complete and reviewed, you can
|
||||
When all of the sections are complete and reviewed, you can
|
||||
launch your experiment to Shield.
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
<div class="col-md-8">
|
||||
<h4 class="md-mt-0">
|
||||
{{ experiment.name }}
|
||||
<span class="badge status-color-{{ experiment.status }}">{{ experiment.status }}</span>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -52,22 +53,14 @@
|
|||
|
||||
<div class="col-md-8">
|
||||
<h5>
|
||||
<span class="badge status-color-{{ experiment.status }}">{{ experiment.status }}</span>
|
||||
by
|
||||
{{ experiment.changes.latest.changed_by }}
|
||||
on
|
||||
{{ experiment.changes.latest.changed_on.date }}
|
||||
Owner: {{ experiment.owner }}
|
||||
</h5>
|
||||
{{ experiment.short_description|linebreaks }}
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 text-right">
|
||||
<h4>
|
||||
{{ experiment.population }}
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 md-mt-5">
|
||||
<p>{{ experiment.short_description }}</p>
|
||||
<h4>{{ experiment.population }}</h4>
|
||||
<p><strong>{{ experiment.proposed_start_date }} - {{ experiment.proposed_end_date }}</strong></p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
Загрузка…
Ссылка в новой задаче