diff --git a/src/visualizations/DeceasedViz/Analysis.fs b/src/visualizations/DeceasedViz/Analysis.fs index e6df953a4..1cf0d02e7 100644 --- a/src/visualizations/DeceasedViz/Analysis.fs +++ b/src/visualizations/DeceasedViz/Analysis.fs @@ -1,13 +1,21 @@ module DeceasedViz.Analysis +open AgeGroupsTimelineViz.Synthesis + type DisplayMetricsType = | HospitalsToDate | HospitalsToday | ByAgeToDate // | ByAgeToday -type DisplayMetrics = { +type VisualizationPage = { Id: string MetricsType: DisplayMetricsType ChartType: string } + +let (|HospitalMetricsType|_|) (metricsType: DisplayMetricsType) = + match metricsType with + | HospitalsToDate -> Some HospitalMetricsType + | HospitalsToday -> Some HospitalMetricsType + | _ -> None diff --git a/src/visualizations/DeceasedViz/Rendering.fs b/src/visualizations/DeceasedViz/Rendering.fs index 955d4c48b..77876eb33 100644 --- a/src/visualizations/DeceasedViz/Rendering.fs +++ b/src/visualizations/DeceasedViz/Rendering.fs @@ -14,7 +14,7 @@ open Highcharts open Types -let availableDisplayMetrics = [| +let availablePages = [| { Id = "deceasedToDate" MetricsType = HospitalsToDate; ChartType = "normal" } { Id = "deceasedToDateRelative" @@ -30,14 +30,14 @@ let availableDisplayMetrics = [| type Msg = | ConsumePatientsData of Result | ConsumeServerError of exn - | ChangeMetrics of DisplayMetrics + | ChangePage of VisualizationPage | RangeSelectionChanged of int let init(statsData : StatsData) : DeceasedVizState * Cmd = let state = { StatsData = statsData PatientsData = [||] - Metrics = availableDisplayMetrics.[0] + Page = availablePages.[0] RangeSelectionButtonIndex = 0 Error = None } @@ -55,8 +55,8 @@ let update (msg: Msg) (state: DeceasedVizState) : DeceasedVizState * Cmd = { state with Error = Some err }, Cmd.none | ConsumeServerError ex -> { state with Error = Some ex.Message }, Cmd.none - | ChangeMetrics metrics -> - { state with Metrics=metrics }, Cmd.none + | ChangePage page -> + { state with Page = page }, Cmd.none | RangeSelectionChanged buttonIndex -> { state with RangeSelectionButtonIndex = buttonIndex }, Cmd.none @@ -80,33 +80,18 @@ let renderChartOptions (state : DeceasedVizState) dispatch = let className = "cases-chart" let scaleType = ScaleType.Linear - let renderSeries series = + let renderSeriesData series = {| ``type`` = "column" visible = true color = series.Color name = I18N.tt "charts.deceased" series.SeriesId - data = - state.PatientsData - |> Seq.map (fun dataPoint -> - {| - x = dataPoint.Date |> jsTime12h - y = getPoint state series dataPoint - seriesId = series.SeriesId - fmtDate = I18N.tOptions "days.longerDate" - {| date = dataPoint.Date |} - fmtTotal = - getPointTotal state series dataPoint |> string - |} |> pojo - ) - |> Array.ofSeq + data = constructSeriesData state series |} |> pojo - let allSeries = [| - for series in hospitalSeries() do - yield renderSeries series - |] + let allSeriesData = + pageSeries state |> List.map renderSeriesData let onRangeSelectorButtonClick(buttonIndex: int) = let res (_ : Browser.Types.Event) = @@ -119,7 +104,7 @@ let renderChartOptions (state : DeceasedVizState) dispatch = scaleType className state.RangeSelectionButtonIndex onRangeSelectorButtonClick {| baseOptions with - series = allSeries + series = allSeriesData plotOptions = pojo {| column = pojo @@ -128,7 +113,7 @@ let renderChartOptions (state : DeceasedVizState) dispatch = groupPadding = 0 pointPadding = 0 borderWidth = 0 |} - series = {| stacking = state.Metrics.ChartType; crisp = true + series = {| stacking = state.Page.ChartType; crisp = true borderWidth = 0 pointPadding = 0; groupPadding = 0 |} @@ -154,22 +139,22 @@ let renderChartContainer (state : DeceasedVizState) dispatch = ] ] -let renderMetricsSelectors activeMetrics dispatch = - let renderSelector (metrics : DisplayMetrics) = - let active = metrics = activeMetrics +let renderPagesSwitchers activePage dispatch = + let renderPageSwitcher (page: VisualizationPage) = + let active = page = activePage Html.div [ - prop.text (I18N.chartText "deceased" metrics.Id) + prop.text (I18N.chartText "deceased" page.Id) Utils.classes [(true, "btn btn-sm metric-selector") (active, "metric-selector--selected selected")] - if not active then prop.onClick (fun _ -> dispatch metrics) + if not active then prop.onClick (fun _ -> dispatch page) if active then prop.style [ style.backgroundColor "#808080" ] ] Html.div [ prop.className "metrics-selectors" - availableDisplayMetrics - |> Array.map renderSelector + availablePages + |> Array.map renderPageSwitcher |> prop.children ] @@ -180,7 +165,7 @@ let render (state: DeceasedVizState) dispatch = | _, None -> Html.div [ renderChartContainer state dispatch - renderMetricsSelectors state.Metrics (ChangeMetrics >> dispatch) + renderPagesSwitchers state.Page (ChangePage >> dispatch) ] let renderChart(statsData: StatsData) = diff --git a/src/visualizations/DeceasedViz/Synthesis.fs b/src/visualizations/DeceasedViz/Synthesis.fs index 3e8349b8d..fbee7ce0c 100644 --- a/src/visualizations/DeceasedViz/Synthesis.fs +++ b/src/visualizations/DeceasedViz/Synthesis.fs @@ -3,11 +3,12 @@ open Data.Patients open DeceasedViz.Analysis open Types +open Highcharts type DeceasedVizState = { StatsData: StatsData PatientsData : PatientsStats [] - Metrics: DisplayMetrics + Page: VisualizationPage RangeSelectionButtonIndex: int Error : string option } @@ -32,7 +33,7 @@ let subtract (a : int option) (b : int option) = | _ -> None let getPoint state (series: SeriesInfo) dataPoint : int option = - match state.Metrics.MetricsType with + match state.Page.MetricsType with | HospitalsToday -> match series.SeriesType with | DeceasedInIcu -> dataPoint.total.deceased.hospital.icu.today @@ -57,7 +58,7 @@ let getPoint state (series: SeriesInfo) dataPoint : int option = |> subtract dataPoint.total.deceasedCare.toDate let getPointTotal state series dataPoint : int option = - match state.Metrics.MetricsType with + match state.Page.MetricsType with | HospitalsToday -> match series.SeriesType with | DeceasedInIcu -> dataPoint.total.deceased.hospital.icu.today @@ -71,10 +72,31 @@ let getPointTotal state series dataPoint : int option = | DeceasedCare -> dataPoint.total.deceasedCare.toDate | DeceasedOther -> dataPoint.total.deceased.toDate -let hospitalSeries() = - [ - { SeriesType = DeceasedInIcu; SeriesId = "deceased-icu"; Color = "#6d5b80" } - { SeriesType = DeceasedAcute; SeriesId = "deceased-acute"; Color = "#8c71a8" } - { SeriesType = DeceasedCare; SeriesId = "deceased-care"; Color = "#a483c7" } - { SeriesType = DeceasedOther; SeriesId = "deceased-rest"; Color = "#c59eef" } - ] +let constructSeriesData state series = + state.PatientsData + |> Seq.map (fun dataPoint -> + {| + x = dataPoint.Date |> jsTime12h + y = getPoint state series dataPoint + seriesId = series.SeriesId + fmtDate = I18N.tOptions "days.longerDate" + {| date = dataPoint.Date |} + fmtTotal = getPointTotal state series dataPoint |> string + |} |> pojo + ) + |> Array.ofSeq + +let pageSeries state = + match state.Page.MetricsType with + | HospitalMetricsType -> + [ + { SeriesType = DeceasedInIcu + SeriesId = "deceased-icu"; Color = "#6d5b80" } + { SeriesType = DeceasedAcute + SeriesId = "deceased-acute"; Color = "#8c71a8" } + { SeriesType = DeceasedCare + SeriesId = "deceased-care"; Color = "#a483c7" } + { SeriesType = DeceasedOther + SeriesId = "deceased-rest"; Color = "#c59eef" } + ] + | _ -> invalidOp "todo"