feat(nimbus): Enrollment and complete days (#11711)
Because - We are not showing days (enrollment days and total duration of the experiment) on the new summary page This commit - Add enrollment days - Add total duration of the experiment Fixes #1 ![Screenshot 2024-11-06 at 12 45 37 PM](https://github.com/user-attachments/assets/5f0580bf-947a-418c-96f3-4c170d46c5c4) 1710
This commit is contained in:
Родитель
b52694d7a8
Коммит
ab212df776
|
@ -818,7 +818,8 @@ Optional - We believe this outcome will <describe impact> on <core metric>
|
|||
WARNING_PREF_FLIPS_PREF_CONTROLLED_BY_FEATURE = (
|
||||
"Pref '{pref}' is controlled by a variable in feature {feature_config_slug}'"
|
||||
)
|
||||
ENROLLMENT_END = "Enrollment End"
|
||||
OBSERVATION = "Observation"
|
||||
ENROLLMENT = "Enrollment"
|
||||
|
||||
|
||||
RISK_QUESTIONS = {
|
||||
|
|
|
@ -628,24 +628,34 @@ class NimbusExperiment(NimbusConstants, TargetingConstants, FilterMixin, models.
|
|||
|
||||
@property
|
||||
def is_draft(self):
|
||||
return self.status == self.Status.DRAFT
|
||||
return (
|
||||
self.status == self.Status.DRAFT
|
||||
and self.publish_status == self.PublishStatus.IDLE
|
||||
)
|
||||
|
||||
@property
|
||||
def is_review(self):
|
||||
return self.is_draft and self.publish_status == self.PublishStatus.REVIEW
|
||||
return self.status == self.Status.DRAFT and self.publish_status in [
|
||||
self.PublishStatus.REVIEW,
|
||||
self.PublishStatus.WAITING,
|
||||
]
|
||||
|
||||
@property
|
||||
def is_preview(self):
|
||||
return self.status == self.Status.PREVIEW
|
||||
|
||||
@property
|
||||
def is_live(self):
|
||||
return self.status == self.Status.LIVE
|
||||
def is_enrollment(self):
|
||||
return self.status == self.Status.LIVE and not self.is_paused_published
|
||||
|
||||
@property
|
||||
def is_complete(self):
|
||||
return self.status == self.Status.COMPLETE
|
||||
|
||||
@property
|
||||
def is_observation(self):
|
||||
return self._enrollment_end_date is not None and not self.is_complete
|
||||
|
||||
@property
|
||||
def is_started(self):
|
||||
return self.status in (self.Status.LIVE, self.Status.COMPLETE)
|
||||
|
@ -806,41 +816,57 @@ class NimbusExperiment(NimbusConstants, TargetingConstants, FilterMixin, models.
|
|||
return (self.computed_end_date - self.enrollment_start_date).days
|
||||
return self.proposed_duration
|
||||
|
||||
@property
|
||||
def computed_observations_days(self):
|
||||
if (
|
||||
enrollment_end_date := (
|
||||
self.actual_enrollment_end_date or self.computed_enrollment_end_date
|
||||
)
|
||||
) and self.computed_end_date:
|
||||
return (self.computed_end_date - enrollment_end_date).days
|
||||
return None
|
||||
|
||||
def timeline(self):
|
||||
timeline_entries = [
|
||||
{
|
||||
"label": self.Status.DRAFT,
|
||||
"date": self.draft_date,
|
||||
"is_active": self.is_draft,
|
||||
"days": None,
|
||||
},
|
||||
{
|
||||
"label": self.Status.PREVIEW,
|
||||
"date": self.preview_date,
|
||||
"is_active": self.is_preview,
|
||||
"days": None,
|
||||
},
|
||||
{
|
||||
"label": self.PublishStatus.REVIEW,
|
||||
"date": self.review_date,
|
||||
"is_active": self.is_review,
|
||||
"days": None,
|
||||
},
|
||||
{
|
||||
"label": self.Status.LIVE,
|
||||
"label": NimbusConstants.ENROLLMENT,
|
||||
"date": self.start_date,
|
||||
"is_active": self.is_live,
|
||||
"is_active": self.is_enrollment,
|
||||
"days": self.computed_enrollment_days,
|
||||
},
|
||||
{
|
||||
"label": self.Status.COMPLETE,
|
||||
"date": self.computed_end_date,
|
||||
"is_active": self.is_complete,
|
||||
"days": self.computed_duration_days,
|
||||
},
|
||||
]
|
||||
if not self.is_rollout:
|
||||
timeline_entries.insert(
|
||||
4,
|
||||
{
|
||||
"label": NimbusConstants.ENROLLMENT_END,
|
||||
"label": NimbusConstants.OBSERVATION,
|
||||
"date": self._enrollment_end_date,
|
||||
"is_active": self._enrollment_end_date is not None,
|
||||
"is_active": self.is_observation,
|
||||
"days": self.computed_observations_days,
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
@ -1689,7 +1689,11 @@ class TestNimbusExperiment(TestCase):
|
|||
|
||||
def test_timeline_dates_includes_correct_status_dates_and_flags(self):
|
||||
experiment = NimbusExperimentFactory.create_with_lifecycle(
|
||||
lifecycle=NimbusExperimentFactory.Lifecycles.LIVE_APPROVE,
|
||||
lifecycle=NimbusExperimentFactory.Lifecycles.ENDING_APPROVE_APPROVE,
|
||||
proposed_enrollment=2,
|
||||
start_date=datetime.date(2023, 1, 4),
|
||||
_enrollment_end_date=datetime.date(2023, 1, 6),
|
||||
end_date=datetime.date(2023, 1, 8),
|
||||
)
|
||||
NimbusChangeLogFactory.create(
|
||||
experiment=experiment,
|
||||
|
@ -1701,14 +1705,14 @@ class TestNimbusExperiment(TestCase):
|
|||
experiment=experiment,
|
||||
old_status=NimbusExperiment.Status.DRAFT,
|
||||
new_status=NimbusExperiment.Status.PREVIEW,
|
||||
changed_on=datetime.datetime(2023, 3, 1),
|
||||
changed_on=datetime.datetime(2023, 1, 2),
|
||||
)
|
||||
|
||||
NimbusChangeLogFactory.create(
|
||||
experiment=experiment,
|
||||
old_publish_status=NimbusExperiment.Status.PREVIEW,
|
||||
new_publish_status=NimbusExperiment.PublishStatus.REVIEW,
|
||||
changed_on=datetime.datetime(2023, 4, 1),
|
||||
changed_on=datetime.datetime(2023, 1, 3),
|
||||
)
|
||||
timeline = experiment.timeline()
|
||||
expected_timeline = [
|
||||
|
@ -1716,33 +1720,45 @@ class TestNimbusExperiment(TestCase):
|
|||
"label": "Draft",
|
||||
"date": experiment.draft_date,
|
||||
"is_active": False,
|
||||
"days": None,
|
||||
},
|
||||
{
|
||||
"label": "Preview",
|
||||
"date": experiment.preview_date,
|
||||
"is_active": False,
|
||||
"days": None,
|
||||
},
|
||||
{
|
||||
"label": "Review",
|
||||
"date": experiment.review_date,
|
||||
"is_active": False,
|
||||
"days": None,
|
||||
},
|
||||
{"label": "Live", "date": experiment.start_date, "is_active": True},
|
||||
{
|
||||
"label": NimbusConstants.ENROLLMENT_END,
|
||||
"label": NimbusConstants.ENROLLMENT,
|
||||
"date": experiment.start_date,
|
||||
"is_active": False,
|
||||
"days": 2,
|
||||
},
|
||||
{
|
||||
"label": NimbusConstants.OBSERVATION,
|
||||
"date": experiment._enrollment_end_date,
|
||||
"is_active": False,
|
||||
"days": 2,
|
||||
},
|
||||
{
|
||||
"label": "Complete",
|
||||
"date": experiment.computed_end_date,
|
||||
"is_active": False,
|
||||
"is_active": True,
|
||||
"days": 4,
|
||||
},
|
||||
]
|
||||
|
||||
for i, expected in enumerate(expected_timeline):
|
||||
self.assertEqual(timeline[i]["label"], expected["label"])
|
||||
self.assertEqual(timeline[i]["date"], expected["date"])
|
||||
self.assertEqual(timeline[i]["is_active"], expected["is_active"])
|
||||
self.assertEqual(timeline[i].get("days"), expected["days"])
|
||||
|
||||
def test_timeline_dates_complete_is_active_when_status_is_complete(self):
|
||||
experiment = NimbusExperimentFactory.create_with_lifecycle(
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<li class="list-group-item flex-fill text-center d-flex flex-column justify-content-center {% if status.is_active %}bg-primary text-white{% endif %}">
|
||||
<strong>{{ status.label }}</strong>
|
||||
<small>{{ status.date|default:'---' }}</small>
|
||||
{% if status.days is not None %}<small>{{ status.days }} day{{ status.days|pluralize }}</small>{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
|
Загрузка…
Ссылка в новой задаче