gov-uk-dashboards 18.1.0__tar.gz → 19.0.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.0.0}/PKG-INFO +1 -1
  2. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/helpers/plotting_helper_functions.py +4 -1
  3. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/leaflet/leaflet_choropleth_map.py +2 -2
  4. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/plotly/stacked_barchart.py +53 -45
  5. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0/gov_uk_dashboards.egg-info}/PKG-INFO +1 -1
  6. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/setup.py +1 -1
  7. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/LICENSE +0 -0
  8. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/MANIFEST.in +0 -0
  9. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/README.md +0 -0
  10. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/__init__.py +0 -0
  11. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/__init__.py +0 -0
  12. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/attach-event-to-dash.js +0 -0
  13. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/custom_map_style_functions.js +0 -0
  14. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/dashboard.css +0 -0
  15. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/fonts/bold-affa96571d-v2.woff +0 -0
  16. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/fonts/bold-b542beb274-v2.woff2 +0 -0
  17. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/fonts/light-94a07e06a1-v2.woff2 +0 -0
  18. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/fonts/light-f591b13f7d-v2.woff +0 -0
  19. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/get_assets_folder.py +0 -0
  20. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.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.0.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.0.0}/gov_uk_dashboards/assets/images/MHCLG-favicon.png +0 -0
  23. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/images/MHCLG_favicon.png +0 -0
  24. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/images/dcms_coatofarms.png +0 -0
  25. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/images/dluhc_favicon.ico +0 -0
  26. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/images/gov_favicon.ico +0 -0
  27. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/images/govuk-crest.svg +0 -0
  28. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/images/hm-government-logo.png +0 -0
  29. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/images/mhclg_coat_of_arms.png +0 -0
  30. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/images/mhclg_white_no_background.png +0 -0
  31. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/images/oflog/MedianAbsolute.png +0 -0
  32. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.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.0.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.0.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.0.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.0.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.0.0}/gov_uk_dashboards/assets/mobile-nav.js +0 -0
  38. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/topojson/usa_110m.json +0 -0
  39. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/assets/topojson/world_110m.json +0 -0
  40. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/axes.py +0 -0
  41. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/colours.py +0 -0
  42. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/__init__.py +0 -0
  43. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/__init__.py +0 -0
  44. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.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.0.0}/gov_uk_dashboards/components/dash/banners.py +0 -0
  46. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/card.py +0 -0
  47. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/card_full_width.py +0 -0
  48. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/collapsible_panel.py +0 -0
  49. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/comparison_la_filter_button.py +0 -0
  50. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/context_banner.py +0 -0
  51. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/dashboard_container.py +0 -0
  52. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/details.py +0 -0
  53. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/download_button.py +0 -0
  54. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/filter_panel.py +0 -0
  55. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/footer.py +0 -0
  56. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/graph.py +0 -0
  57. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/header.py +0 -0
  58. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/heading.py +0 -0
  59. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/home_page_link_button.py +0 -0
  60. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/html_list.py +0 -0
  61. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/key_value_pair.py +0 -0
  62. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/main_content.py +0 -0
  63. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/navbar.py +0 -0
  64. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/no_data_message.py +0 -0
  65. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/notification_banner.py +0 -0
  66. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/paragraph.py +0 -0
  67. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/phase_banner.py +0 -0
  68. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/row_component.py +0 -0
  69. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/side_navbar.py +0 -0
  70. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/table.py +0 -0
  71. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/tooltip.py +0 -0
  72. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/tooltip_title.py +0 -0
  73. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/visualisation_commentary.py +0 -0
  74. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/visualisation_title.py +0 -0
  75. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/dash/warning_text.py +0 -0
  76. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/helpers/__init__.py +0 -0
  77. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.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.0.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.0.0}/gov_uk_dashboards/components/helpers/get_chart_for_download.py +0 -0
  80. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/helpers/update_layout_bgcolor_margin.py +0 -0
  81. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/leaflet/__init__.py +0 -0
  82. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/plotly/__init__.py +0 -0
  83. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/plotly/captioned_figure.py +0 -0
  84. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/plotly/choropleth_map.py +0 -0
  85. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/plotly/enums.py +0 -0
  86. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/components/plotly/time_series_chart.py +0 -0
  87. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/constants.py +0 -0
  88. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/figures/__init__.py +0 -0
  89. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/figures/chart_data.py +0 -0
  90. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/figures/enums/__init__.py +0 -0
  91. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/figures/enums/dash_patterns.py +0 -0
  92. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/figures/line_chart.py +0 -0
  93. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/figures/styles/__init__.py +0 -0
  94. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/figures/styles/line_style.py +0 -0
  95. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/formatting/__init__.py +0 -0
  96. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/formatting/human_readable.py +0 -0
  97. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/formatting/number_formatting.py +0 -0
  98. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.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.0.0}/gov_uk_dashboards/formatting/rounding.py +0 -0
  100. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/lib/__init__.py +0 -0
  101. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/lib/dap/__init__.py +0 -0
  102. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/lib/dap/dap_deployment.py +0 -0
  103. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/lib/dap/get_dataframe_from_cds.py +0 -0
  104. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/lib/datetime_functions/__init__.py +0 -0
  105. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/lib/datetime_functions/datetime_functions.py +0 -0
  106. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/lib/download_functions/__init__.py +0 -0
  107. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.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.0.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.0.0}/gov_uk_dashboards/lib/enable_basic_auth.py +0 -0
  110. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/lib/http_headers.py +0 -0
  111. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/lib/logging.py +0 -0
  112. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/symbols.py +0 -0
  113. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/template.html +0 -0
  114. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards/template.py +0 -0
  115. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards.egg-info/SOURCES.txt +0 -0
  116. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards.egg-info/dependency_links.txt +0 -0
  117. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards.egg-info/requires.txt +0 -0
  118. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.0}/gov_uk_dashboards.egg-info/top_level.txt +0 -0
  119. {gov_uk_dashboards-18.1.0 → gov_uk_dashboards-19.0.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.0.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,6 +63,8 @@ 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,
67
70
  ):
@@ -89,7 +92,7 @@ class StackedBarChart:
89
92
  applicable. Defaults to None.
90
93
  """
91
94
  self.title_data = title_data
92
- self.y_axis_column = y_column
95
+ self.y_axis_column = y_axis_column
93
96
  self.hover_data = hover_data
94
97
  self.df = df
95
98
  self.trace_name_list = trace_name_list
@@ -97,6 +100,8 @@ class StackedBarChart:
97
100
  self.xaxis_tick_text_format = xaxis_tick_text_format
98
101
  self.line_trace_name = line_trace_name
99
102
  self.x_axis_column = x_axis_column
103
+ self.x_unified_hovermode = x_unified_hovermode
104
+ self.hover_distance = hover_distance
100
105
  self.download_chart_button_id = download_chart_button_id
101
106
  self.download_data_button_id = download_data_button_id
102
107
  self.fig = self.create_stacked_bar_chart()
@@ -120,6 +125,43 @@ class StackedBarChart:
120
125
  self.download_data_button_id,
121
126
  )
122
127
 
128
+ def is_json_serializable(self, value):
129
+ "Determines whether value can be converted to json format."
130
+ try:
131
+ json.dumps(value)
132
+ return True
133
+ except (TypeError, OverflowError):
134
+ return False
135
+
136
+ def to_dict(self):
137
+ "Converts class attributes to json format."
138
+ result = {}
139
+ for k, v in self.__dict__.items():
140
+ if self.is_json_serializable(v):
141
+ result[k] = v
142
+ elif isinstance(v, pl.DataFrame):
143
+ result[k] = {"_type": "polars_df", "data": v.to_dicts()}
144
+ elif hasattr(v, "to_dict"):
145
+ result[k] = {"_type": "custom", "data": v.to_dict()}
146
+ else:
147
+ result[k] = f"<<non-serializable: {type(v).__name__}>>"
148
+ return result
149
+
150
+ @classmethod
151
+ def from_dict(cls, data):
152
+ "Creates a class instance from dict of attributes."
153
+ restored = {}
154
+ for k, v in data.items():
155
+ if isinstance(v, dict) and "_type" in v:
156
+ if v["_type"] == "polars_df":
157
+ restored[k] = pl.DataFrame(v["data"])
158
+ elif v["_type"] == "custom":
159
+ # optionally restore known nested types here
160
+ pass
161
+ else:
162
+ restored[k] = v
163
+ return cls(**restored)
164
+
123
165
  def get_stacked_bar_chart_for_download(self):
124
166
  """Return fig with title and subtitle for download as png"""
125
167
  return get_chart_for_download(self, self.create_stacked_bar_chart())
@@ -129,6 +171,7 @@ class StackedBarChart:
129
171
  ):
130
172
  """generates a stacked bar chart"""
131
173
  # pylint: disable=too-many-locals
174
+
132
175
  fig = go.Figure()
133
176
  colour_list = (
134
177
  AFAccessibleColours.CATEGORICAL.value
@@ -140,7 +183,7 @@ class StackedBarChart:
140
183
  )
141
184
  for _, (df, trace_name, colour) in enumerate(
142
185
  zip(
143
- self._get_df_list_for_time_series(),
186
+ self._get_df_list_for_bar_chart(),
144
187
  self.trace_name_list,
145
188
  colour_list,
146
189
  )
@@ -177,7 +220,7 @@ class StackedBarChart:
177
220
  update_layout_bgcolor_margin(fig, "#FFFFFF")
178
221
 
179
222
  fig.update_layout(
180
- legend=get_legend_configuration(),
223
+ legend=get_legend_configuration(reverse_order=True),
181
224
  font={"size": CHART_LABEL_FONT_SIZE},
182
225
  yaxis={
183
226
  "range": [min_y * 1.1, max_y * 1.1],
@@ -188,20 +231,12 @@ class StackedBarChart:
188
231
  showlegend=True,
189
232
  barmode="relative",
190
233
  xaxis={"categoryorder": "category ascending"},
234
+ ## copied from timeseries
235
+ hovermode="x unified" if self.x_unified_hovermode is True else "closest",
236
+ hoverdistance=self.hover_distance, # Increase distance to simulate hover 'always on'
191
237
  )
192
238
  return fig
193
239
 
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
240
  def create_bar_chart_trace(
206
241
  self,
207
242
  df: pl.DataFrame,
@@ -232,6 +267,8 @@ class StackedBarChart:
232
267
  )
233
268
 
234
269
  def _get_hover_template(self, trace_name):
270
+ if self.x_unified_hovermode is True:
271
+ return f"{trace_name}: " + "%{customdata[0]}<extra></extra>"
235
272
  hover_text_headers = self.hover_data[trace_name][HOVER_TEXT_HEADERS]
236
273
  hover_template = (
237
274
  f"{trace_name}<br>"
@@ -246,36 +283,7 @@ class StackedBarChart:
246
283
  customdata = df[self.hover_data[trace_name][CUSTOM_DATA]]
247
284
  return customdata
248
285
 
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]:
286
+ def _get_df_list_for_bar_chart(self) -> list[pl.DataFrame]:
279
287
  if self.trace_name_column is not None:
280
288
  df_list = [
281
289
  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.0.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.0.0",
14
14
  long_description=long_description,
15
15
  long_description_content_type="text/markdown",
16
16
  packages=find_packages(),