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

[B5] Migrate first reports to bootstrap 5! #35704

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
{
"reports": [
"ApplicationStatusReport",
"CaseListReport"
],
"filters": [
"corehq.apps.reports.filters.case_list.CaseListFilter",
"corehq.apps.reports.filters.select.CaseTypeFilter",
"corehq.apps.reports.filters.select.SelectApplicationFilter",
"corehq.apps.reports.filters.select.SelectOpenCloseFilter",
"corehq.apps.reports.filters.users.ExpandedMobileWorkerFilter",
"corehq.apps.reports.standard.cases.filters.CaseSearchFilter"
],
"filter_templates": [
Expand Down
106 changes: 59 additions & 47 deletions corehq/apps/reports/standard/deployments.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class ApplicationStatusReport(GetParamsMixin, PaginatedReportMixin, DeploymentsR
'corehq.apps.reports.filters.select.SelectApplicationFilter'
]
primary_sort_prop = None
use_bootstrap5 = True

@property
def _columns(self):
Expand All @@ -84,37 +85,45 @@ def _columns(self):
return [
DataTablesColumn(_("Username"),
prop_name='username.exact',
sql_col='user_dim__username'),
sql_col='user_dim__username',
use_bootstrap5=self.use_bootstrap5),
DataTablesColumn(_("Assigned Location(s)"),
help_text=_('Assigned locations for the user, with the primary '
'location highlighted in bold.'),
sortable=False),
sortable=False,
use_bootstrap5=self.use_bootstrap5),
DataTablesColumn(_("Last Submission"),
prop_name='reporting_metadata.last_submissions.submission_date',
alt_prop_name='reporting_metadata.last_submission_for_user.submission_date',
sql_col='last_form_submission_date'),
sql_col='last_form_submission_date',
use_bootstrap5=self.use_bootstrap5),
DataTablesColumn(_("Last Sync"),
prop_name='reporting_metadata.last_syncs.sync_date',
alt_prop_name='reporting_metadata.last_sync_for_user.sync_date',
sql_col='last_sync_log_date'),
sql_col='last_sync_log_date',
use_bootstrap5=self.use_bootstrap5),
DataTablesColumn(_("Application"),
help_text=_("The name of the application from the user's last request."),
sortable=False),
sortable=False,
use_bootstrap5=self.use_bootstrap5),
DataTablesColumn(_("Application Version"),
help_text=_("The application version from the user's last request."),
prop_name='reporting_metadata.last_builds.build_version',
alt_prop_name='reporting_metadata.last_build_for_user.build_version',
sql_col='last_form_app_build_version'),
sql_col='last_form_app_build_version',
use_bootstrap5=self.use_bootstrap5),
DataTablesColumn(_("CommCare Version"),
help_text=_("""The CommCare version from the user's last request"""),
prop_name='reporting_metadata.last_submissions.commcare_version',
alt_prop_name='reporting_metadata.last_submission_for_user.commcare_version',
sql_col='last_form_app_commcare_version'),
sql_col='last_form_app_commcare_version',
use_bootstrap5=self.use_bootstrap5),
DataTablesColumn(_("Number of unsent forms in user's phone"),
help_text=_("The number of unsent forms in users' phones for {app_info}".format(
app_info=selected_app_info
)),
sortable=False),
sortable=False,
use_bootstrap5=self.use_bootstrap5),
]

@property
Expand All @@ -124,7 +133,8 @@ def headers(self):
columns.append(
DataTablesColumn(_("Build Profile"),
help_text=_("The build profile from the user's last hearbeat request."),
sortable=False)
sortable=False,
use_bootstrap5=self.use_bootstrap5)
)
headers = DataTablesHeader(*columns)
headers.custom_sort = [[2, 'desc']]
Expand Down Expand Up @@ -162,41 +172,43 @@ def sort_filter(self):

def get_sorting_block(self):
sort_prop_name = 'prop_name' if self.selected_app_id else 'alt_prop_name'
res = []
#the NUMBER of cols sorting
sort_cols = int(self.request.GET.get('iSortingCols', 0))
if sort_cols > 0:
for x in range(sort_cols):
col_key = 'iSortCol_%d' % x
sort_dir = self.request.GET['sSortDir_%d' % x]
col_id = int(self.request.GET[col_key])
col = self.headers.header[col_id]
sort_prop = getattr(col, sort_prop_name) or col.prop_name
if x == 0:
self.primary_sort_prop = sort_prop
if self.selected_app_id:
sort_dict = {
sort_prop: {
"order": sort_dir,
"nested_filter": {
"term": {
self.sort_filter: self.selected_app_id
}
}
}
block = []
for col in self.datatables_params.order:
col_ind = col['column']
sort_dir = col['dir']
dt_column_obj = self.headers.header[col_ind]
sort_prop = getattr(dt_column_obj, sort_prop_name) or dt_column_obj.prop_name
if col_ind == 0:
# this feels like a bit of a hack, but kept it in from the original sorting block
# prior to bootstrap 5 migration. could use a second look in the future
self.primary_sort_prop = sort_prop
if self.selected_app_id:
sort_dict = self._get_selected_app_sort_dict(sort_prop, sort_dir)
else:
sort_dict = {sort_prop: sort_dir}
block.append(sort_dict)
if len(block) == 0 and self.default_sort is not None:
block.append(self.default_sort)
return block
Comment on lines -165 to +192
Copy link
Contributor

@millerdev millerdev Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Difficult to tell what changed here that is B5 related and what is code refactoring. Could those be split into separate commits or is this necessarily a complicated transformation for B5 support?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the whole sorting block changed, I'm not sure I can split it up any further? There is no other way to have a diff

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also FYI this isn't B5 related but Datatables 1.10+ upgrade related, so there isn't going to ever be a clean-cut diff as your would expect with property changes for B5-type changes.

our old version of datatables is not compatible with bootstrap 5, which is why the upgrade was necessary. So any b5 migration of a report, will also require these kind of sorting block updates (if there is a custom sorting block) due to datatables. Relevant context is part of this PR, which we went over as a group #35648

Copy link
Member Author

@biyeun biyeun Jan 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess i could have split out _get_selected_app_sort_dict, but that was the only refactoring related change, and I did that at the end to make the whole sorting block a little more readable. Unlikely I would have changed it from the beginning. Everything else was not a refactor


def _get_selected_app_sort_dict(self, sort_prop, sort_dir):
sort_dict = {
sort_prop: {
"order": sort_dir,
"nested_filter": {
"term": {
self.sort_filter: self.selected_app_id
}
sort_prop_path = sort_prop.split('.')
if sort_prop_path[-1] == 'exact':
sort_prop_path.pop()
sort_prop_path.pop()
if sort_prop_path:
sort_dict[sort_prop]['nested_path'] = '.'.join(sort_prop_path)
else:
sort_dict = {sort_prop: sort_dir}
res.append(sort_dict)
if len(res) == 0 and self.default_sort is not None:
res.append(self.default_sort)
return res
}
}
}
sort_prop_path = sort_prop.split('.')
if sort_prop_path[-1] == 'exact':
sort_prop_path.pop()
sort_prop_path.pop()
if sort_prop_path:
sort_dict[sort_prop]['nested_path'] = '.'.join(sort_prop_path)
return sort_dict

@property
@memoized
Expand Down Expand Up @@ -579,7 +591,7 @@ def _timedelta_class(delta):
return _bootstrap_class(delta, timedelta(days=7), timedelta(days=3))

if not date:
text = format_html('<span class="label label-default">{}</span>', _("Never"))
text = format_html('<span class="badge text-bg-secondary">{}</span>', _("Never"))
else:
text = format_html(
'<span class="{cls}">{text}</span>',
Expand All @@ -602,11 +614,11 @@ def _bootstrap_class(obj, severe, warn):
assumes bigger is worse and default is good.
"""
if obj > severe:
return "label label-danger"
return "badge text-bg-danger"
elif obj > warn:
return "label label-warning"
return "badge text-bg-warning"
else:
return "label label-success"
return "badge text-bg-success"


def _get_histogram_aggregation_for_app(field_name, date_field_name, app_id):
Expand Down