Skip to content

Commit 67945f9

Browse files
authored
Merge pull request #80 from wagtail-nest/feature/79-refactor-create-test-form
Refactor create test form
2 parents 91d0e0c + 7e5bb95 commit 67945f9

File tree

3 files changed

+98
-89
lines changed

3 files changed

+98
-89
lines changed

wagtail_ab_testing/static_src/components/GoalSelector/index.tsx

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ const Field = styled.div<FieldProps>`
113113
display: ${(props) => (props.visible != false ? 'block' : 'none')};
114114
`;
115115

116+
const RequiredMark = () => <span className="w-required-mark">*</span>;
117+
116118
interface GoalSelectorProps {
117119
goalTypesByPageType: {
118120
[pageType: string]: {
@@ -148,38 +150,54 @@ const GoalSelector: FunctionComponent<GoalSelectorProps> = ({
148150

149151
return (
150152
<div>
151-
<Field>
152-
<SunkenLabel>
153+
<Field className="w-panel__wrapper">
154+
<SunkenLabel className="w-field__label">
153155
{gettext('Which page is the goal on?')}
154156
</SunkenLabel>
155157
<GoalPageSelector onChangeSelectedPage={onChangeSelectedPage} />
156158
</Field>
157-
<Field visible={!!goalTypes}>
158-
<SunkenLabel>{gettext('What is the goal?')}</SunkenLabel>
159-
<select name="goal_event">
160-
<option key="" value="">
161-
Choose a goal
162-
</option>
163-
{goalTypes.map(({ slug, name }) => (
164-
<option key={slug} value={slug}>
165-
{name}
159+
<Field visible={!!goalTypes} className="w-panel__wrapper">
160+
<SunkenLabel className="w-field__label">
161+
{gettext('What is the goal?')}
162+
<RequiredMark />
163+
</SunkenLabel>
164+
<div className="w-field__input">
165+
<select name="goal_event">
166+
<option key="" value="">
167+
Choose a goal
166168
</option>
167-
))}
168-
</select>
169-
<p>
170-
{gettext(
171-
'By default pages only have one goal (Page Visit). Read the developer docs to learn why, and how to add custom goals.',
172-
)}
173-
</p>
169+
{goalTypes.map(({ slug, name }) => (
170+
<option key={slug} value={slug}>
171+
{name}
172+
</option>
173+
))}
174+
</select>
175+
</div>
174176
</Field>
177+
<div className="w-panel__wrapper">
178+
<fieldset>
179+
<div className="">
180+
{gettext(
181+
'By default pages only have one goal (Page Visit). Read the developer docs to learn why, and how to add custom goals.',
182+
)}
183+
</div>
184+
</fieldset>
185+
</div>
175186
</div>
176187
);
177188
};
178189

179190
export function initGoalSelector() {
191+
const goalSelectorProps = JSON.parse(
192+
document.getElementById('data-goal-selector-props')?.textContent ||
193+
'{}',
194+
);
195+
180196
document
181197
.querySelectorAll('div[data-component="goal-selector"]')
182198
.forEach((element: HTMLDivElement) => {
199+
element.setAttribute('data-props', goalSelectorProps);
200+
183201
if (!element.dataset.props) {
184202
return;
185203
}

wagtail_ab_testing/templates/wagtail_ab_testing/add_form.html

Lines changed: 21 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -6,80 +6,31 @@
66
{% trans "Create an A/B Test" as title %}
77
{% include "wagtailadmin/shared/header.html" with title=title subtitle=page.title icon='people-arrows' merged=1 %}
88

9-
<form method="post">
10-
{% csrf_token %}
11-
12-
<section class="section">
13-
<div class="section__title">
14-
<div class="section__icon-container">
15-
{% icon "arrow-down" classname="section__icon" %}
16-
</div>
17-
<h3>{% trans "Enter test details" %}</h3>
18-
</div>
19-
20-
<div class="section__content nice-padding">
21-
<ul class="fields">
22-
<li>
23-
{# TODO: Wagtail 6.0 introduced {% formattedfield %} to replace this template include #}
24-
{% include "wagtailadmin/shared/field.html" with field=form.name %}
25-
</li>
26-
<li>
27-
{% include "wagtailadmin/shared/field.html" with field=form.hypothesis %}
28-
</li>
29-
</ul>
30-
</div>
31-
</section>
32-
33-
34-
<section class="section">
35-
<div class="section__title">
36-
<div class="section__icon-container">
37-
{% icon "arrow-down" classname="section__icon" %}
38-
</div>
39-
<h3>{% trans "Choose a goal" %}</h3>
40-
</div>
41-
42-
<div class="section__content nice-padding">
43-
<div data-component="goal-selector" data-props="{{ goal_selector_props }}"></div>
44-
</div>
45-
</section>
46-
47-
48-
<section class="section">
49-
<div class="section__title">
50-
<div class="section__icon-container">
51-
{% icon "arrow-down" classname="section__icon" %}
52-
</div>
53-
<h3>{% trans "Sample size" %}</h3>
54-
</div>
55-
56-
<div class="section__content nice-padding">
57-
<ul class="fields">
58-
<li>
59-
{% include "wagtailadmin/shared/field.html" with field=form.sample_size %}
60-
</li>
61-
</ul>
62-
{% trans 'Need help calculating sample size for A/B tests? Try <a href="https://www.optimizely.com/uk/sample-size-calculator/" target="_blank">Optimisely</a>, <a href="https://www.evanmiller.org/ab-testing/sample-size.html" target="_blank">Evan Miller</a>, or <a href="https://www.abtasty.com/sample-size-calculator/" target="_blank">AB Tasty</a>.' %}
63-
</div>
64-
</section>
65-
66-
<p class="section__content nice-padding">
67-
<button type="submit" class="button button-primary">{% trans "Save" %}</button>
68-
<button type="submit" name="start" class="button button-primary">{% trans "Save and start test" %}</button>
69-
</p>
70-
71-
<div class="nice-padding">
72-
{% help_block status="info"%}
73-
<p>{% trans "A/B tests are calculated using Pearson's chi squared test and are set at 95% confidence level." %}</p>
74-
<p>{% trans "Traffic is split evenly between each version." %}</p>
75-
<p>{% trans 'Users with "<a href="https://en.wikipedia.org/wiki/Do_Not_Track" target="_blank">Do Not Track</a>" enabled are not counted.' %}</p>
76-
{% endhelp_block %}
77-
</div>
78-
</form>
9+
<div class="nice-padding">
10+
<form method="post">
11+
{% csrf_token %}
12+
13+
{% component panel %}
14+
15+
<section class="w-form-width">
16+
<p class="section__content">
17+
<button type="submit" class="button button-primary">{% trans "Save" %}</button>
18+
<button type="submit" name="start" class="button button-primary">{% trans "Save and start test" %}</button>
19+
</p>
20+
21+
{% help_block status="info"%}
22+
<p>{% trans "A/B tests are calculated using Pearson's chi squared test and are set at 95% confidence level." %}</p>
23+
<p>{% trans "Traffic is split evenly between each version." %}</p>
24+
<p>{% trans 'Users with "<a href="https://en.wikipedia.org/wiki/Do_Not_Track" target="_blank">Do Not Track</a>" enabled are not counted.' %}</p>
25+
{% endhelp_block %}
26+
</section>
27+
</form>
28+
</div>
7929
{% endblock %}
8030

8131
{% block extra_js %}
8232
{% include "wagtailadmin/pages/_editor_js.html" %}
33+
{{ goal_selector_props|json_script:"data-goal-selector-props" }}
8334
<script>
8435
{% url 'wagtailadmin_home' as wagtailadmin_root_url %}
8536
wagtailConfig.ADMIN_ROOT_URL = '{{ wagtailadmin_root_url|escapejs }}';

wagtail_ab_testing/views.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
permission_classes,
2121
)
2222
from rest_framework.response import Response
23-
from wagtail.admin import messages
23+
from wagtail.admin import messages, panels
2424
from wagtail.admin.action_menu import ActionMenuItem
2525
from wagtail.admin.filters import DateRangePickerWidget, WagtailFilterSet
2626
from wagtail.admin.views.reports import ReportView
@@ -53,6 +53,40 @@ class Meta:
5353
model = AbTest
5454
fields = ["name", "hypothesis", "goal_event", "goal_page", "sample_size"]
5555

56+
panels = [
57+
panels.MultiFieldPanel(
58+
[
59+
panels.FieldPanel("name"),
60+
panels.FieldPanel("hypothesis"),
61+
],
62+
heading=_("Enter test details"),
63+
),
64+
panels.MultiFieldPanel(
65+
[
66+
# A dummy help panel to mount the react component:
67+
panels.HelpPanel(attrs={"data-component": "goal-selector"}),
68+
],
69+
heading=_("Choose a goal"),
70+
),
71+
panels.MultiFieldPanel(
72+
[
73+
panels.FieldPanel("sample_size"),
74+
panels.HelpPanel(
75+
_(
76+
"Need help calculating sample size for A/B tests? "
77+
'Try <a href="https://www.optimizely.com/uk/sample-size-calculator/" '
78+
'target="_blank">Optimisely</a>, '
79+
'<a href="https://www.evanmiller.org/ab-testing/sample-size.html" '
80+
'target="_blank">Evan Miller</a>, or '
81+
'<a href="https://www.abtasty.com/sample-size-calculator/" '
82+
'target="_blank">AB Tasty</a>.'
83+
)
84+
),
85+
],
86+
heading=_("Sample size"),
87+
),
88+
]
89+
5690

5791
def add_ab_test_checks(request, page):
5892
# User must have permission to edit the page
@@ -150,6 +184,11 @@ def add_form(request, page_id):
150184

151185
event_types = get_event_types().items()
152186

187+
panel = panels.ObjectList(form.panels).bind_to_model(AbTest)
188+
bound_panel = panel.get_bound_panel(
189+
instance=form.instance, form=form, request=request
190+
)
191+
153192
"""
154193
Template: wagtail_ab_testing/add_form.html is rendered here
155194
@@ -163,6 +202,7 @@ def add_form(request, page_id):
163202
{
164203
"page": page,
165204
"form": form,
205+
"panel": bound_panel,
166206
"goal_selector_props": json.dumps(
167207
{
168208
"goalTypesByPageType": {

0 commit comments

Comments
 (0)