Skip to content

Commit 4be41e6

Browse files
committed
feat(nimbus): add results to new nimbus ui
Because * We need to add a results page to the new Nimbus UI * We can use the existing results page until we have a more suitable replacement This commit * Makes a copy of the nimbus-ui React app called results * Removes all components except those necessary for the results page * Adds all of the Makefile entry points to test, lint, etc the new results app * Adds all of the build/copy steps for the new results app to the Dockerfile * Adds a new url/view for the results page in nimbus_ui_new fixes #12707
1 parent 4750e70 commit 4be41e6

File tree

157 files changed

+25349
-22
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

157 files changed

+25349
-22
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ experimenter/experimenter/reporting/reporting-ui/assets/
9494
.tmontmp
9595
experimenter/coverage_html_report/
9696
experimenter/tests/integration/test-reports/
97+
junit.xml
98+
**/coverage_report/
9799

98100
# Dependencies
99101
node_modules

Makefile

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,22 @@ PYTHON_MIGRATE = python manage.py migrate
3737
ESLINT_LEGACY = yarn workspace @experimenter/core lint
3838
ESLINT_FIX_CORE = yarn workspace @experimenter/core lint-fix
3939
ESLINT_NIMBUS_UI = yarn workspace @experimenter/nimbus-ui lint
40+
ESLINT_RESULTS = yarn workspace @experimenter/results lint
4041
ESLINT_FIX_NIMBUS_UI = yarn workspace @experimenter/nimbus-ui lint-fix
42+
ESLINT_FIX_RESULTS = yarn workspace @experimenter/results lint-fix
4143
ESLINT_NIMBUS_UI_NEW = yarn workspace @experimenter/nimbus_ui_new lint
4244
ESLINT_FIX_NIMBUS_UI_NEW = yarn workspace @experimenter/nimbus_ui_new format
4345
TYPECHECK_NIMBUS_UI = yarn workspace @experimenter/nimbus-ui lint:tsc
46+
TYPECHECK_RESULTS = yarn workspace @experimenter/results lint:tsc
4447
DJLINT_CHECK = djlint --check experimenter/nimbus_ui_new/
4548
DJLINT_FIX = djlint --reformat experimenter/nimbus_ui_new/
4649
JS_TEST_LEGACY = yarn workspace @experimenter/core test
4750
JS_TEST_NIMBUS_UI = DEBUG_PRINT_LIMIT=999999 CI=yes yarn workspace @experimenter/nimbus-ui test:cov
51+
JS_TEST_RESULTS = DEBUG_PRINT_LIMIT=999999 CI=yes yarn workspace @experimenter/results test:cov
4852
NIMBUS_SCHEMA_CHECK = python manage.py graphql_schema --out experimenter/nimbus-ui/test_schema.graphql&&diff experimenter/nimbus-ui/test_schema.graphql experimenter/nimbus-ui/schema.graphql || (echo GraphQL Schema is out of sync please run make generate_types;exit 1)
53+
RESULTS_SCHEMA_CHECK = python manage.py graphql_schema --out experimenter/results/test_schema.graphql&&diff experimenter/results/test_schema.graphql experimenter/results/schema.graphql || (echo GraphQL Schema is out of sync please run make generate_types;exit 1)
4954
NIMBUS_TYPES_GENERATE = python manage.py graphql_schema --out experimenter/nimbus-ui/schema.graphql&&yarn workspace @experimenter/nimbus-ui generate-types
55+
RESULTS_TYPES_GENERATE = python manage.py graphql_schema --out experimenter/results/schema.graphql&&yarn workspace @experimenter/results generate-types
5056
RUFF_CHECK = ruff check experimenter/ tests/
5157
RUFF_FIX = ruff check --fix experimenter/ tests/
5258
RUFF_FORMAT_CHECK = ruff format --check --diff . --exclude node_modules
@@ -164,7 +170,7 @@ kill: compose_stop compose_rm docker_prune ## Stop, remove, and prune container
164170

165171
lint: build_test ## Running linting on source code
166172
-docker rm experimenter_test;
167-
$(COMPOSE_TEST_RUN) experimenter sh -c '$(WAIT_FOR_DB) (${PARALLEL} "$(NIMBUS_SCHEMA_CHECK)" "$(PYTHON_CHECK_MIGRATIONS)" "$(CHECK_DOCS)" "$(RUFF_FORMAT_CHECK)" "$(RUFF_CHECK)" "$(DJLINT_CHECK)" "$(ESLINT_LEGACY)" "$(ESLINT_NIMBUS_UI)" "$(ESLINT_NIMBUS_UI_NEW)" "$(TYPECHECK_NIMBUS_UI)" "$(PYTHON_TYPECHECK)" "$(PYTHON_TEST)" "$(JS_TEST_LEGACY)" "$(JS_TEST_NIMBUS_UI)" "$(JS_TEST_REPORTING)") ${COLOR_CHECK}'
173+
$(COMPOSE_TEST_RUN) experimenter sh -c '$(WAIT_FOR_DB) (${PARALLEL} "$(NIMBUS_SCHEMA_CHECK)" "$(PYTHON_CHECK_MIGRATIONS)" "$(CHECK_DOCS)" "$(RUFF_FORMAT_CHECK)" "$(RUFF_CHECK)" "$(DJLINT_CHECK)" "$(ESLINT_LEGACY)" "$(ESLINT_NIMBUS_UI)" "$(ESLINT_RESULTS)" "$(ESLINT_NIMBUS_UI_NEW)" "$(TYPECHECK_NIMBUS_UI)" "$(PYTHON_TYPECHECK)" "$(PYTHON_TEST)" "$(JS_TEST_LEGACY)" "$(JS_TEST_NIMBUS_UI)" "$(JS_TEST_RESULTS)" "$(JS_TEST_REPORTING)") ${COLOR_CHECK}'
168174

169175
check: lint
170176

@@ -212,7 +218,7 @@ generate_types: build_dev
212218
$(COMPOSE_RUN) experimenter sh -c "$(NIMBUS_TYPES_GENERATE)"
213219

214220
format: build_dev ## Format source tree
215-
$(COMPOSE_RUN) experimenter sh -c '${PARALLEL} "$(RUFF_FIX);$(DJLINT_FIX);$(RUFF_FORMAT_FIX)" "$(ESLINT_FIX_CORE)" "$(ESLINT_FIX_NIMBUS_UI)" "$(ESLINT_FIX_NIMBUS_UI_NEW)"'
221+
$(COMPOSE_RUN) experimenter sh -c '${PARALLEL} "$(RUFF_FIX);$(DJLINT_FIX);$(RUFF_FORMAT_FIX)" "$(ESLINT_FIX_CORE)" "$(ESLINT_FIX_NIMBUS_UI)" "$(ESLINT_FIX_RESULTS)" "$(ESLINT_FIX_NIMBUS_UI_NEW)"'
216222
code_format: format
217223

218224
makemigrations: build_dev

docker-compose.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,32 @@ services:
5757
- /experimenter/experimenter/legacy/legacy-ui/core/.cache/
5858
- /experimenter/experimenter/legacy/legacy-ui/core/node_modules/
5959
- /experimenter/experimenter/nimbus-ui/node_modules/
60+
- /experimenter/experimenter/results/node_modules/
6061
- /experimenter/experimenter/nimbus_ui_new/static/node_modules/
6162
- /experimenter/experimenter/served/
6263
- /experimenter/node_modules/
6364
- ${GOOGLE_ADC_FILE}:${GOOGLE_APPLICATION_CREDENTIALS}:ro
6465
command: bash -c "FORCE_COLOR=true yarn workspace @experimenter/nimbus-ui start | cat"
6566

67+
yarn-results:
68+
image: experimenter:dev
69+
env_file: .env
70+
tty: true
71+
ports:
72+
- "3001:3000"
73+
volumes:
74+
- ./experimenter:/experimenter
75+
- media_volume:/experimenter/experimenter/media
76+
- /experimenter/experimenter/legacy/legacy-ui/core/.cache/
77+
- /experimenter/experimenter/legacy/legacy-ui/core/node_modules/
78+
- /experimenter/experimenter/nimbus-ui/node_modules/
79+
- /experimenter/experimenter/results/node_modules/
80+
- /experimenter/experimenter/nimbus_ui_new/static/node_modules/
81+
- /experimenter/experimenter/served/
82+
- /experimenter/node_modules/
83+
- ${GOOGLE_ADC_FILE}:${GOOGLE_APPLICATION_CREDENTIALS}:ro
84+
command: bash -c "FORCE_COLOR=true yarn workspace @experimenter/results start | cat"
85+
6686
worker:
6787
image: experimenter:dev
6888
env_file: .env

experimenter/Dockerfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,13 @@ COPY ./package.json /experimenter/package.json
5252
COPY ./yarn.lock /experimenter/yarn.lock
5353
COPY ./experimenter/legacy/legacy-ui/core/package.json /experimenter/experimenter/legacy/legacy-ui/core/package.json
5454
COPY ./experimenter/nimbus-ui/package.json /experimenter/experimenter/nimbus-ui/package.json
55+
COPY ./experimenter/results/package.json /experimenter/experimenter/results/package.json
5556
COPY ./experimenter/nimbus_ui_new/static/package.json /experimenter/experimenter/nimbus_ui_new/static/package.json
5657
RUN python3 -m pip install setuptools
5758
RUN yarn install --frozen-lockfile
5859
COPY ./experimenter/legacy/legacy-ui/core/ /experimenter/experimenter/legacy/legacy-ui/core/
5960
COPY ./experimenter/nimbus-ui/ /experimenter/experimenter/nimbus-ui/
61+
COPY ./experimenter/results/ /experimenter/experimenter/results/
6062
COPY ./experimenter/nimbus_ui_new/ /experimenter/experimenter/nimbus_ui_new/
6163

6264

@@ -76,6 +78,7 @@ COPY --from=python-builder /usr/local/lib/python3.13/site-packages/ /usr/local/l
7678
# Node packages
7779
COPY --from=node-builder /experimenter/experimenter/legacy/legacy-ui/core/node_modules/ /experimenter/experimenter/legacy/legacy-ui/core/node_modules/
7880
COPY --from=node-builder /experimenter/experimenter/nimbus-ui/node_modules/ /experimenter/experimenter/nimbus-ui/node_modules/
81+
COPY --from=node-builder /experimenter/experimenter/results/node_modules/ /experimenter/experimenter/results/node_modules/
7982
COPY --from=node-builder /experimenter/experimenter/nimbus_ui_new/static/node_modules/ /experimenter/experimenter/nimbus_ui_new/static/node_modules/
8083
COPY --from=node-builder /experimenter/node_modules/ /experimenter/node_modules/
8184

@@ -107,6 +110,10 @@ RUN yarn workspace @experimenter/core build
107110
COPY ./experimenter/nimbus-ui/ /experimenter/experimenter/nimbus-ui/
108111
RUN yarn workspace @experimenter/nimbus-ui build
109112

113+
# Build results assets
114+
COPY ./experimenter/results/ /experimenter/experimenter/results/
115+
RUN yarn workspace @experimenter/results build
116+
110117
# Build nimbus_ui_new assets
111118
COPY ./experimenter/nimbus_ui_new/ /experimenter/experimenter/nimbus_ui_new/
112119
RUN yarn workspace @experimenter/nimbus_ui_new build
@@ -140,6 +147,7 @@ COPY ./experimenter/ /experimenter/experimenter/
140147
COPY ./manifesttool/ /experimenter/manifesttool/
141148
COPY --from=ui /experimenter/experimenter/legacy/legacy-ui/assets/ /experimenter/experimenter/legacy/legacy-ui/assets/
142149
COPY --from=ui /experimenter/experimenter/nimbus-ui/build/ /experimenter/experimenter/nimbus-ui/build/
150+
COPY --from=ui /experimenter/experimenter/results/build/ /experimenter/experimenter/results/build/
143151
COPY --from=ui /experimenter/experimenter/nimbus_ui_new/static/dist/ /experimenter/experimenter/nimbus_ui_new/static/dist/
144152

145153
ENV PYTHONPATH=$PYTHONPATH:/application-services/

experimenter/experimenter/experiments/models.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,9 @@ def get_update_audience_url(self):
487487
def get_detail_preview_recipe_json_url(self):
488488
return f"{self.get_detail_url()}#preview-recipe-json"
489489

490+
def get_results_url(self):
491+
return reverse("nimbus-new-results", kwargs={"slug": self.slug})
492+
490493
@property
491494
def experiment_url(self):
492495
return urljoin(f"https://{settings.HOSTNAME}", self.get_absolute_url())
@@ -1365,6 +1368,10 @@ def has_displayable_results(self):
13651368
def show_results_url(self):
13661369
return self.has_displayable_results and self.results_ready and not self.is_rollout
13671370

1371+
@property
1372+
def disable_results_link(self):
1373+
return not self.show_results_url
1374+
13681375
@property
13691376
def results_expected_date(self):
13701377
if not self.is_rollout:

experimenter/experimenter/nimbus_ui_new/templates/experimenter_base.html

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,27 @@
1515
| Experimenter
1616
</title>
1717
<script src="{% static 'nimbus_ui_new/app.bundle.js' %}"></script>
18+
{% block extra_head %}
19+
{% endblock extra_head %}
20+
1821
</head>
19-
<body
20-
{# djlint:off #}
21-
id="{% block page_id %}{% endblock %}"
22-
{# djlint:on #}
23-
class="bg-body-tertiary">
24-
<div class="container-fluid bg-body border-bottom border-1 mb-4 py-1">
25-
{% include "common/header.html" %}
22+
<body {# djlint:off #}
23+
id="{% block page_id %}{% endblock %}"
24+
{# djlint:on #}
25+
class="bg-body-tertiary">
26+
<div class="container-fluid bg-body border-bottom border-1 mb-4 py-1">
27+
{% include "common/header.html" %}
2628

27-
</div>
28-
<div class="container-fluid">
29-
{% block content %}
30-
{% endblock content %}
29+
</div>
30+
<div class="container-fluid">
31+
{% block content %}
32+
{% endblock content %}
3133

32-
{% include "common/footer.html" %}
34+
{% include "common/footer.html" %}
3335

34-
</div>
35-
{% block extrascripts %}
36-
{% endblock extrascripts %}
36+
</div>
37+
{% block extrascripts %}
38+
{% endblock extrascripts %}
3739

38-
</body>
40+
</body>
3941
</html>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{% extends "nimbus_experiments/experiment_base.html" %}
2+
3+
{% load static %}
4+
{% load nimbus_extras %}
5+
6+
{% block title %}{{ experiment.name }}{% endblock %}
7+
8+
{% block extra_head %}
9+
{% if not USE_YARN_DEV %}
10+
<link rel="stylesheet" href="{% static 'results/static/css/main.css' %}" />
11+
{% endif %}
12+
{% endblock extra_head %}
13+
14+
{% block main_content %}
15+
<div id="root" data-config="{{ APP_CONFIG }}"></div>
16+
{% endblock main_content %}
17+
18+
{% block extrascripts %}
19+
{% if USE_YARN_DEV %}
20+
<script src="http://localhost:3001/static/js/main.js"></script>
21+
{% else %}
22+
<script src="{% static 'results/static/js/main.js' %}"></script>
23+
{% endif %}
24+
{% endblock extrascripts %}

experimenter/experimenter/nimbus_ui_new/templates/nimbus_experiments/sidebar.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div class="nav flex-column nav-pills fw-medium w-100">
22
{% include "common/sidebar_link.html" with title="Summary" link=experiment.get_detail_url icon="fa-regular fa-paper-plane" %}
33
{% include "common/sidebar_link.html" with title="History" link=experiment.get_history_url icon="fa-solid fa-network-wired" active=True %}
4-
{% include "common/sidebar_link.html" with title="Results" link="" icon="fa-solid fa-chart-column" disabled=True %}
4+
{% include "common/sidebar_link.html" with title="Results" link=experiment.get_results_url icon="fa-solid fa-chart-column" disabled=experiment.disable_results_link %}
55

66
<strong class="ms-3">Edit</strong>
77
<hr class="my-0 mb-2">

experimenter/experimenter/nimbus_ui_new/tests/test_views.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2367,3 +2367,17 @@ def test_get_redirects_to_next_step(self, current_url, next_url, data):
23672367
response.headers["HX-Redirect"],
23682368
reverse(next_url, kwargs={"slug": experiment.slug}),
23692369
)
2370+
2371+
2372+
class TestResultsView(AuthTestCase):
2373+
def test_render_to_response(self):
2374+
experiment = NimbusExperimentFactory.create_with_lifecycle(
2375+
NimbusExperimentFactory.Lifecycles.ENDING_APPROVE_APPROVE,
2376+
)
2377+
2378+
response = self.client.get(
2379+
reverse("nimbus-new-results", kwargs={"slug": experiment.slug}),
2380+
)
2381+
self.assertEqual(response.status_code, 200)
2382+
self.assertEqual(response.context["experiment"], experiment)
2383+
self.assertTemplateUsed(response, "nimbus_experiments/results.html")

experimenter/experimenter/nimbus_ui_new/urls.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
PreviewToDraftView,
2828
PreviewToReviewView,
2929
QAStatusUpdateView,
30+
ResultsView,
3031
ReviewToApproveView,
3132
ReviewToDraftView,
3233
SignoffUpdateView,
@@ -208,4 +209,9 @@
208209
CancelEndExperimentView.as_view(),
209210
name="nimbus-new-cancel-end-experiment",
210211
),
212+
re_path(
213+
r"^(?P<slug>[\w-]+)/results/.*",
214+
ResultsView.as_view(),
215+
name="nimbus-new-results",
216+
),
211217
]

0 commit comments

Comments
 (0)