@gen3/frontend 0.10.47 → 0.10.48

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 (265) hide show
  1. package/dist/cjs/index.js +2043 -277
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/dts/components/Login/LoginPanel.d.ts.map +1 -1
  4. package/dist/dts/components/Login/LoginPanel.js +2 -1
  5. package/dist/dts/components/Login/LoginPanel.js.map +1 -1
  6. package/dist/dts/components/charts/Charts.d.ts +1 -2
  7. package/dist/dts/components/charts/Charts.d.ts.map +1 -1
  8. package/dist/dts/components/charts/Charts.js +17 -13
  9. package/dist/dts/components/charts/Charts.js.map +1 -1
  10. package/dist/dts/components/charts/echarts/ReactECharts.d.ts.map +1 -1
  11. package/dist/dts/components/charts/echarts/ReactECharts.js +9 -14
  12. package/dist/dts/components/charts/echarts/ReactECharts.js.map +1 -1
  13. package/dist/dts/components/charts/tests/utils.unit.test.js +2 -2
  14. package/dist/dts/components/charts/tests/utils.unit.test.js.map +1 -1
  15. package/dist/dts/components/charts/types.d.ts +3 -3
  16. package/dist/dts/components/charts/types.d.ts.map +1 -1
  17. package/dist/dts/components/charts/utils.d.ts +2 -3
  18. package/dist/dts/components/charts/utils.d.ts.map +1 -1
  19. package/dist/dts/components/charts/utils.js +2 -3
  20. package/dist/dts/components/charts/utils.js.map +1 -1
  21. package/dist/dts/components/counts/CountsValue.js +1 -1
  22. package/dist/dts/components/counts/CountsValue.js.map +1 -1
  23. package/dist/dts/components/facets/EnumFacet.d.ts +3 -3
  24. package/dist/dts/components/facets/EnumFacet.d.ts.map +1 -1
  25. package/dist/dts/components/facets/EnumFacet.js +8 -233
  26. package/dist/dts/components/facets/EnumFacet.js.map +1 -1
  27. package/dist/dts/components/facets/ExactValueFacet.js +4 -4
  28. package/dist/dts/components/facets/ExactValueFacet.js.map +1 -1
  29. package/dist/dts/components/facets/FacetControlsHeader.d.ts +24 -0
  30. package/dist/dts/components/facets/FacetControlsHeader.d.ts.map +1 -0
  31. package/dist/dts/components/facets/FacetControlsHeader.js +53 -0
  32. package/dist/dts/components/facets/FacetControlsHeader.js.map +1 -0
  33. package/dist/dts/components/facets/FacetEnumList.d.ts +16 -0
  34. package/dist/dts/components/facets/FacetEnumList.d.ts.map +1 -0
  35. package/dist/dts/components/facets/FacetEnumList.js +234 -0
  36. package/dist/dts/components/facets/FacetEnumList.js.map +1 -0
  37. package/dist/dts/components/facets/FacetExpander.d.ts.map +1 -1
  38. package/dist/dts/components/facets/FacetExpander.js +2 -2
  39. package/dist/dts/components/facets/FacetExpander.js.map +1 -1
  40. package/dist/dts/components/facets/FacetSelector.d.ts +13 -0
  41. package/dist/dts/components/facets/FacetSelector.d.ts.map +1 -0
  42. package/dist/dts/components/facets/FacetSelector.js +58 -0
  43. package/dist/dts/components/facets/FacetSelector.js.map +1 -0
  44. package/dist/dts/components/facets/MultiSelectValueFacet.js +5 -5
  45. package/dist/dts/components/facets/MultiSelectValueFacet.js.map +1 -1
  46. package/dist/dts/components/facets/RangeFacet.d.ts +4 -5
  47. package/dist/dts/components/facets/RangeFacet.d.ts.map +1 -1
  48. package/dist/dts/components/facets/RangeFacet.js +4 -4
  49. package/dist/dts/components/facets/RangeFacet.js.map +1 -1
  50. package/dist/dts/components/facets/components.d.ts +1 -1
  51. package/dist/dts/components/facets/components.d.ts.map +1 -1
  52. package/dist/dts/components/facets/components.js +3 -3
  53. package/dist/dts/components/facets/components.js.map +1 -1
  54. package/dist/dts/components/facets/constants.d.ts +1 -0
  55. package/dist/dts/components/facets/constants.d.ts.map +1 -1
  56. package/dist/dts/components/facets/constants.js +1 -0
  57. package/dist/dts/components/facets/constants.js.map +1 -1
  58. package/dist/dts/components/facets/createFacetCard.js +4 -4
  59. package/dist/dts/components/facets/createFacetCard.js.map +1 -1
  60. package/dist/dts/components/facets/index.d.ts +5 -0
  61. package/dist/dts/components/facets/index.d.ts.map +1 -0
  62. package/dist/dts/components/facets/index.js +5 -0
  63. package/dist/dts/components/facets/index.js.map +1 -0
  64. package/dist/dts/components/facets/types.d.ts +29 -13
  65. package/dist/dts/components/facets/types.d.ts.map +1 -1
  66. package/dist/dts/components/facets/types.js.map +1 -1
  67. package/dist/dts/components/facets/utils.d.ts +2 -2
  68. package/dist/dts/components/facets/utils.d.ts.map +1 -1
  69. package/dist/dts/components/facets/utils.js +11 -5
  70. package/dist/dts/components/facets/utils.js.map +1 -1
  71. package/dist/dts/features/CohortBuilder/CohortPanel.d.ts.map +1 -1
  72. package/dist/dts/features/CohortBuilder/CohortPanel.js +4 -2
  73. package/dist/dts/features/CohortBuilder/CohortPanel.js.map +1 -1
  74. package/dist/dts/features/CohortBuilder/ExplorerTable/ExploreTableDetails/RowTableDetailsPanel.js.map +1 -1
  75. package/dist/dts/features/CohortBuilder/QueryExpressionSection.d.ts.map +1 -1
  76. package/dist/dts/features/CohortBuilder/QueryExpressionSection.js +21 -9
  77. package/dist/dts/features/CohortBuilder/QueryExpressionSection.js.map +1 -1
  78. package/dist/dts/features/CohortBuilder/QueryRepresentation.js +2 -2
  79. package/dist/dts/features/CohortBuilder/QueryRepresentation.js.map +1 -1
  80. package/dist/dts/features/CohortBuilder/types.d.ts +6 -4
  81. package/dist/dts/features/CohortBuilder/types.d.ts.map +1 -1
  82. package/dist/dts/features/CohortBuilder/types.js.map +1 -1
  83. package/dist/dts/features/CohortDiscovery/ActionButtonGroup.d.ts +3 -0
  84. package/dist/dts/features/CohortDiscovery/ActionButtonGroup.d.ts.map +1 -0
  85. package/dist/dts/features/CohortDiscovery/ActionButtonGroup.js +13 -0
  86. package/dist/dts/features/CohortDiscovery/ActionButtonGroup.js.map +1 -0
  87. package/dist/dts/features/CohortDiscovery/ChartsAndFacetsPanel.d.ts +16 -0
  88. package/dist/dts/features/CohortDiscovery/ChartsAndFacetsPanel.d.ts.map +1 -0
  89. package/dist/dts/features/CohortDiscovery/ChartsAndFacetsPanel.js +70 -0
  90. package/dist/dts/features/CohortDiscovery/ChartsAndFacetsPanel.js.map +1 -0
  91. package/dist/dts/features/CohortDiscovery/CohortDiscovery.d.ts +4 -0
  92. package/dist/dts/features/CohortDiscovery/CohortDiscovery.d.ts.map +1 -0
  93. package/dist/dts/features/CohortDiscovery/CohortDiscovery.js +17 -0
  94. package/dist/dts/features/CohortDiscovery/CohortDiscovery.js.map +1 -0
  95. package/dist/dts/features/CohortDiscovery/FacetSelectionPanel.d.ts +12 -0
  96. package/dist/dts/features/CohortDiscovery/FacetSelectionPanel.d.ts.map +1 -0
  97. package/dist/dts/features/CohortDiscovery/FacetSelectionPanel.js +26 -0
  98. package/dist/dts/features/CohortDiscovery/FacetSelectionPanel.js.map +1 -0
  99. package/dist/dts/features/CohortDiscovery/FilterExpandSlice.d.ts +11 -0
  100. package/dist/dts/features/CohortDiscovery/FilterExpandSlice.d.ts.map +1 -0
  101. package/dist/dts/features/CohortDiscovery/FilterExpandSlice.js +34 -0
  102. package/dist/dts/features/CohortDiscovery/FilterExpandSlice.js.map +1 -0
  103. package/dist/dts/features/CohortDiscovery/FilterPanels/EnumFacetPanel.d.ts +16 -0
  104. package/dist/dts/features/CohortDiscovery/FilterPanels/EnumFacetPanel.d.ts.map +1 -0
  105. package/dist/dts/features/CohortDiscovery/FilterPanels/EnumFacetPanel.js +22 -0
  106. package/dist/dts/features/CohortDiscovery/FilterPanels/EnumFacetPanel.js.map +1 -0
  107. package/dist/dts/features/CohortDiscovery/FilterPanels/FacetPanelDataHeader.d.ts +8 -0
  108. package/dist/dts/features/CohortDiscovery/FilterPanels/FacetPanelDataHeader.d.ts.map +1 -0
  109. package/dist/dts/features/CohortDiscovery/FilterPanels/FacetPanelDataHeader.js +8 -0
  110. package/dist/dts/features/CohortDiscovery/FilterPanels/FacetPanelDataHeader.js.map +1 -0
  111. package/dist/dts/features/CohortDiscovery/FilterPanels/createFacetPanel.d.ts +5 -0
  112. package/dist/dts/features/CohortDiscovery/FilterPanels/createFacetPanel.d.ts.map +1 -0
  113. package/dist/dts/features/CohortDiscovery/FilterPanels/createFacetPanel.js +10 -0
  114. package/dist/dts/features/CohortDiscovery/FilterPanels/createFacetPanel.js.map +1 -0
  115. package/dist/dts/features/CohortDiscovery/IndexPanel.d.ts +4 -0
  116. package/dist/dts/features/CohortDiscovery/IndexPanel.d.ts.map +1 -0
  117. package/dist/dts/features/CohortDiscovery/IndexPanel.js +96 -0
  118. package/dist/dts/features/CohortDiscovery/IndexPanel.js.map +1 -0
  119. package/dist/dts/features/CohortDiscovery/SelectedFacetsSlice.d.ts +14 -0
  120. package/dist/dts/features/CohortDiscovery/SelectedFacetsSlice.d.ts.map +1 -0
  121. package/dist/dts/features/CohortDiscovery/SelectedFacetsSlice.js +56 -0
  122. package/dist/dts/features/CohortDiscovery/SelectedFacetsSlice.js.map +1 -0
  123. package/dist/dts/features/CohortDiscovery/appApi.d.ts +19 -0
  124. package/dist/dts/features/CohortDiscovery/appApi.d.ts.map +1 -0
  125. package/dist/dts/features/CohortDiscovery/appApi.js +27 -0
  126. package/dist/dts/features/CohortDiscovery/appApi.js.map +1 -0
  127. package/dist/dts/features/CohortDiscovery/hooks.d.ts +4 -0
  128. package/dist/dts/features/CohortDiscovery/hooks.d.ts.map +1 -0
  129. package/dist/dts/features/CohortDiscovery/hooks.js +17 -0
  130. package/dist/dts/features/CohortDiscovery/hooks.js.map +1 -0
  131. package/dist/dts/features/CohortDiscovery/registerApp.d.ts +3 -0
  132. package/dist/dts/features/CohortDiscovery/registerApp.d.ts.map +1 -0
  133. package/dist/dts/features/CohortDiscovery/registerApp.js +17 -0
  134. package/dist/dts/features/CohortDiscovery/registerApp.js.map +1 -0
  135. package/dist/dts/features/CohortDiscovery/types.d.ts +12 -0
  136. package/dist/dts/features/CohortDiscovery/types.d.ts.map +1 -0
  137. package/dist/dts/features/CohortDiscovery/types.js +2 -0
  138. package/dist/dts/features/CohortDiscovery/types.js.map +1 -0
  139. package/dist/dts/features/CohortDiscovery/utils.d.ts +3 -0
  140. package/dist/dts/features/CohortDiscovery/utils.d.ts.map +1 -0
  141. package/dist/dts/features/CohortDiscovery/utils.js +10 -0
  142. package/dist/dts/features/CohortDiscovery/utils.js.map +1 -0
  143. package/dist/dts/features/CohortDiversity/CohortDiversityApp.d.ts +4 -0
  144. package/dist/dts/features/CohortDiversity/CohortDiversityApp.d.ts.map +1 -0
  145. package/dist/dts/features/CohortDiversity/CohortDiversityApp.js +54 -0
  146. package/dist/dts/features/CohortDiversity/CohortDiversityApp.js.map +1 -0
  147. package/dist/dts/features/CohortDiversity/ComnparisonCard.d.ts +15 -0
  148. package/dist/dts/features/CohortDiversity/ComnparisonCard.d.ts.map +1 -0
  149. package/dist/dts/features/CohortDiversity/ComnparisonCard.js +32 -0
  150. package/dist/dts/features/CohortDiversity/ComnparisonCard.js.map +1 -0
  151. package/dist/dts/features/CohortDiversity/ComparisonCards.d.ts +15 -0
  152. package/dist/dts/features/CohortDiversity/ComparisonCards.d.ts.map +1 -0
  153. package/dist/dts/features/CohortDiversity/ComparisonCards.js +14 -0
  154. package/dist/dts/features/CohortDiversity/ComparisonCards.js.map +1 -0
  155. package/dist/dts/features/CohortDiversity/appApi.d.ts +8 -0
  156. package/dist/dts/features/CohortDiversity/appApi.d.ts.map +1 -0
  157. package/dist/dts/features/CohortDiversity/appApi.js +4 -0
  158. package/dist/dts/features/CohortDiversity/appApi.js.map +1 -0
  159. package/dist/dts/features/CohortDiversity/charts/BarComparison.d.ts +5 -0
  160. package/dist/dts/features/CohortDiversity/charts/BarComparison.d.ts.map +1 -0
  161. package/dist/dts/features/CohortDiversity/charts/BarComparison.js +70 -0
  162. package/dist/dts/features/CohortDiversity/charts/BarComparison.js.map +1 -0
  163. package/dist/dts/features/CohortDiversity/charts/ChartCard.d.ts +16 -0
  164. package/dist/dts/features/CohortDiversity/charts/ChartCard.d.ts.map +1 -0
  165. package/dist/dts/features/CohortDiversity/charts/ChartCard.js +45 -0
  166. package/dist/dts/features/CohortDiversity/charts/ChartCard.js.map +1 -0
  167. package/dist/dts/features/CohortDiversity/charts/ComparisonCharts.d.ts +13 -0
  168. package/dist/dts/features/CohortDiversity/charts/ComparisonCharts.d.ts.map +1 -0
  169. package/dist/dts/features/CohortDiversity/charts/ComparisonCharts.js +18 -0
  170. package/dist/dts/features/CohortDiversity/charts/ComparisonCharts.js.map +1 -0
  171. package/dist/dts/features/CohortDiversity/charts/RadarComparison.d.ts +5 -0
  172. package/dist/dts/features/CohortDiversity/charts/RadarComparison.d.ts.map +1 -0
  173. package/dist/dts/features/CohortDiversity/charts/RadarComparison.js +90 -0
  174. package/dist/dts/features/CohortDiversity/charts/RadarComparison.js.map +1 -0
  175. package/dist/dts/features/CohortDiversity/charts/diversityChartsFactory.d.ts +6 -0
  176. package/dist/dts/features/CohortDiversity/charts/diversityChartsFactory.d.ts.map +1 -0
  177. package/dist/dts/features/CohortDiversity/charts/diversityChartsFactory.js +24 -0
  178. package/dist/dts/features/CohortDiversity/charts/diversityChartsFactory.js.map +1 -0
  179. package/dist/dts/features/CohortDiversity/charts/types.d.ts +12 -0
  180. package/dist/dts/features/CohortDiversity/charts/types.d.ts.map +1 -0
  181. package/dist/dts/features/CohortDiversity/charts/types.js +2 -0
  182. package/dist/dts/features/CohortDiversity/charts/types.js.map +1 -0
  183. package/dist/dts/features/CohortDiversity/charts/utils.d.ts +2 -0
  184. package/dist/dts/features/CohortDiversity/charts/utils.d.ts.map +1 -0
  185. package/dist/dts/features/CohortDiversity/charts/utils.js +4 -0
  186. package/dist/dts/features/CohortDiversity/charts/utils.js.map +1 -0
  187. package/dist/dts/features/CohortDiversity/diversityApi.d.ts +141 -0
  188. package/dist/dts/features/CohortDiversity/diversityApi.d.ts.map +1 -0
  189. package/dist/dts/features/CohortDiversity/diversityApi.js +14 -0
  190. package/dist/dts/features/CohortDiversity/diversityApi.js.map +1 -0
  191. package/dist/dts/features/CohortDiversity/registerApp.d.ts +3 -0
  192. package/dist/dts/features/CohortDiversity/registerApp.d.ts.map +1 -0
  193. package/dist/dts/features/CohortDiversity/registerApp.js +19 -0
  194. package/dist/dts/features/CohortDiversity/registerApp.js.map +1 -0
  195. package/dist/dts/features/CohortDiversity/statistics/StatisticsCard.d.ts +9 -0
  196. package/dist/dts/features/CohortDiversity/statistics/StatisticsCard.d.ts.map +1 -0
  197. package/dist/dts/features/CohortDiversity/statistics/StatisticsCard.js +68 -0
  198. package/dist/dts/features/CohortDiversity/statistics/StatisticsCard.js.map +1 -0
  199. package/dist/dts/features/CohortDiversity/statistics/StatisticsPanel.d.ts +13 -0
  200. package/dist/dts/features/CohortDiversity/statistics/StatisticsPanel.d.ts.map +1 -0
  201. package/dist/dts/features/CohortDiversity/statistics/StatisticsPanel.js +16 -0
  202. package/dist/dts/features/CohortDiversity/statistics/StatisticsPanel.js.map +1 -0
  203. package/dist/dts/features/CohortDiversity/statistics/data/data.d.ts +2 -0
  204. package/dist/dts/features/CohortDiversity/statistics/data/data.d.ts.map +1 -0
  205. package/dist/dts/features/CohortDiversity/statistics/data/data.js +50 -0
  206. package/dist/dts/features/CohortDiversity/statistics/data/data.js.map +1 -0
  207. package/dist/dts/features/CohortDiversity/statistics/data/tests/diversityResponse.json +228 -0
  208. package/dist/dts/features/CohortDiversity/statistics/data/tests/processHistogramResponse.unit.test.d.ts +2 -0
  209. package/dist/dts/features/CohortDiversity/statistics/data/tests/processHistogramResponse.unit.test.d.ts.map +1 -0
  210. package/dist/dts/features/CohortDiversity/statistics/data/tests/processHistogramResponse.unit.test.js +365 -0
  211. package/dist/dts/features/CohortDiversity/statistics/data/tests/processHistogramResponse.unit.test.js.map +1 -0
  212. package/dist/dts/features/CohortDiversity/statistics/data/utils.d.ts +49 -0
  213. package/dist/dts/features/CohortDiversity/statistics/data/utils.d.ts.map +1 -0
  214. package/dist/dts/features/CohortDiversity/statistics/data/utils.js +146 -0
  215. package/dist/dts/features/CohortDiversity/statistics/data/utils.js.map +1 -0
  216. package/dist/dts/features/CohortDiversity/statistics/queries.d.ts +6 -0
  217. package/dist/dts/features/CohortDiversity/statistics/queries.d.ts.map +1 -0
  218. package/dist/dts/features/CohortDiversity/statistics/queries.js +24 -0
  219. package/dist/dts/features/CohortDiversity/statistics/queries.js.map +1 -0
  220. package/dist/dts/features/CohortDiversity/types.d.ts +26 -0
  221. package/dist/dts/features/CohortDiversity/types.d.ts.map +1 -0
  222. package/dist/dts/features/CohortDiversity/types.js +2 -0
  223. package/dist/dts/features/CohortDiversity/types.js.map +1 -0
  224. package/dist/dts/features/Discovery/Charts/ChartsPanel.d.ts.map +1 -1
  225. package/dist/dts/features/Discovery/Charts/ChartsPanel.js +44 -33
  226. package/dist/dts/features/Discovery/Charts/ChartsPanel.js.map +1 -1
  227. package/dist/dts/features/Discovery/TableRenderers/RowRendererFactory.d.ts.map +1 -1
  228. package/dist/dts/features/Discovery/TableRenderers/RowRendererFactory.js +1 -1
  229. package/dist/dts/features/Discovery/TableRenderers/RowRendererFactory.js.map +1 -1
  230. package/dist/dts/features/Navigation/NavigationBar.d.ts.map +1 -1
  231. package/dist/dts/features/Navigation/NavigationBar.js +1 -1
  232. package/dist/dts/features/Navigation/NavigationBar.js.map +1 -1
  233. package/dist/dts/features/Navigation/TopBar.d.ts.map +1 -1
  234. package/dist/dts/features/Navigation/TopBar.js +1 -1
  235. package/dist/dts/features/Navigation/TopBar.js.map +1 -1
  236. package/dist/dts/index.d.ts +3 -1
  237. package/dist/dts/index.d.ts.map +1 -1
  238. package/dist/dts/index.js +3 -1
  239. package/dist/dts/index.js.map +1 -1
  240. package/dist/dts/lib/common/staticProps.js +1 -1
  241. package/dist/dts/lib/common/staticProps.js.map +1 -1
  242. package/dist/dts/lib/content/types.d.ts +6 -0
  243. package/dist/dts/lib/content/types.d.ts.map +1 -1
  244. package/dist/dts/lib/session/session.js.map +1 -1
  245. package/dist/dts/pages/admin/authz/data.d.ts.map +1 -1
  246. package/dist/dts/pages/admin/authz/data.js +5 -2
  247. package/dist/dts/pages/admin/authz/data.js.map +1 -1
  248. package/dist/dts/types/common.d.ts +5 -0
  249. package/dist/dts/types/common.d.ts.map +1 -0
  250. package/dist/dts/types/common.js +2 -0
  251. package/dist/dts/types/common.js.map +1 -0
  252. package/dist/dts/types/index.d.ts +1 -0
  253. package/dist/dts/types/index.d.ts.map +1 -1
  254. package/dist/dts/types/index.js +1 -0
  255. package/dist/dts/types/index.js.map +1 -1
  256. package/dist/dts/utils/isType.d.ts.map +1 -1
  257. package/dist/dts/utils/strings.d.ts +4 -0
  258. package/dist/dts/utils/strings.d.ts.map +1 -1
  259. package/dist/dts/utils/strings.js +15 -3
  260. package/dist/dts/utils/strings.js.map +1 -1
  261. package/dist/esm/index.js +2045 -283
  262. package/dist/esm/index.js.map +1 -1
  263. package/dist/index.d.ts +36 -22
  264. package/dist/tsconfig.tsbuildinfo +1 -1
  265. package/package.json +5 -3
package/dist/esm/index.js CHANGED
@@ -3,15 +3,15 @@ import * as React from 'react';
3
3
  import React__default, { useState, useCallback, useEffect, useContext, useRef, createElement, createContext, useMemo, forwardRef, useReducer } from 'react';
4
4
  import { twMerge } from 'tailwind-merge';
5
5
  import Image from 'next/image';
6
- import { toString, isArray, get, partial, omit, capitalize as capitalize$1 } from 'lodash';
6
+ import { toString, capitalize as capitalize$1, isArray, get, partial, omit } from 'lodash';
7
7
  import Link from 'next/link';
8
- import { FaExternalLinkAlt, FaQuestion, FaExclamation, FaExclamationTriangle, FaUndo, FaPlus, FaGraduationCap, FaRegQuestionCircle, FaVideo, FaCircle } from 'react-icons/fa';
8
+ import { FaExternalLinkAlt, FaQuestion, FaExclamation, FaExclamationTriangle, FaUndo, FaPlus, FaChartPie, FaGraduationCap, FaRegQuestionCircle, FaVideo, FaCircle } from 'react-icons/fa';
9
9
  import { Icon, addCollection } from '@iconify/react';
10
- import { Tooltip, UnstyledButton, Menu, Text, Button, Box, Badge, Alert, Tabs, Accordion, Stack, Group, Drawer, CopyButton, LoadingOverlay, factory, useProps, useMantineTheme, getStyleObject, Paper, Checkbox, SegmentedControl, Loader, Grid, Card, Table, ColorSwatch, Modal, Switch, Divider, Autocomplete, TextInput, Title, Avatar, Select, Textarea, FileButton, Anchor, ThemeIcon, ActionIcon, NumberInput, RangeSlider, MultiSelect, Center, MantineProvider, createTheme, Highlight, List } from '@mantine/core';
10
+ import { Tooltip, UnstyledButton, Menu, Text, Button, Box, Badge, Alert, Tabs, Accordion, Stack, Group, Drawer, CopyButton, LoadingOverlay, factory, useProps, useMantineTheme, getStyleObject, Paper, Checkbox, SegmentedControl, Loader, Grid, Card, Table, ColorSwatch, Modal, Switch, Divider, Autocomplete, TextInput, Title, Avatar, Select, Textarea, FileButton, Anchor, ThemeIcon, ActionIcon, NumberInput, RangeSlider, MultiSelect, Center, Flex, ScrollArea, rem, MantineProvider, createTheme, Highlight, List } from '@mantine/core';
11
11
  import { useRouter } from 'next/router';
12
12
  import { usePathname } from 'next/navigation';
13
- import { MdLogin, MdKeyboardDoubleArrowLeft, MdUndo, MdSearch, MdClose, MdInfo, MdAddCircle, MdRemoveCircle, MdFlip, MdOutlineArrowBack, MdOutlineArrowForward, MdOutlineArrowBackIos, MdOutlineArrowForwardIos, MdKeyboardArrowDown, MdKeyboardArrowUp, MdDownload, MdFormatQuote, MdOutlineSearch, MdOutlineBarChart, MdGroup, MdDelete } from 'react-icons/md';
14
- import { useCoreDispatch, useLazyFetchUserDetailsQuery, useCoreSelector, selectUserAuthStatus, GEN3_REDIRECT_URL, showModal, Modals, GEN3_FENCE_API, isAuthenticated, selectUserDetails, useIsUserLoggedIn, fieldNameToTitle, useGetMDSQuery, selectAuthzMappingData, useGetAggMDSQuery, useAskQuestionMutation, useGetIndexAggMDSQuery, useGetTagsQuery, useUserAuth, useGetAuthzMappingsQuery, useGetLoginProvidersQuery, hideModal, useGetCSRFQuery, selectCurrentModal, updateCohortFilter, selectIndexedFilterByName, isOperationWithField, removeCohortFilter, trimFirstFieldNameToTitle, selectCohortFilters, handleOperation, selectCurrentCohortId, clearCohortFilters, selectCurrentCohortName, useGeneralGQLQuery, selectIndexFilters, useGetRawDataAndTotalCountsQuery, Accessibility, downloadFromGuppyToBlob, downloadJSONDataFromGuppy, useGetAggsQuery, extractEnumFilterValue, useGetCountsQuery, selectHeadersWithCSRFToken, GEN3_GUPPY_API, GEN3_COMMONS_NAME, CoreProvider, useGetCredentialsQuery, useRemoveCredentialMutation, useAddNewCredentialMutation, useGetExternalLoginsQuery, useGetDictionaryQuery, useGetProjectsDetailsQuery, useGetSubmissionsQuery, useLazyGetCrosswalkDataQuery } from '@gen3/core';
13
+ import { MdLogin, MdKeyboardDoubleArrowLeft, MdUndo, MdSearch, MdClose, MdInfo, MdExpandLess, MdExpandMore, MdFlip, MdAddCircle, MdRemoveCircle, MdOutlineArrowBack, MdOutlineArrowForward, MdOutlineArrowBackIos, MdOutlineArrowForwardIos, MdKeyboardArrowDown, MdKeyboardArrowUp, MdDownload, MdFormatQuote, MdOutlineSearch, MdOutlineBarChart, MdGroup, MdDelete } from 'react-icons/md';
14
+ import { useCoreDispatch, useLazyFetchUserDetailsQuery, useCoreSelector, selectUserAuthStatus, GEN3_REDIRECT_URL, showModal, Modals, GEN3_FENCE_API, isAuthenticated, selectUserDetails, useIsUserLoggedIn, fieldNameToTitle, useGetMDSQuery, selectAuthzMappingData, useGetAggMDSQuery, useAskQuestionMutation, useGetIndexAggMDSQuery, useGetTagsQuery, useUserAuth, useGetAuthzMappingsQuery, useGetLoginProvidersQuery, hideModal, useGetCSRFQuery, selectCurrentModal, updateCohortFilter, selectIndexedFilterByName, isOperationWithField, removeCohortFilter, trimFirstFieldNameToTitle, selectCohortFilters, handleOperation, selectCurrentCohortId, clearCohortFilters, selectCurrentCohortName, useGeneralGQLQuery, selectIndexFilters, useGetRawDataAndTotalCountsQuery, Accessibility, downloadFromGuppyToBlob, downloadJSONDataFromGuppy, useGetAggsQuery, extractEnumFilterValue, useGetCountsQuery, selectHeadersWithCSRFToken, GEN3_GUPPY_API, GEN3_COMMONS_NAME, createAppStore, createGen3AppWithOwnStore, createAppApiForRTKQ, getGen3AppId, CoreProvider, useGetCredentialsQuery, useRemoveCredentialMutation, useAddNewCredentialMutation, useGetExternalLoginsQuery, useGetDictionaryQuery, useGetProjectsDetailsQuery, useGetSubmissionsQuery, useLazyGetCrosswalkDataQuery } from '@gen3/core';
15
15
  import { useDeepCompareEffect, useDeepCompareMemo, useDeepCompareCallback } from 'use-deep-compare';
16
16
  import 'swr';
17
17
  import { getCookie, deleteCookie, setCookie } from 'cookies-next';
@@ -25,7 +25,7 @@ import { useMantineReactTable, MantineReactTable } from 'mantine-react-table';
25
25
  import { JSONPath } from 'jsonpath-plus';
26
26
  import { LuClock, LuCircleSlash, LuUnlock, LuLock, LuRefreshCw } from 'react-icons/lu';
27
27
  import tinycolor from 'tinycolor2';
28
- import { useDisclosure, useDidUpdate, mergeRefs, useReducedMotion, useElementSize, useClipboard, useMediaQuery, useLocalStorage, useScrollIntoView } from '@mantine/hooks';
28
+ import { useDisclosure, useDidUpdate, mergeRefs, useReducedMotion, useResizeObserver, useElementSize, useClipboard, useMediaQuery, useLocalStorage, useScrollIntoView } from '@mantine/hooks';
29
29
  import { FiDownload, FiMoreVertical } from 'react-icons/fi';
30
30
  import { TiArrowUnsorted, TiArrowSortedUp, TiArrowSortedDown } from 'react-icons/ti';
31
31
  import { flushSync } from 'react-dom';
@@ -47,6 +47,11 @@ import { IoMdArrowDropdown, IoMdRefresh, IoMdLogIn } from 'react-icons/io';
47
47
  import GraphiQL from 'graphiql';
48
48
  import fs from 'fs';
49
49
  import path from 'path';
50
+ import { PersistGate } from 'redux-persist/integration/react';
51
+ import { persistReducer, persistStore } from 'redux-persist';
52
+ import { combineReducers } from 'redux';
53
+ import storage from 'redux-persist/lib/storage';
54
+ import { createSlice } from '@reduxjs/toolkit';
50
55
  import { ModalsProvider } from '@mantine/modals';
51
56
  import dynamic from 'next/dynamic';
52
57
  import { useForm } from '@mantine/form';
@@ -647,7 +652,9 @@ const TopBar = ({ items, loginButtonVisibility = LoginButtonVisibility.Hidden, c
647
652
  return /*#__PURE__*/ jsx("div", {
648
653
  children: /*#__PURE__*/ jsx("header", {
649
654
  className: extractClassName('root', mergedClassnames),
650
- children: /*#__PURE__*/ jsxs("nav", {
655
+ children: /*#__PURE__*/ jsxs("div", {
656
+ role: "navigation",
657
+ "aria-label": "top most navigation",
651
658
  className: "flex items-center align-middle",
652
659
  children: [
653
660
  processTopBarItems(items, loginButtonVisibility === LoginButtonVisibility.Visible),
@@ -793,6 +800,8 @@ const NavigationLogo = ({ src, title, description, width, height, divider = fals
793
800
  router.pathname
794
801
  ]);
795
802
  return /*#__PURE__*/ jsxs("div", {
803
+ role: "navigation",
804
+ "aria-label": "main site navigation",
796
805
  className: extractClassName('root', mergedClassnames),
797
806
  children: [
798
807
  /*#__PURE__*/ jsx("div", {
@@ -1248,7 +1257,7 @@ class DiscoveryRowRendererFactory {
1248
1257
  }
1249
1258
  static getRowRenderer(type, functionName) {
1250
1259
  if (!(type in DiscoveryRowRendererFactory.getInstance().RowRendererCatalog)) {
1251
- console.log('No row renderer found for type: ', type);
1260
+ console.warn('No row renderer found for type: ', type);
1252
1261
  return defaultRowRenderer;
1253
1262
  }
1254
1263
  return DiscoveryRowRendererFactory.getInstance().RowRendererCatalog[type][functionName] ?? defaultRowRenderer;
@@ -1468,6 +1477,15 @@ const focusStyles = 'focus-visible:outline-none focus-visible:ring-offset-2 focu
1468
1477
  const stripTrailingSlash = (str)=>{
1469
1478
  return str.endsWith('/') ? str.slice(0, -1) : str;
1470
1479
  };
1480
+ const SPECIAL_CASE_FIELDS = {
1481
+ icd_10_code: 'ICD-10 Code'
1482
+ };
1483
+ const toDisplayName = (field)=>{
1484
+ const parsed = field.split('.');
1485
+ const fieldName = parsed.at(-1);
1486
+ if (!fieldName) return 'NotSet';
1487
+ return fieldName.split('_').map((w)=>capitalize$1(w)).join(' ');
1488
+ };
1471
1489
 
1472
1490
  const isArrayOfString = (value)=>{
1473
1491
  return Array.isArray(value) && value.every((element)=>typeof element === 'string');
@@ -3082,18 +3100,18 @@ const defaultStatisticRenderer = ({ value, label, ...props })=>{
3082
3100
  ]
3083
3101
  });
3084
3102
  };
3085
- const DefaultRendererCatalog$1 = {
3103
+ const DefaultRendererCatalog$2 = {
3086
3104
  string: {
3087
3105
  default: defaultStatisticRenderer
3088
3106
  }
3089
3107
  };
3090
- let instance$3;
3108
+ let instance$4;
3091
3109
  const StatisticRendererFactory = ()=>{
3092
- if (!instance$3) {
3093
- instance$3 = new RenderFactoryTypedInstance();
3094
- instance$3.registerRendererCatalog(DefaultRendererCatalog$1);
3110
+ if (!instance$4) {
3111
+ instance$4 = new RenderFactoryTypedInstance();
3112
+ instance$4.registerRendererCatalog(DefaultRendererCatalog$2);
3095
3113
  }
3096
- return instance$3;
3114
+ return instance$4;
3097
3115
  };
3098
3116
 
3099
3117
  const BuildSummaryStatisticPanel = (summaries = [])=>{
@@ -3159,11 +3177,10 @@ const processRangeKeyLabel = (key)=>{
3159
3177
  /**
3160
3178
  * Computes the row span for each item in the charts object.
3161
3179
  *
3162
- * @param { Record<string, SummaryChart>} charts - The charts object containing summary charts.
3180
+ * @param { number } numItems - The charts object containing summary charts.
3163
3181
  * @param {number} [numCols=3] - The number of columns per row.
3164
3182
  * @returns {number[]} - An array of row spans for each item in the charts object.
3165
- */ const computeRowSpan = (charts, numCols = 3)=>{
3166
- const numItems = Object.keys(charts).length;
3183
+ */ const computeRowSpan = (numItems, numCols = 3)=>{
3167
3184
  // compute the row span for the last row
3168
3185
  const numLastRow = numItems % numCols;
3169
3186
  let spans = new Array(numItems - numLastRow).fill(Math.floor(12 / numCols));
@@ -3172,24 +3189,15 @@ const processRangeKeyLabel = (key)=>{
3172
3189
  };
3173
3190
 
3174
3191
  const ReactECharts = ({ option, style, settings, loading, theme })=>{
3175
- const chartRef = useRef(null);
3192
+ const [chartRoot, setChartRoot] = useState(undefined);
3193
+ const [chartRef, rect] = useResizeObserver();
3176
3194
  useDeepCompareEffect(()=>{
3177
3195
  // Initialize chart
3178
3196
  let chart;
3179
3197
  if (chartRef.current !== null) {
3180
3198
  chart = init(chartRef.current, theme);
3181
3199
  }
3182
- // Add chart resize listener
3183
- // ResizeObserver is leading to a bit janky UX
3184
- function resizeChart(event) {
3185
- chart?.resize();
3186
- }
3187
- window.addEventListener('resize', resizeChart);
3188
- // Return cleanup function
3189
- return ()=>{
3190
- chart?.dispose();
3191
- window.removeEventListener('resize', resizeChart);
3192
- };
3200
+ setChartRoot(chart);
3193
3201
  }, [
3194
3202
  theme
3195
3203
  ]);
@@ -3214,7 +3222,14 @@ const ReactECharts = ({ option, style, settings, loading, theme })=>{
3214
3222
  }, [
3215
3223
  loading
3216
3224
  ]);
3225
+ useDeepCompareEffect(()=>{
3226
+ chartRoot?.resize();
3227
+ }, [
3228
+ rect
3229
+ ]);
3217
3230
  return /*#__PURE__*/ jsx("div", {
3231
+ role: "figure",
3232
+ "aria-label": "Data Chart",
3218
3233
  ref: chartRef,
3219
3234
  style: {
3220
3235
  width: '100%',
@@ -3470,13 +3485,13 @@ const DefaultChartCatalog = {
3470
3485
  donut: DonutChart
3471
3486
  }
3472
3487
  };
3473
- let instance$2 = undefined;
3488
+ let instance$3 = undefined;
3474
3489
  const ChartRendererFactory = ()=>{
3475
- if (!instance$2) {
3476
- instance$2 = new RenderFactoryTypedInstance();
3477
- instance$2.registerRendererCatalog(DefaultChartCatalog);
3490
+ if (!instance$3) {
3491
+ instance$3 = new RenderFactoryTypedInstance();
3492
+ instance$3.registerRendererCatalog(DefaultChartCatalog);
3478
3493
  }
3479
- return instance$2;
3494
+ return instance$3;
3480
3495
  };
3481
3496
 
3482
3497
  /** createChart selects which type of chart element to create depending on the
@@ -3504,9 +3519,14 @@ const chartColors = [
3504
3519
  '#ea7ccc'
3505
3520
  ];
3506
3521
  //The Charts component maps the data from ChartsProps into a grid of createChart() ReactNodes
3507
- const Charts = ({ index, charts, data, counts, isSuccess, numCols = DEFAULT_COLS, style = 'tile', showLegends = false })=>{
3508
- const spans = computeRowSpan(charts, numCols);
3522
+ const Charts = ({ charts, data, counts, isSuccess, numCols = DEFAULT_COLS, style = 'tile', showLegends = false })=>{
3523
+ const spans = computeRowSpan(Object.keys(charts).length, numCols);
3509
3524
  const chartCard = (field, indexNum)=>{
3525
+ if (!(field in data)) {
3526
+ return /*#__PURE__*/ jsx(ErrorCard, {
3527
+ message: `${field} not found in data`
3528
+ });
3529
+ }
3510
3530
  const LegendRows = ({ data })=>{
3511
3531
  const moreThanMaxRows = data.length > MAX_LEGEND_ROWS;
3512
3532
  const limitedRows = moreThanMaxRows ? data.slice(0, MAX_LEGEND_ROWS) : data;
@@ -3646,7 +3666,7 @@ const Charts = ({ index, charts, data, counts, isSuccess, numCols = DEFAULT_COLS
3646
3666
  td: 'p-1 leading-3',
3647
3667
  th: 'p-1 leading-3 [text-shadow:_1px_0_#000]',
3648
3668
  thead: 'border-b',
3649
- tbody: 'before:content-[\'\'] before:block before:p-1'
3669
+ tbody: "before:content-[''] before:block before:p-1"
3650
3670
  },
3651
3671
  children: [
3652
3672
  /*#__PURE__*/ jsx(Table.Thead, {
@@ -3679,7 +3699,7 @@ const Charts = ({ index, charts, data, counts, isSuccess, numCols = DEFAULT_COLS
3679
3699
  })
3680
3700
  ]
3681
3701
  })
3682
- }, `${index}-${indexNum}-charts-${field}-col`);
3702
+ }, `${indexNum}-charts-${field}-col`);
3683
3703
  };
3684
3704
  return /*#__PURE__*/ jsx(Grid, {
3685
3705
  className: "w-full",
@@ -3931,10 +3951,11 @@ const ChartsPanel = ({ config })=>{
3931
3951
  const chartDataTemp = {};
3932
3952
  config?.charts?.forEach((chart, index)=>{
3933
3953
  chartDataTemp[`testName${index}`] = {
3954
+ //TODO use from data
3934
3955
  title: chart.title,
3935
3956
  chartType: chart.chartType,
3936
3957
  valueType: chart.valueType,
3937
- dataLabels: chart.dataLabels //TODO get from code and not from setup
3958
+ dataLabels: chart.dataLabels
3938
3959
  };
3939
3960
  });
3940
3961
  return chartDataTemp;
@@ -3979,10 +4000,9 @@ const ChartsPanel = ({ config })=>{
3979
4000
  children: /*#__PURE__*/ jsx(Charts, {
3980
4001
  showLegends: showLegends,
3981
4002
  style: "box",
3982
- index: 'subjectsCharts',
3983
4003
  charts: chartsProperties(),
3984
4004
  data: {
3985
- 'testName0': [
4005
+ testName0: [
3986
4006
  {
3987
4007
  key: 'a',
3988
4008
  count: 11
@@ -4004,7 +4024,7 @@ const ChartsPanel = ({ config })=>{
4004
4024
  count: 0
4005
4025
  }
4006
4026
  ],
4007
- 'testName1': [
4027
+ testName1: [
4008
4028
  {
4009
4029
  key: 'a',
4010
4030
  count: 11
@@ -4018,7 +4038,7 @@ const ChartsPanel = ({ config })=>{
4018
4038
  count: 3
4019
4039
  }
4020
4040
  ],
4021
- 'testName2': [
4041
+ testName2: [
4022
4042
  {
4023
4043
  key: 'a',
4024
4044
  count: 11
@@ -4032,7 +4052,7 @@ const ChartsPanel = ({ config })=>{
4032
4052
  count: 3
4033
4053
  }
4034
4054
  ],
4035
- 'testName3': [
4055
+ testName3: [
4036
4056
  {
4037
4057
  key: 'a',
4038
4058
  count: 1
@@ -5927,7 +5947,7 @@ const LoginPanel = (loginConfig)=>{
5927
5947
  /*#__PURE__*/ jsx(LoginProvidersPanel, {
5928
5948
  handleLoginSelected: handleFenceLoginSelected
5929
5949
  }),
5930
- loginConfig?.showCredentialsLogin && /*#__PURE__*/ jsx(CredentialsLogin, {
5950
+ loginConfig?.showCredentialsLogin && process.env.NODE_ENV === 'development' && /*#__PURE__*/ jsx(CredentialsLogin, {
5931
5951
  handleLogin: handleCredentialsLogin
5932
5952
  }),
5933
5953
  bottomContent?.map((content, index)=>content?.email ? /*#__PURE__*/ createElement(ContactWithEmailContent, {
@@ -6409,7 +6429,7 @@ const processRangeData = (data)=>{
6409
6429
  }
6410
6430
  };
6411
6431
  // Process facets to determine if they are enum, exact, or range
6412
- const classifyFacets = (data, index, fieldMapping, facetDefinitionsFromConfig)=>{
6432
+ const classifyFacets = (data, index, fieldMapping = [], facetDefinitionsFromConfig = {})=>{
6413
6433
  if (typeof data !== 'object' || data === null) return {};
6414
6434
  // otherwise enum facet
6415
6435
  return Object.entries(data).reduce((acc, [fieldKey, value])=>{
@@ -6417,7 +6437,7 @@ const classifyFacets = (data, index, fieldMapping, facetDefinitionsFromConfig)=>
6417
6437
  const dataField = fieldKey.split('.')?.slice(-1)[0] ?? fieldKey;
6418
6438
  // check if range facet
6419
6439
  const type = value.length === 1 && isArray(value[0].key) ? 'range' : 'enum';
6420
- const facetName = fieldMapping.find((x)=>x.field === fieldKey)?.name ?? undefined;
6440
+ const facetName = fieldMapping.find((x)=>x.field === fieldKey)?.name ?? fieldNameToTitle(fieldKey);
6421
6441
  const facetDef = facetDefinitionsFromConfig[fieldKey] ?? {};
6422
6442
  return {
6423
6443
  ...acc,
@@ -6428,7 +6448,7 @@ const classifyFacets = (data, index, fieldMapping, facetDefinitionsFromConfig)=>
6428
6448
  type: facetDef.type ?? type,
6429
6449
  index: index,
6430
6450
  description: facetDef.description ?? 'Not Available',
6431
- label: facetDef.description ?? facetName,
6451
+ label: facetDef.label ?? facetName,
6432
6452
  // assumption is that the initial data has the min and max values
6433
6453
  range: facetDef.range ?? type === 'range' ? {
6434
6454
  minimum: Math.floor(Number(value[0].key[0])),
@@ -6470,7 +6490,10 @@ const buildNested = (field, leafOperand)=>{
6470
6490
  };
6471
6491
  };
6472
6492
  const useGetFacetFilters = (index, field)=>{
6473
- return useCoreSelector((state)=>selectIndexedFilterByName(state, index, field));
6493
+ return useCoreSelector((state)=>selectIndexedFilterByName(state, index, field) ?? {
6494
+ operator: 'and',
6495
+ operands: []
6496
+ });
6474
6497
  };
6475
6498
  /**
6476
6499
  * Given an operation, determine if range is open or closed and extract
@@ -6529,47 +6552,157 @@ inline-flex
6529
6552
  items-center
6530
6553
  hover:text-primary-lightest
6531
6554
  `;
6532
- const controlsIconStyle = 'text-primary-contrast-darker hover:text-primary-lighter';
6555
+ const controlsIconStyle = 'text-secondary-contrast hover:text-secondary-lighter';
6533
6556
  const FacetText = tw.div`
6534
- text-secondary-contrast font-heading font-semibold text-[1.25em] break-words py-2
6557
+ text-secondary-contrast font-heading font-semibold text-sm break-words
6535
6558
  `;
6536
6559
  const FacetHeader = tw.div`
6537
- flex items-start justify-between flex-nowrap bg-secondary px-1.5
6560
+ flex items-start justify-between items-center flex-nowrap bg-secondary px-1.5
6538
6561
  `;
6539
6562
 
6540
- const OverflowTooltippedLabel = ({ children, label, className = 'flex-grow font-heading text-md pt-0.5' })=>{
6541
- const [showTooltip, setShowTooltip] = useState(false);
6542
- return /*#__PURE__*/ jsx(Tooltip, {
6543
- label: label,
6544
- disabled: !showTooltip,
6545
- position: "top-start",
6546
- offset: 5,
6547
- multiline: true,
6548
- withArrow: true,
6549
- arrowOffset: 20,
6550
- classNames: {
6551
- tooltip: 'bg-base-min bg-opacity-90 text-base-contrast-min shadow-lg font-content font-medium text-xs',
6552
- arrow: 'bg-base-min bg-opacity-90'
6553
- },
6554
- children: /*#__PURE__*/ jsx("div", {
6555
- className: `${className} truncate ... `,
6556
- ref: (el)=>{
6557
- if (el) {
6558
- if (el.clientWidth < el.scrollWidth) {
6559
- setShowTooltip(true);
6560
- } else {
6561
- setShowTooltip(false);
6562
- }
6563
- }
6564
- },
6565
- children: children
6566
- })
6563
+ /**
6564
+ * Component for the common controls on the header of different type facet cards
6565
+ * @param field - filter this FacetCard manages
6566
+ * @param description - describes information about the facet
6567
+ * @param hooks - object defining the hooks required by this facet component
6568
+ * @param facetName - name of the Facet in human-readable form
6569
+ * @param showSearch - if the search icon show be displayed
6570
+ * @param showFlip - if the flip icon should be displayed
6571
+ * @param showClearSelection - if the clear selection icon should be displayed
6572
+ * @param isFacetView - if the facet selection view (and not the chart view) is displayed
6573
+ * @param toggleFlip - function to switch the facet/chart view
6574
+ * @param toggleSearch - function to switch if the search bart is displayed
6575
+ * @param dismissCallback - if facet can be removed, supply a function which will ensure the "dismiss" control will be visible
6576
+ * @param header - object containing the display components to use for the header
6577
+ */ const FacetControlsHeader = ({ field, description, hooks, facetName, showSearch = false, showFlip = false, showClearSelection = true, isFacetView = false, toggleFlip = undefined, toggleSearch = undefined, dismissCallback = undefined, header = {
6578
+ Panel: FacetHeader,
6579
+ Label: FacetText,
6580
+ iconStyle: controlsIconStyle
6581
+ } })=>{
6582
+ const clearFilters = hooks.useClearFilter();
6583
+ const isFilterExpanded = hooks?.useFilterExpanded && hooks.useFilterExpanded(field);
6584
+ const toggleExpandFilter = hooks?.useToggleExpandFilter && hooks.useToggleExpandFilter();
6585
+ useEffect(()=>{
6586
+ // Initialize filter as expanded
6587
+ if (isFilterExpanded === undefined && toggleExpandFilter) {
6588
+ toggleExpandFilter(field, true);
6589
+ }
6590
+ }, [
6591
+ field,
6592
+ isFilterExpanded,
6593
+ toggleExpandFilter
6594
+ ]);
6595
+ return /*#__PURE__*/ jsxs(header.Panel, {
6596
+ children: [
6597
+ /*#__PURE__*/ jsxs("div", {
6598
+ className: "flex flex-row items-center",
6599
+ children: [
6600
+ toggleExpandFilter && /*#__PURE__*/ jsx(Tooltip, {
6601
+ label: isFilterExpanded ? 'Collapse card' : 'Expand card',
6602
+ children: /*#__PURE__*/ jsx(ActionIcon, {
6603
+ variant: "subtle",
6604
+ onClick: ()=>toggleExpandFilter(field, !isFilterExpanded),
6605
+ className: "mt-0.5 -ml-1.5",
6606
+ "aria-expanded": isFilterExpanded,
6607
+ "aria-label": isFilterExpanded ? 'Collapse card' : 'Expand card',
6608
+ children: isFilterExpanded ? /*#__PURE__*/ jsx(MdExpandLess, {
6609
+ size: "3em",
6610
+ color: "accent.4",
6611
+ "aria-hidden": "true"
6612
+ }) : /*#__PURE__*/ jsx(MdExpandMore, {
6613
+ size: "3em",
6614
+ color: "accent.4",
6615
+ "aria-hidden": "true"
6616
+ })
6617
+ })
6618
+ }),
6619
+ /*#__PURE__*/ jsx(Tooltip, {
6620
+ label: description,
6621
+ position: "bottom-start",
6622
+ multiline: true,
6623
+ w: 220,
6624
+ withArrow: true,
6625
+ transitionProps: {
6626
+ duration: 200,
6627
+ transition: 'fade'
6628
+ },
6629
+ disabled: !description,
6630
+ children: /*#__PURE__*/ jsx(header.Label, {
6631
+ children: facetName ? facetName : fieldNameToTitle(field)
6632
+ })
6633
+ })
6634
+ ]
6635
+ }),
6636
+ /*#__PURE__*/ jsxs("div", {
6637
+ className: "flex flex-row",
6638
+ children: [
6639
+ showSearch ? /*#__PURE__*/ jsx(Tooltip, {
6640
+ label: "Search values",
6641
+ children: /*#__PURE__*/ jsx(FacetIconButton, {
6642
+ onClick: ()=>{
6643
+ if (toggleExpandFilter) toggleExpandFilter(field, true);
6644
+ if (toggleSearch) toggleSearch();
6645
+ },
6646
+ "aria-label": "Search",
6647
+ children: /*#__PURE__*/ jsx(MdSearch, {
6648
+ size: "1.45em",
6649
+ className: header.iconStyle,
6650
+ "aria-hidden": "true"
6651
+ })
6652
+ })
6653
+ }) : null,
6654
+ showFlip ? /*#__PURE__*/ jsx(Tooltip, {
6655
+ label: isFacetView ? 'Chart view' : 'Selection view',
6656
+ children: /*#__PURE__*/ jsx(FacetIconButton, {
6657
+ onClick: ()=>{
6658
+ if (toggleExpandFilter) toggleExpandFilter(field, true);
6659
+ if (toggleFlip) toggleFlip();
6660
+ },
6661
+ "aria-pressed": !isFacetView,
6662
+ "aria-label": isFacetView ? 'Chart view' : 'Selection view',
6663
+ children: /*#__PURE__*/ jsx(MdFlip, {
6664
+ size: "1.45em",
6665
+ className: header.iconStyle,
6666
+ "aria-hidden": "true"
6667
+ })
6668
+ })
6669
+ }) : null,
6670
+ showClearSelection && /*#__PURE__*/ jsx(Tooltip, {
6671
+ label: "Clear selection",
6672
+ children: /*#__PURE__*/ jsx(FacetIconButton, {
6673
+ onClick: ()=>clearFilters(field),
6674
+ "aria-label": "clear selection",
6675
+ children: /*#__PURE__*/ jsx(FaUndo, {
6676
+ size: "1.0em",
6677
+ className: header.iconStyle,
6678
+ "aria-hidden": "true"
6679
+ })
6680
+ })
6681
+ }),
6682
+ dismissCallback ? /*#__PURE__*/ jsx(Tooltip, {
6683
+ label: "Remove the facet",
6684
+ children: /*#__PURE__*/ jsx(FacetIconButton, {
6685
+ onClick: ()=>{
6686
+ dismissCallback(field);
6687
+ },
6688
+ "aria-label": "Remove the facet",
6689
+ children: /*#__PURE__*/ jsx(MdClose, {
6690
+ size: "1.25em",
6691
+ className: header.iconStyle,
6692
+ "aria-hidden": "true"
6693
+ })
6694
+ })
6695
+ }) : null
6696
+ ]
6697
+ })
6698
+ ]
6567
6699
  });
6568
6700
  };
6569
6701
 
6570
6702
  const DEFAULT_VISIBLE_ITEMS = 6;
6571
6703
  const DEFAULT_MINIMUM = 0;
6572
6704
  const DEFAULT_MAXIMUM = 100;
6705
+ const BAD_DATA_MESSAGE = 'No data for this field';
6573
6706
 
6574
6707
  const sortTypeToAriaDescription = (sortTypeAndDirection, valueLabel, field)=>{
6575
6708
  if (sortTypeAndDirection.type === 'alpha') {
@@ -6669,13 +6802,43 @@ const sortTypeToAriaDescription = (sortTypeAndDirection, valueLabel, field)=>{
6669
6802
  });
6670
6803
  };
6671
6804
 
6805
+ const OverflowTooltippedLabel = ({ children, label, className = 'flex-grow font-heading text-md pt-0.5' })=>{
6806
+ const [showTooltip, setShowTooltip] = useState(false);
6807
+ return /*#__PURE__*/ jsx(Tooltip, {
6808
+ label: label,
6809
+ disabled: !showTooltip,
6810
+ position: "top-start",
6811
+ offset: 5,
6812
+ multiline: true,
6813
+ withArrow: true,
6814
+ arrowOffset: 20,
6815
+ classNames: {
6816
+ tooltip: 'bg-base-min bg-opacity-90 text-base-contrast-min shadow-lg font-content font-medium text-xs',
6817
+ arrow: 'bg-base-min bg-opacity-90'
6818
+ },
6819
+ children: /*#__PURE__*/ jsx("div", {
6820
+ className: `${className} truncate ... `,
6821
+ ref: (el)=>{
6822
+ if (el) {
6823
+ if (el.clientWidth < el.scrollWidth) {
6824
+ setShowTooltip(true);
6825
+ } else {
6826
+ setShowTooltip(false);
6827
+ }
6828
+ }
6829
+ },
6830
+ children: children
6831
+ })
6832
+ });
6833
+ };
6834
+
6672
6835
  const ExpanderLabel = tw.div`
6673
6836
  text-accent-content-darker
6674
6837
  p-1
6675
6838
  font-bold
6676
6839
  cursor-pointer
6677
6840
  text-xs
6678
- font-content-noto
6841
+ font-content
6679
6842
  `;
6680
6843
  /**
6681
6844
  * Component which manages the compact/expanded state of a FacetCard
@@ -6684,7 +6847,7 @@ font-content-noto
6684
6847
  * @param onShowChanged - callback to call when the expand/compact button is clicked
6685
6848
  */ const FacetExpander = ({ remainingValues, isGroupExpanded, onShowChanged })=>{
6686
6849
  return /*#__PURE__*/ jsx("div", {
6687
- className: "mt-3 flex flex-row justify-end border-t-2 p-1.5",
6850
+ className: `mt-3 flex flex-row justify-end ${remainingValues > 0 && 'border-t-2'} p-1.5`,
6688
6851
  children: remainingValues > 0 && !isGroupExpanded ? /*#__PURE__*/ jsx("button", {
6689
6852
  onClick: ()=>onShowChanged(!isGroupExpanded),
6690
6853
  "data-testid": "plus-icon",
@@ -6693,7 +6856,7 @@ font-content-noto
6693
6856
  children: [
6694
6857
  /*#__PURE__*/ jsx(MdAddCircle, {
6695
6858
  className: "text-accent",
6696
- size: "1.5em",
6859
+ size: "1rem",
6697
6860
  "aria-hidden": "true"
6698
6861
  }, "show-more"),
6699
6862
  /*#__PURE__*/ jsxs(ExpanderLabel, {
@@ -6712,7 +6875,7 @@ font-content-noto
6712
6875
  children: [
6713
6876
  /*#__PURE__*/ jsx(MdRemoveCircle, {
6714
6877
  className: "text-accent",
6715
- size: "1.5em",
6878
+ size: "1rem",
6716
6879
  onClick: ()=>onShowChanged(!isGroupExpanded),
6717
6880
  "aria-hidden": "true"
6718
6881
  }, "show-less"),
@@ -6725,35 +6888,32 @@ font-content-noto
6725
6888
  });
6726
6889
  };
6727
6890
 
6728
- const EnumFacet = ({ field, dataHooks, valueLabel, description, facetName, showPercent = true, hideIfEmpty = true, showSearch = true, showFlip = false, startShowingData = true, dismissCallback = undefined, width = undefined, header = {
6729
- Panel: FacetHeader,
6730
- Label: FacetText,
6731
- iconStyle: controlsIconStyle
6732
- } })=>{
6891
+ const FacetEnumList = ({ field, facetName, hooks, valueLabel, isFacetView = true, isSearching = false, showPercent = false, hideIfEmpty = false, showSorting = true })=>{
6733
6892
  const [isGroupExpanded, setIsGroupExpanded] = useState(false);
6734
- const [isSearching, setIsSearching] = useState(false);
6893
+ const cardRef = useRef(null);
6894
+ const searchInputRef = useRef(null);
6735
6895
  const [searchTerm, setSearchTerm] = useState('');
6896
+ const { data, enumFilters, isSuccess, error } = hooks.useGetFacetData(field);
6897
+ const [selectedEnums, setSelectedEnums] = useState(enumFilters ?? []);
6898
+ const totalCount = hooks?.useTotalCounts ? hooks.useTotalCounts() : 1;
6899
+ const clearFilters = hooks.useClearFilter();
6900
+ const updateFacetFilters = hooks.useUpdateFacetFilters();
6901
+ const isFilterExpanded = hooks?.useFilterExpanded && hooks.useFilterExpanded(field);
6902
+ const showFilters = isFilterExpanded === undefined || isFilterExpanded;
6736
6903
  const [sortedData, setSortedData] = useState({});
6737
6904
  const [sortType, setSortType] = useState({
6738
6905
  type: 'alpha',
6739
6906
  direction: 'asc'
6740
6907
  });
6741
- const [isFacetView, setIsFacetView] = useState(startShowingData);
6742
- const { data, enumFilters, isSuccess } = dataHooks.useGetFacetData(field);
6743
- const cardRef = useRef(null);
6744
- const [selectedEnums, setSelectedEnums] = useState(enumFilters ?? []);
6745
- const searchInputRef = useRef(null);
6746
- const totalCount = 1000;
6747
- // TODO Determine if total count is needed
6748
- // const totalCount = dataHooks.useTotalCounts();
6749
- const clearFilters = dataHooks.useClearFilter();
6750
- const updateFacetFilters = dataHooks.useUpdateFacetFilters();
6751
6908
  useEffect(()=>{
6752
6909
  if (isSearching) {
6753
6910
  searchInputRef?.current?.focus();
6911
+ } else if (searchTerm.length > 0) {
6912
+ setSearchTerm('');
6754
6913
  }
6755
6914
  }, [
6756
- isSearching
6915
+ isSearching,
6916
+ searchTerm
6757
6917
  ]);
6758
6918
  useDeepCompareEffect(()=>{
6759
6919
  setSelectedEnums(enumFilters ?? []);
@@ -6780,13 +6940,6 @@ const EnumFacet = ({ field, dataHooks, valueLabel, description, facetName, showP
6780
6940
  updateFacetEnum(field, updated ?? [], updateFacetFilters, clearFilters);
6781
6941
  }
6782
6942
  };
6783
- const toggleSearch = ()=>{
6784
- setIsSearching(!isSearching);
6785
- setSearchTerm('');
6786
- };
6787
- const toggleFlip = ()=>{
6788
- setIsFacetView(!isFacetView);
6789
- };
6790
6943
  const [facetChartData, setFacetChartData] = useState({
6791
6944
  filteredData: [],
6792
6945
  filteredDataObj: {},
@@ -6799,9 +6952,9 @@ const EnumFacet = ({ field, dataHooks, valueLabel, description, facetName, showP
6799
6952
  const calcCardStyle = useDeepCompareCallback((remainingValues)=>{
6800
6953
  if (isGroupExpanded) {
6801
6954
  const cardHeight = remainingValues > 16 ? 96 : remainingValues > 0 ? Math.min(96, remainingValues * 5 + 40) : 24;
6802
- return `flex-none h-${cardHeight} overflow-y-scroll `;
6955
+ return `flex-none h-${cardHeight} overflow-y-scroll pl-3`;
6803
6956
  } else {
6804
- return 'overflow-hidden h-auto';
6957
+ return 'overflow-hidden h-auto mr-3 pl-3';
6805
6958
  }
6806
6959
  }, [
6807
6960
  isGroupExpanded
@@ -6897,68 +7050,14 @@ const EnumFacet = ({ field, dataHooks, valueLabel, description, facetName, showP
6897
7050
  return null; // nothing to render if visibleItems == 0
6898
7051
  }
6899
7052
  return /*#__PURE__*/ jsxs("div", {
6900
- className: `flex flex-col ${width ? width : 'mx-1'} bg-base-max relative shadow-lg border-base-lighter border-1 rounded-b-md text-xs transition`,
6901
- id: field,
7053
+ className: showFilters ? 'h-full' : 'h-0 invisible',
7054
+ "aria-hidden": !showFilters,
6902
7055
  children: [
6903
- /*#__PURE__*/ jsx("div", {
6904
- children: /*#__PURE__*/ jsxs(header.Panel, {
6905
- children: [
6906
- /*#__PURE__*/ jsx(Tooltip, {
6907
- label: description,
6908
- position: "bottom-start",
6909
- multiline: true,
6910
- w: 220,
6911
- withArrow: true,
6912
- disabled: !description,
6913
- children: /*#__PURE__*/ jsx(header.Label, {
6914
- children: facetName ? facetName : fieldNameToTitle(field)
6915
- })
6916
- }),
6917
- /*#__PURE__*/ jsxs("div", {
6918
- className: "flex flex-row",
6919
- children: [
6920
- showSearch ? /*#__PURE__*/ jsx(FacetIconButton, {
6921
- onClick: toggleSearch,
6922
- "aria-label": "Search",
6923
- children: /*#__PURE__*/ jsx(MdSearch, {
6924
- size: "1.45em",
6925
- className: header.iconStyle
6926
- })
6927
- }) : null,
6928
- showFlip ? /*#__PURE__*/ jsx(FacetIconButton, {
6929
- onClick: toggleFlip,
6930
- "aria-label": "Flip between form and chart",
6931
- children: /*#__PURE__*/ jsx(MdFlip, {
6932
- size: "1.45em",
6933
- className: header.iconStyle
6934
- })
6935
- }) : null,
6936
- /*#__PURE__*/ jsx(FacetIconButton, {
6937
- onClick: ()=>clearFilters(field),
6938
- "aria-label": "clear selection",
6939
- children: /*#__PURE__*/ jsx(FaUndo, {
6940
- size: "1.25em",
6941
- className: header.iconStyle
6942
- })
6943
- }),
6944
- dismissCallback ? /*#__PURE__*/ jsx(FacetIconButton, {
6945
- onClick: ()=>{
6946
- clearFilters(field);
6947
- dismissCallback(field);
6948
- },
6949
- "aria-label": "Remove the facet",
6950
- children: /*#__PURE__*/ jsx(MdClose, {
6951
- size: "1.25em",
6952
- className: header.iconStyle
6953
- })
6954
- }) : null
6955
- ]
6956
- })
6957
- ]
6958
- })
6959
- }),
6960
- /*#__PURE__*/ jsxs("div", {
6961
- className: "h-full",
7056
+ ' ',
7057
+ isSuccess && error ? /*#__PURE__*/ jsx("div", {
7058
+ className: "m-4 font-content pb-2",
7059
+ children: BAD_DATA_MESSAGE
7060
+ }) : /*#__PURE__*/ jsxs(Fragment, {
6962
7061
  children: [
6963
7062
  isSearching && /*#__PURE__*/ jsx(TextInput, {
6964
7063
  value: searchTerm,
@@ -6984,12 +7083,12 @@ const EnumFacet = ({ field, dataHooks, valueLabel, description, facetName, showP
6984
7083
  children: [
6985
7084
  /*#__PURE__*/ jsxs("div", {
6986
7085
  children: [
6987
- /*#__PURE__*/ jsx(FacetSortPanel, {
7086
+ showSorting ? /*#__PURE__*/ jsx(FacetSortPanel, {
6988
7087
  sortType: sortType,
6989
7088
  valueLabel: valueLabel,
6990
7089
  setSort: setSortType,
6991
7090
  field: facetName ? facetName : fieldNameToTitle(field)
6992
- }),
7091
+ }) : false,
6993
7092
  /*#__PURE__*/ jsxs("div", {
6994
7093
  className: facetChartData.cardStyle,
6995
7094
  role: "group",
@@ -7000,14 +7099,14 @@ const EnumFacet = ({ field, dataHooks, valueLabel, description, facetName, showP
7000
7099
  "data-testid": "loading-spinner"
7001
7100
  }),
7002
7101
  facetChartData.filteredData.length == 0 ? /*#__PURE__*/ jsx("div", {
7003
- className: "mx-4 font-content",
7004
- children: "No data for this field"
7102
+ className: "mx-4 font-content text-sm",
7103
+ children: BAD_DATA_MESSAGE
7005
7104
  }) : isSuccess ? !sortedData || Object.entries(sortedData).length === 0 ? /*#__PURE__*/ jsx("div", {
7006
7105
  className: "mx-4",
7007
7106
  children: "No results found"
7008
7107
  }) : Object.entries(sortedData ?? {}).map(([value, count])=>{
7009
7108
  return /*#__PURE__*/ jsxs("div", {
7010
- className: "flex flex-row items-center gap-x-1 px-2 ",
7109
+ className: "flex flex-row items-center gap-x-1",
7011
7110
  children: [
7012
7111
  /*#__PURE__*/ jsx("div", {
7013
7112
  className: "flex-none",
@@ -7015,11 +7114,12 @@ const EnumFacet = ({ field, dataHooks, valueLabel, description, facetName, showP
7015
7114
  "data-testid": `checkbox-${value}`,
7016
7115
  value: value,
7017
7116
  size: "xs",
7018
- color: "accent",
7117
+ color: "accent.4",
7019
7118
  onChange: (e)=>handleChange(e.currentTarget.value, e.currentTarget.checked),
7020
7119
  "aria-label": `${value}`,
7021
7120
  classNames: {
7022
- input: 'bg-base hover:bg-accent-darker'
7121
+ input: 'hover:bg-accent-darker',
7122
+ label: 'text-xs font-normal font-content'
7023
7123
  },
7024
7124
  checked: selectedEnums && selectedEnums.includes(value)
7025
7125
  })
@@ -7027,16 +7127,16 @@ const EnumFacet = ({ field, dataHooks, valueLabel, description, facetName, showP
7027
7127
  /*#__PURE__*/ jsx(OverflowTooltippedLabel, {
7028
7128
  label: value,
7029
7129
  children: /*#__PURE__*/ jsx("span", {
7030
- className: "font-content",
7130
+ className: "text-xs font-normal font-content",
7031
7131
  children: value
7032
7132
  })
7033
7133
  }),
7034
7134
  /*#__PURE__*/ jsx("div", {
7035
- className: "flex-none text-right w-14 font-content",
7135
+ className: "flex-none text-right w-14 text-xs font-normal font-content",
7036
7136
  children: count.toLocaleString()
7037
7137
  }),
7038
7138
  showPercent ? /*#__PURE__*/ jsxs("div", {
7039
- className: "flex-none text-right w-18 font-content",
7139
+ className: "flex-none text-right w-18 text-xs font-normal font-content",
7040
7140
  children: [
7041
7141
  "(",
7042
7142
  (count / totalCount * 100).toFixed(2),
@@ -7055,6 +7155,7 @@ const EnumFacet = ({ field, dataHooks, valueLabel, description, facetName, showP
7055
7155
  className: "flex-none",
7056
7156
  children: /*#__PURE__*/ jsx(Checkbox, {
7057
7157
  size: "xs",
7158
+ radius: "xs",
7058
7159
  className: "bg-base-lightest text-primary-contrast-lightest hover:bg-base-darkest hover:text-base-contrast-darkest"
7059
7160
  })
7060
7161
  }),
@@ -7072,11 +7173,11 @@ const EnumFacet = ({ field, dataHooks, valueLabel, description, facetName, showP
7072
7173
  })
7073
7174
  ]
7074
7175
  }),
7075
- /*#__PURE__*/ jsx(FacetExpander, {
7176
+ facetChartData.remainingValues > 0 ? /*#__PURE__*/ jsx(FacetExpander, {
7076
7177
  remainingValues: facetChartData.remainingValues,
7077
7178
  isGroupExpanded: isGroupExpanded,
7078
7179
  onShowChanged: setIsGroupExpanded
7079
- })
7180
+ }) : null
7080
7181
  ]
7081
7182
  }),
7082
7183
  /*#__PURE__*/ jsx("div", {
@@ -7103,6 +7204,52 @@ const EnumFacet = ({ field, dataHooks, valueLabel, description, facetName, showP
7103
7204
  });
7104
7205
  };
7105
7206
 
7207
+ const EnumFacet = ({ field, hooks, valueLabel, description, facetName, showPercent = true, hideIfEmpty = true, showSearch = true, showFlip = false, startShowingData = true, dismissCallback = undefined, width = undefined, header = {
7208
+ Panel: FacetHeader,
7209
+ Label: FacetText,
7210
+ iconStyle: controlsIconStyle
7211
+ } })=>{
7212
+ const [isSearching, setIsSearching] = useState(false);
7213
+ const [isFacetView, setIsFacetView] = useState(startShowingData);
7214
+ const toggleSearch = ()=>{
7215
+ setIsSearching(!isSearching);
7216
+ };
7217
+ const toggleFlip = ()=>{
7218
+ setIsFacetView(!isFacetView);
7219
+ };
7220
+ return /*#__PURE__*/ jsxs("div", {
7221
+ className: `flex flex-col ${width ? width : 'mx-1'} bg-base-max relative shadow-lg border-base-lighter border-1 rounded-b-md text-xs transition`,
7222
+ id: field,
7223
+ children: [
7224
+ /*#__PURE__*/ jsx("div", {
7225
+ children: /*#__PURE__*/ jsx(FacetControlsHeader, {
7226
+ field: field,
7227
+ description: description,
7228
+ hooks: hooks,
7229
+ facetName: facetName,
7230
+ showSearch: showSearch,
7231
+ showFlip: showFlip,
7232
+ isFacetView: isFacetView,
7233
+ toggleFlip: toggleFlip,
7234
+ toggleSearch: toggleSearch,
7235
+ dismissCallback: dismissCallback,
7236
+ header: header
7237
+ })
7238
+ }),
7239
+ /*#__PURE__*/ jsx(FacetEnumList, {
7240
+ field: field,
7241
+ facetName: facetName,
7242
+ valueLabel: valueLabel,
7243
+ hooks: hooks,
7244
+ isFacetView: isFacetView,
7245
+ isSearching: isSearching,
7246
+ hideIfEmpty: hideIfEmpty,
7247
+ showPercent: showPercent
7248
+ })
7249
+ ]
7250
+ });
7251
+ };
7252
+
7106
7253
  const createBucket = (field, lower, upper)=>({
7107
7254
  operator: 'and',
7108
7255
  operands: [
@@ -7118,17 +7265,17 @@ const createBucket = (field, lower, upper)=>({
7118
7265
  }
7119
7266
  ]
7120
7267
  });
7121
- const RangeFacet = ({ field, dataHooks, valueLabel, description, facetName, minimum = DEFAULT_MINIMUM, maximum = DEFAULT_MAXIMUM, showPercent = true, hideIfEmpty = true, showSearch = true, showFlip = true, startShowingData = true, dismissCallback = undefined, width = undefined, header = {
7268
+ const RangeFacet = ({ field, hooks, valueLabel, description, facetName, minimum = DEFAULT_MINIMUM, maximum = DEFAULT_MAXIMUM, showPercent = true, hideIfEmpty = true, showSearch = true, showFlip = true, startShowingData = true, dismissCallback = undefined, width = undefined, header = {
7122
7269
  Panel: FacetHeader,
7123
7270
  Label: FacetText,
7124
7271
  iconStyle: controlsIconStyle
7125
7272
  } })=>{
7126
- const { data, rangeFilters, isSuccess } = dataHooks.useGetFacetData(field);
7273
+ const { data, rangeFilters, isSuccess } = hooks.useGetFacetData(field);
7127
7274
  const [minMaxValue, setMinMaxValue] = React__default.useState({
7128
7275
  from: minimum,
7129
7276
  to: maximum
7130
7277
  });
7131
- const clearRangeFilterFromCohort = dataHooks.useClearFilter();
7278
+ const clearRangeFilterFromCohort = hooks.useClearFilter();
7132
7279
  const clearFilters = useCallback(()=>{
7133
7280
  setMinMaxValue({
7134
7281
  from: minimum,
@@ -7141,7 +7288,7 @@ const RangeFacet = ({ field, dataHooks, valueLabel, description, facetName, mini
7141
7288
  maximum,
7142
7289
  minimum
7143
7290
  ]);
7144
- const updateRangeFilter = dataHooks.useUpdateFacetFilters();
7291
+ const updateRangeFilter = hooks.useUpdateFacetFilters();
7145
7292
  const updateFilters = useCallback((from, to)=>{
7146
7293
  updateRangeFilter(field, createBucket(field, from, to));
7147
7294
  setMinMaxValue({
@@ -7275,13 +7422,13 @@ const instanceOfIncludesExcludes$1 = (op)=>[
7275
7422
  * @param width - width of the facet
7276
7423
  * @param hooks - hooks to use for the facet
7277
7424
  * @category Facets
7278
- */ const MultiSelectValueFacet = ({ field, description, facetName = undefined, dismissCallback = undefined, width = undefined, dataHooks })=>{
7425
+ */ const MultiSelectValueFacet = ({ field, description, facetName = undefined, dismissCallback = undefined, width = undefined, hooks })=>{
7279
7426
  const [selectedValues, setSelectedValues] = useState([]); // Handle the state of the TextInput
7280
- const clearFilters = dataHooks.useClearFilter();
7281
- const updateFacetFilters = dataHooks.useUpdateFacetFilters();
7427
+ const clearFilters = hooks.useClearFilter();
7428
+ const updateFacetFilters = hooks.useUpdateFacetFilters();
7282
7429
  const facetTitle = facetName ? facetName : trimFirstFieldNameToTitle(field, true);
7283
- const facetValue = dataHooks.useGetFacetFilters(field);
7284
- const facetDataValues = dataHooks.useGetFacetData(field);
7430
+ const facetValue = hooks.useGetFacetFilters(field);
7431
+ const facetDataValues = hooks.useGetFacetData(field);
7285
7432
  const dataValues = useMemo(()=>{
7286
7433
  if (facetDataValues?.data) {
7287
7434
  return Object.keys(facetDataValues.data).map((key)=>{
@@ -7426,12 +7573,12 @@ const instanceOfIncludesExcludes = (op)=>[
7426
7573
  * @param width - width of the facet
7427
7574
  * @param hooks - hooks to use for the facet
7428
7575
  * @category Facets
7429
- */ const ExactValueFacet = ({ field, description, facetName = undefined, dismissCallback = undefined, width = undefined, dataHooks })=>{
7576
+ */ const ExactValueFacet = ({ field, description, facetName = undefined, dismissCallback = undefined, width = undefined, hooks })=>{
7430
7577
  const [textValue, setTextValue] = useState(''); // Handle the state of the TextInput
7431
- const clearFilters = dataHooks.useClearFilter();
7432
- const updateFacetFilters = dataHooks.useUpdateFacetFilters();
7578
+ const clearFilters = hooks.useClearFilter();
7579
+ const updateFacetFilters = hooks.useUpdateFacetFilters();
7433
7580
  const facetTitle = facetName ? facetName : trimFirstFieldNameToTitle(field, true);
7434
- const facetValue = dataHooks.useGetFacetFilters(field);
7581
+ const facetValue = hooks.useGetFacetFilters(field);
7435
7582
  const textValues = useMemo(()=>extractValues(facetValue), [
7436
7583
  facetValue
7437
7584
  ]);
@@ -7582,7 +7729,7 @@ const createFacetCard = (facetDefinition, valueLabel, dataFunctions, idPrefix, d
7582
7729
  description: description,
7583
7730
  hideIfEmpty: hideIfEmpty,
7584
7731
  width: width,
7585
- dataHooks: dataFunctions,
7732
+ hooks: dataFunctions,
7586
7733
  showPercent: false
7587
7734
  }, `${idPrefix}-enum-${field}`),
7588
7735
  range: /*#__PURE__*/ jsx(RangeFacet, {
@@ -7592,7 +7739,7 @@ const createFacetCard = (facetDefinition, valueLabel, dataFunctions, idPrefix, d
7592
7739
  description: description,
7593
7740
  hideIfEmpty: hideIfEmpty,
7594
7741
  width: width,
7595
- dataHooks: dataFunctions,
7742
+ hooks: dataFunctions,
7596
7743
  minimum: facetDefinition.range?.minimum,
7597
7744
  maximum: facetDefinition.range?.maximum
7598
7745
  }, `${idPrefix}-range-${field}`),
@@ -7602,7 +7749,7 @@ const createFacetCard = (facetDefinition, valueLabel, dataFunctions, idPrefix, d
7602
7749
  description: description,
7603
7750
  hideIfEmpty: hideIfEmpty,
7604
7751
  width: width,
7605
- dataHooks: dataFunctions
7752
+ hooks: dataFunctions
7606
7753
  }, `${idPrefix}-exact-${field}`),
7607
7754
  multiselect: /*#__PURE__*/ jsx(MultiSelectValueFacet, {
7608
7755
  field: field,
@@ -7610,7 +7757,7 @@ const createFacetCard = (facetDefinition, valueLabel, dataFunctions, idPrefix, d
7610
7757
  description: description,
7611
7758
  hideIfEmpty: hideIfEmpty,
7612
7759
  width: width,
7613
- dataHooks: dataFunctions
7760
+ hooks: dataFunctions
7614
7761
  }, `${idPrefix}-exact-${field}`)
7615
7762
  }[type]
7616
7763
  }, `${idPrefix}-enum-${field}`);
@@ -7661,7 +7808,7 @@ const QueryFieldLabel = tw.div`
7661
7808
  bg-accent-cool-lightest
7662
7809
  text-base-darkest
7663
7810
  uppercase
7664
- px-1
7811
+ px-2 pl-1
7665
7812
  border-primary-darkest
7666
7813
  border-r-[1.5px]
7667
7814
  flex
@@ -7762,7 +7909,7 @@ const IncludeExcludeQueryElement = ({ index, field, path, operator, operands })=
7762
7909
  color: "accent.5",
7763
7910
  size: "md",
7764
7911
  pr: 0,
7765
- className: "normal-case items-center max-w-[162px] cursor-pointer pl-0 pr-0 hover:bg-accent-darker",
7912
+ className: "normal-case items-center max-w-[162px] cursor-pointer pl-2 pr-0 hover:bg-accent-darker",
7766
7913
  rightSection: /*#__PURE__*/ jsx(RemoveButton, {
7767
7914
  value: value
7768
7915
  }),
@@ -8207,7 +8354,7 @@ const QueryExpressionSection = ({ index, filters, currentCohortName, currentCoho
8207
8354
  setExpandedState
8208
8355
  ],
8209
8356
  children: /*#__PURE__*/ jsxs("div", {
8210
- className: "flex flex-col w-full bg-primary",
8357
+ className: "flex flex-col w-full bg-primary-lighter",
8211
8358
  children: [
8212
8359
  /*#__PURE__*/ jsxs("div", {
8213
8360
  "data-testid": "text-cohort-filters-top-row",
@@ -8444,12 +8591,12 @@ const LinkCellFunctionCatalog = {
8444
8591
  default: RenderLinkCell,
8445
8592
  linkWithValueMap: RenderLinkCellUsingValueMap
8446
8593
  };
8447
- let instance$1;
8594
+ let instance$2;
8448
8595
  const ExplorerTableCellRendererFactory = ()=>{
8449
- if (!instance$1) {
8450
- instance$1 = new RenderFactoryTypedInstance();
8596
+ if (!instance$2) {
8597
+ instance$2 = new RenderFactoryTypedInstance();
8451
8598
  }
8452
- return instance$1;
8599
+ return instance$2;
8453
8600
  };
8454
8601
  // register default cell renderers
8455
8602
  const registerExplorerDefaultCellRenderers = ()=>{
@@ -8603,21 +8750,21 @@ const RowTableDetailsPanel = ({ row })=>{
8603
8750
  });
8604
8751
  };
8605
8752
 
8606
- let instance;
8607
- const DefaultRendererCatalog = {
8753
+ let instance$1;
8754
+ const DefaultRendererCatalog$1 = {
8608
8755
  tableDetails: {
8609
8756
  default: RowTableDetailsPanel,
8610
8757
  queryRowDetails: QueryRowDetailsPanel
8611
8758
  }
8612
8759
  };
8613
8760
  const ExplorerTableDetailsPanelFactory = ()=>{
8614
- if (!instance) {
8615
- instance = new RenderFactoryTypedInstance();
8761
+ if (!instance$1) {
8762
+ instance$1 = new RenderFactoryTypedInstance();
8616
8763
  }
8617
- return instance;
8764
+ return instance$1;
8618
8765
  };
8619
8766
  const registerCohortBuilderDefaultPreviewRenderers = ()=>{
8620
- ExplorerTableDetailsPanelFactory().registerRendererCatalog(DefaultRendererCatalog);
8767
+ ExplorerTableDetailsPanelFactory().registerRendererCatalog(DefaultRendererCatalog$1);
8621
8768
  };
8622
8769
 
8623
8770
  const DEFAULT_PROPS = {
@@ -8857,7 +9004,7 @@ const CountsValue = ({ label, isSuccess, counts })=>{
8857
9004
  shadow: "xs",
8858
9005
  p: "xs",
8859
9006
  withBorder: true,
8860
- className: "bg-primary font-heading text-md font-semibold",
9007
+ className: "bg-primary text-primary-contrast font-heading text-md font-semibold",
8861
9008
  children: `${counts?.toLocaleString() ?? '...'} ${label}`
8862
9009
  })
8863
9010
  ]
@@ -9595,7 +9742,7 @@ const SinglePanel = ({ filters, tabTitle, facetDefinitions, facetDataHooks })=>{
9595
9742
  ...acc
9596
9743
  };
9597
9744
  }, {});
9598
- const facetDefs = classifyFacets(data, index, guppyConfig.fieldMapping, configFacetDefs ?? {});
9745
+ const facetDefs = classifyFacets(data, index, guppyConfig?.fieldMapping ?? [], configFacetDefs ?? {});
9599
9746
  setFacetDefinitions(facetDefs);
9600
9747
  // setup summary charts since nested fields can be listed by the split field name
9601
9748
  const summaryCharts = Object.keys(charts).reduce((acc, field)=>{
@@ -9669,14 +9816,13 @@ const SinglePanel = ({ filters, tabTitle, facetDefinitions, facetDataHooks })=>{
9669
9816
  filter: cohortFilters
9670
9817
  }),
9671
9818
  /*#__PURE__*/ jsx(CountsValue, {
9672
- label: guppyConfig.nodeCountTitle,
9819
+ label: guppyConfig?.nodeCountTitle || toDisplayName(index),
9673
9820
  counts: counts,
9674
9821
  isSuccess: isCountSuccess
9675
9822
  })
9676
9823
  ]
9677
9824
  }),
9678
9825
  /*#__PURE__*/ jsx(Charts, {
9679
- index: index,
9680
9826
  charts: summaryCharts,
9681
9827
  data: data ?? EmptyData,
9682
9828
  counts: counts,
@@ -9781,88 +9927,1701 @@ const CohortBuilder = ({ explorerConfig })=>{
9781
9927
  });
9782
9928
  };
9783
9929
 
9784
- var GqlQueryEditor$2 = /*#__PURE__*/Object.freeze({
9785
- __proto__: null,
9786
- default: GqlQueryEditor$1
9787
- });
9930
+ var GqlQueryEditor$2 = /*#__PURE__*/Object.freeze({
9931
+ __proto__: null,
9932
+ default: GqlQueryEditor$1
9933
+ });
9934
+
9935
+ const WorkspacesPanel = ()=>{
9936
+ return /*#__PURE__*/ jsx(Center, {
9937
+ className: "m-20 w-full",
9938
+ children: /*#__PURE__*/ jsx(Text, {
9939
+ size: "2rem",
9940
+ children: "Coming soon."
9941
+ })
9942
+ });
9943
+ };
9944
+
9945
+ class FilesystemContent {
9946
+ constructor({ rootPath }){
9947
+ this.rootPath = rootPath || '';
9948
+ }
9949
+ async get(filepath) {
9950
+ try {
9951
+ return await JSON.parse(fs.readFileSync(path.join(this.rootPath, filepath)).toString('utf-8'));
9952
+ } catch (err) {
9953
+ throw new Error(`Cannot process ${filepath}`);
9954
+ }
9955
+ }
9956
+ }
9957
+
9958
+ class ContentDatabase {
9959
+ constructor(config){
9960
+ this.config = config;
9961
+ this.store = config.store;
9962
+ }
9963
+ async get(filepath) {
9964
+ return this.store.get(filepath);
9965
+ }
9966
+ }
9967
+
9968
+ const GEN3_FRONTEND_CONFIGURATION_ROOT = process.env.GEN3_FRONTEND_CONFIGURATION_ROOT || './';
9969
+
9970
+ const ContentRoot = GEN3_FRONTEND_CONFIGURATION_ROOT;
9971
+ const setup = ()=>{
9972
+ const config = {
9973
+ store: new FilesystemContent({
9974
+ rootPath: ContentRoot
9975
+ })
9976
+ };
9977
+ return new ContentDatabase(config);
9978
+ };
9979
+ const ContentSource = setup();
9980
+
9981
+ /**
9982
+ * Retrieves navigation page layout properties from configuration.
9983
+ * Note: GEN3_COMMONS_NAME depends on siteConfig.json value in the data commons package
9984
+ * @returns A Promise resolving to an object containing header and footer props.
9985
+ */ const getNavPageLayoutPropsFromConfig = async ()=>{
9986
+ const navigationConfigJSON = await ContentSource.get(`config/${GEN3_COMMONS_NAME}/navigation.json`);
9987
+ let bannerConfigJSON = [];
9988
+ try {
9989
+ bannerConfigJSON = await ContentSource.get(`config/${GEN3_COMMONS_NAME}/banner.json`);
9990
+ } catch (e) {
9991
+ console.warn('No banner config found at: ', `config/${GEN3_COMMONS_NAME}/banner.json`);
9992
+ }
9993
+ const { topBar, navigation, type = 'original' } = navigationConfigJSON;
9994
+ const headerProps = {
9995
+ top: topBar,
9996
+ navigation: navigation,
9997
+ banners: bannerConfigJSON,
9998
+ type
9999
+ };
10000
+ const footerProps = await ContentSource.get(`config/${GEN3_COMMONS_NAME}/footer.json`);
10001
+ return {
10002
+ headerProps,
10003
+ footerProps,
10004
+ headerData: {
10005
+ title: 'Gen3 Frontend Framework Page',
10006
+ content: 'Gen3 Frontend Framework Page',
10007
+ key: 'gen3-common-page'
10008
+ }
10009
+ };
10010
+ };
10011
+
10012
+ const FacetSelector = ({ category, facetName, hooks, width = 'w-full', description, fields, selectedFields, updateSelectedField, showSearch = true, header = {
10013
+ Panel: FacetHeader,
10014
+ Label: FacetText,
10015
+ iconStyle: controlsIconStyle
10016
+ } })=>{
10017
+ const [isGroupExpanded, setIsGroupExpanded] = useState(false);
10018
+ const [isSearching, setIsSearching] = useState(false);
10019
+ const [searchTerm, setSearchTerm] = useState('');
10020
+ const cardRef = useRef(null);
10021
+ const isFilterExpanded = hooks.useFilterExpanded && hooks.useFilterExpanded(category);
10022
+ const showFilters = isFilterExpanded === undefined || isFilterExpanded;
10023
+ const searchInputRef = useRef(null);
10024
+ const toggleSearch = ()=>{
10025
+ setIsSearching(!isSearching);
10026
+ setSearchTerm('');
10027
+ };
10028
+ useEffect(()=>{
10029
+ if (isSearching) {
10030
+ searchInputRef?.current?.focus();
10031
+ }
10032
+ }, [
10033
+ isSearching
10034
+ ]);
10035
+ const filteredFields = useDeepCompareMemo(()=>{
10036
+ if (!searchTerm) return fields;
10037
+ return fields.filter((f)=>f.description?.toLowerCase().includes(searchTerm.toLowerCase()) || toDisplayName(f?.label ?? f.field).toLowerCase().includes(searchTerm.toLowerCase()));
10038
+ }, [
10039
+ searchTerm,
10040
+ fields
10041
+ ]);
10042
+ const remainingValues = filteredFields.length - DEFAULT_VISIBLE_ITEMS;
10043
+ return /*#__PURE__*/ jsxs("div", {
10044
+ className: `flex flex-col ${width ? width : 'mx-1'} bg-base-max relative border-base-light border-1 rounded-b-md transition`,
10045
+ id: category,
10046
+ children: [
10047
+ /*#__PURE__*/ jsx("div", {
10048
+ children: /*#__PURE__*/ jsx(FacetControlsHeader, {
10049
+ field: category,
10050
+ description: description,
10051
+ hooks: hooks,
10052
+ facetName: facetName,
10053
+ showSearch: showSearch,
10054
+ toggleSearch: toggleSearch,
10055
+ header: header
10056
+ })
10057
+ }),
10058
+ /*#__PURE__*/ jsx("div", {
10059
+ className: showFilters ? 'h-full' : 'h-0 invisible',
10060
+ "aria-hidden": !showFilters,
10061
+ children: /*#__PURE__*/ jsxs(Fragment, {
10062
+ children: [
10063
+ isSearching && /*#__PURE__*/ jsx(TextInput, {
10064
+ "data-testid": "textbox-search-values",
10065
+ value: searchTerm,
10066
+ onChange: (e)=>setSearchTerm(e.target.value),
10067
+ "aria-label": `category ${facetName}`,
10068
+ className: 'p-2',
10069
+ placeholder: "Search",
10070
+ ref: searchInputRef,
10071
+ rightSection: searchTerm.length > 0 && /*#__PURE__*/ jsx(ActionIcon, {
10072
+ onClick: ()=>{
10073
+ setSearchTerm('');
10074
+ searchInputRef?.current?.focus();
10075
+ },
10076
+ className: "border-0",
10077
+ children: /*#__PURE__*/ jsx(MdClose, {
10078
+ "aria-label": "clear search"
10079
+ })
10080
+ }),
10081
+ role: "search"
10082
+ }),
10083
+ /*#__PURE__*/ jsxs("div", {
10084
+ className: "flip-card",
10085
+ ref: cardRef,
10086
+ children: [
10087
+ /*#__PURE__*/ jsx("div", {
10088
+ className: "card-face bg-base-max rounded-b-xs flex flex-col gap-y-1 justify-between",
10089
+ children: /*#__PURE__*/ jsx("div", {
10090
+ children: filteredFields.length == 0 ? /*#__PURE__*/ jsx("div", {
10091
+ className: "mx-4 font-content text-sm",
10092
+ children: BAD_DATA_MESSAGE
10093
+ }) : filteredFields.map((facet)=>{
10094
+ const label = fieldNameToTitle(facet.field);
10095
+ return /*#__PURE__*/ jsxs("div", {
10096
+ className: "flex justify-between items-center px-2 my-1",
10097
+ children: [
10098
+ /*#__PURE__*/ jsx(Text, {
10099
+ size: "sm",
10100
+ fw: 400,
10101
+ children: label
10102
+ }),
10103
+ /*#__PURE__*/ jsx(Switch, {
10104
+ "data-testid": `switch-${label}`,
10105
+ "aria-label": `select ${facet.field}`,
10106
+ color: "accent",
10107
+ checked: selectedFields && selectedFields.includes(facet.field),
10108
+ onChange: ()=>updateSelectedField(facet.field)
10109
+ })
10110
+ ]
10111
+ }, facet.field);
10112
+ })
10113
+ })
10114
+ }),
10115
+ remainingValues > 0 ? /*#__PURE__*/ jsx(FacetExpander, {
10116
+ remainingValues: remainingValues,
10117
+ isGroupExpanded: isGroupExpanded,
10118
+ onShowChanged: setIsGroupExpanded
10119
+ }) : null
10120
+ ]
10121
+ })
10122
+ ]
10123
+ })
10124
+ })
10125
+ ]
10126
+ });
10127
+ };
10128
+
10129
+ const FacetSelectionPanel = ({ categories, hooks, selectedFields, updateSelectedField })=>{
10130
+ const panels = useDeepCompareMemo(()=>{
10131
+ return categories.map((item)=>{
10132
+ const fields = item.fields.map((f)=>item.fieldsConfig[f]);
10133
+ return /*#__PURE__*/ jsx(FacetSelector, {
10134
+ fields: fields,
10135
+ category: item.title,
10136
+ facetName: item.title,
10137
+ selectedFields: selectedFields,
10138
+ updateSelectedField: updateSelectedField,
10139
+ hooks: {
10140
+ ...hooks
10141
+ }
10142
+ }, item.title);
10143
+ });
10144
+ }, [
10145
+ categories,
10146
+ selectedFields,
10147
+ updateSelectedField,
10148
+ hooks
10149
+ ]);
10150
+ return /*#__PURE__*/ jsx("div", {
10151
+ className: "w-1/3 flex flex-col p-4 gap-y-6",
10152
+ children: panels
10153
+ });
10154
+ };
10155
+
10156
+ const initialState$1 = {};
10157
+ const expandSlice = createSlice({
10158
+ name: 'CohortDiscovery/filterExpand',
10159
+ initialState: initialState$1,
10160
+ reducers: {
10161
+ toggleCategoryFilter: (state, action)=>{
10162
+ return {
10163
+ ...state,
10164
+ [action.payload.field]: action.payload.expanded
10165
+ };
10166
+ },
10167
+ toggleAllFilters: (state, action)=>{
10168
+ return Object.fromEntries(Object.keys(state).map((k)=>[
10169
+ k,
10170
+ action.payload
10171
+ ]));
10172
+ }
10173
+ }
10174
+ });
10175
+ const filtersExpandedReducer = expandSlice.reducer;
10176
+ const { toggleCategoryFilter, toggleAllFilters } = expandSlice.actions;
10177
+ const selectFilterExpanded = (state, field)=>state.filtersExpandedState?.[field];
10178
+
10179
+ const initialState = {};
10180
+ const selectIndexFacets = createSlice({
10181
+ name: 'CohortDiscovery/filterExpand',
10182
+ initialState: initialState,
10183
+ reducers: {
10184
+ addFacetSelection: (state, action)=>{
10185
+ if (!(action.payload.index in state)) {
10186
+ return {
10187
+ ...state,
10188
+ ...{
10189
+ [action.payload.index]: [
10190
+ action.payload.field
10191
+ ]
10192
+ }
10193
+ };
10194
+ } else return {
10195
+ ...state,
10196
+ [action.payload.index]: [
10197
+ ...state[action.payload.index],
10198
+ action.payload.field
10199
+ ]
10200
+ };
10201
+ },
10202
+ removeFacetSelection: (state, action)=>{
10203
+ if (!(action.payload.index in state[action.payload.index])) return state;
10204
+ if (action.payload.field in state[action.payload.index]) {
10205
+ return {
10206
+ ...state,
10207
+ ...{
10208
+ [action.payload.index]: state[action.payload.index].filter((x)=>x !== action.payload.field)
10209
+ }
10210
+ };
10211
+ }
10212
+ }
10213
+ }
10214
+ });
10215
+ const selectedFacetsReducer = selectIndexFacets.reducer;
10216
+ selectIndexFacets.actions;
10217
+
10218
+ const _APP_NAME$2 = 'CohortDiscovery';
10219
+ const persistConfig = {
10220
+ key: _APP_NAME$2,
10221
+ version: 1,
10222
+ storage,
10223
+ whitelist: [
10224
+ 'filterExpandState'
10225
+ ]
10226
+ };
10227
+ // create the store, context and selector for the ProjectsCenter
10228
+ // Note the project app has a local store and context which isolates
10229
+ // the filters and other store/cache values
10230
+ const reducers = combineReducers({
10231
+ selectedIndexFacets: selectedFacetsReducer,
10232
+ filtersExpandedState: filtersExpandedReducer
10233
+ });
10234
+ const { id, AppStore, AppContext, useAppSelector, useAppDispatch } = createAppStore({
10235
+ reducers: persistReducer(persistConfig, reducers),
10236
+ name: _APP_NAME$2,
10237
+ version: '0.0.1'
10238
+ });
10239
+
10240
+ const useToggleExpandFilter = ()=>{
10241
+ const dispatch = useAppDispatch();
10242
+ return (field, expanded)=>{
10243
+ dispatch(toggleCategoryFilter({
10244
+ field,
10245
+ expanded
10246
+ }));
10247
+ };
10248
+ };
10249
+ const useFilterExpandedState = (field)=>{
10250
+ return useAppSelector((state)=>selectFilterExpanded(state, field));
10251
+ };
10252
+
10253
+ const EnumFacetToHistogramArray = (data)=>{
10254
+ if (!data) return [];
10255
+ return Object.entries(data).reduce((acc, [key, count])=>{
10256
+ acc.push({
10257
+ key,
10258
+ count
10259
+ });
10260
+ return acc;
10261
+ }, []);
10262
+ };
10263
+
10264
+ const FacetPanelDataHeader = ({ label, valueLabel })=>{
10265
+ return /*#__PURE__*/ jsxs(Group, {
10266
+ justify: "space-between",
10267
+ className: "border-1 border-base p-2 px-4",
10268
+ children: [
10269
+ /*#__PURE__*/ jsx("div", {
10270
+ className: "flex",
10271
+ children: /*#__PURE__*/ jsx(Text, {
10272
+ size: "sm",
10273
+ fw: 600,
10274
+ children: label
10275
+ })
10276
+ }),
10277
+ /*#__PURE__*/ jsx(Text, {
10278
+ size: "sm",
10279
+ fw: 600,
10280
+ children: valueLabel
10281
+ })
10282
+ ]
10283
+ });
10284
+ };
10285
+
10286
+ const EnumFacetPanel = ({ facet, hooks, valueLabel, showTotals = false, chartType = 'bar' })=>{
10287
+ const { field, label } = facet;
10288
+ const facetName = useMemo(()=>label ?? fieldNameToTitle(field), [
10289
+ label,
10290
+ field
10291
+ ]);
10292
+ const { data } = hooks.useGetFacetData(field);
10293
+ const chart = createChart(chartType, {
10294
+ data: EnumFacetToHistogramArray(data),
10295
+ total: 1,
10296
+ valueType: 'count'
10297
+ });
10298
+ return /*#__PURE__*/ jsxs("div", {
10299
+ className: "flex flex-col bg-base-max relative border-base border-1 rounded-b-md transition",
10300
+ children: [
10301
+ /*#__PURE__*/ jsxs("div", {
10302
+ className: "flex justify-between px-4 py-2 bg-base-lightest border-b-1 border-base",
10303
+ children: [
10304
+ /*#__PURE__*/ jsx(Text, {
10305
+ size: "sm",
10306
+ fw: 600,
10307
+ children: facetName
10308
+ }),
10309
+ showTotals ? /*#__PURE__*/ jsx(Text, {
10310
+ children: "Todo"
10311
+ }) : null
10312
+ ]
10313
+ }),
10314
+ /*#__PURE__*/ jsx("div", {
10315
+ className: "px-4 pb-4 pt-8",
10316
+ children: chart
10317
+ }),
10318
+ /*#__PURE__*/ jsx(FacetPanelDataHeader, {
10319
+ label: facetName,
10320
+ valueLabel: valueLabel
10321
+ }),
10322
+ /*#__PURE__*/ jsx("div", {
10323
+ className: "p-4 pt-2 pb-2",
10324
+ children: /*#__PURE__*/ jsx(FacetEnumList, {
10325
+ field: field,
10326
+ valueLabel: valueLabel,
10327
+ hooks: hooks,
10328
+ showSorting: false
10329
+ })
10330
+ })
10331
+ ]
10332
+ });
10333
+ };
10334
+
10335
+ const createFacetPanel = (facet, chartType, valueLabel, hooks)=>{
10336
+ switch(facet.type){
10337
+ case 'enum':
10338
+ return /*#__PURE__*/ jsx(EnumFacetPanel, {
10339
+ facet: facet,
10340
+ chartType: chartType,
10341
+ valueLabel: valueLabel,
10342
+ hooks: hooks
10343
+ });
10344
+ }
10345
+ return null;
10346
+ };
10347
+
10348
+ /**
10349
+ * CartsAndFacetsPanel component
10350
+ *
10351
+ * @param {string} index - The index type used for querying data.
10352
+ * @param {Array} facets - The list of facets to be rendered.
10353
+ * @returns {JSX.Element} The rendered component showing facets.
10354
+ */ const ChartsAndFacetsPanel = ({ index, facets })=>{
10355
+ const cohortFilters = useCoreSelector((state)=>selectIndexFilters(state, index));
10356
+ const { data, isSuccess, isError: isAggsQueryError } = useGetAggsQuery({
10357
+ type: index,
10358
+ fields: facets.map((x)=>x.field),
10359
+ filters: cohortFilters
10360
+ });
10361
+ const getEnumFacetData = useDeepCompareCallback((field)=>{
10362
+ return {
10363
+ data: processBucketData(data?.[field]),
10364
+ enumFilters: field in cohortFilters.root ? extractEnumFilterValue(cohortFilters.root[field]) : undefined,
10365
+ isSuccess: isSuccess
10366
+ };
10367
+ }, [
10368
+ cohortFilters,
10369
+ cohortFilters.root,
10370
+ data,
10371
+ isSuccess
10372
+ ]);
10373
+ const getRangeFacetData = useDeepCompareCallback((field)=>{
10374
+ return {
10375
+ data: processRangeData(data?.[field]),
10376
+ filters: extractRangeValues(cohortFilters.root[field]),
10377
+ isSuccess: isSuccess
10378
+ };
10379
+ }, [
10380
+ data,
10381
+ cohortFilters.root,
10382
+ isSuccess
10383
+ ]);
10384
+ const facetHooks = useDeepCompareMemo(()=>{
10385
+ return {
10386
+ enum: {
10387
+ useGetFacetData: getEnumFacetData,
10388
+ useUpdateFacetFilters: partial(useUpdateFilters, index),
10389
+ useGetFacetFilters: partial(useGetFacetFilters, index),
10390
+ useClearFilter: partial(useClearFilters, index),
10391
+ useTotalCounts: undefined
10392
+ }
10393
+ };
10394
+ }, [
10395
+ getEnumFacetData,
10396
+ getRangeFacetData,
10397
+ index
10398
+ ]);
10399
+ const panels = useDeepCompareMemo(()=>{
10400
+ return facets.map((facet)=>createFacetPanel(facet, 'bar', fieldNameToTitle(index), facetHooks.enum));
10401
+ }, [
10402
+ facets,
10403
+ index,
10404
+ facetHooks.enum
10405
+ ]);
10406
+ const spans = computeRowSpan(panels.length);
10407
+ return /*#__PURE__*/ jsx(Grid, {
10408
+ className: "w-full mx-2 bg-base-max p-4",
10409
+ children: panels.map((panel, index)=>/*#__PURE__*/ jsx(Grid.Col, {
10410
+ span: spans[index],
10411
+ children: panel
10412
+ }, `${index}-charts-${facets[index].field}-col`))
10413
+ });
10414
+ };
10415
+
10416
+ const ActionButtonGroup = ()=>{
10417
+ return /*#__PURE__*/ jsxs(Group, {
10418
+ gap: "xs",
10419
+ className: "flex pt-4 pl-2",
10420
+ children: [
10421
+ /*#__PURE__*/ jsx(Button, {
10422
+ size: "sm",
10423
+ variant: "outline",
10424
+ color: "secondary.4",
10425
+ classNames: {
10426
+ root: 'bg-base-max'
10427
+ },
10428
+ children: "Save Cohort"
10429
+ }),
10430
+ /*#__PURE__*/ jsx(Button, {
10431
+ size: "sm",
10432
+ variant: "outline",
10433
+ color: "secondary.4",
10434
+ classNames: {
10435
+ root: 'bg-base-max'
10436
+ },
10437
+ children: "Export Cohort"
10438
+ }),
10439
+ /*#__PURE__*/ jsx(Button, {
10440
+ size: "sm",
10441
+ variant: "outline",
10442
+ color: "secondary.4",
10443
+ classNames: {
10444
+ root: 'bg-base-max'
10445
+ },
10446
+ children: "Import Cohort"
10447
+ })
10448
+ ]
10449
+ });
10450
+ };
10451
+
10452
+ const IndexPanel = ({ dataConfig, tabs, tabTitle })=>{
10453
+ const [activeFieldDefinitions, setActiveFieldDefinitions] = useState([]);
10454
+ const index = dataConfig.dataType;
10455
+ const fields = useMemo(()=>getAllFieldsFromFilterConfigs(tabs ?? []), [
10456
+ tabs
10457
+ ]);
10458
+ const [facetDefinitions, setFacetDefinitions] = useState({});
10459
+ const [categories, setCategories] = useState([]);
10460
+ const cohortFilters = useCoreSelector((state)=>selectIndexFilters(state, index));
10461
+ const queryFields = categories.length === 0 ? fields : activeFieldDefinitions.map((x)=>x.field);
10462
+ const { data, isSuccess, isError: isAggsQueryError } = useGetAggsQuery({
10463
+ type: index,
10464
+ fields: queryFields,
10465
+ filters: cohortFilters
10466
+ }, {
10467
+ skip: queryFields.length === 0
10468
+ });
10469
+ const updateFields = useDeepCompareCallback((field)=>{
10470
+ if (activeFieldDefinitions.some((facetDef)=>facetDef.field === field)) {
10471
+ setActiveFieldDefinitions((prevState)=>{
10472
+ return prevState.filter((f)=>f.field !== field);
10473
+ });
10474
+ } else {
10475
+ setActiveFieldDefinitions((prevState)=>[
10476
+ ...prevState,
10477
+ facetDefinitions[field]
10478
+ ]);
10479
+ }
10480
+ }, [
10481
+ activeFieldDefinitions,
10482
+ facetDefinitions
10483
+ ]);
10484
+ // Set the facet definitions based on the data only the first time the data is loaded
10485
+ useDeepCompareEffect(()=>{
10486
+ if (isSuccess && Object.keys(facetDefinitions).length === 0) {
10487
+ const configFacetDefs = tabs.reduce((acc, tab)=>{
10488
+ return {
10489
+ ...tab.fieldsConfig,
10490
+ ...acc
10491
+ };
10492
+ }, {});
10493
+ const facetDefs = classifyFacets(data, index, [], configFacetDefs);
10494
+ setFacetDefinitions(facetDefs);
10495
+ // setup categories
10496
+ const categories = tabs.reduce((acc, tab)=>{
10497
+ const updatedTab = tab;
10498
+ if (!updatedTab?.fieldsConfig) {
10499
+ updatedTab.fieldsConfig = {};
10500
+ }
10501
+ updatedTab.fields.forEach((x)=>{
10502
+ tab.fieldsConfig[x] = {
10503
+ ...tab.fieldsConfig[x],
10504
+ ...x in facetDefs ? facetDefs[x] : {}
10505
+ };
10506
+ });
10507
+ acc.push(updatedTab);
10508
+ return acc;
10509
+ }, []);
10510
+ setCategories(categories);
10511
+ }
10512
+ }, [
10513
+ isSuccess,
10514
+ data,
10515
+ facetDefinitions,
10516
+ index
10517
+ ]);
10518
+ if (isAggsQueryError) {
10519
+ return /*#__PURE__*/ jsx(ErrorCard, {
10520
+ message: "Unable to fetch data from server"
10521
+ });
10522
+ }
10523
+ return /*#__PURE__*/ jsxs(Stack, {
10524
+ children: [
10525
+ /*#__PURE__*/ jsx(CohortManager, {
10526
+ index: index
10527
+ }),
10528
+ /*#__PURE__*/ jsxs(Flex, {
10529
+ className: "w-full h-full bg-base-light",
10530
+ children: [
10531
+ /*#__PURE__*/ jsx(FacetSelectionPanel, {
10532
+ categories: categories,
10533
+ selectedFields: activeFieldDefinitions.map((x)=>x.field),
10534
+ updateSelectedField: updateFields,
10535
+ hooks: {
10536
+ useClearFilter: ()=>(field)=>null,
10537
+ useToggleExpandFilter: useToggleExpandFilter,
10538
+ useFilterExpanded: useFilterExpandedState
10539
+ }
10540
+ }),
10541
+ /*#__PURE__*/ jsxs(Stack, {
10542
+ className: "w-full",
10543
+ children: [
10544
+ /*#__PURE__*/ jsx(ActionButtonGroup, {}),
10545
+ /*#__PURE__*/ jsx(ChartsAndFacetsPanel, {
10546
+ index: index,
10547
+ facets: activeFieldDefinitions
10548
+ })
10549
+ ]
10550
+ })
10551
+ ]
10552
+ })
10553
+ ]
10554
+ });
10555
+ };
10556
+
10557
+ const persistor = persistStore(AppStore);
10558
+ const CohortDiscovery = (config)=>{
10559
+ const { isLoading } = useGetCSRFQuery(); // need for Guppy
10560
+ if (isLoading) {
10561
+ return /*#__PURE__*/ jsx(Center, {
10562
+ maw: 400,
10563
+ h: 100,
10564
+ mx: "auto",
10565
+ children: /*#__PURE__*/ jsx(Loader, {
10566
+ variant: "dots"
10567
+ })
10568
+ });
10569
+ }
10570
+ return /*#__PURE__*/ jsx(Fragment, {
10571
+ children: /*#__PURE__*/ jsx(PersistGate, {
10572
+ persistor: persistor,
10573
+ children: /*#__PURE__*/ jsx("div", {
10574
+ className: "w-full h-full",
10575
+ children: /*#__PURE__*/ jsx(IndexPanel, {
10576
+ dataConfig: config.dataIndexes[0].dataConfig,
10577
+ tabTitle: config.dataIndexes[0].tabTitle,
10578
+ tabs: config.dataIndexes[0].tabs
10579
+ })
10580
+ })
10581
+ })
10582
+ });
10583
+ };
10584
+
10585
+ const _APP_NAME$1 = 'CohortDiscovery'; // This wil be the route name of the app
10586
+ const registerCohortDiscoveryApp = ()=>createGen3AppWithOwnStore({
10587
+ App: CohortDiscovery,
10588
+ id: id,
10589
+ name: _APP_NAME$1,
10590
+ version: 'v1.0.0',
10591
+ requiredEntityTypes: [],
10592
+ store: AppStore,
10593
+ context: AppContext
10594
+ });
10595
+
10596
+ const roundTo2AfterDecimal = (number)=>{
10597
+ return Math.round((number + Number.EPSILON) * 100) / 100;
10598
+ };
10599
+
10600
+ const processComparisonData$1 = (baseData, comparisonData)=>{
10601
+ return [
10602
+ {
10603
+ name: baseData.label,
10604
+ type: 'bar',
10605
+ barGap: 0,
10606
+ itemStyle: {
10607
+ color: '#4e79a7'
10608
+ },
10609
+ data: baseData.data.map((item)=>roundTo2AfterDecimal(item.count)),
10610
+ emphasis: {
10611
+ focus: 'series'
10612
+ }
10613
+ },
10614
+ {
10615
+ name: comparisonData.label,
10616
+ type: 'bar',
10617
+ itemStyle: {
10618
+ color: '#f28e2c'
10619
+ },
10620
+ data: comparisonData.data.map((item)=>roundTo2AfterDecimal(item.count)),
10621
+ emphasis: {
10622
+ focus: 'series'
10623
+ }
10624
+ }
10625
+ ];
10626
+ };
10627
+ const BarComparison = ({ baseDataset, comparisonDataset, title, yAxisLabel = 'percent' })=>{
10628
+ const categories = baseDataset.data.map((d)=>truncateString(processLabel$1(d.key), 35));
10629
+ const chartDefinition = useMemo(()=>{
10630
+ const series = processComparisonData$1(baseDataset, comparisonDataset);
10631
+ return {
10632
+ aria: {
10633
+ enabled: true
10634
+ },
10635
+ tooltip: {
10636
+ trigger: 'axis',
10637
+ axisPointer: {
10638
+ type: 'shadow'
10639
+ }
10640
+ },
10641
+ title: {
10642
+ text: title,
10643
+ left: 'center'
10644
+ },
10645
+ legend: {
10646
+ data: [
10647
+ baseDataset.label,
10648
+ comparisonDataset.label
10649
+ ],
10650
+ bottom: '5%'
10651
+ },
10652
+ xAxis: {
10653
+ type: 'category',
10654
+ data: categories,
10655
+ axisTick: {
10656
+ show: false
10657
+ }
10658
+ },
10659
+ yAxis: {
10660
+ type: 'value',
10661
+ name: yAxisLabel
10662
+ },
10663
+ series: series
10664
+ };
10665
+ }, [
10666
+ baseDataset,
10667
+ categories,
10668
+ comparisonDataset,
10669
+ title,
10670
+ yAxisLabel
10671
+ ]);
10672
+ return /*#__PURE__*/ jsx("div", {
10673
+ role: "region",
10674
+ "aria-labelledby": "bar-comparison-title",
10675
+ className: "flex flex-col w-full h-96",
10676
+ children: /*#__PURE__*/ jsx(ReactECharts, {
10677
+ option: chartDefinition,
10678
+ settings: {
10679
+ notMerge: true
10680
+ }
10681
+ })
10682
+ });
10683
+ };
10684
+
10685
+ const processComparisonData = (baseData, comparisonData)=>{
10686
+ const maxB = baseData.data.reduce((acc, curr)=>{
10687
+ return Math.max(curr.count, acc);
10688
+ }, 0);
10689
+ const maxC = comparisonData.data.reduce((acc, curr)=>{
10690
+ return Math.max(curr.count, acc);
10691
+ }, 0);
10692
+ return {
10693
+ data: [
10694
+ {
10695
+ type: 'radar',
10696
+ data: [
10697
+ {
10698
+ value: baseData.data.map((item)=>roundTo2AfterDecimal(item.count)),
10699
+ name: baseData.label,
10700
+ itemStyle: {
10701
+ color: '#4e79a7'
10702
+ },
10703
+ areaStyle: {
10704
+ opacity: 0.3
10705
+ }
10706
+ },
10707
+ {
10708
+ value: comparisonData.data.map((item)=>roundTo2AfterDecimal(item.count)),
10709
+ name: comparisonData.label,
10710
+ itemStyle: {
10711
+ color: '#f28e2c'
10712
+ },
10713
+ areaStyle: {
10714
+ opacity: 0.3
10715
+ }
10716
+ }
10717
+ ]
10718
+ }
10719
+ ],
10720
+ maxBase: maxB,
10721
+ maxComparison: maxC
10722
+ };
10723
+ };
10724
+ const RadarComparison = ({ baseDataset, comparisonDataset, title, yAxisLabel = 'percent' })=>{
10725
+ const categories = baseDataset.data.map((d)=>truncateString(processLabel$1(d.key), 35));
10726
+ const chartDefinition = useMemo(()=>{
10727
+ const series = processComparisonData(baseDataset, comparisonDataset);
10728
+ const option = {
10729
+ aria: {
10730
+ enabled: true
10731
+ },
10732
+ title: {
10733
+ text: title,
10734
+ left: 'center'
10735
+ },
10736
+ legend: {
10737
+ data: [
10738
+ baseDataset.label,
10739
+ comparisonDataset.label
10740
+ ],
10741
+ bottom: '5%'
10742
+ },
10743
+ radar: {
10744
+ indicator: categories.map((group)=>({
10745
+ name: group,
10746
+ max: Math.max(series.maxBase, series.maxComparison)
10747
+ })),
10748
+ axisLine: {
10749
+ lineStyle: {
10750
+ color: '#4e79a7'
10751
+ }
10752
+ },
10753
+ splitLine: {
10754
+ show: true,
10755
+ lineStyle: {
10756
+ color: [
10757
+ '#8c8989',
10758
+ '#8aa0ae'
10759
+ ]
10760
+ }
10761
+ },
10762
+ center: [
10763
+ '50%',
10764
+ '50%'
10765
+ ],
10766
+ radius: '65%'
10767
+ },
10768
+ series: series.data,
10769
+ tooltip: {
10770
+ trigger: 'item'
10771
+ }
10772
+ };
10773
+ return option;
10774
+ }, [
10775
+ baseDataset,
10776
+ categories,
10777
+ comparisonDataset,
10778
+ title,
10779
+ yAxisLabel
10780
+ ]);
10781
+ return /*#__PURE__*/ jsx("div", {
10782
+ role: "region",
10783
+ "aria-labelledby": "radar-comparison-title",
10784
+ className: "flex flex-col w-full h-96",
10785
+ children: /*#__PURE__*/ jsx(ReactECharts, {
10786
+ option: chartDefinition,
10787
+ settings: {
10788
+ notMerge: true
10789
+ }
10790
+ })
10791
+ });
10792
+ };
10793
+
10794
+ let instance = undefined;
10795
+ const DefaultComparisonChart = ()=>{
10796
+ return /*#__PURE__*/ jsx("div", {
10797
+ children: "Chart not configured"
10798
+ });
10799
+ };
10800
+ const DefaultRendererCatalog = {
10801
+ comparison: {
10802
+ default: DefaultComparisonChart,
10803
+ barComparison: BarComparison,
10804
+ radarComparison: RadarComparison
10805
+ }
10806
+ };
10807
+ const DiversityChartsFactory = ()=>{
10808
+ if (!instance) {
10809
+ instance = new RenderFactoryTypedInstance();
10810
+ instance.registerRendererCatalog(DefaultRendererCatalog);
10811
+ }
10812
+ return instance;
10813
+ };
10814
+
10815
+ DiversityChartsFactory();
10816
+ const generateChart = (groundData, groundLabel, comparisonData, comparisonLabel, field, config, showTitle = true)=>{
10817
+ // Check if the field exists in the datasets
10818
+ if (!(field in groundData) || !(field in comparisonData)) {
10819
+ console.error(`Field ${field} does not exist in provided data.`);
10820
+ return /*#__PURE__*/ jsx("span", {
10821
+ children: "Error: Data field missing"
10822
+ });
10823
+ }
10824
+ const chartRenderer = DiversityChartsFactory().getRenderer('comparison', config.chartType);
10825
+ // Check if renderer is the DefaultItemRenderer to log a warning
10826
+ if (chartRenderer === DefaultComparisonChart) {
10827
+ console.warn(`No specific renderer found for ${config.chartType}. Using default renderer.`);
10828
+ }
10829
+ return chartRenderer({
10830
+ baseDataset: {
10831
+ data: groundData[field],
10832
+ label: groundLabel
10833
+ },
10834
+ comparisonDataset: {
10835
+ data: comparisonData[field],
10836
+ label: comparisonLabel
10837
+ },
10838
+ title: showTitle ? fieldNameToTitle(field) : ''
10839
+ });
10840
+ };
10841
+
10842
+ // Compute statistics
10843
+ const computeStatistics = (baseData, comparisonData)=>{
10844
+ const buckets = baseData.map((item)=>typeof item.key !== 'string' ? `${item.key[0]} to ${item.key[1]}` : item.key);
10845
+ const baseValues = baseData.map((item)=>item.count);
10846
+ const cmpValues = comparisonData.map((item)=>item.count);
10847
+ // Mean Absolute Error (MAE)
10848
+ const mae = baseValues.reduce((sum, value, index)=>sum + Math.abs(value - cmpValues[index]), 0) / buckets.length;
10849
+ // Root Mean Square Error (RMSE)
10850
+ const rmse = Math.sqrt(baseValues.reduce((sum, value, index)=>sum + Math.pow(value - cmpValues[index], 2), 0) / buckets.length);
10851
+ // Pearson Correlation Coefficient
10852
+ const baseAve = baseValues.reduce((sum, value)=>sum + value, 0) / buckets.length;
10853
+ const cmpAvg = cmpValues.reduce((sum, value)=>sum + value, 0) / buckets.length;
10854
+ const numerator = baseValues.reduce((sum, value, index)=>sum + (value - baseAve) * (cmpValues[index] - cmpAvg), 0);
10855
+ const denominator = Math.sqrt(baseValues.reduce((sum, value)=>sum + Math.pow(value - baseAve, 2), 0) * cmpValues.reduce((sum, value)=>sum + Math.pow(value - cmpAvg, 2), 0));
10856
+ const correlation = numerator / denominator;
10857
+ const robustChiSquare = baseValues.reduce((sum, expected, index)=>{
10858
+ const observed = cmpValues[index];
10859
+ if (expected === 0 && observed === 0) {
10860
+ return sum; // Both expected and observed are 0, no contribution to chi-square
10861
+ } else if (expected === 0) {
10862
+ return sum + observed; // Add observed value to chi-square when expected is 0
10863
+ } else {
10864
+ return sum + Math.pow(observed - expected, 2) / expected;
10865
+ }
10866
+ }, 0);
10867
+ // Chi-Square Contributions
10868
+ const chiSquareContributions = buckets.map((group, index)=>{
10869
+ const expected = baseValues[index];
10870
+ const observed = cmpValues[index];
10871
+ let contribution = 0;
10872
+ if (expected === 0 && observed === 0) {
10873
+ contribution = 0;
10874
+ } else if (expected === 0) {
10875
+ contribution = observed;
10876
+ } else {
10877
+ contribution = Math.pow(observed - expected, 2) / expected;
10878
+ }
10879
+ return {
10880
+ group,
10881
+ contribution
10882
+ };
10883
+ });
10884
+ return {
10885
+ mae,
10886
+ rmse,
10887
+ correlation,
10888
+ robustChiSquare,
10889
+ chiSquareContributions
10890
+ };
10891
+ };
10892
+ const LabeledValueRow = ({ label, value })=>{
10893
+ return /*#__PURE__*/ jsxs(Group, {
10894
+ justify: "space-between",
10895
+ children: [
10896
+ /*#__PURE__*/ jsx(Text, {
10897
+ fw: 600,
10898
+ size: "sm",
10899
+ className: "uppercase",
10900
+ children: label
10901
+ }),
10902
+ /*#__PURE__*/ jsx(Text, {
10903
+ size: "sm",
10904
+ c: "primary",
10905
+ children: value
10906
+ })
10907
+ ]
10908
+ });
10909
+ };
10910
+ const StatisticsCard = ({ baseData, comparisonData })=>{
10911
+ const metrics = computeStatistics(baseData, comparisonData);
10912
+ return /*#__PURE__*/ jsxs(Stack, {
10913
+ gap: "xs",
10914
+ children: [
10915
+ /*#__PURE__*/ jsx(LabeledValueRow, {
10916
+ label: "Mean Absolute Error (MAE)",
10917
+ value: metrics.mae.toFixed(4)
10918
+ }),
10919
+ /*#__PURE__*/ jsx(LabeledValueRow, {
10920
+ label: "Root Mean Square Error (RMSE)",
10921
+ value: metrics.rmse.toFixed(4)
10922
+ }),
10923
+ /*#__PURE__*/ jsx(LabeledValueRow, {
10924
+ label: "Pearson Correlation Coefficient",
10925
+ value: metrics.correlation.toFixed(4)
10926
+ }),
10927
+ /*#__PURE__*/ jsx(LabeledValueRow, {
10928
+ label: "Robust Chi-Square Statistic",
10929
+ value: metrics.robustChiSquare.toFixed(4)
10930
+ }),
10931
+ /*#__PURE__*/ jsx(Text, {
10932
+ fw: 600,
10933
+ size: "sm",
10934
+ className: "uppercase",
10935
+ children: "Chi-Square Contributions by Group"
10936
+ }),
10937
+ /*#__PURE__*/ jsx(ScrollArea, {
10938
+ h: 200,
10939
+ children: /*#__PURE__*/ jsxs(Table, {
10940
+ striped: true,
10941
+ withTableBorder: true,
10942
+ withColumnBorders: true,
10943
+ stickyHeader: true,
10944
+ stickyHeaderOffset: 0,
10945
+ children: [
10946
+ /*#__PURE__*/ jsx(Table.Thead, {
10947
+ children: /*#__PURE__*/ jsxs(Table.Tr, {
10948
+ children: [
10949
+ /*#__PURE__*/ jsx(Table.Th, {
10950
+ children: "Group"
10951
+ }),
10952
+ /*#__PURE__*/ jsx(Table.Th, {
10953
+ children: "Contribution"
10954
+ })
10955
+ ]
10956
+ })
10957
+ }),
10958
+ /*#__PURE__*/ jsx(Table.Tbody, {
10959
+ children: metrics.chiSquareContributions.map(({ group, contribution })=>/*#__PURE__*/ jsxs(Table.Tr, {
10960
+ children: [
10961
+ /*#__PURE__*/ jsx(Table.Td, {
10962
+ children: group
10963
+ }),
10964
+ /*#__PURE__*/ jsx(Table.Td, {
10965
+ children: contribution.toFixed(4)
10966
+ })
10967
+ ]
10968
+ }, group))
10969
+ })
10970
+ ]
10971
+ })
10972
+ })
10973
+ ]
10974
+ });
10975
+ };
10976
+
10977
+ const ComparisonChart = ({ config, groundData, groundLabel, comparisonData, comparisonLabel, field, chartType })=>{
10978
+ return generateChart(groundData, groundLabel, comparisonData, comparisonLabel, field, {
10979
+ ...config,
10980
+ chartType: chartType
10981
+ }, false);
10982
+ };
10983
+ const ComparisonCard = ({ config, groundData, groundLabel, comparisonData, comparisonLabel, field, style = 'box' })=>{
10984
+ const [viewType, setViewType] = useState(config.chartType);
10985
+ return /*#__PURE__*/ jsxs(Card, {
10986
+ shadow: "xs",
10987
+ withBorder: style === 'box',
10988
+ className: "h-full",
10989
+ children: [
10990
+ /*#__PURE__*/ jsx(Card.Section, {
10991
+ inheritPadding: true,
10992
+ py: "xs",
10993
+ withBorder: style === 'box',
10994
+ children: /*#__PURE__*/ jsxs(Group, {
10995
+ justify: "space-between",
10996
+ children: [
10997
+ /*#__PURE__*/ jsx(Text, {
10998
+ fw: 600,
10999
+ children: fieldNameToTitle(field)
11000
+ }),
11001
+ /*#__PURE__*/ jsx(SegmentedControl, {
11002
+ value: viewType,
11003
+ onChange: setViewType,
11004
+ data: [
11005
+ {
11006
+ label: 'Bar',
11007
+ value: 'barComparison'
11008
+ },
11009
+ {
11010
+ label: 'Radar',
11011
+ value: 'radarComparison'
11012
+ },
11013
+ {
11014
+ label: 'Statistics',
11015
+ value: 'statisticsComparison'
11016
+ }
11017
+ ]
11018
+ })
11019
+ ]
11020
+ })
11021
+ }),
11022
+ viewType == 'statisticsComparison' ? /*#__PURE__*/ jsx("div", {
11023
+ className: "h-96 m-2",
11024
+ children: /*#__PURE__*/ jsx(StatisticsCard, {
11025
+ baseData: groundData[field],
11026
+ comparisonData: comparisonData[field]
11027
+ })
11028
+ }) : /*#__PURE__*/ jsx(ComparisonChart, {
11029
+ config: config,
11030
+ groundData: groundData,
11031
+ groundLabel: groundLabel,
11032
+ comparisonData: comparisonData,
11033
+ comparisonLabel: comparisonLabel,
11034
+ field: field,
11035
+ chartType: viewType
11036
+ })
11037
+ ]
11038
+ });
11039
+ };
9788
11040
 
9789
- const WorkspacesPanel = ()=>{
9790
- return /*#__PURE__*/ jsx(Center, {
9791
- className: "m-20 w-full",
9792
- children: /*#__PURE__*/ jsx(Text, {
9793
- size: "2rem",
9794
- children: "Coming soon."
11041
+ const ComparisonCharts = ({ ground, groundLabel, comparison, comparisonLabel, comparisonChartsConfig, numberOfColumns = 2, style = 'tile' })=>{
11042
+ const spans = computeRowSpan(Object.keys(comparisonChartsConfig).length, numberOfColumns);
11043
+ return /*#__PURE__*/ jsx(Grid, {
11044
+ className: "w-full p-4",
11045
+ children: Object.entries(comparisonChartsConfig).map(([field, config], indexNum)=>{
11046
+ return /*#__PURE__*/ jsx(Grid.Col, {
11047
+ span: spans[indexNum],
11048
+ children: /*#__PURE__*/ jsx(ComparisonCard, {
11049
+ config: config,
11050
+ groundData: ground,
11051
+ groundLabel: groundLabel,
11052
+ comparisonData: comparison,
11053
+ comparisonLabel: comparisonLabel,
11054
+ field: field
11055
+ })
11056
+ }, `${indexNum}-charts-${field}-col`);
9795
11057
  })
9796
11058
  });
9797
11059
  };
9798
11060
 
9799
- class FilesystemContent {
9800
- constructor({ rootPath }){
9801
- this.rootPath = rootPath || '';
11061
+ /**
11062
+ * Converts a deeply nested data structure of numbers into a structured aggregation data format.
11063
+ *
11064
+ * @param {Record<string, Record<string, Record<string, number>>>} data - The input data where the structure
11065
+ * consists of three levels of nested records:
11066
+ * - The outermost level is keyed by source identifiers.
11067
+ * - The middle level is keyed by aggregation identifiers.
11068
+ * - The innermost level is keyed by histogram keys with corresponding numeric counts.
11069
+ *
11070
+ * @return {Record<string, AggregationsData>} - A newly structured data object where:
11071
+ * - The outermost level is the same as the input.
11072
+ * - Each aggregation identifier now maps to an array of histogram objects with key-count pairs.
11073
+ */ const convertToAggregateData = (data)=>{
11074
+ const result = {};
11075
+ for (const [sourceKey, sourceValue] of Object.entries(data)){
11076
+ const aggData = {};
11077
+ for (const [aggKey, aggValue] of Object.entries(sourceValue)){
11078
+ const histogramDataArray = [];
11079
+ for (const [key, count] of Object.entries(aggValue)){
11080
+ histogramDataArray.push({
11081
+ key,
11082
+ count
11083
+ });
11084
+ }
11085
+ aggData[aggKey] = histogramDataArray;
11086
+ }
11087
+ result[sourceKey] = aggData;
9802
11088
  }
9803
- async get(filepath) {
9804
- try {
9805
- return await JSON.parse(fs.readFileSync(path.join(this.rootPath, filepath)).toString('utf-8'));
9806
- } catch (err) {
9807
- throw new Error(`Cannot process ${filepath}`);
11089
+ return result;
11090
+ };
11091
+ /**
11092
+ * Converts histogram response data into percentages based on the total counts.
11093
+ *
11094
+ * @param {Record<string, any>} data - The input data containing histogram details and total counts.
11095
+ *
11096
+ * @returns {AggregationsData} The processed histogram data where counts are converted to percentages.
11097
+ */ const processHistogramResponseAsPercentage = (data)=>{
11098
+ const pathData = JSONPath({
11099
+ json: data,
11100
+ path: '$..histogram',
11101
+ resultType: 'all'
11102
+ });
11103
+ const totalData = JSONPath({
11104
+ json: data,
11105
+ path: '$.._totalCount',
11106
+ resultType: 'value'
11107
+ });
11108
+ const total = totalData[0];
11109
+ const results = pathData.reduce((acc, element)=>{
11110
+ const key = element.pointer.split('/').slice(-2, -1)[0];
11111
+ if (isArray(element.value[0].key) && element.value[0].key.length == 2) {
11112
+ if (!(key in acc)) acc[key] = [];
11113
+ return {
11114
+ ...acc,
11115
+ [key]: [
11116
+ {
11117
+ key: `${element.value[0].key[0]}-${element.value[0].key[1]}`,
11118
+ count: element.value[0].count / total * 100
11119
+ },
11120
+ ...acc[key]
11121
+ ]
11122
+ };
11123
+ }
11124
+ return {
11125
+ ...acc,
11126
+ [key]: element.value.map((x)=>{
11127
+ return {
11128
+ key: x.key,
11129
+ count: x.count / total * 100
11130
+ };
11131
+ })
11132
+ };
11133
+ }, {});
11134
+ return results;
11135
+ };
11136
+ /**
11137
+ * Takes an object of type AggregationsData and normalizes the
11138
+ * 'age_at_index' property by converting the age keys to a string format.
11139
+ *
11140
+ * This function checks if the 'age_at_index' key exists in the input object.
11141
+ * If it does, it transforms each age entry by appending ' Years' to the age
11142
+ * value and returns the updated object. If the 'age_at_index' key does not exist,
11143
+ * it returns the original data.
11144
+ *
11145
+ * @param {AggregationsData} data - The input data object containing the age aggregations.
11146
+ * @returns {AggregationsData} - The transformed data object with normalized age keys.
11147
+ */ const normalizeAgeOfIndex = (data)=>{
11148
+ if (!('age_at_index' in data)) return data;
11149
+ const newKeys = data['age_at_index'].map((x)=>{
11150
+ return {
11151
+ key: `${x.key} Years`,
11152
+ count: x.count
11153
+ };
11154
+ });
11155
+ return {
11156
+ ...data,
11157
+ age_at_index: newKeys
11158
+ };
11159
+ };
11160
+ /**
11161
+ * Aligns the source data with the target structure by mapping items based on their keys and updating the counts.
11162
+ *
11163
+ * This function takes two sets of aggregation data, aligns them by their categories and individual keys,
11164
+ * and updates the counts from the source data. If a category or its items are missing in the source data,
11165
+ * a count of 0 is assigned to those items in the resulting aligned data structure.
11166
+ *
11167
+ * @param {AggregationsData} sourceData - The source aggregation data containing key-value pairs with the count.
11168
+ * @param {AggregationsData} targetStructure - The target aggregation structure used to align and structure the result.
11169
+ * @return {AggregationsData} The aligned data with updated counts from the source data, maintaining the target structure.
11170
+ */ const alignData = (sourceData, targetStructure)=>{
11171
+ const result = {};
11172
+ for(const category in targetStructure){
11173
+ if (category in sourceData) {
11174
+ result[category] = targetStructure[category].map((targetItem)=>{
11175
+ const sourceItem = sourceData[category].find((item)=>item.key === targetItem.key);
11176
+ return sourceItem ? {
11177
+ ...targetItem,
11178
+ count: sourceItem.count
11179
+ } : {
11180
+ ...targetItem,
11181
+ count: 0
11182
+ };
11183
+ });
9808
11184
  }
9809
11185
  }
9810
- }
11186
+ // TODO: report missing?
11187
+ // TODO: make this configurable
11188
+ return result;
11189
+ };
9811
11190
 
9812
- class ContentDatabase {
9813
- constructor(config){
9814
- this.config = config;
9815
- this.store = config.store;
11191
+ const getStaticDiversityData = (dataset)=>{
11192
+ return convertToAggregateData({
11193
+ census: {
11194
+ age_at_index: {
11195
+ '0-4 Years': 6,
11196
+ '5-11 Years': 8.7,
11197
+ '12-15 Years': 5.1,
11198
+ '16-17 Years': 2.5,
11199
+ '18-29 Years': 16.4,
11200
+ '30-39 Years': 13.5,
11201
+ '40-49 Years': 12.3,
11202
+ '50-64 Years': 19.2,
11203
+ '65-74 Years': 9.6,
11204
+ '75-84 Years': 4.9,
11205
+ '85-89 Years': 2
11206
+ },
11207
+ race: {
11208
+ White: 61.6315330007,
11209
+ 'Black or African American': 12.4013544021,
11210
+ Asian: 5.9997260938,
11211
+ Other: 18.6347237845,
11212
+ 'American Indian or Alaska Native': 1.1244963298,
11213
+ 'Native Hawaiian or Other Pacific Islander': 0.2081663891,
11214
+ 'Not Reported': 0
11215
+ },
11216
+ ethnicity: {
11217
+ 'Hispanic or Latino': 18.7298774077,
11218
+ 'Not Hispanic or Latino': 81.2701225923,
11219
+ 'Not Reported': 0
11220
+ },
11221
+ sex: {
11222
+ Female: 50.75,
11223
+ Male: 49.25,
11224
+ 'Not Reported': 0
11225
+ },
11226
+ race_and_ethnicity: {
11227
+ 'Hispanic or Latino': 18.45,
11228
+ 'American Indian or Alaska Native, Not Hispanic or Latino': 0.74,
11229
+ 'Asian, Not Hispanic or Latino': 5.76,
11230
+ 'Black, Not Hispanic or Latino': 12.54,
11231
+ 'Native Hawaiian or Other Pacific Islander, Not Hispanic or Latino': 0.182,
11232
+ 'White, Not Hispanic or Latino': 60.11,
11233
+ 'Multiple or Other, Not Hispanic or Latino': 2.22,
11234
+ 'Not Reported': 0
11235
+ }
11236
+ }
11237
+ })[dataset];
11238
+ };
11239
+
11240
+ const convertToValidJSON = (inputString)=>{
11241
+ // Remove all newline characters and extra spaces
11242
+ let cleanedString = inputString.replace(/\s+/g, ' ').trim();
11243
+ // Add quotes around property names that aren't already quoted
11244
+ cleanedString = cleanedString.replace(/(\w+):/g, '"$1":');
11245
+ // Replace single quotes with double quotes (if any)
11246
+ cleanedString = cleanedString.replace(/'/g, '"');
11247
+ return cleanedString;
11248
+ };
11249
+ const createDiversityQuery = (fields = {
11250
+ age_at_index: 'age_at_index',
11251
+ sex: 'sex',
11252
+ ethnicity: 'ethnicity',
11253
+ race: 'race'
11254
+ })=>{
11255
+ // TODO refactor to make this usable for all facets
11256
+ return {
11257
+ query: `
11258
+ query ($filter_0_4: JSON, $filter_5_11: JSON, $filter_12_15: JSON, $filter_16_17: JSON, $filter_18_29: JSON, $filter_30_39: JSON, $filter_40_49: JSON, $filter_50_64: JSON, $filter_65_74: JSON, $filter_75_84: JSON, $filter_85_plus: JSON) {
11259
+ _aggregation {
11260
+ case {
11261
+ _totalCount
11262
+ ${fields['sex']} {
11263
+ histogram {
11264
+ key
11265
+ count
11266
+ }
11267
+ }
11268
+ ${fields['ethnicity']} {
11269
+ histogram {
11270
+ key
11271
+ count
11272
+ }
11273
+ },
11274
+ ${fields['race']} {
11275
+ histogram {
11276
+ key
11277
+ count
11278
+ }
11279
+ }
9816
11280
  }
9817
- async get(filepath) {
9818
- return this.store.get(filepath);
11281
+ case_0_4: case(filter: $filter_0_4, filterSelf: true, accessibility: all) {
11282
+ ${fields['age_at_index']} {
11283
+ histogram {
11284
+ key
11285
+ count
11286
+ }
11287
+ }
9819
11288
  }
9820
- }
9821
-
9822
- const GEN3_FRONTEND_CONFIGURATION_ROOT = process.env.GEN3_FRONTEND_CONFIGURATION_ROOT || './';
9823
-
9824
- const ContentRoot = GEN3_FRONTEND_CONFIGURATION_ROOT;
9825
- const setup = ()=>{
9826
- const config = {
9827
- store: new FilesystemContent({
9828
- rootPath: ContentRoot
9829
- })
11289
+ case_5_11: case(filter: $filter_5_11, filterSelf: true, accessibility: all) {
11290
+ ${fields['age_at_index']} {
11291
+ histogram {
11292
+ key
11293
+ count
11294
+ }
11295
+ }
11296
+ }
11297
+ case_12_15: case(filter: $filter_12_15, filterSelf: true, accessibility: all) {
11298
+ ${fields['age_at_index']} {
11299
+ histogram {
11300
+ key
11301
+ count
11302
+ }
11303
+ }
11304
+ }
11305
+ case_16_17: case(filter: $filter_16_17, filterSelf: true, accessibility: all) {
11306
+ ${fields['age_at_index']} {
11307
+ histogram {
11308
+ key
11309
+ count
11310
+ }
11311
+ }
11312
+ }
11313
+ case_18_29: case(filter: $filter_18_29, filterSelf: true, accessibility: all) {
11314
+ ${fields['age_at_index']} {
11315
+ histogram {
11316
+ key
11317
+ count
11318
+ }
11319
+ }
11320
+ }
11321
+ case_30_39: case(filter: $filter_30_39, filterSelf: true, accessibility: all) {
11322
+ ${fields['age_at_index']} {
11323
+ histogram {
11324
+ key
11325
+ count
11326
+ }
11327
+ }
11328
+ }
11329
+ case_40_49: case(filter: $filter_40_49, filterSelf: true, accessibility: all) {
11330
+ ${fields['age_at_index']} {
11331
+ histogram {
11332
+ key
11333
+ count
11334
+ }
11335
+ }
11336
+ }
11337
+ case_50_64: case(filter: $filter_50_64, filterSelf: true, accessibility: all) {
11338
+ ${fields['age_at_index']} {
11339
+ histogram {
11340
+ key
11341
+ count
11342
+ }
11343
+ }
11344
+ }
11345
+ case_65_74: case(filter: $filter_65_74, filterSelf: true, accessibility: all) {
11346
+ ${fields['age_at_index']} {
11347
+ histogram {
11348
+ key
11349
+ count
11350
+ }
11351
+ }
11352
+ }
11353
+ case_75_84: case(filter: $filter_75_84, filterSelf: true, accessibility: all) {
11354
+ ${fields['age_at_index']} {
11355
+ histogram {
11356
+ key
11357
+ count
11358
+ }
11359
+ }
11360
+ }
11361
+ case_85_plus: case(filter: $filter_85_plus, filterSelf: true, accessibility: all) {
11362
+ ${fields['age_at_index']} {
11363
+ histogram {
11364
+ key
11365
+ count
11366
+ }
11367
+ }
11368
+ }
11369
+ }
11370
+ }`,
11371
+ variables: convertToValidJSON(`{ "filter_0_4": {
11372
+ "AND": [
11373
+ {
11374
+ ">=": {
11375
+ ${fields['age_at_index']}: 0
11376
+ }
11377
+ },
11378
+ {
11379
+ "<=": {
11380
+ ${fields['age_at_index']}: 4
11381
+ }
11382
+ }
11383
+ ]
11384
+ },
11385
+ "filter_5_11": {
11386
+ "AND": [
11387
+ {
11388
+ ">=": {
11389
+ ${fields['age_at_index']}: 5
11390
+ }
11391
+ },
11392
+ {
11393
+ "<=": {
11394
+ ${fields['age_at_index']}: 11
11395
+ }
11396
+ }
11397
+ ]
11398
+ },
11399
+ "filter_12_15": {
11400
+ "AND": [
11401
+ {
11402
+ ">=": {
11403
+ ${fields['age_at_index']}: 12
11404
+ }
11405
+ },
11406
+ {
11407
+ "<=": {
11408
+ ${fields['age_at_index']}: 15
11409
+ }
11410
+ }
11411
+ ]
11412
+ },
11413
+ "filter_16_17": {
11414
+ "AND": [
11415
+ {
11416
+ ">=": {
11417
+ ${fields['age_at_index']}: 16
11418
+ }
11419
+ },
11420
+ {
11421
+ "<=": {
11422
+ ${fields['age_at_index']}: 17
11423
+ }
11424
+ }
11425
+ ]
11426
+ },
11427
+ "filter_18_29": {
11428
+ "AND": [
11429
+ {
11430
+ ">=": {
11431
+ ${fields['age_at_index']}: 18
11432
+ }
11433
+ },
11434
+ {
11435
+ "<=": {
11436
+ ${fields['age_at_index']}: 29
11437
+ }
11438
+ }
11439
+ ]
11440
+ },
11441
+ "filter_30_39": {
11442
+ "AND": [
11443
+ {
11444
+ ">=": {
11445
+ ${fields['age_at_index']}: 30
11446
+ }
11447
+ },
11448
+ {
11449
+ "<=": {
11450
+ ${fields['age_at_index']}: 39
11451
+ }
11452
+ }
11453
+ ]
11454
+ },
11455
+ "filter_40_49": {
11456
+ "AND": [
11457
+ {
11458
+ ">=": {
11459
+ ${fields['age_at_index']}: 40
11460
+ }
11461
+ },
11462
+ {
11463
+ "<=": {
11464
+ ${fields['age_at_index']}: 49
11465
+ }
11466
+ }
11467
+ ]
11468
+ },
11469
+ "filter_50_64": {
11470
+ "AND": [
11471
+ {
11472
+ ">=": {
11473
+ ${fields['age_at_index']}: 50
11474
+ }
11475
+ },
11476
+ {
11477
+ "<=": {
11478
+ ${fields['age_at_index']}: 64
11479
+ }
11480
+ }
11481
+ ]
11482
+ },
11483
+ "filter_65_74": {
11484
+ "AND": [
11485
+ {
11486
+ ">=": {
11487
+ ${fields['age_at_index']}: 65
11488
+ }
11489
+ },
11490
+ {
11491
+ "<=": {
11492
+ ${fields['age_at_index']}: 74
11493
+ }
11494
+ }
11495
+ ]
11496
+ },
11497
+ "filter_75_84": {
11498
+ "AND": [
11499
+ {
11500
+ ">=": {
11501
+ ${fields['age_at_index']}: 75
11502
+ }
11503
+ },
11504
+ {
11505
+ "<=": {
11506
+ ${fields['age_at_index']}: 84
11507
+ }
11508
+ }
11509
+ ]
11510
+ },
11511
+ "filter_85_plus": {
11512
+ "AND": [
11513
+ {
11514
+ ">=": {
11515
+ ${fields['age_at_index']}: 85
11516
+ }
11517
+ }
11518
+ ]
11519
+ }
11520
+ }`)
9830
11521
  };
9831
- return new ContentDatabase(config);
9832
11522
  };
9833
- const ContentSource = setup();
9834
11523
 
9835
- /**
9836
- * Retrieves navigation page layout properties from configuration.
9837
- * Note: GEN3_COMMONS_NAME depends on siteConfig.json value in the data commons package
9838
- * @returns A Promise resolving to an object containing header and footer props.
9839
- */ const getNavPageLayoutPropsFromConfig = async ()=>{
9840
- const navigationConfigJSON = await ContentSource.get(`config/${GEN3_COMMONS_NAME}/navigation.json`);
9841
- let bannerConfigJSON = [];
9842
- try {
9843
- bannerConfigJSON = await ContentSource.get(`config/${GEN3_COMMONS_NAME}/banner.json`);
9844
- } catch (e) {
9845
- console.log('No banner config found at: ', `config/${GEN3_COMMONS_NAME}/banner.json`);
9846
- }
9847
- const { topBar, navigation, type = 'original' } = navigationConfigJSON;
9848
- const headerProps = {
9849
- top: topBar,
9850
- navigation: navigation,
9851
- banners: bannerConfigJSON,
9852
- type
9853
- };
9854
- const footerProps = await ContentSource.get(`config/${GEN3_COMMONS_NAME}/footer.json`);
9855
- return {
9856
- headerProps,
9857
- footerProps,
9858
- headerData: {
9859
- title: 'Gen3 Frontend Framework Page',
9860
- content: 'Gen3 Frontend Framework Page',
9861
- key: 'gen3-common-page'
11524
+ const CohortDiversityApp = (config)=>{
11525
+ const groundDataset = getStaticDiversityData(config.datasets.ground.dataset);
11526
+ const gqlQuery = createDiversityQuery(); // TODO: add field mapping
11527
+ const { data: rawComparisonDataset, isLoading: isComparisonLoading, isError: isComparisonError } = useGeneralGQLQuery({
11528
+ query: gqlQuery.query,
11529
+ variables: JSON.parse(gqlQuery.variables)
11530
+ });
11531
+ const comparisonDataset = useMemo(()=>{
11532
+ if (rawComparisonDataset) {
11533
+ const results = processHistogramResponseAsPercentage(rawComparisonDataset.data);
11534
+ return alignData(normalizeAgeOfIndex(results), groundDataset);
9862
11535
  }
9863
- };
11536
+ return undefined;
11537
+ }, [
11538
+ groundDataset,
11539
+ rawComparisonDataset
11540
+ ]);
11541
+ if (isComparisonError) {
11542
+ return /*#__PURE__*/ jsx(ErrorCard, {
11543
+ message: 'Unable to get data need for Cohort Diversity'
11544
+ });
11545
+ }
11546
+ if (isComparisonLoading) {
11547
+ return /*#__PURE__*/ jsx(LoadingOverlay, {
11548
+ visible: true
11549
+ });
11550
+ }
11551
+ return /*#__PURE__*/ jsxs(Stack, {
11552
+ classNames: {
11553
+ root: 'w-full m-4 mb-2'
11554
+ },
11555
+ "aria-label": "Main Content of Cohort Diversity App",
11556
+ children: [
11557
+ /*#__PURE__*/ jsx(Title, {
11558
+ order: 1,
11559
+ size: "h3",
11560
+ children: "Cohort Diversity Visualization"
11561
+ }),
11562
+ /*#__PURE__*/ jsx(Accordion, {
11563
+ variant: "filled",
11564
+ chevronPosition: "left",
11565
+ children: /*#__PURE__*/ jsxs(Accordion.Item, {
11566
+ value: "summaryCharts",
11567
+ "aria-label": "Summary Charts",
11568
+ children: [
11569
+ /*#__PURE__*/ jsx(Accordion.Control, {
11570
+ children: /*#__PURE__*/ jsxs("div", {
11571
+ className: "flex items-center justify-start space-x-2 text-accent",
11572
+ children: [
11573
+ /*#__PURE__*/ jsx(FaChartPie, {
11574
+ style: {
11575
+ color: 'secondary.4',
11576
+ width: rem(32),
11577
+ height: rem(32)
11578
+ }
11579
+ }),
11580
+ /*#__PURE__*/ jsx(Text, {
11581
+ fw: 600,
11582
+ children: "Summary Charts"
11583
+ })
11584
+ ]
11585
+ })
11586
+ }),
11587
+ /*#__PURE__*/ jsx(Accordion.Panel, {
11588
+ children: /*#__PURE__*/ jsx(Charts, {
11589
+ data: groundDataset ?? {},
11590
+ charts: config.charts,
11591
+ isSuccess: true,
11592
+ numCols: 2
11593
+ })
11594
+ })
11595
+ ]
11596
+ })
11597
+ }),
11598
+ /*#__PURE__*/ jsx(ComparisonCharts, {
11599
+ ground: groundDataset ?? {},
11600
+ groundLabel: config.datasets.ground.label,
11601
+ comparison: comparisonDataset ?? {},
11602
+ comparisonLabel: config.datasets.comparison[0].label,
11603
+ comparisonChartsConfig: config.comparisonCharts,
11604
+ numberOfColumns: config?.numberOfColumns
11605
+ })
11606
+ ]
11607
+ });
9864
11608
  };
9865
11609
 
11610
+ const { appApi: diversityApi, appStore, appContext } = createAppApiForRTKQ('cohortDiversity');
11611
+
11612
+ const _APP_NAME = 'CohortDiversity'; // This wil be the route name of the app
11613
+ const _APP_VERSION = '1.0.0';
11614
+ const AppId = getGen3AppId(_APP_NAME, _APP_VERSION);
11615
+ const registerCohortDiversityApp = ()=>createGen3AppWithOwnStore({
11616
+ App: CohortDiversityApp,
11617
+ name: _APP_NAME,
11618
+ version: 'v1.0.0',
11619
+ id: AppId,
11620
+ requiredEntityTypes: [],
11621
+ store: appStore,
11622
+ context: appContext
11623
+ });
11624
+
9866
11625
  // Define theme for mantine v7
9867
11626
  const createMantineTheme = (fonts, colors)=>{
9868
11627
  const theme = createTheme({
@@ -13041,7 +14800,10 @@ const AdminAuthZPageGetServerSideProps = async ()=>{
13041
14800
  try {
13042
14801
  const contents = fs.readFileSync(path.join(rootPath, filepath), 'utf8');
13043
14802
  data = await YAML.parse(contents);
13044
- } catch (err) {
14803
+ } catch (error) {
14804
+ if (error instanceof Error) {
14805
+ console.error(error.message);
14806
+ }
13045
14807
  throw new Error(`Cannot process ${rootPath}${filepath}`);
13046
14808
  }
13047
14809
  return {
@@ -14017,5 +15779,5 @@ async function credentialsLogout(req, res) {
14017
15779
  res.redirect(307, '/');
14018
15780
  }
14019
15781
 
14020
- export { AISearchPageGetServerSideProps, AdminAuthZPageGetServerSideProps, AiSearch, AISearchPage as AiSearchPage, AuthzPage, BaseModal, Charts, CohortBuilder, ColorThemePage, ColorThemePageGetServerSideProps, ContentSource, CreateCredentialsAPIKeyModal, CrosswalkPage, CrosswalkPageGetServerSideProps, Custom404Page, DictionaryPage, DictionaryPageGetServerSideProps, DiscoveryCellRendererFactory, DiscoveryProvider as DiscoveryConfigProvider, DiscoveryIndexPanel, DiscoveryPage, DiscoveryPageGetServerSideProps, DiscoveryRowRendererFactory, EnumFacetChart, ErrorCard, ExplorerPage, ExplorerPageGetServerSideProps, ExplorerTableCellRendererFactory, ExplorerTableDetailsPanelFactory, FirstTimeModal, Footer, Gen3Link, Gen3ModalsProvider, Gen3Provider, GqlQueryEditor$1 as GqlQueryEditor, Header, HoverLink, LandingPage, LandingPageGetStaticProps, LoginButton, LoginPage, LoginPageGetServerSideProps, LoginPanel, LoginProvidersPanel, NavPageLayout, NavigationBar, NavigationButton, NoAccessModal, ProfilePage, ProfilePageGetServerSideProps, ProfileProvider, QueryPage, QueryPageGetServerSideProps, ReactECharts, ResourcesFilters, SessionExpiredModal, StudyGroup, SubmissionPage, SubmissionPageGetServerSideProps, TagCloud, TailwindConfig, User, WorkspacesPage, WorkspacesPageGetServerSideProps, WorkspacesPanel, capitalize, computeRowSpan, create10ColorAccessibleContrast, create10ColorPallet, credentialsLogin, credentialsLogout, extractObjectKey, focusStyles, getCurrentUnixTimestamp, getNavPageLayoutPropsFromConfig, getParamsValueAsString, getTagInfo, hasOwnProperty, isArrayOfString, isPropertyKey, isTextTransform$1 as isTextTransform, processLabel$1 as processLabel, processRangeKeyLabel, registerCohortBuilderDefaultPreviewRenderers, registerDefaultDiscoveryDataLoaders, registerDiscoveryDefaultCellRenderers, registerDiscoveryDefaultStudyPreviewRenderers, registerExplorerDefaultCellRenderers, removeKey$1 as removeKey, resourcePathFromProjectID, sessionLogout, sessionToken, stripTrailingSlash, truncateString, unixTimeToString, useDiscoveryContext, userHasMethodForServiceOnResource$1 as userHasMethodForServiceOnResource };
15782
+ export { AISearchPageGetServerSideProps, AdminAuthZPageGetServerSideProps, AiSearch, AISearchPage as AiSearchPage, AuthzPage, BaseModal, Charts, CohortBuilder, ColorThemePage, ColorThemePageGetServerSideProps, ContentSource, CreateCredentialsAPIKeyModal, CrosswalkPage, CrosswalkPageGetServerSideProps, Custom404Page, DictionaryPage, DictionaryPageGetServerSideProps, DiscoveryCellRendererFactory, DiscoveryProvider as DiscoveryConfigProvider, DiscoveryIndexPanel, DiscoveryPage, DiscoveryPageGetServerSideProps, DiscoveryRowRendererFactory, EnumFacetChart, ErrorCard, ExplorerPage, ExplorerPageGetServerSideProps, ExplorerTableCellRendererFactory, ExplorerTableDetailsPanelFactory, FirstTimeModal, Footer, Gen3Link, Gen3ModalsProvider, Gen3Provider, GqlQueryEditor$1 as GqlQueryEditor, Header, HoverLink, LandingPage, LandingPageGetStaticProps, LoginButton, LoginPage, LoginPageGetServerSideProps, LoginPanel, LoginProvidersPanel, NavPageLayout, NavigationBar, NavigationButton, NoAccessModal, ProfilePage, ProfilePageGetServerSideProps, ProfileProvider, QueryPage, QueryPageGetServerSideProps, ReactECharts, ResourcesFilters, SPECIAL_CASE_FIELDS, SessionExpiredModal, StudyGroup, SubmissionPage, SubmissionPageGetServerSideProps, TagCloud, TailwindConfig, User, WorkspacesPage, WorkspacesPageGetServerSideProps, WorkspacesPanel, capitalize, computeRowSpan, create10ColorAccessibleContrast, create10ColorPallet, credentialsLogin, credentialsLogout, extractObjectKey, focusStyles, getCurrentUnixTimestamp, getNavPageLayoutPropsFromConfig, getParamsValueAsString, getTagInfo, hasOwnProperty, isArrayOfString, isPropertyKey, isTextTransform$1 as isTextTransform, processLabel$1 as processLabel, processRangeKeyLabel, registerCohortBuilderDefaultPreviewRenderers, registerCohortDiscoveryApp, registerCohortDiversityApp, registerDefaultDiscoveryDataLoaders, registerDiscoveryDefaultCellRenderers, registerDiscoveryDefaultStudyPreviewRenderers, registerExplorerDefaultCellRenderers, removeKey$1 as removeKey, resourcePathFromProjectID, sessionLogout, sessionToken, stripTrailingSlash, toDisplayName, truncateString, unixTimeToString, useDiscoveryContext, userHasMethodForServiceOnResource$1 as userHasMethodForServiceOnResource };
14021
15783
  //# sourceMappingURL=index.js.map