diff --git a/WordPress/Classes/ViewRelated/Stats/Charts/Charts+Support.swift b/WordPress/Classes/ViewRelated/Stats/Charts/Charts+Support.swift index 41afc79b6942..d70dc6a710b3 100644 --- a/WordPress/Classes/ViewRelated/Stats/Charts/Charts+Support.swift +++ b/WordPress/Classes/ViewRelated/Stats/Charts/Charts+Support.swift @@ -18,7 +18,7 @@ extension BarChartDataSet { // MARK: - Charts protocols -/// Describes the visual appearance of a BarChartView. Implementation TBD. +/// Describes the visual appearance of a BarChartView. /// protocol BarChartStyling { @@ -37,6 +37,9 @@ protocol BarChartStyling { /// This corresponds to the color of labels on the chart var labelColor: UIColor { get } + /// This corresponds to the legend color; currently only applicable when Views/Visitors overlaid. + var legendColor: UIColor? { get } + /// If specified, a legend will be presented with this value. It maps to the secondary bar color above. var legendTitle: String? { get } diff --git a/WordPress/Classes/ViewRelated/Stats/Charts/PeriodChart.swift b/WordPress/Classes/ViewRelated/Stats/Charts/PeriodChart.swift index ad5e50a1f565..456beb969ca8 100644 --- a/WordPress/Classes/ViewRelated/Stats/Charts/PeriodChart.swift +++ b/WordPress/Classes/ViewRelated/Stats/Charts/PeriodChart.swift @@ -75,6 +75,11 @@ private final class PeriodChartDataTransformer { effectiveWidth = range / effectiveBars } + let totalViews = summaryData.compactMap({$0.viewsCount}).reduce(0, +) + let totalVisitors = summaryData.compactMap({$0.visitorsCount}).reduce(0, +) + let totalLikes = summaryData.compactMap({$0.likesCount}).reduce(0, +) + let totalComments = summaryData.compactMap({$0.commentsCount}).reduce(0, +) + var viewEntries = [BarChartDataEntry]() var visitorEntries = [BarChartDataEntry]() var likeEntries = [BarChartDataEntry]() @@ -85,10 +90,11 @@ private final class PeriodChartDataTransformer { let x = offset - let viewEntry = BarChartDataEntry(x: x, y: Double(datum.viewsCount)) - let visitorEntry = BarChartDataEntry(x: x, y: Double(datum.visitorsCount)) - let likeEntry = BarChartDataEntry(x: x, y: Double(datum.likesCount)) - let commentEntry = BarChartDataEntry(x: x, y: Double(datum.commentsCount)) + // If the chart has no data, show "stub" bars + let viewEntry = BarChartDataEntry(x: x, y: totalViews > 0 ? Double(datum.viewsCount) : 1.0) + let visitorEntry = BarChartDataEntry(x: x, y: totalVisitors > 0 ? Double(datum.visitorsCount) : 1.0) + let likeEntry = BarChartDataEntry(x: x, y: totalLikes > 0 ? Double(datum.likesCount) : 1.0) + let commentEntry = BarChartDataEntry(x: x, y: totalComments > 0 ? Double(datum.commentsCount) : 1.0) viewEntries.append(viewEntry) visitorEntries.append(visitorEntry) @@ -130,24 +136,52 @@ private final class PeriodChartDataTransformer { let horizontalAxisFormatter = HorizontalAxisFormatter(initialDateInterval: firstDateInterval, period: data.period) let chartStyling: [BarChartStyling] = [ - ViewsPeriodChartStyling(xAxisValueFormatter: horizontalAxisFormatter), - DefaultPeriodChartStyling(xAxisValueFormatter: horizontalAxisFormatter), - DefaultPeriodChartStyling(xAxisValueFormatter: horizontalAxisFormatter), - DefaultPeriodChartStyling(xAxisValueFormatter: horizontalAxisFormatter), + ViewsPeriodChartStyling(primaryBarColor: primaryBarColor(forCount: totalViews), + secondaryBarColor: secondaryBarColor(forCount: totalVisitors), + primaryHighlightColor: primaryHighlightColor(forCount: totalViews), + secondaryHighlightColor: secondaryHighlightColor(forCount: totalVisitors), + xAxisValueFormatter: horizontalAxisFormatter), + DefaultPeriodChartStyling(primaryBarColor: primaryBarColor(forCount: totalVisitors), + primaryHighlightColor: primaryHighlightColor(forCount: totalVisitors), + xAxisValueFormatter: horizontalAxisFormatter), + DefaultPeriodChartStyling(primaryBarColor: primaryBarColor(forCount: totalLikes), + primaryHighlightColor: primaryHighlightColor(forCount: totalLikes), + xAxisValueFormatter: horizontalAxisFormatter), + DefaultPeriodChartStyling(primaryBarColor: primaryBarColor(forCount: totalComments), + primaryHighlightColor: primaryHighlightColor(forCount: totalComments), + xAxisValueFormatter: horizontalAxisFormatter), ] return (barChartDataConvertibles, chartStyling) } + + static func primaryBarColor(forCount count: Int) -> UIColor { + return count > 0 ? WPStyleGuide.wordPressBlue() : WPStyleGuide.lightGrey() + } + + static func secondaryBarColor(forCount count: Int) -> UIColor { + return count > 0 ? WPStyleGuide.darkBlue() : WPStyleGuide.lightGrey() + } + + static func primaryHighlightColor(forCount count: Int) -> UIColor? { + return count > 0 ? WPStyleGuide.jazzyOrange() : nil + } + + static func secondaryHighlightColor(forCount count: Int) -> UIColor? { + return count > 0 ? WPStyleGuide.fireOrange() : nil + } + } // MARK: - ViewsPeriodChartStyling private struct ViewsPeriodChartStyling: BarChartStyling { - let primaryBarColor: UIColor = WPStyleGuide.wordPressBlue() - let secondaryBarColor: UIColor? = WPStyleGuide.darkBlue() - let primaryHighlightColor: UIColor? = WPStyleGuide.jazzyOrange() - let secondaryHighlightColor: UIColor? = WPStyleGuide.fireOrange() + let primaryBarColor: UIColor + let secondaryBarColor: UIColor? + let primaryHighlightColor: UIColor? + let secondaryHighlightColor: UIColor? let labelColor: UIColor = WPStyleGuide.grey() + let legendColor: UIColor? = WPStyleGuide.wordPressBlue() let legendTitle: String? = NSLocalizedString("Visitors", comment: "This appears in the legend of the period chart; Visitors are superimposed over Views in that case.") let lineColor: UIColor = WPStyleGuide.greyLighten30() let xAxisValueFormatter: IAxisValueFormatter @@ -157,11 +191,12 @@ private struct ViewsPeriodChartStyling: BarChartStyling { // MARK: - DefaultPeriodChartStyling private struct DefaultPeriodChartStyling: BarChartStyling { - let primaryBarColor: UIColor = WPStyleGuide.wordPressBlue() + let primaryBarColor: UIColor let secondaryBarColor: UIColor? = nil - let primaryHighlightColor: UIColor? = WPStyleGuide.jazzyOrange() + let primaryHighlightColor: UIColor? let secondaryHighlightColor: UIColor? = nil let labelColor: UIColor = WPStyleGuide.grey() + let legendColor: UIColor? = nil let legendTitle: String? = nil let lineColor: UIColor = WPStyleGuide.greyLighten30() let xAxisValueFormatter: IAxisValueFormatter diff --git a/WordPress/Classes/ViewRelated/Stats/Charts/PostChart.swift b/WordPress/Classes/ViewRelated/Stats/Charts/PostChart.swift index 15cd0cebc609..0aaa34a7ee1d 100644 --- a/WordPress/Classes/ViewRelated/Stats/Charts/PostChart.swift +++ b/WordPress/Classes/ViewRelated/Stats/Charts/PostChart.swift @@ -101,13 +101,16 @@ private final class PostChartDataTransformer { effectiveWidth = range / effectiveBars } + let totalViews = data.compactMap({$0.viewsCount}).reduce(0, +) + var entries = [BarChartDataEntry]() for datum in data { let dateInterval = datum.postDateTimeInterval ?? 0 let offset = dateInterval - firstDateInterval let x = offset - let y = Double(datum.viewsCount) + // If the chart has no data, show "stub" bars + let y = totalViews > 0 ? Double(datum.viewsCount) : 1.0 let entry = BarChartDataEntry(x: x, y: y) entries.append(entry) @@ -117,20 +120,32 @@ private final class PostChartDataTransformer { chartData.barWidth = effectiveWidth let xAxisFormatter: IAxisValueFormatter = HorizontalAxisFormatter(initialDateInterval: firstDateInterval) - let styling = PostChartStyling(primaryHighlightColor: type.highlightColor, xAxisValueFormatter: xAxisFormatter) + let styling = PostChartStyling(primaryBarColor: primaryBarColor(forCount: totalViews), + primaryHighlightColor: primaryHighlightColor(forType: type, withCount: totalViews), + xAxisValueFormatter: xAxisFormatter) return (chartData, styling) } + + static func primaryBarColor(forCount count: Int) -> UIColor { + return count > 0 ? WPStyleGuide.wordPressBlue() : WPStyleGuide.lightGrey() + } + + static func primaryHighlightColor(forType type: PostChartType, withCount count: Int) -> UIColor? { + return count > 0 ? type.highlightColor : nil + } + } // MARK: - PostChartStyling private struct PostChartStyling: BarChartStyling { - let primaryBarColor: UIColor = WPStyleGuide.wordPressBlue() + let primaryBarColor: UIColor let secondaryBarColor: UIColor? = nil let primaryHighlightColor: UIColor? let secondaryHighlightColor: UIColor? = nil let labelColor: UIColor = WPStyleGuide.grey() + let legendColor: UIColor? = nil let legendTitle: String? = nil let lineColor: UIColor = WPStyleGuide.greyLighten30() let xAxisValueFormatter: IAxisValueFormatter diff --git a/WordPress/Classes/ViewRelated/Stats/Charts/StatsBarChartView.swift b/WordPress/Classes/ViewRelated/Stats/Charts/StatsBarChartView.swift index 1c8e2eade65f..bedeed15c53d 100644 --- a/WordPress/Classes/ViewRelated/Stats/Charts/StatsBarChartView.swift +++ b/WordPress/Classes/ViewRelated/Stats/Charts/StatsBarChartView.swift @@ -221,9 +221,13 @@ private extension StatsBarChartView { primaryDataSet.colors = [ styling.primaryBarColor ] primaryDataSet.drawValuesEnabled = false - primaryDataSet.highlightAlpha = Constants.highlightAlpha if let initialHighlightColor = styling.primaryHighlightColor { + primaryDataSet.highlightAlpha = Constants.highlightAlpha primaryDataSet.highlightColor = initialHighlightColor + primaryDataSet.highlightEnabled = true + } else { + primaryDataSet.highlightEnabled = false + highlightPerTapEnabled = false } // Secondary @@ -263,7 +267,7 @@ private extension StatsBarChartView { func configureLegendIfNeeded() { legend.enabled = false - guard let legendColor = styling.secondaryBarColor, let legendTitle = styling.legendTitle, legendView == nil else { + guard let legendColor = styling.legendColor, let legendTitle = styling.legendTitle, legendView == nil else { return } diff --git a/WordPress/Classes/ViewRelated/Stats/Period Stats/SiteStatsPeriodViewModel.swift b/WordPress/Classes/ViewRelated/Stats/Period Stats/SiteStatsPeriodViewModel.swift index 8febd512a3f1..6120de6cf47f 100644 --- a/WordPress/Classes/ViewRelated/Stats/Period Stats/SiteStatsPeriodViewModel.swift +++ b/WordPress/Classes/ViewRelated/Stats/Period Stats/SiteStatsPeriodViewModel.swift @@ -118,6 +118,10 @@ private extension SiteStatsPeriodViewModel { if mostRecentChartData == nil { mostRecentChartData = periodSummary + } else if let mostRecentChartData = mostRecentChartData, + let periodSummary = periodSummary, + mostRecentChartData.periodEndDate == periodSummary.periodEndDate { + self.mostRecentChartData = periodSummary } else if let periodSummary = periodSummary, let chartData = mostRecentChartData, periodSummary.periodEndDate > chartData.periodEndDate { mostRecentChartData = chartData }