Add owner field to experiment fixes #327

This commit is contained in:
Jared Kerim 2018-05-08 16:07:24 -04:00 коммит произвёл Jared Kerim
Родитель 3bd9383ece
Коммит b9c5464b62
11 изменённых файлов: 118 добавлений и 73 удалений

Просмотреть файл

@ -100,6 +100,14 @@ class ExperimentConstants(object):
'Does this study affect a large number of Release users?') 'Does this study affect a large number of Release users?')
# Help texts # 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(""" PROJECT_HELP_TEXT = format_lazy("""
<p> <p>
Choose which project this experiment belongs to. Choose which project this experiment belongs to.

Просмотреть файл

@ -1,6 +1,7 @@
import json import json
from django import forms from django import forms
from django.contrib.auth import get_user_model
from django.utils.text import slugify from django.utils.text import slugify
from experimenter.projects.forms import AutoNameSlugFormMixin from experimenter.projects.forms import AutoNameSlugFormMixin
@ -36,6 +37,7 @@ class NameSlugMixin(object):
class ControlVariantForm(NameSlugMixin, forms.ModelForm): class ControlVariantForm(NameSlugMixin, forms.ModelForm):
description = forms.CharField( description = forms.CharField(
label='Description', label='Description',
help_text=Experiment.CONTROL_DESCRIPTION_HELP_TEXT, help_text=Experiment.CONTROL_DESCRIPTION_HELP_TEXT,
@ -84,6 +86,7 @@ class ControlVariantForm(NameSlugMixin, forms.ModelForm):
class ExperimentalVariantForm(NameSlugMixin, forms.ModelForm): class ExperimentalVariantForm(NameSlugMixin, forms.ModelForm):
slug = forms.CharField(required=False) slug = forms.CharField(required=False)
experiment = forms.ModelChoiceField( experiment = forms.ModelChoiceField(
required=False, queryset=Experiment.objects.all()) required=False, queryset=Experiment.objects.all())
@ -152,6 +155,14 @@ class ChangeLogMixin(object):
class ExperimentOverviewForm( class ExperimentOverviewForm(
AutoNameSlugFormMixin, ChangeLogMixin, forms.ModelForm): 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( project = forms.ModelChoiceField(
required=False, required=False,
label='Project', label='Project',
@ -206,6 +217,7 @@ class ExperimentOverviewForm(
class Meta: class Meta:
model = Experiment model = Experiment
fields = [ fields = [
'owner',
'project', 'project',
'name', 'name',
'slug', '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): class Experiment(ExperimentConstants, models.Model):
owner = models.ForeignKey(get_user_model(), blank=True, null=True)
project = models.ForeignKey( project = models.ForeignKey(
'projects.Project', 'projects.Project',
blank=True, blank=True,

Просмотреть файл

@ -16,6 +16,7 @@ faker = FakerFactory.create()
class ExperimentFactory(factory.django.DjangoModelFactory): class ExperimentFactory(factory.django.DjangoModelFactory):
owner = factory.SubFactory(UserFactory)
project = factory.SubFactory(ProjectFactory) project = factory.SubFactory(ProjectFactory)
name = factory.LazyAttribute(lambda o: faker.catch_phrase()) name = factory.LazyAttribute(lambda o: faker.catch_phrase())
slug = factory.LazyAttribute(lambda o: slugify(o.name)) slug = factory.LazyAttribute(lambda o: slugify(o.name))

Просмотреть файл

@ -198,6 +198,7 @@ class TestExperimentOverviewForm(MockRequestMixin, TestCase):
self.project = ProjectFactory.create() self.project = ProjectFactory.create()
self.data = { self.data = {
'owner': self.user.id,
'project': self.project.id, 'project': self.project.id,
'name': 'A new experiment!', 'name': 'A new experiment!',
'short_description': 'Let us learn new things', 'short_description': 'Let us learn new things',
@ -215,6 +216,7 @@ class TestExperimentOverviewForm(MockRequestMixin, TestCase):
self.assertTrue(form.is_valid()) self.assertTrue(form.is_valid())
experiment = form.save() experiment = form.save()
self.assertEqual(experiment.owner, self.user)
self.assertEqual(experiment.project, self.project) self.assertEqual(experiment.project, self.project)
self.assertEqual(experiment.status, experiment.STATUS_DRAFT) self.assertEqual(experiment.status, experiment.STATUS_DRAFT)
self.assertEqual(experiment.name, self.data['name']) self.assertEqual(experiment.name, self.data['name'])

Просмотреть файл

@ -110,6 +110,8 @@ class ExperimentCreateView(ExperimentFormMixin, CreateView):
if 'project' in self.request.GET: if 'project' in self.request.GET:
initial['project'] = self.request.GET['project'] initial['project'] = self.request.GET['project']
initial['owner'] = self.request.user.id
return initial return initial

Просмотреть файл

@ -62,7 +62,7 @@
<footer> <footer>
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-md-12 text-center"> <div class="col-md-12 md-mb-20 text-center">
<hr/> <hr/>
© Mozilla Corporation 2018 © Mozilla Corporation 2018
</div> </div>

Просмотреть файл

@ -9,7 +9,7 @@
<div class="col-md-9"> <div class="col-md-9">
<a class="noanchorstyle spaced-text" href="{% url "experiments-detail" slug=experiment.slug %}"> <a class="noanchorstyle spaced-text" href="{% url "experiments-detail" slug=experiment.slug %}">
{{ object.name }} {{ experiment.name }}
</a> </a>
<span class="badge status-color-{{ experiment.status }}">{{ experiment.status }}</span> <span class="badge status-color-{{ experiment.status }}">{{ experiment.status }}</span>
</div> </div>
@ -29,30 +29,31 @@
{% if experiment.is_draft %} {% if experiment.is_draft %}
<div class="col-md-4 text-right"> <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> </div>
{% endif %} {% endif %}
</div> </div>
<div class="row card md-pt-15 md-pb-10"> <div class="row card md-pt-15 md-pb-10">
{% if object.is_launched %} {% if experiment.is_launched %}
<iframe style="display:block" scrolling="no" frameBorder="0" width="100%" height="450px" src="{{ object.enrollment_dashboard_url }}" ></iframe> <iframe style="display:block" scrolling="no" frameBorder="0" width="100%" height="450px" src="{{ experiment.enrollment_dashboard_url }}" ></iframe>
{% else %} {% else %}
<div class="col-md-6"> <div class="col-md-8">
<p><strong>{{ object.proposed_start_date }} - {{ object.proposed_end_date }}</strong></p> <p><strong>Owner: {{ experiment.owner }}</strong></p>
</div> </div>
<div class="col-md-6 text-right"> <div class="col-md-4 text-right">
<h4 class="md-mt-0">{{ object.population }}</h4> <h4 class="md-mt-0">{{ experiment.population }}</h4>
<p><strong>{{ experiment.proposed_start_date }} - {{ experiment.proposed_end_date }}</strong></p>
</div> </div>
<div class="col-md-12 md-mt-10"> <div class="col-md-12">
{{ object.short_description|linebreaks }} {{ experiment.short_description|linebreaks }}
</div> </div>
{% endif %} {% endif %}
</div> </div>
<div class="row md-mt-20"> <div class="row md-mt-20">
<h4 class="col-md-8"> <h4 class="col-md-8">
{% if not object.completed_variants %} {% if not experiment.completed_variants %}
<span class="icon-warning glyphicon glyphicon-exclamation-sign"></span> <span class="icon-warning glyphicon glyphicon-exclamation-sign"></span>
{% endif %} {% endif %}
Firefox Pref &amp; Branches Firefox Pref &amp; Branches
@ -60,31 +61,31 @@
{% if experiment.is_draft %} {% if experiment.is_draft %}
<div class="col-md-4 text-right"> <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> </div>
{% endif %} {% endif %}
</div> </div>
<div class="row card md-pt-15 md-pb-10"> <div class="row card md-pt-15 md-pb-10">
{% if object.variants.all %} {% if experiment.variants.all %}
{% for variant in object.variants.all %} {% for variant in experiment.variants.all %}
<div class="col-md-12 {% if not forloop.last %}md-mb-15{% endif %}"> <div class="col-md-12 {% if not forloop.last %}md-mb-15{% endif %}">
<h4 class="md-mt-0">{{ variant.ratio }}% {{ variant.name }}</h4> <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> <p>{{ variant.description }}</p>
</div> </div>
{% endfor %} {% endfor %}
{% else %} {% 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 %} {% endif %}
</div> </div>
<div class="row md-mt-20"> <div class="row md-mt-20">
<h4 class="col-md-8"> <h4 class="col-md-8">
{% if not object.completed_objectives %} {% if not experiment.completed_objectives %}
<span class="icon-warning glyphicon glyphicon-exclamation-sign"></span> <span class="icon-warning glyphicon glyphicon-exclamation-sign"></span>
{% endif %} {% endif %}
Objectives Objectives
@ -92,24 +93,24 @@
{% if experiment.is_draft %} {% if experiment.is_draft %}
<div class="col-md-4 text-right"> <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> </div>
{% endif %} {% endif %}
</div> </div>
<div class="row card md-pt-15 md-pb-10"> <div class="row card md-pt-15 md-pb-10">
<div class="col-md-12"> <div class="col-md-12">
{% if object.completed_objectives %} {% if experiment.completed_objectives %}
{{ object.objectives|linebreaks }} {{ experiment.objectives|linebreaks }}
{% else %} {% 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 %} {% endif %}
</div> </div>
</div> </div>
<div class="row md-mt-20"> <div class="row md-mt-20">
<h4 class="col-md-8"> <h4 class="col-md-8">
{% if not object.completed_objectives %} {% if not experiment.completed_objectives %}
<span class="icon-warning glyphicon glyphicon-exclamation-sign"></span> <span class="icon-warning glyphicon glyphicon-exclamation-sign"></span>
{% endif %} {% endif %}
Analysis Analysis
@ -117,25 +118,25 @@
{% if experiment.is_draft %} {% if experiment.is_draft %}
<div class="col-md-4 text-right"> <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> </div>
{% endif %} {% endif %}
</div> </div>
<div class="row card md-pt-15 md-pb-10"> <div class="row card md-pt-15 md-pb-10">
<div class="col-md-12"> <div class="col-md-12">
{% if object.completed_objectives %} {% if experiment.completed_objectives %}
{{ object.analysis|linebreaks }} {{ experiment.analysis|linebreaks }}
{% else %} {% 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 %} {% endif %}
</div> </div>
</div> </div>
<div class="row md-mt-20"> <div class="row md-mt-20">
<h4 class="col-md-8"> <h4 class="col-md-8">
{% if not object.completed_risks %} {% if not experiment.completed_risks %}
<span class="icon-warning glyphicon glyphicon-exclamation-sign"></span> <span class="icon-warning glyphicon glyphicon-exclamation-sign"></span>
{% endif %} {% endif %}
Risk Assessment Risk Assessment
@ -143,42 +144,42 @@
{% if experiment.is_draft %} {% if experiment.is_draft %}
<div class="col-md-4 text-right"> <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> </div>
{% endif %} {% endif %}
</div> </div>
<div class="row card md-pt-15 md-pb-10"> <div class="row card md-pt-15 md-pb-10">
<div class="col-md-12"> <div class="col-md-12">
{% if object.completed_risks %} {% if experiment.completed_risks %}
<p><strong>{{ object.RISK_PARTNER_RELATED_LABEL }}</strong></p> <p><strong>{{ experiment.RISK_PARTNER_RELATED_LABEL }}</strong></p>
<p>{{ object.risk_partner_related|yesno:"Yes,No" }}</p> <p>{{ experiment.risk_partner_related|yesno:"Yes,No" }}</p>
<p><strong>{{ object.RISK_BRAND_LABEL }}</strong></p> <p><strong>{{ experiment.RISK_BRAND_LABEL }}</strong></p>
<p>{{ object.risk_brand|yesno:"Yes,No" }}</p> <p>{{ experiment.risk_brand|yesno:"Yes,No" }}</p>
<p><strong>{{ object.RISK_FAST_SHIPPED_LABEL }}</strong></p> <p><strong>{{ experiment.RISK_FAST_SHIPPED_LABEL }}</strong></p>
<p>{{ object.risk_fast_shipped|yesno:"Yes,No" }}</p> <p>{{ experiment.risk_fast_shipped|yesno:"Yes,No" }}</p>
<p><strong>{{ object.RISK_CONFIDENTIAL_LABEL }}</strong></p> <p><strong>{{ experiment.RISK_CONFIDENTIAL_LABEL }}</strong></p>
<p>{{ object.risk_confidential|yesno:"Yes,No" }}</p> <p>{{ experiment.risk_confidential|yesno:"Yes,No" }}</p>
<p><strong>{{ object.RISK_RELEASE_POPULATION_LABEL }}</strong></p> <p><strong>{{ experiment.RISK_RELEASE_POPULATION_LABEL }}</strong></p>
<p>{{ object.risk_release_population|yesno:"Yes,No" }}</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> <h5>RASCI Owners and Deliverables</h5>
{{ object.risks|linebreaks }} {{ experiment.risks|linebreaks }}
{% endif %} {% endif %}
{% else %} {% 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 %} {% endif %}
</div> </div>
</div> </div>
<div class="row md-mt-20"> <div class="row md-mt-20">
<h4 class="col-md-8"> <h4 class="col-md-8">
{% if not object.completed_risks %} {% if not experiment.completed_risks %}
<span class="icon-warning glyphicon glyphicon-exclamation-sign"></span> <span class="icon-warning glyphicon glyphicon-exclamation-sign"></span>
{% endif %} {% endif %}
Testing Plan Testing Plan
@ -186,17 +187,17 @@
{% if experiment.is_draft %} {% if experiment.is_draft %}
<div class="col-md-4 text-right"> <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> </div>
{% endif %} {% endif %}
</div> </div>
<div class="row card md-pt-15 md-pb-10"> <div class="row card md-pt-15 md-pb-10">
<div class="col-md-12"> <div class="col-md-12">
{% if object.completed_risks %} {% if experiment.completed_risks %}
{{ object.testing|linebreaks }} {{ experiment.testing|linebreaks }}
{% else %} {% 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 %} {% endif %}
</div> </div>
</div> </div>
@ -206,7 +207,7 @@
<div class="col-md-3"> <div class="col-md-3">
{% if experiment.is_draft %} {% if experiment.is_draft %}
{% if object.is_ready_for_review %} {% if experiment.is_ready_for_review %}
<form <form
action="{% url "experiments-status-update" slug=experiment.slug %}" action="{% url "experiments-status-update" slug=experiment.slug %}"
method="POST" method="POST"
@ -253,7 +254,7 @@
{% endif %} {% endif %}
<h5>History</h5> <h5>History</h5>
{% for change in object.changes.all reversed %} {% for change in experiment.changes.all reversed %}
<div class="row help-block"> <div class="row help-block">
<div class="col-md-12"> <div class="col-md-12">
<p>{{ change.changed_on.date }}</p> <p>{{ change.changed_on.date }}</p>

Просмотреть файл

@ -1,7 +1,7 @@
{% extends "experiments/edit_base.html" %} {% extends "experiments/edit_base.html" %}
{% load static %} {% load static %}
{% block edit_title %} {% block edit_title %}
{% if object %} {% if object %}
Edit {{ object.name }} Edit {{ object.name }}
@ -15,22 +15,24 @@
{% endblock %} {% endblock %}
{% block edit_form %} {% block edit_form %}
<form <form
class="form-horizontal" class="form-horizontal"
method="POST" method="POST"
enctype='multipart/form-data' enctype='multipart/form-data'
> >
{% csrf_token %} {% 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.name %}
{% include "experiments/field_inline.html" with field=form.short_description %} {% include "experiments/field_inline.html" with field=form.short_description %}
<div class="form-group"> <div class="form-group">
<div class="{% if form.errors.population_percent %}has-error{% endif %}"> <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> <label class="col-md-3 control-label" for="{{ form.population_percent.id_for_label }}">{{ form.population_percent.label }}</label>
<div class="col-md-2 "> <div class="col-md-2 ">
{{ form.population_percent }} {{ form.population_percent }}
</div> </div>
</div> </div>
<div class="col-md-1"> <div class="col-md-1">
@ -45,7 +47,7 @@
{% if form.errors.population_percent %} {% if form.errors.population_percent %}
<div class="col-md-9 col-md-offset-3 has-error text-right"> <div class="col-md-9 col-md-offset-3 has-error text-right">
{% for error in form.errors.population_percent %} {% 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 %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
@ -58,9 +60,9 @@
</div> </div>
{% include "experiments/field_inline.html" with field=form.client_matching %} {% 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_start_date %}
{% include "experiments/field_inline.html" with field=form.proposed_end_date %} {% include "experiments/field_inline.html" with field=form.proposed_end_date %}
<div class="form-group"> <div class="form-group">
@ -79,7 +81,7 @@
{% block edit_info %} {% block edit_info %}
<h4><span class="glyphicon glyphicon-info-sign"></span> Getting Started</h4> <h4><span class="glyphicon glyphicon-info-sign"></span> Getting Started</h4>
<p> <p>
Your experiment will start as a draft. Your experiment will start as a draft.
</p> </p>
<p> <p>
Fill out the information on this page to save your draft. Fill out the information on this page to save your draft.
@ -89,7 +91,7 @@
now or later. now or later.
</p> </p>
<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. launch your experiment to Shield.
</p> </p>
{% endblock %} {% endblock %}

Просмотреть файл

@ -44,6 +44,7 @@
<div class="col-md-8"> <div class="col-md-8">
<h4 class="md-mt-0"> <h4 class="md-mt-0">
{{ experiment.name }} {{ experiment.name }}
<span class="badge status-color-{{ experiment.status }}">{{ experiment.status }}</span>
</h4> </h4>
</div> </div>
</div> </div>
@ -52,22 +53,14 @@
<div class="col-md-8"> <div class="col-md-8">
<h5> <h5>
<span class="badge status-color-{{ experiment.status }}">{{ experiment.status }}</span> Owner: {{ experiment.owner }}
by
{{ experiment.changes.latest.changed_by }}
on
{{ experiment.changes.latest.changed_on.date }}
</h5> </h5>
{{ experiment.short_description|linebreaks }}
</div> </div>
<div class="col-md-4 text-right"> <div class="col-md-4 text-right">
<h4> <h4>{{ experiment.population }}</h4>
{{ experiment.population }} <p><strong>{{ experiment.proposed_start_date }} - {{ experiment.proposed_end_date }}</strong></p>
</h4>
</div>
<div class="col-md-12 md-mt-5">
<p>{{ experiment.short_description }}</p>
</div> </div>
</div> </div>