Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore responsiveness to B5-migrated forms #35533

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6751c83
Document responsive form layout on Bootstrap 5
millerdev Dec 10, 2024
3552c8f
B5 crispy horizontal forms
millerdev Dec 10, 2024
1cabe25
Remove redundant B5 form class assignemnts
millerdev Dec 10, 2024
1ac2e1f
Adjust column widths for crispy horizontal forms
millerdev Dec 10, 2024
ba97060
Form style extensions to simplify field classes
millerdev Dec 12, 2024
af45509
Simplify field classes in styleguide examples
millerdev Dec 12, 2024
7627001
BootstrapCheckboxInput now optional on Bootstrap 5
millerdev Dec 11, 2024
ec7bad9
B3 form style extensions
millerdev Dec 12, 2024
b089038
Remove unneeded B5 branching in crispy helper code
millerdev Dec 12, 2024
2f9365c
"Bootstrap 5 Migration - Rebuilt diffs"
millerdev Dec 12, 2024
8549a39
Remove unused offsets
millerdev Dec 13, 2024
3ad244e
Preserve horizontal forms in B5 change guides
millerdev Dec 13, 2024
040d2cd
Updated program form
orangejenny Dec 17, 2024
faf6ac7
Updated DatasourceExportDownloadForm
orangejenny Dec 17, 2024
df92ad0
Updated HQPasswordChangeForm
orangejenny Dec 17, 2024
56fa7ed
Updated EnterpriseManageMobileWorkersForm
orangejenny Dec 17, 2024
ddaa885
Updated HQApiKeyForm
orangejenny Dec 17, 2024
8b32785
Updated LocationFilterForm
orangejenny Dec 17, 2024
e76c202
Updated AddPhoneNumberForm
orangejenny Dec 17, 2024
e1de3b8
Updated EmailSMTPSettingsForm
orangejenny Dec 17, 2024
6a3d251
Updated integration forms
orangejenny Dec 17, 2024
f91e9af
Updated GroupMembershipForm
orangejenny Dec 17, 2024
30485a4
Updated EnterpriseSettingsForm
orangejenny Dec 17, 2024
f9fb830
Updated UpdateMyAccountInfoForm
orangejenny Dec 17, 2024
d57b919
Updated KeywordForm
orangejenny Dec 17, 2024
d991d25
Updated DataSetMapForm
orangejenny Dec 17, 2024
e4acd06
Updated ProductForm
orangejenny Dec 17, 2024
20c5dbb
Updated NotificationCreationForm
orangejenny Dec 17, 2024
4e1d669
Updated commtrack consumption and settings forms
orangejenny Dec 17, 2024
32b1785
Updated FHIRRepeaterForm
orangejenny Dec 17, 2024
1cffcf7
Updated UsersAtLocationForm
orangejenny Dec 17, 2024
0814e07
Removed unneeded attribute
orangejenny Dec 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion corehq/apps/app_execution/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ def __init__(self, request, *args, **kwargs):
if self.instance.id:
self.fields["username"].initial = self.instance.django_user.username
self.helper = hqcrispy.HQFormHelper()
self.helper.form_class = "form-horizontal"

fields = [
"name",
Expand Down
55 changes: 29 additions & 26 deletions corehq/apps/commtrack/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@
from django.utils.translation import gettext_lazy
from django.utils.html import format_html

from crispy_forms.bootstrap import PrependedText, StrictButton
from crispy_forms.helper import FormHelper
from crispy_forms.bootstrap import StrictButton
from crispy_forms.layout import Fieldset, Layout

from corehq.apps.consumption.shortcuts import (
get_default_monthly_consumption,
set_default_consumption_for_product,
)
from corehq.apps.hqwebapp.widgets import BootstrapCheckboxInput
from corehq.apps.hqwebapp.crispy import FormActions, HQFormHelper
from corehq.apps.products.models import SQLProduct


class CommTrackSettingsForm(forms.Form):
use_auto_emergency_levels = forms.BooleanField(label='', required=False, widget=BootstrapCheckboxInput(
inline_label=gettext_lazy("Use default emergency levels")
))
use_auto_emergency_levels = forms.BooleanField(
label=gettext_lazy("Use default emergency levels"),
required=False,
)

stock_emergency_level = forms.DecimalField(
label=gettext_lazy("Emergency Level (months)"), required=False)
Expand All @@ -28,22 +28,25 @@ class CommTrackSettingsForm(forms.Form):
stock_overstock_threshold = forms.DecimalField(
label=gettext_lazy("Overstock Level (months)"), required=False)

use_auto_consumption = forms.BooleanField(label='', required=False, widget=BootstrapCheckboxInput(
inline_label=gettext_lazy("Use automatic consumption calculation")
))
use_auto_consumption = forms.BooleanField(
label=gettext_lazy("Use automatic consumption calculation"),
required=False,
)
consumption_min_transactions = forms.IntegerField(
label=gettext_lazy("Minimum Transactions (Count)"), required=False)
consumption_min_window = forms.IntegerField(
label=gettext_lazy("Minimum Window for Calculation (Days)"), required=False)
consumption_optimal_window = forms.IntegerField(
label=gettext_lazy("Optimal Window for Calculation (Days)"), required=False)
individual_consumption_defaults = forms.BooleanField(label='', required=False, widget=BootstrapCheckboxInput(
inline_label=gettext_lazy("Configure consumption defaults individually by supply point")
))
individual_consumption_defaults = forms.BooleanField(
label=gettext_lazy("Configure consumption defaults individually by supply point"),
required=False,
)

sync_consumption_fixtures = forms.BooleanField(label='', required=False, widget=BootstrapCheckboxInput(
inline_label=gettext_lazy("Sync consumption fixtures")
))
sync_consumption_fixtures = forms.BooleanField(
label=gettext_lazy("Sync consumption fixtures"),
required=False,
)

def clean(self):
cleaned_data = super(CommTrackSettingsForm, self).clean()
Expand All @@ -66,8 +69,7 @@ def clean(self):

def __init__(self, *args, **kwargs):
domain = kwargs.pop('domain')
self.helper = FormHelper()
self.helper.label_class = 'form-label'
self.helper = HQFormHelper()

self.helper.layout = Layout(
Fieldset(
Expand All @@ -78,20 +80,22 @@ def __init__(self, *args, **kwargs):
),
Fieldset(
_('Consumption Settings'),
PrependedText('use_auto_consumption', ''),
'use_auto_consumption',
'consumption_min_transactions',
'consumption_min_window',
'consumption_optimal_window',
PrependedText('individual_consumption_defaults', ''),
'individual_consumption_defaults',
),
Fieldset(
_('Phone Settings'),
PrependedText('sync_consumption_fixtures', ''),
'sync_consumption_fixtures',
),
StrictButton(
_("Submit"),
type="submit",
css_class='btn-primary',
FormActions(
StrictButton(
_("Submit"),
type="submit",
css_class='btn-primary',
)
)
)

Expand All @@ -112,9 +116,8 @@ class ConsumptionForm(forms.Form):
def __init__(self, domain, *args, **kwargs):
self.domain = domain
super(ConsumptionForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper = HQFormHelper()
self.helper.form_tag = False
self.helper.label_class = 'form-label'

layout = []
products = SQLProduct.active_objects.filter(domain=domain)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@
<legend>{% trans 'Edit Default Monthly Consumption' %}</legend>
{% crispy form %}
</fieldset>
<button type="submit" class="btn btn-primary">
{% trans "Update Default Consumption Info" %}
</button>
<div class="form-actions row">
<div class="field-control">
<button type="submit" class="btn btn-primary">
{% trans "Update Default Consumption Info" %}
</button>
</div>
</div>
</form>
{% endblock %}
1 change: 0 additions & 1 deletion corehq/apps/domain/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -1273,7 +1273,6 @@ def __init__(self, domain, can_edit_eula, *args, user, **kwargs):
)

self.helper = hqcrispy.HQFormHelper()
self.helper.form_class = "form-horizontal"
self.helper.layout = crispy.Layout(
crispy.Fieldset(
_("Basic Information"),
Expand Down
14 changes: 8 additions & 6 deletions corehq/apps/email/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,14 @@ def helper(self):
hqcrispy.CheckboxField('use_tracking_headers'),
crispy.Field('sns_secret'),
crispy.Field('ses_config_set_name'),
twbscrispy.StrictButton(
_("Saved"),
type="submit",
css_class="btn-primary disable-on-submit",
data_bind="text: buttonText, enable: isFormChanged",
),
hqcrispy.FormActions(
twbscrispy.StrictButton(
_("Saved"),
type="submit",
css_class="btn-primary disable-on-submit",
data_bind="text: buttonText, enable: isFormChanged",
),
)
)
return helper

Expand Down
42 changes: 22 additions & 20 deletions corehq/apps/enterprise/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

from crispy_forms import layout as crispy
from crispy_forms.bootstrap import PrependedText, StrictButton
from crispy_forms.helper import FormHelper

from corehq.apps.accounting.utils import domain_has_privilege
from corehq.apps.hqwebapp import crispy as hqcrispy
from corehq.apps.hqwebapp.widgets import BootstrapCheckboxInput
from corehq.apps.export.models.export_settings import ExportFileType
from corehq.privileges import DEFAULT_EXPORT_SETTINGS
Expand Down Expand Up @@ -131,16 +131,15 @@ def __init__(self, *args, **kwargs):
kwargs['initial'].update(self.export_settings.as_dict())

super(EnterpriseSettingsForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper = hqcrispy.HQFormHelper(self)
self.helper.form_id = 'enterprise-settings-form'
self.helper.form_action = reverse("edit_enterprise_settings", args=[self.domain])
self.helper.label_class = 'form-label'
self.helper.layout = crispy.Layout(
crispy.Fieldset(
_("Edit Enterprise Settings"),
PrependedText('restrict_domain_creation', ''),
hqcrispy.CheckboxField('restrict_domain_creation'),
crispy.Div(
PrependedText('restrict_signup', '', data_bind='checked: restrictSignup'),
hqcrispy.CheckboxField('restrict_signup', data_bind='checked: restrictSignup'),
),
crispy.Div(
crispy.Field('restrict_signup_message'),
Expand All @@ -157,29 +156,31 @@ def __init__(self, *args, **kwargs):
crispy.Div(
crispy.Field('forms_filetype'),
),
PrependedText('forms_auto_convert', ''),
PrependedText('forms_auto_format_cells', ''),
PrependedText('forms_expand_checkbox', ''),
hqcrispy.CheckboxField('forms_auto_convert'),
hqcrispy.CheckboxField('forms_auto_format_cells'),
hqcrispy.CheckboxField('forms_expand_checkbox'),
),
crispy.Fieldset(
_("Edit Default Case Export Settings"),
crispy.Div(
crispy.Field('cases_filetype')
),
PrependedText('cases_auto_convert', ''),
hqcrispy.CheckboxField('cases_auto_convert'),
),
crispy.Fieldset(
_("Edit Default OData Export Settings"),
PrependedText('odata_expand_checkbox', ''),
hqcrispy.CheckboxField('odata_expand_checkbox'),
),
)
)

self.helper.layout.append(
StrictButton(
_("Update Enterprise Settings"),
type="submit",
css_class='btn-primary',
hqcrispy.FormActions(
StrictButton(
_("Update Enterprise Settings"),
type="submit",
css_class='btn-primary',
)
)
)

Expand Down Expand Up @@ -286,9 +287,8 @@ def __init__(self, *args, **kwargs):
}

super().__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper = hqcrispy.HQFormHelper(self)
self.helper.form_id = 'emw-settings-form'
self.helper.label_class = 'form-label'
self.helper.layout = crispy.Layout(
crispy.Fieldset(
_("Manage Mobile Workers"),
Expand All @@ -298,10 +298,12 @@ def __init__(self, *args, **kwargs):
),
PrependedText('allow_custom_deactivation', ''),
),
StrictButton(
_("Update Settings"),
type="submit",
css_class='btn-primary',
hqcrispy.FormActions(
StrictButton(
_("Update Settings"),
type="submit",
css_class='btn-primary',
)
)
)

Expand Down
16 changes: 9 additions & 7 deletions corehq/apps/export/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import dateutil
from crispy_forms import layout as crispy
from crispy_forms.helper import FormHelper
from corehq.apps.hqwebapp import crispy as hqcrispy
from crispy_forms.bootstrap import StrictButton

from corehq import privileges
Expand Down Expand Up @@ -1078,7 +1078,7 @@ class DatasourceExportDownloadForm(forms.Form):

def __init__(self, domain, *args, **kwargs):
super(DatasourceExportDownloadForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper = HQFormHelper()

self.fields['data_source'].choices = self.domain_datasources(domain)

Expand All @@ -1094,11 +1094,13 @@ def __init__(self, domain, *args, **kwargs):
data_bind='visible: haveDatasources'
),
),
StrictButton(
_("Download Data Export Tool query file"),
type="submit",
css_class="btn-primary",
data_bind="enable: haveDatasources"
hqcrispy.FormActions(
StrictButton(
_("Download Data Export Tool query file"),
type="submit",
css_class="btn-primary",
data_bind="enable: haveDatasources"
),
),
)

Expand Down
29 changes: 5 additions & 24 deletions corehq/apps/hqwebapp/crispy.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import re
from contextlib import contextmanager
from django.forms.widgets import DateTimeInput
from django.template.loader import render_to_string
Expand All @@ -13,11 +12,9 @@
from crispy_forms.layout import LayoutObject
from crispy_forms.utils import flatatt, get_template_pack, render_field

CSS_LABEL_CLASS = 'col-xs-12 col-sm-4 col-md-4 col-lg-2'
CSS_LABEL_CLASS_BOOTSTRAP5 = 'col-xs-12 col-sm-4 col-md-4 col-lg-3'
CSS_FIELD_CLASS = 'col-xs-12 col-sm-8 col-md-8 col-lg-6'
CSS_FIELD_CLASS_BOOTSTRAP5 = 'col-xs-12 col-sm-8 col-md-8 col-lg-9'
CSS_ACTION_CLASS = CSS_FIELD_CLASS + ' col-sm-offset-4 col-md-offset-4 col-lg-offset-2'
CSS_LABEL_CLASS = 'field-label'
CSS_FIELD_CLASS = 'field-control'
CSS_ACTION_CLASS = CSS_FIELD_CLASS


class HQFormHelper(FormHelper):
Expand All @@ -28,13 +25,7 @@ class HQFormHelper(FormHelper):
def __init__(self, *args, **kwargs):
super(HQFormHelper, self).__init__(*args, **kwargs)
from corehq.apps.hqwebapp.utils.bootstrap import get_bootstrap_version, BOOTSTRAP_5
bootstrap_version = get_bootstrap_version()
use_bootstrap5 = bootstrap_version == BOOTSTRAP_5
if use_bootstrap5:
self.label_class = CSS_LABEL_CLASS_BOOTSTRAP5
self.field_class = CSS_FIELD_CLASS_BOOTSTRAP5
self.use_bootstrap5 = use_bootstrap5
self.form_class = 'form'
self.use_bootstrap5 = get_bootstrap_version() == BOOTSTRAP_5

if 'autocomplete' not in self.attrs:
self.attrs.update({
Expand Down Expand Up @@ -76,15 +67,7 @@ class ErrorsOnlyField(Field):


def get_form_action_class():
"""This is only valid for bootstrap 5"""
return CSS_LABEL_CLASS_BOOTSTRAP5.replace('col', 'offset') + ' ' + CSS_FIELD_CLASS_BOOTSTRAP5


def _get_offsets(context):
label_class = context.get('label_class', '')
use_bootstrap5 = context.get('use_bootstrap5')
return (label_class.replace('col', 'offset') if use_bootstrap5
else re.sub(r'(xs|sm|md|lg)-', r'\g<1>-offset-', label_class))
return CSS_FIELD_CLASS


class FormActions(OriginalFormActions):
Expand All @@ -102,11 +85,9 @@ def render(self, form, context, template_pack=None, **kwargs):
template_pack=template_pack,
)
fields_html = mark_safe(fields_html) # nosec: just concatenated safe fields
offsets = _get_offsets(context)
context.update({
'formactions': self,
'fields_output': fields_html,
'offsets': offsets,
'field_class': context.get('field_class', '')
})
return render_to_string(self.template, context.flatten())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.field-label {
&:extend(.col-xs-12, .col-sm-4, .col-md-4, .col-lg-2);
}

.field-label + .field-control {
&:extend(.col-xs-12, .col-sm-8, .col-md-8, .col-lg-6);
}

:not(.field-label) + .field-control,
.form-actions > .field-control:first-child,
.form-group > .field-control:first-child {
&:extend(
.col-sm-offset-4, .col-md-offset-4, .col-lg-offset-2,
.col-xs-12, .col-sm-8, .col-md-8, .col-lg-6
);
}
1 change: 1 addition & 0 deletions corehq/apps/hqwebapp/static/hqwebapp/less/bootstrap.less
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// Core variables and mixins
@import "_hq/includes/variables.less";
@import "_hq/includes/mixins.less";
@import "_hq/includes/extensions.less";

// Reset and dependencies
@import "../../../../../../node_modules/bootstrap/less/normalize.less";
Expand Down
Loading
Loading