Skip to content

Commit

Permalink
Merge pull request #10263 from woocommerce/issue/10162-dashboard-pars…
Browse files Browse the repository at this point in the history
…ing-error

[Resilience] Customize dashboard error message for parsing errors
  • Loading branch information
rachelmcr authored Jul 20, 2023
2 parents 6a158b5 + 6cd1d33 commit e7c6337
Show file tree
Hide file tree
Showing 14 changed files with 235 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import UIKit
///
protocol DashboardUI: UIViewController {
/// Called when the Dashboard should display syncing error
var displaySyncingError: () -> Void { get set }
var displaySyncingError: (Error) -> Void { get set }

/// Called when the user pulls to refresh
var onPullToRefresh: @MainActor () async -> Void { get set }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,7 @@ final class DashboardViewController: UIViewController {

/// Top banner that shows an error if there is a problem loading data
///
private lazy var topBannerView = {
ErrorTopBannerFactory.createTopBanner(expandedStateChangeHandler: {},
onTroubleshootButtonPressed: { [weak self] in
guard let self = self else { return }

WebviewHelper.launch(WooConstants.URLs.troubleshootErrorLoadingData.asURL(), with: self)
},
onContactSupportButtonPressed: { [weak self] in
guard let self = self else { return }
let supportForm = SupportFormHostingController(viewModel: .init())
supportForm.show(from: self)
})
}()
private var topBannerView: TopBannerView?

private var announcementViewHostingController: ConstraintsUpdatingHostingController<AnnouncementCardWrapper>?

Expand Down Expand Up @@ -354,7 +342,6 @@ private extension DashboardViewController {

func configureHeaderStackView() {
configureSubtitle()
configureErrorBanner()
containerStackView.addArrangedSubview(headerStackView)
}

Expand All @@ -365,13 +352,6 @@ private extension DashboardViewController {
headerStackView.addArrangedSubview(innerStackView)
}

func configureErrorBanner() {
headerStackView.addArrangedSubviews([topBannerView, spacerView])
// Don't show the error banner subviews until they are needed
topBannerView.isHidden = true
spacerView.isHidden = true
}

func addViewBelowHeaderStackView(contentView: UIView) {
let indexAfterHeader = (containerStackView.arrangedSubviews.firstIndex(of: headerStackView) ?? -1) + 1
containerStackView.insertArrangedSubview(contentView, at: indexAfterHeader)
Expand Down Expand Up @@ -688,16 +668,34 @@ private extension DashboardViewController {

/// Display the error banner at the top of the dashboard content (below the site title)
///
func showTopBannerView() {
topBannerView.isHidden = false
spacerView.isHidden = false
func showTopBannerView(for error: Error) {
if topBannerView != nil { // Clear the top banner first, if needed
hideTopBannerView()
}

let errorBanner = ErrorTopBannerFactory.createTopBanner(for: error,
expandedStateChangeHandler: {},
onTroubleshootButtonPressed: { [weak self] in
guard let self else { return }
WebviewHelper.launch(WooConstants.URLs.troubleshootErrorLoadingData.asURL(), with: self)
},
onContactSupportButtonPressed: { [weak self] in
guard let self else { return }
let supportForm = SupportFormHostingController(viewModel: .init())
supportForm.show(from: self)
})

// Configure header stack view
topBannerView = errorBanner
headerStackView.addArrangedSubviews([errorBanner, spacerView])
}

/// Hide the error banner
///
func hideTopBannerView() {
topBannerView.isHidden = true
spacerView.isHidden = true
topBannerView?.removeFromSuperview()
spacerView.removeFromSuperview()
topBannerView = nil
}

func updateUI(site: Site) {
Expand Down Expand Up @@ -875,8 +873,8 @@ private extension DashboardViewController {
// Sets `dashboardUI` after its view is added to the view hierarchy so that observers can update UI based on its view.
dashboardUI = updatedDashboardUI

updatedDashboardUI.displaySyncingError = { [weak self] in
self?.showTopBannerView()
updatedDashboardUI.displaySyncingError = { [weak self] error in
self?.showTopBannerView(for: error)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ final class DeprecatedDashboardStatsViewController: UIViewController {
// MARK: DashboardUI conformance
// Everything is empty as this deprecated stats screen is static
extension DeprecatedDashboardStatsViewController: DashboardUI {
var displaySyncingError: () -> Void {
var displaySyncingError: (Error) -> Void {
get {
return {}
return { _ in }
}
set {}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import class WidgetKit.WidgetCenter
final class StoreStatsAndTopPerformersViewController: TabbedViewController {
// MARK: - DashboardUI protocol

var displaySyncingError: () -> Void = {}
var displaySyncingError: (Error) -> Void = { _ in }

var onPullToRefresh: @MainActor () async -> Void = {}

Expand Down Expand Up @@ -430,7 +430,7 @@ private extension StoreStatsAndTopPerformersViewController {
}
trackDashboardStatsSyncComplete()
default:
displaySyncingError()
displaySyncingError(error)
trackDashboardStatsSyncComplete(withError: error)
}
}
Expand All @@ -440,7 +440,7 @@ private extension StoreStatsAndTopPerformersViewController {
case let siteStatsStoreError as SiteStatsStoreError:
handleSiteStatsStoreError(error: siteStatsStoreError)
default:
displaySyncingError()
displaySyncingError(error)
trackDashboardStatsSyncComplete(withError: error)
}
}
Expand Down
20 changes: 20 additions & 0 deletions WooCommerce/WooCommerce.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1898,6 +1898,11 @@
CEEC9B6021E79CAA0055EEF0 /* FeatureFlagTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEC9B5F21E79CAA0055EEF0 /* FeatureFlagTests.swift */; };
CEEC9B6421E7AB850055EEF0 /* AppRatingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEC9B6221E79EE00055EEF0 /* AppRatingManager.swift */; };
CEEC9B6621E7C5200055EEF0 /* AppRatingManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEC9B6521E7C5200055EEF0 /* AppRatingManagerTests.swift */; };
CEF5A28F2A68466E0059CFD3 /* stats_summary_day.json in Resources */ = {isa = PBXBuildFile; fileRef = CEF5A28E2A68466E0059CFD3 /* stats_summary_day.json */; };
CEF5A2912A68467C0059CFD3 /* stats_summary_week.json in Resources */ = {isa = PBXBuildFile; fileRef = CEF5A2902A68467C0059CFD3 /* stats_summary_week.json */; };
CEF5A2952A68469B0059CFD3 /* stats_summary_month.json in Resources */ = {isa = PBXBuildFile; fileRef = CEF5A2942A68469B0059CFD3 /* stats_summary_month.json */; };
CEF5A2972A6846A50059CFD3 /* stats_summary_year.json in Resources */ = {isa = PBXBuildFile; fileRef = CEF5A2962A6846A50059CFD3 /* stats_summary_year.json */; };
CEF5A29B2A6849DB0059CFD3 /* reports_products.json in Resources */ = {isa = PBXBuildFile; fileRef = CEF5A29A2A6849DB0059CFD3 /* reports_products.json */; };
D41C9F2E26D9A0E900993558 /* WhatsNewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41C9F2D26D9A0E900993558 /* WhatsNewViewModel.swift */; };
D41C9F3126D9A43200993558 /* WhatsNewViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41C9F3026D9A43200993558 /* WhatsNewViewModelTests.swift */; };
D449C51B26DE6B5000D75B02 /* ReportList.swift in Sources */ = {isa = PBXBuildFile; fileRef = D449C51826DE6B5000D75B02 /* ReportList.swift */; };
Expand Down Expand Up @@ -4299,6 +4304,11 @@
CEEC9B5F21E79CAA0055EEF0 /* FeatureFlagTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureFlagTests.swift; sourceTree = "<group>"; };
CEEC9B6221E79EE00055EEF0 /* AppRatingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRatingManager.swift; sourceTree = "<group>"; };
CEEC9B6521E7C5200055EEF0 /* AppRatingManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRatingManagerTests.swift; sourceTree = "<group>"; };
CEF5A28E2A68466E0059CFD3 /* stats_summary_day.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = stats_summary_day.json; sourceTree = "<group>"; };
CEF5A2902A68467C0059CFD3 /* stats_summary_week.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = stats_summary_week.json; sourceTree = "<group>"; };
CEF5A2942A68469B0059CFD3 /* stats_summary_month.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = stats_summary_month.json; sourceTree = "<group>"; };
CEF5A2962A6846A50059CFD3 /* stats_summary_year.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = stats_summary_year.json; sourceTree = "<group>"; };
CEF5A29A2A6849DB0059CFD3 /* reports_products.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = reports_products.json; sourceTree = "<group>"; };
D41C9F2426D97D5400993558 /* IconListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconListItem.swift; sourceTree = "<group>"; };
D41C9F2626D994CD00993558 /* ReportListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportListView.swift; sourceTree = "<group>"; };
D41C9F2826D99E9700993558 /* LargeTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LargeTitleView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -9146,6 +9156,7 @@
800A5BC3275889EC009DE2CD /* reports_revenue_stats_month.json */,
800A5BC4275889EC009DE2CD /* reports_revenue_stats_year.json */,
CCFC00C223E9BD5500157A78 /* reports_revenue_stats.json */,
CEF5A29A2A6849DB0059CFD3 /* reports_products.json */,
);
path = "wc-analytics";
sourceTree = "<group>";
Expand Down Expand Up @@ -9273,6 +9284,10 @@
CCFC00E223E9BD5500157A78 /* stats_visits_week.json */,
CCFC00E123E9BD5500157A78 /* stats_visits_month.json */,
CCFC00E023E9BD5500157A78 /* stats_visits_year.json */,
CEF5A28E2A68466E0059CFD3 /* stats_summary_day.json */,
CEF5A2902A68467C0059CFD3 /* stats_summary_week.json */,
CEF5A2942A68469B0059CFD3 /* stats_summary_month.json */,
CEF5A2962A6846A50059CFD3 /* stats_summary_year.json */,
);
path = stats;
sourceTree = "<group>";
Expand Down Expand Up @@ -11244,6 +11259,7 @@
buildActionMask = 2147483647;
files = (
80E6FC6D276312D50086CD67 /* products.json in Resources */,
CEF5A28F2A68466E0059CFD3 /* stats_summary_day.json in Resources */,
80B8D3492785A0A900FE6E6B /* products_list_3.json in Resources */,
800A5BB827586A96009DE2CD /* products_reviews_6156.json in Resources */,
D8CD0605258B384E00B52D63 /* oauth2_token-error.json in Resources */,
Expand All @@ -11259,6 +11275,7 @@
800A5BA5275719E5009DE2CD /* orders_2201_shipment_trackings.json in Resources */,
800A5BAA2758661B009DE2CD /* products_2123.json in Resources */,
80DA4F1C29CC505800BDF3BF /* products_search_results.json in Resources */,
CEF5A2952A68469B0059CFD3 /* stats_summary_month.json in Resources */,
CCF27B35280EF69700B755E1 /* orders_3337_add_product.json in Resources */,
800A5B9B2755E0B9009DE2CD /* orders_any.json in Resources */,
800A5BB2275869DC009DE2CD /* products_reviews_6154.json in Resources */,
Expand Down Expand Up @@ -11286,10 +11303,13 @@
80CC810729E6763F00CA1687 /* products_add_new_variable_2131.json in Resources */,
800A5B972755BA02009DE2CD /* status.json in Resources */,
800A5BC8275889ED009DE2CD /* reports_revenue_stats_year.json in Resources */,
CEF5A29B2A6849DB0059CFD3 /* reports_products.json in Resources */,
CC2A08062863222500510C4B /* orders_3337_add_fee.json in Resources */,
800A5BBC27586AE1009DE2CD /* products_reviews_6162.json in Resources */,
80A6430E2A026D0800F65C0C /* complete_cash_simple_payment.json in Resources */,
80A643022A010F2100F65C0C /* connection_tokens.json in Resources */,
CEF5A2912A68467C0059CFD3 /* stats_summary_week.json in Resources */,
CEF5A2972A6846A50059CFD3 /* stats_summary_year.json in Resources */,
800A5B6127548F53009DE2CD /* sites_posts_password.json in Resources */,
800A5BB427586A0E009DE2CD /* products_reviews_6155.json in Resources */,
800A5B5F27548F31009DE2CD /* site_info_wordpress_com.json in Resources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"request": {
"method": "GET",
"urlPath": "/rest/v1.1/jetpack-blogs/161477129/rest-api/",
"queryParameters": {
"json": {
"equalTo": "true"
},
"path": {
"matches": "\/wc-analytics\/reports\/products(.*)"
}
}
},
"response": {
"status": 200,
"jsonBody": {
"data": [{
"product_id": 2130,
"items_sold": 3,
"net_revenue": 450,
"orders_count": 3,
"extended_info": {
"name": "Black Coral shades",
"price": 150,
"image": "https:\/\/example.com\/wp-content\/uploads\/2020\/01\/Mask-Group-1.png?w=201",
"permalink": "https:\/\/example.com\/product\/black-coral-shades\/",
"stock_status": "instock",
"stock_quantity": 0,
"manage_stock": false,
"low_stock_amount": 2,
"category_ids": [],
"sku": ""
}
}, {
"product_id": 2123,
"items_sold": 1,
"net_revenue": 140,
"orders_count": 1,
"extended_info": {
"name": "Malaya shades",
"price": 140,
"image": "https:\/\/example.com\/wp-content\/uploads\/2020\/01\/Mask-Group.png?w=201",
"permalink": "https:\/\/example.com\/product\/malaya-shades\/",
"stock_status": "instock",
"stock_quantity": 0,
"manage_stock": false,
"low_stock_amount": 2,
"category_ids": [],
"sku": ""
}
}, {
"product_id": 2132,
"items_sold": 1,
"net_revenue": 120,
"orders_count": 1,
"extended_info": {
"name": "Rose Gold shades",
"price": 120,
"image": "https:\/\/example.com\/wp-content\/uploads\/2020\/01\/Mask-Group-2.png?w=201",
"permalink": "https:\/\/example.com\/product\/rose-gold-shades\/",
"stock_status": "instock",
"stock_quantity": 0,
"manage_stock": false,
"low_stock_amount": 2,
"category_ids": [],
"sku": ""
}
}]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"request": {
"method": "GET",
"urlPath": "/rest/v1.1/sites/161477129/stats/summary/",
"queryParameters": {
"period": {
"equalTo": "day"
},
"date": {
"matches": "(.*)"
}
}
},
"response": {
"status": 200,
"jsonBody": {
"date": "{{now format='yyyy-MM-dd'}}",
"period": "day",
"views": 0,
"visitors": 0,
"likes": 0,
"reblogs": 0,
"comments": 0,
"followers": 1
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"request": {
"method": "GET",
"urlPath": "/rest/v1.1/sites/161477129/stats/summary/",
"queryParameters": {
"period": {
"equalTo": "month"
},
"date": {
"matches": "(.*)"
}
}
},
"response": {
"status": 200,
"jsonBody": {
"date": "{{now format='yyyy-MM-dd'}}",
"period": "month",
"views": 0,
"visitors": 0,
"likes": 0,
"reblogs": 0,
"comments": 0,
"followers": 1
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"request": {
"method": "GET",
"urlPath": "/rest/v1.1/sites/161477129/stats/summary/",
"queryParameters": {
"period": {
"equalTo": "week"
},
"date": {
"matches": "(.*)"
}
}
},
"response": {
"status": 200,
"jsonBody": {
"date": "{{now format='yyyy-MM-dd'}}",
"period": "week",
"views": 0,
"visitors": 0,
"likes": 0,
"reblogs": 0,
"comments": 0,
"followers": 1
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"request": {
"method": "GET",
"urlPath": "/rest/v1.1/sites/161477129/stats/summary/",
"queryParameters": {
"period": {
"equalTo": "year"
},
"date": {
"matches": "(.*)"
}
}
},
"response": {
"status": 200,
"jsonBody": {
"date": "{{now format='yyyy-MM-dd'}}",
"period": "year",
"views": 0,
"visitors": 0,
"likes": 0,
"reblogs": 0,
"comments": 0,
"followers": 1
}
}
}
Loading

0 comments on commit e7c6337

Please sign in to comment.