gov-uk-dashboards 18.1.0__tar.gz → 19.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. {gov_uk_dashboards-18.1.0/gov_uk_dashboards.egg-info → gov_uk_dashboards-19.1.0}/PKG-INFO +1 -1
  2. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/helpers/plotting_helper_functions.py +4 -1
  3. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/leaflet/leaflet_choropleth_map.py +2 -2
  4. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/plotly/stacked_barchart.py +75 -45
  5. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0/gov_uk_dashboards.egg-info}/PKG-INFO +1 -1
  6. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/setup.py +1 -1
  7. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/LICENSE +0 -0
  8. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/MANIFEST.in +0 -0
  9. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/README.md +0 -0
  10. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/__init__.py +0 -0
  11. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/__init__.py +0 -0
  12. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/attach-event-to-dash.js +0 -0
  13. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/custom_map_style_functions.js +0 -0
  14. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/dashboard.css +0 -0
  15. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/fonts/bold-affa96571d-v2.woff +0 -0
  16. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/fonts/bold-b542beb274-v2.woff2 +0 -0
  17. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/fonts/light-94a07e06a1-v2.woff2 +0 -0
  18. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/fonts/light-f591b13f7d-v2.woff +0 -0
  19. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/get_assets_folder.py +0 -0
  20. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/govuk-frontend-3.14.0.min.js +0 -0
  21. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/DLUHC_WHITE_Master_AW_sm.png +0 -0
  22. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/MHCLG-favicon.png +0 -0
  23. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/MHCLG_favicon.png +0 -0
  24. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/dcms_coatofarms.png +0 -0
  25. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/dluhc_favicon.ico +0 -0
  26. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/gov_favicon.ico +0 -0
  27. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/govuk-crest.svg +0 -0
  28. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/hm-government-logo.png +0 -0
  29. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/mhclg_coat_of_arms.png +0 -0
  30. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/mhclg_white_no_background.png +0 -0
  31. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/oflog/MedianAbsolute.png +0 -0
  32. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/oflog/how_to_1_selecting_data.png +0 -0
  33. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/oflog/how_to_2_viewing_tabs.png +0 -0
  34. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/oflog/how_to_3_viewing_charts.png +0 -0
  35. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/oflog/how_to_4_viewing_trends.png +0 -0
  36. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/images/oflog/how_to_5_viewing_tables.png +0 -0
  37. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/mobile-nav.js +0 -0
  38. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/topojson/usa_110m.json +0 -0
  39. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/assets/topojson/world_110m.json +0 -0
  40. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/axes.py +0 -0
  41. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/colours.py +0 -0
  42. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/__init__.py +0 -0
  43. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/__init__.py +0 -0
  44. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/apply_and_reset_filters_buttons.py +0 -0
  45. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/banners.py +0 -0
  46. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/card.py +0 -0
  47. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/card_full_width.py +0 -0
  48. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/collapsible_panel.py +0 -0
  49. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/comparison_la_filter_button.py +0 -0
  50. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/context_banner.py +0 -0
  51. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/dashboard_container.py +0 -0
  52. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/details.py +0 -0
  53. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/download_button.py +0 -0
  54. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/filter_panel.py +0 -0
  55. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/footer.py +0 -0
  56. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/graph.py +0 -0
  57. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/header.py +0 -0
  58. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/heading.py +0 -0
  59. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/home_page_link_button.py +0 -0
  60. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/html_list.py +0 -0
  61. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/key_value_pair.py +0 -0
  62. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/main_content.py +0 -0
  63. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/navbar.py +0 -0
  64. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/no_data_message.py +0 -0
  65. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/notification_banner.py +0 -0
  66. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/paragraph.py +0 -0
  67. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/phase_banner.py +0 -0
  68. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/row_component.py +0 -0
  69. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/side_navbar.py +0 -0
  70. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/table.py +0 -0
  71. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/tooltip.py +0 -0
  72. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/tooltip_title.py +0 -0
  73. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/visualisation_commentary.py +0 -0
  74. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/visualisation_title.py +0 -0
  75. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/dash/warning_text.py +0 -0
  76. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/helpers/__init__.py +0 -0
  77. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/helpers/display_chart_or_table_with_header.py +0 -0
  78. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/helpers/generate_dash_graph_from_figure.py +0 -0
  79. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/helpers/get_chart_for_download.py +0 -0
  80. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/helpers/update_layout_bgcolor_margin.py +0 -0
  81. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/leaflet/__init__.py +0 -0
  82. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/plotly/__init__.py +0 -0
  83. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/plotly/captioned_figure.py +0 -0
  84. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/plotly/choropleth_map.py +0 -0
  85. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/plotly/enums.py +0 -0
  86. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/components/plotly/time_series_chart.py +0 -0
  87. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/constants.py +0 -0
  88. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/figures/__init__.py +0 -0
  89. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/figures/chart_data.py +0 -0
  90. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/figures/enums/__init__.py +0 -0
  91. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/figures/enums/dash_patterns.py +0 -0
  92. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/figures/line_chart.py +0 -0
  93. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/figures/styles/__init__.py +0 -0
  94. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/figures/styles/line_style.py +0 -0
  95. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/formatting/__init__.py +0 -0
  96. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/formatting/human_readable.py +0 -0
  97. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/formatting/number_formatting.py +0 -0
  98. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/formatting/round_and_add_prefix_and_suffix.py +0 -0
  99. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/formatting/rounding.py +0 -0
  100. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/lib/__init__.py +0 -0
  101. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/lib/dap/__init__.py +0 -0
  102. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/lib/dap/dap_deployment.py +0 -0
  103. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/lib/dap/get_dataframe_from_cds.py +0 -0
  104. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/lib/datetime_functions/__init__.py +0 -0
  105. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/lib/datetime_functions/datetime_functions.py +0 -0
  106. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/lib/download_functions/__init__.py +0 -0
  107. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/lib/download_functions/convert_fig_to_image_and_download.py +0 -0
  108. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/lib/download_functions/download_csv_with_headers.py +0 -0
  109. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/lib/enable_basic_auth.py +0 -0
  110. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/lib/http_headers.py +0 -0
  111. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/lib/logging.py +0 -0
  112. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/symbols.py +0 -0
  113. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/template.html +0 -0
  114. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards/template.py +0 -0
  115. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards.egg-info/SOURCES.txt +0 -0
  116. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards.egg-info/dependency_links.txt +0 -0
  117. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards.egg-info/requires.txt +0 -0
  118. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/gov_uk_dashboards.egg-info/top_level.txt +0 -0
  119. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.1.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gov_uk_dashboards
3
- Version: 18.1.0
3
+ Version: 19.1.0
4
4
  Summary: Provides access to functionality common to creating a data dashboard.
5
5
  Author: Department for Levelling Up, Housing and Communities
6
6
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@
4
4
  from gov_uk_dashboards.constants import CHART_LABEL_FONT_SIZE
5
5
 
6
6
 
7
- def get_legend_configuration(itemclick=True, itemdoubleclick=True):
7
+ def get_legend_configuration(itemclick=True, itemdoubleclick=True, reverse_order=False):
8
8
  """
9
9
  Returns the legend configuration for charts with customizable interaction settings.
10
10
  Args:
@@ -12,9 +12,11 @@ def get_legend_configuration(itemclick=True, itemdoubleclick=True):
12
12
  Set to True by default, allowing click interactions.
13
13
  itemdoubleclick (bool): Determines the behavior when double-clicking on a legend item.
14
14
  Set to True by default, allowing double-click interactions.
15
+ reverse_order (bool): Whether to reverse legend order. Defaults to False.
15
16
  Returns:
16
17
  dict: A dictionary containing the configuration settings for the legend.
17
18
  """
19
+ traceorder = {} if not reverse_order else {"traceorder": "reversed"}
18
20
  return {
19
21
  "x": 0,
20
22
  "y": -0.22,
@@ -24,6 +26,7 @@ def get_legend_configuration(itemclick=True, itemdoubleclick=True):
24
26
  "font": {"size": CHART_LABEL_FONT_SIZE},
25
27
  "itemclick": "toggle" if itemclick else False,
26
28
  "itemdoubleclick": "toggle" if itemdoubleclick else False,
29
+ **traceorder,
27
30
  }
28
31
 
29
32
 
@@ -17,8 +17,8 @@ from gov_uk_dashboards.formatting.number_formatting import (
17
17
 
18
18
  class LeafletChoroplethMap:
19
19
  """Class for generating leaflet choropleth map charts.
20
- Note: dataframe_function must contain columns: 'Region', 'Area_Code',
21
- column_to_plot, hover_text_columns
20
+ Note: Values in the numeric column should use 1 for the highest value, with larger numbers
21
+ representing lower values.
22
22
  If color_scale_is_discrete is false, colour scale will be continuous, otherwise it will be
23
23
  discrete"""
24
24
 
@@ -1,5 +1,6 @@
1
1
  """stacked_barchart function"""
2
2
 
3
+ import json
3
4
  import math
4
5
  from typing import Optional
5
6
  from dash import html
@@ -54,7 +55,7 @@ class StackedBarChart:
54
55
  def __init__(
55
56
  self,
56
57
  title_data: TitleDataStructure,
57
- y_column: str,
58
+ y_axis_column: str,
58
59
  hover_data: HoverDataByTrace,
59
60
  df: pl.DataFrame,
60
61
  trace_name_list: list[str],
@@ -62,8 +63,11 @@ class StackedBarChart:
62
63
  xaxis_tick_text_format: XAxisFormat = XAxisFormat.YEAR.value,
63
64
  line_trace_name: Optional[str] = None,
64
65
  x_axis_column=DATE_VALID,
66
+ x_unified_hovermode: Optional[bool] = False,
67
+ hover_distance: Optional[int] = 1,
65
68
  download_chart_button_id: Optional[str] = None,
66
69
  download_data_button_id: Optional[str] = None,
70
+ total_trace_name: Optional[str] = None,
67
71
  ):
68
72
  """Initializes the StackedBarChart instance.
69
73
  To display the chart, call the `get_stacked_bar_chart()` method.
@@ -87,9 +91,12 @@ class StackedBarChart:
87
91
  if applicable. Defaults to None.
88
92
  download_data_button_id (Optional[str], optional): ID for the data download button, if
89
93
  applicable. Defaults to None.
94
+ total_trace_name (Optional[str], optional): Name for an optional total to be added to
95
+ bottom of hover text, must be in MEASURE column of df, line_trace_name will display
96
+ in legend. Defaults to None.
90
97
  """
91
98
  self.title_data = title_data
92
- self.y_axis_column = y_column
99
+ self.y_axis_column = y_axis_column
93
100
  self.hover_data = hover_data
94
101
  self.df = df
95
102
  self.trace_name_list = trace_name_list
@@ -97,8 +104,11 @@ class StackedBarChart:
97
104
  self.xaxis_tick_text_format = xaxis_tick_text_format
98
105
  self.line_trace_name = line_trace_name
99
106
  self.x_axis_column = x_axis_column
107
+ self.x_unified_hovermode = x_unified_hovermode
108
+ self.hover_distance = hover_distance
100
109
  self.download_chart_button_id = download_chart_button_id
101
110
  self.download_data_button_id = download_data_button_id
111
+ self.total_trace_name = total_trace_name
102
112
  self.fig = self.create_stacked_bar_chart()
103
113
 
104
114
  def get_stacked_bar_chart(self) -> html.Div:
@@ -120,6 +130,43 @@ class StackedBarChart:
120
130
  self.download_data_button_id,
121
131
  )
122
132
 
133
+ def is_json_serializable(self, value):
134
+ "Determines whether value can be converted to json format."
135
+ try:
136
+ json.dumps(value)
137
+ return True
138
+ except (TypeError, OverflowError):
139
+ return False
140
+
141
+ def to_dict(self):
142
+ "Converts class attributes to json format."
143
+ result = {}
144
+ for k, v in self.__dict__.items():
145
+ if self.is_json_serializable(v):
146
+ result[k] = v
147
+ elif isinstance(v, pl.DataFrame):
148
+ result[k] = {"_type": "polars_df", "data": v.to_dicts()}
149
+ elif hasattr(v, "to_dict"):
150
+ result[k] = {"_type": "custom", "data": v.to_dict()}
151
+ else:
152
+ result[k] = f"<<non-serializable: {type(v).__name__}>>"
153
+ return result
154
+
155
+ @classmethod
156
+ def from_dict(cls, data):
157
+ "Creates a class instance from dict of attributes."
158
+ restored = {}
159
+ for k, v in data.items():
160
+ if isinstance(v, dict) and "_type" in v:
161
+ if v["_type"] == "polars_df":
162
+ restored[k] = pl.DataFrame(v["data"])
163
+ elif v["_type"] == "custom":
164
+ # optionally restore known nested types here
165
+ pass
166
+ else:
167
+ restored[k] = v
168
+ return cls(**restored)
169
+
123
170
  def get_stacked_bar_chart_for_download(self):
124
171
  """Return fig with title and subtitle for download as png"""
125
172
  return get_chart_for_download(self, self.create_stacked_bar_chart())
@@ -129,7 +176,25 @@ class StackedBarChart:
129
176
  ):
130
177
  """generates a stacked bar chart"""
131
178
  # pylint: disable=too-many-locals
179
+
132
180
  fig = go.Figure()
181
+ if self.total_trace_name is not None:
182
+ df = self.df.filter(pl.col(MEASURE) == self.total_trace_name)
183
+
184
+ fig.add_trace(
185
+ go.Scatter(
186
+ x=df[self.x_axis_column],
187
+ y=df[self.y_axis_column],
188
+ customdata=self._get_custom_data(self.total_trace_name, df),
189
+ mode="markers",
190
+ marker={"color": "white", "opacity": 0},
191
+ name=self.total_trace_name + LEGEND_SPACING,
192
+ hovertemplate="Total income: %{customdata[0]}<extra></extra>",
193
+ showlegend=False,
194
+ hoverinfo="skip",
195
+ legendrank=1,
196
+ )
197
+ )
133
198
  colour_list = (
134
199
  AFAccessibleColours.CATEGORICAL.value
135
200
  if len(self.trace_name_list) != 2
@@ -140,7 +205,7 @@ class StackedBarChart:
140
205
  )
141
206
  for _, (df, trace_name, colour) in enumerate(
142
207
  zip(
143
- self._get_df_list_for_time_series(),
208
+ self._get_df_list_for_bar_chart(),
144
209
  self.trace_name_list,
145
210
  colour_list,
146
211
  )
@@ -177,7 +242,7 @@ class StackedBarChart:
177
242
  update_layout_bgcolor_margin(fig, "#FFFFFF")
178
243
 
179
244
  fig.update_layout(
180
- legend=get_legend_configuration(),
245
+ legend=get_legend_configuration(reverse_order=True),
181
246
  font={"size": CHART_LABEL_FONT_SIZE},
182
247
  yaxis={
183
248
  "range": [min_y * 1.1, max_y * 1.1],
@@ -188,20 +253,12 @@ class StackedBarChart:
188
253
  showlegend=True,
189
254
  barmode="relative",
190
255
  xaxis={"categoryorder": "category ascending"},
256
+ ## copied from timeseries
257
+ hovermode="x unified" if self.x_unified_hovermode is True else "closest",
258
+ hoverdistance=self.hover_distance, # Increase distance to simulate hover 'always on'
191
259
  )
192
260
  return fig
193
261
 
194
- def _format_x_axis(self, fig):
195
- tick_text, tick_values, range_x = self._get_x_axis_content()
196
- fig.update_xaxes(
197
- tickvals=tick_values,
198
- ticktext=tick_text,
199
- tickmode="array",
200
- range=range_x,
201
- )
202
-
203
- return tick_values
204
-
205
262
  def create_bar_chart_trace(
206
263
  self,
207
264
  df: pl.DataFrame,
@@ -232,6 +289,8 @@ class StackedBarChart:
232
289
  )
233
290
 
234
291
  def _get_hover_template(self, trace_name):
292
+ if self.x_unified_hovermode is True:
293
+ return f"{trace_name}: " + "%{customdata[0]}<extra></extra>"
235
294
  hover_text_headers = self.hover_data[trace_name][HOVER_TEXT_HEADERS]
236
295
  hover_template = (
237
296
  f"{trace_name}<br>"
@@ -246,36 +305,7 @@ class StackedBarChart:
246
305
  customdata = df[self.hover_data[trace_name][CUSTOM_DATA]]
247
306
  return customdata
248
307
 
249
- def _get_x_axis_content(self):
250
- """Generates tick text and values for the x-axis based on the unique years calculated from
251
- the FINANCIAL_YEAR_ENDING column in the dataframe.
252
- Returns:
253
- tuple: A tuple containing tick_text, tick_values and range_x.
254
- """
255
- if self.xaxis_tick_text_format == XAxisFormat.YEAR.value:
256
- year_list = self.df[FINANCIAL_YEAR_ENDING].unique().to_list()
257
- int_min_year = int(min(year_list))
258
- int_max_year = int(max(year_list))
259
-
260
- tick_text = []
261
- year = int_min_year
262
- while year <= int_max_year:
263
- tick_text.append(str(year + 1))
264
- year = year + 1
265
-
266
- tick_values = tick_text
267
-
268
- range_x = [
269
- tick_values[0],
270
- tick_values[-1],
271
- ]
272
- else:
273
- raise ValueError(
274
- f"Invalid xaxis_tick_text_format: {self.xaxis_tick_text_format}"
275
- )
276
- return tick_text, tick_values, range_x
277
-
278
- def _get_df_list_for_time_series(self) -> list[pl.DataFrame]:
308
+ def _get_df_list_for_bar_chart(self) -> list[pl.DataFrame]:
279
309
  if self.trace_name_column is not None:
280
310
  df_list = [
281
311
  self.df.filter(pl.col(self.trace_name_column) == trace_name)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gov_uk_dashboards
3
- Version: 18.1.0
3
+ Version: 19.1.0
4
4
  Summary: Provides access to functionality common to creating a data dashboard.
5
5
  Author: Department for Levelling Up, Housing and Communities
6
6
  Description-Content-Type: text/markdown
@@ -10,7 +10,7 @@ setup(
10
10
  author="Department for Levelling Up, Housing and Communities",
11
11
  description="Provides access to functionality common to creating a data dashboard.",
12
12
  name="gov_uk_dashboards",
13
- version="18.1.0",
13
+ version="19.1.0",
14
14
  long_description=long_description,
15
15
  long_description_content_type="text/markdown",
16
16
  packages=find_packages(),