From ad1f177883a78cb6826d4048544418e9b354a1bf Mon Sep 17 00:00:00 2001 From: "Thuy.Copeland" Date: Tue, 7 Aug 2018 15:05:55 -0500 Subject: [PATCH 001/116] Make the shipping address optional. Add a check to see if an order has a shipping address --- Networking/Networking/Model/Order.swift | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Networking/Networking/Model/Order.swift b/Networking/Networking/Model/Order.swift index 7dc7a99629b..0af97664a75 100644 --- a/Networking/Networking/Model/Order.swift +++ b/Networking/Networking/Model/Order.swift @@ -28,7 +28,7 @@ public struct Order: Decodable { public let items: [OrderItem] public let billingAddress: Address - public let shippingAddress: Address + public let shippingAddress: Address? public let coupons: [OrderCouponLine] /// Order struct initializer. @@ -53,7 +53,7 @@ public struct Order: Decodable { paymentMethodTitle: String, items: [OrderItem], billingAddress: Address, - shippingAddress: Address, + shippingAddress: Address?, coupons: [OrderCouponLine]) { self.siteID = siteID @@ -116,12 +116,19 @@ public struct Order: Decodable { let paymentMethodTitle = try container.decode(String.self, forKey: .paymentMethodTitle) let items = try container.decode([OrderItem].self, forKey: .items) - let shippingAddress = try container.decode(Address.self, forKey: .shippingAddress) + let shippingAddress = try container.decodeIfPresent(Address.self, forKey: .shippingAddress) let billingAddress = try container.decode(Address.self, forKey: .billingAddress) let coupons = try container.decode([OrderCouponLine].self, forKey: .couponLines) self.init(siteID: siteID, orderID: orderID, parentID: parentID, customerID: customerID, number: number, status: status, currency: currency, customerNote: customerNote, dateCreated: dateCreated, dateModified: dateModified, datePaid: datePaid, discountTotal: discountTotal, discountTax: discountTax, shippingTotal: shippingTotal, shippingTax: shippingTax, total: total, totalTax: totalTax, paymentMethodTitle: paymentMethodTitle, items: items, billingAddress: billingAddress, shippingAddress: shippingAddress, coupons: coupons) // initialize the struct } + + func hasSeparateShippingDetails() -> Bool { + if let shipping = shippingAddress { + return !shipping.country.isEmpty + } + return false + } } From 3274400aa9407a16b891d07f2919d6de69b44568 Mon Sep 17 00:00:00 2001 From: "Thuy.Copeland" Date: Wed, 8 Aug 2018 11:18:34 -0500 Subject: [PATCH 002/116] Handle the shipping address as optional --- .../Model/Order+ReadOnlyConvertible.swift | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/Yosemite/Yosemite/Model/Order+ReadOnlyConvertible.swift b/Yosemite/Yosemite/Model/Order+ReadOnlyConvertible.swift index 0defe0acc9f..3185ca549ed 100644 --- a/Yosemite/Yosemite/Model/Order+ReadOnlyConvertible.swift +++ b/Yosemite/Yosemite/Model/Order+ReadOnlyConvertible.swift @@ -42,17 +42,19 @@ extension Storage.Order: ReadOnlyConvertible { billingPhone = order.billingAddress.phone billingEmail = order.billingAddress.email - shippingFirstName = order.shippingAddress.firstName - shippingLastName = order.shippingAddress.lastName - shippingCompany = order.shippingAddress.company - shippingAddress1 = order.shippingAddress.address1 - shippingAddress2 = order.shippingAddress.address2 - shippingCity = order.shippingAddress.city - shippingState = order.shippingAddress.state - shippingPostcode = order.shippingAddress.postcode - shippingCountry = order.shippingAddress.country - shippingPhone = order.shippingAddress.phone - shippingEmail = order.shippingAddress.email + if let shippingAddress = order.shippingAddress { + shippingFirstName = shippingAddress.firstName + shippingLastName = shippingAddress.lastName + shippingCompany = shippingAddress.company + shippingAddress1 = shippingAddress.address1 + shippingAddress2 = shippingAddress.address2 + shippingCity = shippingAddress.city + shippingState = shippingAddress.state + shippingPostcode = shippingAddress.postcode + shippingCountry = shippingAddress.country + shippingPhone = shippingAddress.phone + shippingEmail = shippingAddress.email + } } /// Returns a ReadOnly version of the receiver. @@ -85,6 +87,14 @@ extension Storage.Order: ReadOnlyConvertible { coupons: orderCoupons) } + public func hasSeparateShippingDetails() -> Bool { + let order = toReadOnly() + if let shipping = order.shippingAddress { + return !shipping.country.isEmpty + } + return false + } + // MARK: - Private Helpers From 6baed4fee96afe3c80fb73ba8b4d65ad3e2fa6c5 Mon Sep 17 00:00:00 2001 From: "Thuy.Copeland" Date: Wed, 8 Aug 2018 13:57:01 -0500 Subject: [PATCH 003/116] Substitute the billing address if the shipping address doesn't exist --- .../ViewModels/OrderDetailsViewModel.swift | 7 +++++-- .../Orders/FulfillViewController.swift | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/WooCommerce/Classes/ViewModels/OrderDetailsViewModel.swift b/WooCommerce/Classes/ViewModels/OrderDetailsViewModel.swift index 17235c0ff99..d16289c155c 100644 --- a/WooCommerce/Classes/ViewModels/OrderDetailsViewModel.swift +++ b/WooCommerce/Classes/ViewModels/OrderDetailsViewModel.swift @@ -15,7 +15,7 @@ class OrderDetailsViewModel { } var summaryTitle: String { - return "#\(order.number) \(order.shippingAddress.firstName) \(order.shippingAddress.lastName)" + return "#\(order.number) \(order.billingAddress.firstName) \(order.billingAddress.lastName)" } var summaryDateCreated: String { @@ -60,7 +60,10 @@ class OrderDetailsViewModel { } var shippingViewModel: ContactViewModel { - return ContactViewModel(with: order.shippingAddress, contactType: ContactType.shipping) + if let shippingAddress = order.shippingAddress { + return ContactViewModel(with: shippingAddress, contactType: ContactType.shipping) + } + return ContactViewModel(with: order.billingAddress, contactType: ContactType.billing) } var shippingAddress: String? { return shippingViewModel.formattedAddress diff --git a/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift index 31a0b94489f..c6a5a8bdd27 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift @@ -257,7 +257,12 @@ private extension FulfillViewController { fatalError() } - let address = order.shippingAddress + var address: Address + if let shippingAddress = order.shippingAddress { + address = shippingAddress + } else { + address = order.billingAddress + } cell.title = NSLocalizedString("Shipping details", comment: "Shipping title for customer info cell") cell.name = address.fullName @@ -377,7 +382,13 @@ private extension Section { let address: Section = { let title = NSLocalizedString("Customer Information", comment: "") - let row = Row.address(shipping: order.shippingAddress) + let displayAddress: Address + if let shippingAddress = order.shippingAddress { + displayAddress = shippingAddress + } else { + displayAddress = order.billingAddress + } + let row = Row.address(shipping: displayAddress) return Section(title: title, secondaryTitle: nil, rows: [row]) }() From 4df8ddef66977048a3a8e0389b779d8ab7031e86 Mon Sep 17 00:00:00 2001 From: "Thuy.Copeland" Date: Wed, 8 Aug 2018 14:57:17 -0500 Subject: [PATCH 004/116] Move function to correct class Because we have to check for the optional shippingAddress anyway, --- Networking/Networking/Model/Order.swift | 7 ------- WooCommerce/Classes/Model/Order+Woo.swift | 9 +++++++++ Yosemite/Yosemite/Model/Order+ReadOnlyConvertible.swift | 8 -------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/Networking/Networking/Model/Order.swift b/Networking/Networking/Model/Order.swift index 0af97664a75..7e993815f9c 100644 --- a/Networking/Networking/Model/Order.swift +++ b/Networking/Networking/Model/Order.swift @@ -122,13 +122,6 @@ public struct Order: Decodable { self.init(siteID: siteID, orderID: orderID, parentID: parentID, customerID: customerID, number: number, status: status, currency: currency, customerNote: customerNote, dateCreated: dateCreated, dateModified: dateModified, datePaid: datePaid, discountTotal: discountTotal, discountTax: discountTax, shippingTotal: shippingTotal, shippingTax: shippingTax, total: total, totalTax: totalTax, paymentMethodTitle: paymentMethodTitle, items: items, billingAddress: billingAddress, shippingAddress: shippingAddress, coupons: coupons) // initialize the struct } - - func hasSeparateShippingDetails() -> Bool { - if let shipping = shippingAddress { - return !shipping.country.isEmpty - } - return false - } } diff --git a/WooCommerce/Classes/Model/Order+Woo.swift b/WooCommerce/Classes/Model/Order+Woo.swift index 64cb6df4637..e385d2a02e6 100644 --- a/WooCommerce/Classes/Model/Order+Woo.swift +++ b/WooCommerce/Classes/Model/Order+Woo.swift @@ -14,4 +14,13 @@ extension Order { return NSLocale(localeIdentifier: identifier).currencySymbol } + + /// Determines if a shipping address exists. + /// + var hasSeparateShippingDetail: Bool { + if let shipping = self.shippingAddress { + return !shipping.country.isEmpty + } + return false + } } diff --git a/Yosemite/Yosemite/Model/Order+ReadOnlyConvertible.swift b/Yosemite/Yosemite/Model/Order+ReadOnlyConvertible.swift index 3185ca549ed..4904b13532c 100644 --- a/Yosemite/Yosemite/Model/Order+ReadOnlyConvertible.swift +++ b/Yosemite/Yosemite/Model/Order+ReadOnlyConvertible.swift @@ -87,14 +87,6 @@ extension Storage.Order: ReadOnlyConvertible { coupons: orderCoupons) } - public func hasSeparateShippingDetails() -> Bool { - let order = toReadOnly() - if let shipping = order.shippingAddress { - return !shipping.country.isEmpty - } - return false - } - // MARK: - Private Helpers From 1052987d983166a790751c0d79dbba763fbf1119 Mon Sep 17 00:00:00 2001 From: "Thuy.Copeland" Date: Wed, 8 Aug 2018 15:15:08 -0500 Subject: [PATCH 005/116] Display billing address if there is no shipping address --- WooCommerce/Classes/ViewModels/OrderDetailsViewModel.swift | 7 ++++--- .../Classes/ViewRelated/Orders/FulfillViewController.swift | 7 +------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/WooCommerce/Classes/ViewModels/OrderDetailsViewModel.swift b/WooCommerce/Classes/ViewModels/OrderDetailsViewModel.swift index d16289c155c..1c550f41868 100644 --- a/WooCommerce/Classes/ViewModels/OrderDetailsViewModel.swift +++ b/WooCommerce/Classes/ViewModels/OrderDetailsViewModel.swift @@ -60,10 +60,11 @@ class OrderDetailsViewModel { } var shippingViewModel: ContactViewModel { - if let shippingAddress = order.shippingAddress { - return ContactViewModel(with: shippingAddress, contactType: ContactType.shipping) + if order.hasSeparateShippingDetail { + return ContactViewModel(with: order.shippingAddress!, contactType: ContactType.shipping) } - return ContactViewModel(with: order.billingAddress, contactType: ContactType.billing) + + return ContactViewModel(with: order.billingAddress, contactType: ContactType.shipping) } var shippingAddress: String? { return shippingViewModel.formattedAddress diff --git a/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift index c6a5a8bdd27..cd81af15333 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift @@ -257,12 +257,7 @@ private extension FulfillViewController { fatalError() } - var address: Address - if let shippingAddress = order.shippingAddress { - address = shippingAddress - } else { - address = order.billingAddress - } + let address = order.hasSeparateShippingDetail ? order.shippingAddress! : order.billingAddress cell.title = NSLocalizedString("Shipping details", comment: "Shipping title for customer info cell") cell.name = address.fullName From 40cce2480d37d1ac892dc4af0077f076e60539c7 Mon Sep 17 00:00:00 2001 From: Jorge Leandro Perez Date: Wed, 8 Aug 2018 17:28:06 -0300 Subject: [PATCH 006/116] OrderDetailsViewController: Notice Helper --- .../OrderDetails/OrderDetailsViewController.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift index 92d632b1e4e..13e5cb2688a 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift @@ -180,6 +180,21 @@ private extension OrderDetailsViewController { } } +// MARK: - Notices +// +private extension OrderDetailsViewController { + + /// Displays a Notice onscreen, indicating that the current Order has been deleted from the Store. + /// + func displayOrderDeletedNotice() { + let title = NSLocalizedString("Deleted: Order #\(viewModel.order.number)", comment: "Order Notice") + let message = NSLocalizedString("The order has been deleted from your Store!", + comment: "Displayed whenever the Details for an Order that just got deleted was onscreen.") + + let notice = Notice(title: title, message: message, feedbackType: .error) + AppDelegate.shared.noticePresenter.enqueue(notice: notice) + } +} // MARK: - Action Handlers // From 0949c51b462fe3a2cd069d93ddc6b9dfb1af3521 Mon Sep 17 00:00:00 2001 From: Jorge Leandro Perez Date: Wed, 8 Aug 2018 17:28:24 -0300 Subject: [PATCH 007/116] OrderDetailsViewController: Wiring EntityListener --- .../OrderDetailsViewController.swift | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift index 13e5cb2688a..3c61bbc90fd 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift @@ -38,24 +38,21 @@ class OrderDetailsViewController: UIViewController { } private var sections = [Section]() - /// TODO: Replace with `ResultController` (OR) `ObjectController` ASAP + /// EntityListener: Update / Deletion Notifications. /// - private lazy var resultsController: ResultsController = { - let storageManager = AppDelegate.shared.storageManager - let predicate = NSPredicate(format: "orderID = %ld", self.viewModel.order.orderID) - let descriptor = NSSortDescriptor(key: "orderID", ascending: true) - - return ResultsController(storageManager: storageManager, matching: predicate, sortedBy: [descriptor]) + private lazy var entityListener: EntityListener = { + return EntityListener(storageManager: AppDelegate.shared.storageManager, readOnlyEntity: viewModel.order) }() + // MARK: - View Lifecycle override func viewDidLoad() { super.viewDidLoad() configureNavigation() configureTableView() - configureResultsController() + configureEntityListener() registerTableViewCells() registerTableViewHeaderFooters() } @@ -95,17 +92,24 @@ private extension OrderDetailsViewController { navigationItem.backBarButtonItem = UIBarButtonItem(title: String(), style: .plain, target: nil, action: nil) } - /// TODO: Replace with `ResultController` (OR) `ObjectController` ASAP + /// Setup: EntityListener /// - func configureResultsController() { - try? resultsController.performFetch() - resultsController.onDidChangeContent = { [weak self] in - guard let `self` = self, let order = self.resultsController.fetchedObjects.first else { + func configureEntityListener() { + entityListener.onUpsert = { [weak self] order in + guard let `self` = self else { return } - self.viewModel = OrderDetailsViewModel(order: order) } + + entityListener.onDelete = { [weak self] in + guard let `self` = self else { + return + } + + self.navigationController?.popViewController(animated: true) + self.displayOrderDeletedNotice() + } } /// Setup: Sections From 2ed20aa13dcb8217f2d73a697a8740a81633ad06 Mon Sep 17 00:00:00 2001 From: "Thuy.Copeland" Date: Wed, 8 Aug 2018 16:18:10 -0500 Subject: [PATCH 008/116] Update Address in Networking to throw an error upon parsing a field with an empty string value --- Networking/Networking/Model/Address.swift | 32 +++++++++++++++++++++++ Networking/Networking/Model/Order.swift | 3 ++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Networking/Networking/Model/Address.swift b/Networking/Networking/Model/Address.swift index 679d1df0fc1..3b2375d1d13 100644 --- a/Networking/Networking/Model/Address.swift +++ b/Networking/Networking/Model/Address.swift @@ -16,6 +16,13 @@ public struct Address: Decodable { public let phone: String? public let email: String? + /// Make Address conform to Error protocol. + /// + enum AddressParseError: Error { + case emptyStringDetected + } + + /// Designated Initializer. /// public init(firstName: String, lastName: String, company: String?, address1: String, address2: String?, city: String, state: String, postcode: String, country: String, phone: String?, email: String?) { @@ -31,6 +38,31 @@ public struct Address: Decodable { self.phone = phone self.email = email } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + let firstName = try container.decode(String.self, forKey: .firstName) + let lastName = try container.decode(String.self, forKey: .lastName) + let company = try container.decodeIfPresent(String.self, forKey: .company) + let address1 = try container.decode(String.self, forKey: .address1) + let address2 = try container.decodeIfPresent(String.self, forKey: .address2) + let city = try container.decode(String.self, forKey: .city) + let state = try container.decode(String.self, forKey: .state) + let postcode = try container.decode(String.self, forKey: .postcode) + let country = try container.decode(String.self, forKey: .country) + let phone = try container.decodeIfPresent(String.self, forKey: .phone) + let email = try container.decodeIfPresent(String.self, forKey: .email) + + let parsedItems = [firstName, lastName, company, address1, address2, city, state, country, phone, email] + for item in parsedItems { + if let parsed = item, parsed.isEmpty { + throw AddressParseError.emptyStringDetected + } + } + + self.init(firstName: firstName, lastName: lastName, company: company, address1: address1, address2: address2, city: city, state: state, postcode: postcode, country: country, phone: phone, email: email) + } } diff --git a/Networking/Networking/Model/Order.swift b/Networking/Networking/Model/Order.swift index 7e993815f9c..9b15edbfd41 100644 --- a/Networking/Networking/Model/Order.swift +++ b/Networking/Networking/Model/Order.swift @@ -116,7 +116,8 @@ public struct Order: Decodable { let paymentMethodTitle = try container.decode(String.self, forKey: .paymentMethodTitle) let items = try container.decode([OrderItem].self, forKey: .items) - let shippingAddress = try container.decodeIfPresent(Address.self, forKey: .shippingAddress) + let shippingAddress = try? container.decode(Address.self, forKey: .shippingAddress) + let billingAddress = try container.decode(Address.self, forKey: .billingAddress) let coupons = try container.decode([OrderCouponLine].self, forKey: .couponLines) From 8eb36cb79c63c47523ab4f3a7afb79e30614e8a2 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Wed, 8 Aug 2018 17:01:15 -0500 Subject: [PATCH 009/116] Dashboard WIP: Added pager and VC stubs --- Podfile | 1 + Podfile.lock | 6 +- .../Dashboard/Dashboard.storyboard | 87 ++++++++++++++++++- .../Dashboard/DashboardViewController.swift | 1 + .../MyStore/MyStoreStatsViewController.swift | 54 ++++++++++++ .../MyStore/PeriodDataViewController.swift | 23 +++++ .../WooCommerce.xcodeproj/project.pbxproj | 28 ++++-- 7 files changed, 192 insertions(+), 8 deletions(-) create mode 100644 WooCommerce/Classes/ViewRelated/Dashboard/MyStore/MyStoreStatsViewController.swift create mode 100644 WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift diff --git a/Podfile b/Podfile index 71421bcd2be..247f5df90e6 100644 --- a/Podfile +++ b/Podfile @@ -29,6 +29,7 @@ target 'WooCommerce' do pod 'Crashlytics', '~> 3.10' pod 'KeychainAccess', '~> 3.1' pod 'CocoaLumberjack/Swift', '~> 3.4' + pod 'XLPagerTabStrip', '~> 8.0' # Unit Tests # ========== diff --git a/Podfile.lock b/Podfile.lock index cffa4cffb0f..09d5e896c98 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -64,6 +64,7 @@ PODS: - FormatterKit/TimeIntervalFormatter (= 1.8.2) - WordPressUI (1.0.6) - wpxmlrpc (0.8.3) + - XLPagerTabStrip (8.0.1) DEPENDENCIES: - Alamofire (~> 4.7) @@ -74,6 +75,7 @@ DEPENDENCIES: - KeychainAccess (~> 3.1) - WordPressAuthenticator (= 1.0.5) - WordPressShared (= 1.0.8) + - XLPagerTabStrip (~> 8.0) SPEC REPOS: https://github.com/cocoapods/specs.git: @@ -98,6 +100,7 @@ SPEC REPOS: - WordPressShared - WordPressUI - wpxmlrpc + - XLPagerTabStrip EXTERNAL SOURCES: Automattic-Tracks-iOS: @@ -132,7 +135,8 @@ SPEC CHECKSUMS: WordPressShared: 063e1e8b1a7aaf635abf17f091a2d235a068abdc WordPressUI: af141587ec444f9af753a00605bd0d3f14d8d8a3 wpxmlrpc: bfc572f62ce7ee897f6f38b098d2ba08732ecef4 + XLPagerTabStrip: c908b17cbf42fcd2598ee1adfc49bae25444d88a -PODFILE CHECKSUM: 9c0f38b4e1f7d6de164e2c4279a5112a7f95f936 +PODFILE CHECKSUM: fad8937db279e4bf9807a4985a2418c4832c9b35 COCOAPODS: 1.5.3 diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard b/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard index 6ba8d70dd3b..626821ad3a6 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard @@ -9,6 +9,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -16,7 +65,41 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -28,7 +111,7 @@ - + diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift index c473ce721c8..202bed7a7d4 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift @@ -16,6 +16,7 @@ class DashboardViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() setupNavigation() + view.backgroundColor = StyleManager.tableViewBackgroundColor } func setupNavigation() { diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/MyStoreStatsViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/MyStoreStatsViewController.swift new file mode 100644 index 00000000000..747415b36bb --- /dev/null +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/MyStoreStatsViewController.swift @@ -0,0 +1,54 @@ +import UIKit +import XLPagerTabStrip + + +// MARK: - MyStoreStatsViewController +// +class MyStoreStatsViewController: ButtonBarPagerTabStripViewController { + + // MARK: - View Lifecycle + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + override func viewDidLoad() { + // change selected bar color + settings.style.buttonBarBackgroundColor = .white + settings.style.buttonBarItemBackgroundColor = .white + settings.style.selectedBarBackgroundColor = StyleManager.wooCommerceBrandColor + settings.style.buttonBarItemFont = .body + settings.style.selectedBarHeight = 2.0 + settings.style.buttonBarMinimumLineSpacing = 0 + settings.style.buttonBarItemTitleColor = StyleManager.wooGreyMid + settings.style.buttonBarItemsShouldFillAvailableWidth = true + settings.style.buttonBarLeftContentInset = 0 + settings.style.buttonBarRightContentInset = 0 + settings.style.buttonBarItemLeftRightMargin = 12.0 + + changeCurrentIndexProgressive = { (oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: CGFloat, changeCurrentIndex: Bool, animated: Bool) -> Void in + guard changeCurrentIndex == true else { return } + oldCell?.label.textColor = StyleManager.wooGreyMid + newCell?.label.textColor = StyleManager.wooCommerceBrandColor + } + super.viewDidLoad() + } + + override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { + + let child_1 = PeriodDataViewController() + child_1.view.backgroundColor = StyleManager.statusSuccessColor + child_1.tabTitle = "Days" + let child_2 = PeriodDataViewController() + child_2.view.backgroundColor = StyleManager.statusDangerColor + child_2.tabTitle = "Weeks" + let child_3 = PeriodDataViewController() + child_3.view.backgroundColor = StyleManager.statusNotIdentifiedBoldColor + child_3.tabTitle = "Months" + let child_4 = PeriodDataViewController() + child_4.view.backgroundColor = StyleManager.statusPrimaryBoldColor + child_4.tabTitle = "Years" + + return [child_1, child_2, child_3, child_4] + } +} diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift new file mode 100644 index 00000000000..9911b11a1c3 --- /dev/null +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift @@ -0,0 +1,23 @@ +import UIKit +import Yosemite +import XLPagerTabStrip + + +class PeriodDataViewController: UIViewController, IndicatorInfoProvider { + + var tabTitle: String = "1" + + override func viewDidLoad() { + super.viewDidLoad() + view.backgroundColor = StyleManager.tableViewBackgroundColor + } +} + + +// MARK: - IndicatorInfoProvider Confromance +// +extension PeriodDataViewController { + func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo { + return IndicatorInfo(title: tabTitle) + } +} diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index b5cf4c619a9..fe352677b00 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -21,12 +21,14 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 74036CC0211B882100E462C2 /* PeriodDataViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74036CBF211B882100E462C2 /* PeriodDataViewController.swift */; }; 7403F7E220EC04070097198F /* OrderStatusViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7403F7E120EC04070097198F /* OrderStatusViewModel.swift */; }; 7421344A210A323C00C13890 /* WooAnalyticsStat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74213449210A323C00C13890 /* WooAnalyticsStat.swift */; }; 746791632108D7C0007CF1DC /* WooAnalyticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 746791622108D7C0007CF1DC /* WooAnalyticsTests.swift */; }; 746791662108D87B007CF1DC /* MockupAnalyticsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 746791652108D87B007CF1DC /* MockupAnalyticsProvider.swift */; }; 747AA0892107CEC60047A89B /* AnalyticsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 747AA0882107CEC60047A89B /* AnalyticsProvider.swift */; }; 747AA08B2107CF8D0047A89B /* TracksProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 747AA08A2107CF8D0047A89B /* TracksProvider.swift */; }; + 74AFF2EA211B9B1B0038153A /* MyStoreStatsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74AFF2E9211B9B1B0038153A /* MyStoreStatsViewController.swift */; }; 86DBBB0BDEA3488E2BEBB314 /* Pods_WooCommerce.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BABE5E07DD787ECA6D2A76DE /* Pods_WooCommerce.framework */; }; 93BCF01F20DC2CE200EBF7A1 /* bash_secrets.tpl in Resources */ = {isa = PBXBuildFile; fileRef = 93BCF01E20DC2CE200EBF7A1 /* bash_secrets.tpl */; }; B50911302049E27A007D25DC /* DashboardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B509112D2049E27A007D25DC /* DashboardViewController.swift */; }; @@ -96,8 +98,8 @@ B5DBF3C320E1484400B53AED /* StoresManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DBF3C220E1484400B53AED /* StoresManagerTests.swift */; }; B5DBF3C520E148E000B53AED /* DeauthenticatedState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DBF3C420E148E000B53AED /* DeauthenticatedState.swift */; }; B5DBF3CB20E149CC00B53AED /* AuthenticatedState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DBF3CA20E149CC00B53AED /* AuthenticatedState.swift */; }; - B873E8F8E103966D2182EE67 /* Pods_WooCommerceTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6DC4526F9A7357761197EBF0 /* Pods_WooCommerceTests.framework */; }; B5E96B3821137AA100DF68D0 /* OrderStatus+Woo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E96B3721137AA100DF68D0 /* OrderStatus+Woo.swift */; }; + B873E8F8E103966D2182EE67 /* Pods_WooCommerceTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6DC4526F9A7357761197EBF0 /* Pods_WooCommerceTests.framework */; }; CE17C2E220ACA06800AFBD20 /* BillingDetailsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE17C2E020ACA06800AFBD20 /* BillingDetailsTableViewCell.swift */; }; CE17C2E320ACA06800AFBD20 /* BillingDetailsTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CE17C2E120ACA06800AFBD20 /* BillingDetailsTableViewCell.xib */; }; CE1CCB402056F21C000EE3AC /* Style.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1CCB3F2056F21C000EE3AC /* Style.swift */; }; @@ -193,12 +195,14 @@ /* Begin PBXFileReference section */ 33035144757869DE5E4DC88A /* Pods-WooCommerce.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WooCommerce.release.xcconfig"; path = "../Pods/Target Support Files/Pods-WooCommerce/Pods-WooCommerce.release.xcconfig"; sourceTree = ""; }; 6DC4526F9A7357761197EBF0 /* Pods_WooCommerceTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WooCommerceTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 74036CBF211B882100E462C2 /* PeriodDataViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeriodDataViewController.swift; sourceTree = ""; }; 7403F7E120EC04070097198F /* OrderStatusViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderStatusViewModel.swift; sourceTree = ""; }; 74213449210A323C00C13890 /* WooAnalyticsStat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooAnalyticsStat.swift; sourceTree = ""; }; 746791622108D7C0007CF1DC /* WooAnalyticsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooAnalyticsTests.swift; sourceTree = ""; }; 746791652108D87B007CF1DC /* MockupAnalyticsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockupAnalyticsProvider.swift; sourceTree = ""; }; 747AA0882107CEC60047A89B /* AnalyticsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsProvider.swift; sourceTree = ""; }; 747AA08A2107CF8D0047A89B /* TracksProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracksProvider.swift; sourceTree = ""; }; + 74AFF2E9211B9B1B0038153A /* MyStoreStatsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyStoreStatsViewController.swift; sourceTree = ""; }; 8A659E65308A3D9DD79A95F9 /* Pods-WooCommerceTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WooCommerceTests.release.xcconfig"; path = "../Pods/Target Support Files/Pods-WooCommerceTests/Pods-WooCommerceTests.release.xcconfig"; sourceTree = ""; }; 90AC1C0B391E04A837BDC64E /* Pods-WooCommerce.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WooCommerce.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-WooCommerce/Pods-WooCommerce.debug.xcconfig"; sourceTree = ""; }; 93BCF01E20DC2CE200EBF7A1 /* bash_secrets.tpl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = bash_secrets.tpl; sourceTree = ""; }; @@ -360,6 +364,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 74036CBE211B87FD00E462C2 /* MyStore */ = { + isa = PBXGroup; + children = ( + 74036CBF211B882100E462C2 /* PeriodDataViewController.swift */, + 74AFF2E9211B9B1B0038153A /* MyStoreStatsViewController.swift */, + ); + path = MyStore; + sourceTree = ""; + }; 746791642108D853007CF1DC /* Mockups */ = { isa = PBXGroup; children = ( @@ -692,6 +705,7 @@ CE85FD5120F677460080B73E /* Dashboard */ = { isa = PBXGroup; children = ( + 74036CBE211B87FD00E462C2 /* MyStore */, CE85FD5820F7A59E0080B73E /* Settings */, CE85FD5220F677770080B73E /* Dashboard.storyboard */, B509112D2049E27A007D25DC /* DashboardViewController.swift */, @@ -1021,6 +1035,7 @@ "${BUILT_PRODUCTS_DIR}/WordPressKit/WordPressKit.framework", "${BUILT_PRODUCTS_DIR}/WordPressShared/WordPressShared.framework", "${BUILT_PRODUCTS_DIR}/WordPressUI/WordPressUI.framework", + "${BUILT_PRODUCTS_DIR}/XLPagerTabStrip/XLPagerTabStrip.framework", "${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework", "${BUILT_PRODUCTS_DIR}/wpxmlrpc/wpxmlrpc.framework", ); @@ -1044,6 +1059,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WordPressKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WordPressShared.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WordPressUI.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/XLPagerTabStrip.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lottie.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/wpxmlrpc.framework", ); @@ -1146,6 +1162,8 @@ CE1EC8EC20B8A3FF009762BF /* LeftImageTableViewCell.swift in Sources */, B57C744520F55BA600EEFC87 /* NSObject+Helpers.swift in Sources */, B57C744E20F56E3800EEFC87 /* UITableViewCell+Helpers.swift in Sources */, + 74036CC0211B882100E462C2 /* PeriodDataViewController.swift in Sources */, + 74AFF2EA211B9B1B0038153A /* MyStoreStatsViewController.swift in Sources */, 7403F7E220EC04070097198F /* OrderStatusViewModel.swift in Sources */, CE32B10D20BEDE1C006FBCF4 /* TwoColumnSectionHeaderView.swift in Sources */, B57B678E21078C5400AF8905 /* OrderItemViewModel.swift in Sources */, @@ -1218,7 +1236,7 @@ CODE_SIGN_STYLE = Automatic; INFOPLIST_PREFIX_HEADER = InfoPlist.h; PRODUCT_NAME = "$(TARGET_NAME)"; - SECRETS_PATH = "$HOME/.woo_app_credentials.json"; + SECRETS_PATH = $HOME/.woo_app_credentials.json; VALID_ARCHS = "$(inherited)"; }; name = Debug; @@ -1229,7 +1247,7 @@ CODE_SIGN_STYLE = Automatic; INFOPLIST_PREFIX_HEADER = InfoPlist.h; PRODUCT_NAME = "$(TARGET_NAME)"; - SECRETS_PATH = "$HOME/.woo_app_credentials.json"; + SECRETS_PATH = $HOME/.woo_app_credentials.json; VALID_ARCHS = "$(inherited)"; }; name = Release; @@ -1367,7 +1385,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = "WooCommerce Development"; - SECRETS_PATH = "$HOME/.woo_app_credentials.json"; + SECRETS_PATH = $HOME/.woo_app_credentials.json; SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; USER_HEADER_SEARCH_PATHS = ""; @@ -1393,7 +1411,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.automattic.woocommerce; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "WooCommerce App Store"; - SECRETS_PATH = "$HOME/.woo_app_credentials.json"; + SECRETS_PATH = $HOME/.woo_app_credentials.json; SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; USER_HEADER_SEARCH_PATHS = ""; From 8062deee683f72da5bbac230eb4ccad6acaf5518 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Thu, 9 Aug 2018 08:30:36 -0500 Subject: [PATCH 010/116] Adjusted pager view --- .../Classes/ViewRelated/Dashboard/Dashboard.storyboard | 6 +++--- .../Dashboard/MyStore/MyStoreStatsViewController.swift | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard b/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard index 626821ad3a6..4cb4ca6b1aa 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard @@ -21,10 +21,10 @@ - + - + @@ -35,7 +35,7 @@ - + diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/MyStoreStatsViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/MyStoreStatsViewController.swift index 747415b36bb..402a9dc325c 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/MyStoreStatsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/MyStoreStatsViewController.swift @@ -17,7 +17,7 @@ class MyStoreStatsViewController: ButtonBarPagerTabStripViewController { settings.style.buttonBarBackgroundColor = .white settings.style.buttonBarItemBackgroundColor = .white settings.style.selectedBarBackgroundColor = StyleManager.wooCommerceBrandColor - settings.style.buttonBarItemFont = .body + settings.style.buttonBarItemFont = .headline settings.style.selectedBarHeight = 2.0 settings.style.buttonBarMinimumLineSpacing = 0 settings.style.buttonBarItemTitleColor = StyleManager.wooGreyMid From 7555f095d4964ca7141e78a3a96fe4c95ced2e16 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Thu, 9 Aug 2018 08:45:22 -0500 Subject: [PATCH 011/116] WIP tweaks to StoreStatsViewController --- .../Dashboard/Dashboard.storyboard | 4 +- ...r.swift => StoreStatsViewController.swift} | 64 +++++++++++++------ .../WooCommerce.xcodeproj/project.pbxproj | 8 +-- 3 files changed, 50 insertions(+), 26 deletions(-) rename WooCommerce/Classes/ViewRelated/Dashboard/MyStore/{MyStoreStatsViewController.swift => StoreStatsViewController.swift} (62%) diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard b/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard index 4cb4ca6b1aa..5bcc4b57dee 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard @@ -9,10 +9,10 @@ - + - + diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/MyStoreStatsViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift similarity index 62% rename from WooCommerce/Classes/ViewRelated/Dashboard/MyStore/MyStoreStatsViewController.swift rename to WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift index 402a9dc325c..c71aab93295 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/MyStoreStatsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift @@ -4,16 +4,48 @@ import XLPagerTabStrip // MARK: - MyStoreStatsViewController // -class MyStoreStatsViewController: ButtonBarPagerTabStripViewController { +class StoreStatsViewController: ButtonBarPagerTabStripViewController { - // MARK: - View Lifecycle + // MARK: View Lifecycle required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func viewDidLoad() { - // change selected bar color + // This 👇 must be called before super.viewDidLoad() + configureTabStrip() + + super.viewDidLoad() + } + + // MARK: PagerTabStripDataSource + + override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { + + let child_1 = PeriodDataViewController() + child_1.view.backgroundColor = StyleManager.statusSuccessColor + child_1.tabTitle = Tabs.titleDay + let child_2 = PeriodDataViewController() + child_2.view.backgroundColor = StyleManager.statusDangerColor + child_2.tabTitle = Tabs.titleWeek + let child_3 = PeriodDataViewController() + child_3.view.backgroundColor = StyleManager.statusNotIdentifiedBoldColor + child_3.tabTitle = Tabs.titleMonth + let child_4 = PeriodDataViewController() + child_4.view.backgroundColor = StyleManager.statusPrimaryBoldColor + child_4.tabTitle = Tabs.titleYear + + return [child_1, child_2, child_3, child_4] + } +} + + +// MARK: - User Interface Initialization +// +private extension StoreStatsViewController { + + func configureTabStrip() { settings.style.buttonBarBackgroundColor = .white settings.style.buttonBarItemBackgroundColor = .white settings.style.selectedBarBackgroundColor = StyleManager.wooCommerceBrandColor @@ -31,24 +63,16 @@ class MyStoreStatsViewController: ButtonBarPagerTabStripViewController { oldCell?.label.textColor = StyleManager.wooGreyMid newCell?.label.textColor = StyleManager.wooCommerceBrandColor } - super.viewDidLoad() } +} - override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { - - let child_1 = PeriodDataViewController() - child_1.view.backgroundColor = StyleManager.statusSuccessColor - child_1.tabTitle = "Days" - let child_2 = PeriodDataViewController() - child_2.view.backgroundColor = StyleManager.statusDangerColor - child_2.tabTitle = "Weeks" - let child_3 = PeriodDataViewController() - child_3.view.backgroundColor = StyleManager.statusNotIdentifiedBoldColor - child_3.tabTitle = "Months" - let child_4 = PeriodDataViewController() - child_4.view.backgroundColor = StyleManager.statusPrimaryBoldColor - child_4.tabTitle = "Years" - - return [child_1, child_2, child_3, child_4] +// MARK: - Constants! +// +private extension StoreStatsViewController { + enum Tabs { + static let titleDay = NSLocalizedString("Days", comment: "Title of stats tab for a specific period — plural form of day.") + static let titleWeek = NSLocalizedString("Weeks", comment: "Title of stats tab for a specific period — plural form of week.") + static let titleMonth = NSLocalizedString("Months", comment: "Title of stats tab for a specific period — plural form of month.") + static let titleYear = NSLocalizedString("Years", comment: "Title of stats tab for a specific period — plural form of year.") } } diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index fe352677b00..b5e2b768cee 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -28,7 +28,7 @@ 746791662108D87B007CF1DC /* MockupAnalyticsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 746791652108D87B007CF1DC /* MockupAnalyticsProvider.swift */; }; 747AA0892107CEC60047A89B /* AnalyticsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 747AA0882107CEC60047A89B /* AnalyticsProvider.swift */; }; 747AA08B2107CF8D0047A89B /* TracksProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 747AA08A2107CF8D0047A89B /* TracksProvider.swift */; }; - 74AFF2EA211B9B1B0038153A /* MyStoreStatsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74AFF2E9211B9B1B0038153A /* MyStoreStatsViewController.swift */; }; + 74AFF2EA211B9B1B0038153A /* StoreStatsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74AFF2E9211B9B1B0038153A /* StoreStatsViewController.swift */; }; 86DBBB0BDEA3488E2BEBB314 /* Pods_WooCommerce.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BABE5E07DD787ECA6D2A76DE /* Pods_WooCommerce.framework */; }; 93BCF01F20DC2CE200EBF7A1 /* bash_secrets.tpl in Resources */ = {isa = PBXBuildFile; fileRef = 93BCF01E20DC2CE200EBF7A1 /* bash_secrets.tpl */; }; B50911302049E27A007D25DC /* DashboardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B509112D2049E27A007D25DC /* DashboardViewController.swift */; }; @@ -202,7 +202,7 @@ 746791652108D87B007CF1DC /* MockupAnalyticsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockupAnalyticsProvider.swift; sourceTree = ""; }; 747AA0882107CEC60047A89B /* AnalyticsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsProvider.swift; sourceTree = ""; }; 747AA08A2107CF8D0047A89B /* TracksProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracksProvider.swift; sourceTree = ""; }; - 74AFF2E9211B9B1B0038153A /* MyStoreStatsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyStoreStatsViewController.swift; sourceTree = ""; }; + 74AFF2E9211B9B1B0038153A /* StoreStatsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreStatsViewController.swift; sourceTree = ""; }; 8A659E65308A3D9DD79A95F9 /* Pods-WooCommerceTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WooCommerceTests.release.xcconfig"; path = "../Pods/Target Support Files/Pods-WooCommerceTests/Pods-WooCommerceTests.release.xcconfig"; sourceTree = ""; }; 90AC1C0B391E04A837BDC64E /* Pods-WooCommerce.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WooCommerce.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-WooCommerce/Pods-WooCommerce.debug.xcconfig"; sourceTree = ""; }; 93BCF01E20DC2CE200EBF7A1 /* bash_secrets.tpl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = bash_secrets.tpl; sourceTree = ""; }; @@ -368,7 +368,7 @@ isa = PBXGroup; children = ( 74036CBF211B882100E462C2 /* PeriodDataViewController.swift */, - 74AFF2E9211B9B1B0038153A /* MyStoreStatsViewController.swift */, + 74AFF2E9211B9B1B0038153A /* StoreStatsViewController.swift */, ); path = MyStore; sourceTree = ""; @@ -1163,7 +1163,7 @@ B57C744520F55BA600EEFC87 /* NSObject+Helpers.swift in Sources */, B57C744E20F56E3800EEFC87 /* UITableViewCell+Helpers.swift in Sources */, 74036CC0211B882100E462C2 /* PeriodDataViewController.swift in Sources */, - 74AFF2EA211B9B1B0038153A /* MyStoreStatsViewController.swift in Sources */, + 74AFF2EA211B9B1B0038153A /* StoreStatsViewController.swift in Sources */, 7403F7E220EC04070097198F /* OrderStatusViewModel.swift in Sources */, CE32B10D20BEDE1C006FBCF4 /* TwoColumnSectionHeaderView.swift in Sources */, B57B678E21078C5400AF8905 /* OrderItemViewModel.swift in Sources */, From 836cab0a3bfd91cd5c4fac4549db868f06fc34f5 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Thu, 9 Aug 2018 10:04:10 -0500 Subject: [PATCH 012/116] Dashboard: UITweaks based on design docs --- .../Dashboard/Dashboard.storyboard | 13 +++--- .../Dashboard/DashboardViewController.swift | 41 +++++++++++++++++-- .../MyStore/StoreStatsViewController.swift | 37 +++++++++-------- 3 files changed, 63 insertions(+), 28 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard b/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard index 5bcc4b57dee..e1b253506ce 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard @@ -14,11 +14,11 @@ - + - + @@ -35,7 +35,7 @@ - + @@ -70,17 +70,17 @@ - + - + - + @@ -106,6 +106,7 @@ + diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift index 202bed7a7d4..4f3401d8d26 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift @@ -1,12 +1,23 @@ import UIKit import Gridicons +import CocoaLumberjack // MARK: - DashboardViewController // class DashboardViewController: UIViewController { - // MARK: - View Lifecycle + // MARK: Properties + + @IBOutlet private weak var scrollView: UIScrollView! + + private lazy var refreshControl: UIRefreshControl = { + let refreshControl = UIRefreshControl() + refreshControl.addTarget(self, action: #selector(pullToRefresh), for: .valueChanged) + return refreshControl + }() + + // MARK: View Lifecycle required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) @@ -15,11 +26,22 @@ class DashboardViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - setupNavigation() + configureNavigation() + configureView() + } +} + + +// MARK: - Configuration +// +extension DashboardViewController { + + func configureView() { view.backgroundColor = StyleManager.tableViewBackgroundColor + scrollView.refreshControl = refreshControl } - func setupNavigation() { + func configureNavigation() { title = NSLocalizedString("My Store", comment: "Dashboard navigation title") let rightBarButton = UIBarButtonItem(image: Gridicon.iconOfType(.cog), style: .plain, @@ -36,14 +58,25 @@ class DashboardViewController: UIViewController { navigationItem.backBarButtonItem = backButton } +} - // MARK: - Actions + +// MARK: - Action Handlers +// +extension DashboardViewController { @objc func settingsTapped() { performSegue(withIdentifier: Constants.settingsSegue, sender: nil) } + + @objc func pullToRefresh() { + // TODO: Implement pull-to-refresh + self.refreshControl.endRefreshing() + DDLogDebug("Pulling to refresh!") + } } + // MARK: - Constants // private extension DashboardViewController { diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift index c71aab93295..c2edbd92cf5 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift @@ -25,16 +25,16 @@ class StoreStatsViewController: ButtonBarPagerTabStripViewController { let child_1 = PeriodDataViewController() child_1.view.backgroundColor = StyleManager.statusSuccessColor - child_1.tabTitle = Tabs.titleDay + child_1.tabTitle = TabStrip.titleDay let child_2 = PeriodDataViewController() child_2.view.backgroundColor = StyleManager.statusDangerColor - child_2.tabTitle = Tabs.titleWeek + child_2.tabTitle = TabStrip.titleWeek let child_3 = PeriodDataViewController() child_3.view.backgroundColor = StyleManager.statusNotIdentifiedBoldColor - child_3.tabTitle = Tabs.titleMonth + child_3.tabTitle = TabStrip.titleMonth let child_4 = PeriodDataViewController() child_4.view.backgroundColor = StyleManager.statusPrimaryBoldColor - child_4.tabTitle = Tabs.titleYear + child_4.tabTitle = TabStrip.titleYear return [child_1, child_2, child_3, child_4] } @@ -49,30 +49,31 @@ private extension StoreStatsViewController { settings.style.buttonBarBackgroundColor = .white settings.style.buttonBarItemBackgroundColor = .white settings.style.selectedBarBackgroundColor = StyleManager.wooCommerceBrandColor - settings.style.buttonBarItemFont = .headline - settings.style.selectedBarHeight = 2.0 - settings.style.buttonBarMinimumLineSpacing = 0 - settings.style.buttonBarItemTitleColor = StyleManager.wooGreyMid - settings.style.buttonBarItemsShouldFillAvailableWidth = true - settings.style.buttonBarLeftContentInset = 0 - settings.style.buttonBarRightContentInset = 0 - settings.style.buttonBarItemLeftRightMargin = 12.0 + settings.style.buttonBarItemFont = StyleManager.subheadlineFont + settings.style.selectedBarHeight = TabStrip.selectedBarHeight + settings.style.buttonBarItemTitleColor = StyleManager.wooGreyTextMin + settings.style.buttonBarItemsShouldFillAvailableWidth = false + settings.style.buttonBarItemLeftRightMargin = TabStrip.buttonLeftRightMargin changeCurrentIndexProgressive = { (oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: CGFloat, changeCurrentIndex: Bool, animated: Bool) -> Void in guard changeCurrentIndex == true else { return } - oldCell?.label.textColor = StyleManager.wooGreyMid + oldCell?.label.textColor = StyleManager.wooGreyTextMin newCell?.label.textColor = StyleManager.wooCommerceBrandColor } } } + // MARK: - Constants! // private extension StoreStatsViewController { - enum Tabs { - static let titleDay = NSLocalizedString("Days", comment: "Title of stats tab for a specific period — plural form of day.") - static let titleWeek = NSLocalizedString("Weeks", comment: "Title of stats tab for a specific period — plural form of week.") - static let titleMonth = NSLocalizedString("Months", comment: "Title of stats tab for a specific period — plural form of month.") - static let titleYear = NSLocalizedString("Years", comment: "Title of stats tab for a specific period — plural form of year.") + enum TabStrip { + static let titleDay = NSLocalizedString("Days", comment: "Title of stats tab for a specific period — plural form of day.") + static let titleWeek = NSLocalizedString("Weeks", comment: "Title of stats tab for a specific period — plural form of week.") + static let titleMonth = NSLocalizedString("Months", comment: "Title of stats tab for a specific period — plural form of month.") + static let titleYear = NSLocalizedString("Years", comment: "Title of stats tab for a specific period — plural form of year.") + + static let buttonLeftRightMargin: CGFloat = 14.0 + static let selectedBarHeight: CGFloat = 3.0 } } From 41327e6bdf677b1bc45a7fc3c918532ba288e737 Mon Sep 17 00:00:00 2001 From: "Thuy.Copeland" Date: Thu, 9 Aug 2018 10:13:05 -0500 Subject: [PATCH 013/116] Unwrap optional shipping addresses before unit testing --- .../NetworkingTests/Mapper/OrderListMapperTests.swift | 6 +++++- Networking/NetworkingTests/Mapper/OrderMapperTests.swift | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Networking/NetworkingTests/Mapper/OrderListMapperTests.swift b/Networking/NetworkingTests/Mapper/OrderListMapperTests.swift index d5629042f4c..ee23ddaa30a 100644 --- a/Networking/NetworkingTests/Mapper/OrderListMapperTests.swift +++ b/Networking/NetworkingTests/Mapper/OrderListMapperTests.swift @@ -55,7 +55,11 @@ class OrderListMapperTests: XCTestCase { XCTAssert(orders.count == 3) let firstOrder = orders[0] - let dummyAddresses = [firstOrder.billingAddress, firstOrder.shippingAddress] + var dummyAddresses = [Address]() + if let shippingAddress = firstOrder.shippingAddress { + dummyAddresses.append(shippingAddress) + } + dummyAddresses.append(firstOrder.billingAddress) for address in dummyAddresses { XCTAssertEqual(address.firstName, "Johnny") diff --git a/Networking/NetworkingTests/Mapper/OrderMapperTests.swift b/Networking/NetworkingTests/Mapper/OrderMapperTests.swift index 789d37202ad..f5e12970d4a 100644 --- a/Networking/NetworkingTests/Mapper/OrderMapperTests.swift +++ b/Networking/NetworkingTests/Mapper/OrderMapperTests.swift @@ -50,7 +50,11 @@ class OrderMapperTests: XCTestCase { return } - let dummyAddresses = [order.billingAddress, order.shippingAddress] + var dummyAddresses = [Address]() + if let shippingAddress = order.shippingAddress { + dummyAddresses.append(shippingAddress) + } + dummyAddresses.append(order.billingAddress) for address in dummyAddresses { XCTAssertEqual(address.firstName, "Johnny") From c831f77100b9cffe0c88bed806b14fbc89325ef1 Mon Sep 17 00:00:00 2001 From: "Thuy.Copeland" Date: Thu, 9 Aug 2018 10:22:44 -0500 Subject: [PATCH 014/116] country.isEmpty is the main determinate for an empty address --- Networking/Networking/Model/Address.swift | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Networking/Networking/Model/Address.swift b/Networking/Networking/Model/Address.swift index 3b2375d1d13..3de795a6fa6 100644 --- a/Networking/Networking/Model/Address.swift +++ b/Networking/Networking/Model/Address.swift @@ -54,11 +54,10 @@ public struct Address: Decodable { let phone = try container.decodeIfPresent(String.self, forKey: .phone) let email = try container.decodeIfPresent(String.self, forKey: .email) - let parsedItems = [firstName, lastName, company, address1, address2, city, state, country, phone, email] - for item in parsedItems { - if let parsed = item, parsed.isEmpty { - throw AddressParseError.emptyStringDetected - } + // Check for an empty country, because on Android that's how + // we determine if the shipping address should be considered empty. + if country.isEmpty { + throw AddressParseError.emptyStringDetected } self.init(firstName: firstName, lastName: lastName, company: company, address1: address1, address2: address2, city: city, state: state, postcode: postcode, country: country, phone: phone, email: email) From 68951377432b6647d4accfe7470ce30cd7b89091 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Thu, 9 Aug 2018 10:44:30 -0500 Subject: [PATCH 015/116] Dashboard: borders --- .../Dashboard/Dashboard.storyboard | 28 +++++++++++++++++-- .../MyStore/StoreStatsViewController.swift | 18 ++++++++++-- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard b/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard index e1b253506ce..8721da5f370 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Dashboard.storyboard @@ -20,8 +20,15 @@ + + + + + + + - + @@ -34,9 +41,23 @@ + + + + + + + - + + + + + + + + @@ -50,8 +71,11 @@ + + + diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift index c2edbd92cf5..544fb673b33 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift @@ -6,6 +6,12 @@ import XLPagerTabStrip // class StoreStatsViewController: ButtonBarPagerTabStripViewController { + // MARK: Properties + + @IBOutlet weak var topBorder: UIView! + @IBOutlet weak var middleBorder: UIView! + @IBOutlet weak var bottomBorder: UIView! + // MARK: View Lifecycle required init?(coder aDecoder: NSCoder) { @@ -13,10 +19,10 @@ class StoreStatsViewController: ButtonBarPagerTabStripViewController { } override func viewDidLoad() { - // This 👇 must be called before super.viewDidLoad() - configureTabStrip() - + configureTabStrip() // 👈 must be called before super.viewDidLoad() super.viewDidLoad() + + configureView() } // MARK: PagerTabStripDataSource @@ -45,6 +51,12 @@ class StoreStatsViewController: ButtonBarPagerTabStripViewController { // private extension StoreStatsViewController { + func configureView() { + topBorder.backgroundColor = StyleManager.wooGreyBorder + middleBorder.backgroundColor = StyleManager.wooGreyBorder + bottomBorder.backgroundColor = StyleManager.wooGreyBorder + } + func configureTabStrip() { settings.style.buttonBarBackgroundColor = .white settings.style.buttonBarItemBackgroundColor = .white From ef3c1caa9b70d621d7cf62cc223b3dd32b08706c Mon Sep 17 00:00:00 2001 From: "Thuy.Copeland" Date: Thu, 9 Aug 2018 10:59:18 -0500 Subject: [PATCH 016/116] Force-unwrap shipping address if it has a country property that is not empty --- WooCommerce/Classes/Model/Order+Woo.swift | 2 +- .../Classes/ViewRelated/Orders/FulfillViewController.swift | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/WooCommerce/Classes/Model/Order+Woo.swift b/WooCommerce/Classes/Model/Order+Woo.swift index e385d2a02e6..8d0734bd795 100644 --- a/WooCommerce/Classes/Model/Order+Woo.swift +++ b/WooCommerce/Classes/Model/Order+Woo.swift @@ -18,7 +18,7 @@ extension Order { /// Determines if a shipping address exists. /// var hasSeparateShippingDetail: Bool { - if let shipping = self.shippingAddress { + if let shipping = shippingAddress { return !shipping.country.isEmpty } return false diff --git a/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift index cd81af15333..8a78570c546 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift @@ -377,9 +377,9 @@ private extension Section { let address: Section = { let title = NSLocalizedString("Customer Information", comment: "") - let displayAddress: Address - if let shippingAddress = order.shippingAddress { - displayAddress = shippingAddress + var displayAddress: Address + if order.hasSeparateShippingDetail { + displayAddress = order.shippingAddress! } else { displayAddress = order.billingAddress } From e6cd39c65bd35ea25500937508b2d110a1d8d0ff Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Thu, 9 Aug 2018 12:09:24 -0500 Subject: [PATCH 017/116] Dashboard layout updates --- WooCommerce/Classes/Styles/Style.swift | 6 + .../MyStore/PeriodDataViewController.swift | 42 ++++- .../MyStore/PeriodDataViewController.xib | 160 ++++++++++++++++++ .../MyStore/StoreStatsViewController.swift | 4 - .../WooCommerce.xcodeproj/project.pbxproj | 4 + 5 files changed, 210 insertions(+), 6 deletions(-) create mode 100644 WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.xib diff --git a/WooCommerce/Classes/Styles/Style.swift b/WooCommerce/Classes/Styles/Style.swift index 875a403a978..fc86cc0f70c 100644 --- a/WooCommerce/Classes/Styles/Style.swift +++ b/WooCommerce/Classes/Styles/Style.swift @@ -21,6 +21,7 @@ protocol Style { var navBarImage: UIImage { get } var sectionBackgroundColor: UIColor { get } var sectionTitleColor: UIColor { get } + var statsBigDataFont: UIFont { get } var statusDangerColor: UIColor { get } var statusDangerBoldColor: UIColor { get } var statusNotIdentifiedColor: UIColor { get } @@ -60,6 +61,7 @@ class DefaultStyle: Style { let navBarImage = UIImage(named: "woo-logo")! let sectionBackgroundColor = UIColor(red: 239.0/255.0, green: 239.0/255.0, blue: 244.0/255.0, alpha: 1.0) let sectionTitleColor = UIColor.darkGray + let statsBigDataFont = UIFont.systemFont(ofSize: 32.0, weight: .regular) let statusDangerColor = UIColor(red: 255.0/255.0, green: 230.0/255.0, blue: 229.0/255.0, alpha: 1.0) let statusDangerBoldColor = UIColor(red: 255.0/255.0, green: 197.0/255.0, blue: 195.0/255.0, alpha: 1.0) let statusNotIdentifiedColor = UIColor(red: 235.0/255.0, green: 235.0/255.0, blue: 235.0/255.0, alpha: 1.0) @@ -165,6 +167,10 @@ class StyleManager { return active.sectionTitleColor } + static var statsBigDataFont: UIFont { + return active.statsBigDataFont + } + static var statusDangerColor: UIColor { return active.statusDangerColor } diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift index 9911b11a1c3..1b39ead5001 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift @@ -5,11 +5,21 @@ import XLPagerTabStrip class PeriodDataViewController: UIViewController, IndicatorInfoProvider { - var tabTitle: String = "1" + @IBOutlet weak var visitorsTitle: UILabel! + @IBOutlet weak var visitorsData: UILabel! + @IBOutlet weak var ordersTitle: UILabel! + @IBOutlet weak var ordersData: UILabel! + @IBOutlet weak var revenueTitle: UILabel! + @IBOutlet weak var revenueData: UILabel! + @IBOutlet weak var lastUpdated: UILabel! + @IBOutlet weak var chartView: UIView! + @IBOutlet weak var borderView: UIView! + + var tabTitle: String = "" override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = StyleManager.tableViewBackgroundColor + configureView() } } @@ -21,3 +31,31 @@ extension PeriodDataViewController { return IndicatorInfo(title: tabTitle) } } + + +// MARK: - User Interface Initialization +// +private extension PeriodDataViewController { + + func configureView() { + view.backgroundColor = .white + borderView.backgroundColor = StyleManager.wooGreyBorder + + // Titles + visitorsTitle.applyFootnoteStyle() + ordersTitle.applyFootnoteStyle() + revenueTitle.applyFootnoteStyle() + + // Data + visitorsData.font = StyleManager.statsBigDataFont + visitorsData.textColor = StyleManager.defaultTextColor + ordersData.font = StyleManager.statsBigDataFont + ordersData.textColor = StyleManager.defaultTextColor + revenueData.font = StyleManager.statsBigDataFont + revenueData.textColor = StyleManager.defaultTextColor + + // Footer + lastUpdated.font = UIFont.footnote + lastUpdated.textColor = StyleManager.wooGreyTextMin + } +} diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.xib b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.xib new file mode 100644 index 00000000000..32b72e2b3fe --- /dev/null +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.xib @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift index 544fb673b33..49036c665a1 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift @@ -30,16 +30,12 @@ class StoreStatsViewController: ButtonBarPagerTabStripViewController { override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] { let child_1 = PeriodDataViewController() - child_1.view.backgroundColor = StyleManager.statusSuccessColor child_1.tabTitle = TabStrip.titleDay let child_2 = PeriodDataViewController() - child_2.view.backgroundColor = StyleManager.statusDangerColor child_2.tabTitle = TabStrip.titleWeek let child_3 = PeriodDataViewController() - child_3.view.backgroundColor = StyleManager.statusNotIdentifiedBoldColor child_3.tabTitle = TabStrip.titleMonth let child_4 = PeriodDataViewController() - child_4.view.backgroundColor = StyleManager.statusPrimaryBoldColor child_4.tabTitle = TabStrip.titleYear return [child_1, child_2, child_3, child_4] diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index b5e2b768cee..9a69ab9a543 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -29,6 +29,7 @@ 747AA0892107CEC60047A89B /* AnalyticsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 747AA0882107CEC60047A89B /* AnalyticsProvider.swift */; }; 747AA08B2107CF8D0047A89B /* TracksProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 747AA08A2107CF8D0047A89B /* TracksProvider.swift */; }; 74AFF2EA211B9B1B0038153A /* StoreStatsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74AFF2E9211B9B1B0038153A /* StoreStatsViewController.swift */; }; + 74E0F441211C9AE600A79CCE /* PeriodDataViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 74E0F440211C9AE600A79CCE /* PeriodDataViewController.xib */; }; 86DBBB0BDEA3488E2BEBB314 /* Pods_WooCommerce.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BABE5E07DD787ECA6D2A76DE /* Pods_WooCommerce.framework */; }; 93BCF01F20DC2CE200EBF7A1 /* bash_secrets.tpl in Resources */ = {isa = PBXBuildFile; fileRef = 93BCF01E20DC2CE200EBF7A1 /* bash_secrets.tpl */; }; B50911302049E27A007D25DC /* DashboardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B509112D2049E27A007D25DC /* DashboardViewController.swift */; }; @@ -203,6 +204,7 @@ 747AA0882107CEC60047A89B /* AnalyticsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsProvider.swift; sourceTree = ""; }; 747AA08A2107CF8D0047A89B /* TracksProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracksProvider.swift; sourceTree = ""; }; 74AFF2E9211B9B1B0038153A /* StoreStatsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreStatsViewController.swift; sourceTree = ""; }; + 74E0F440211C9AE600A79CCE /* PeriodDataViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PeriodDataViewController.xib; sourceTree = ""; }; 8A659E65308A3D9DD79A95F9 /* Pods-WooCommerceTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WooCommerceTests.release.xcconfig"; path = "../Pods/Target Support Files/Pods-WooCommerceTests/Pods-WooCommerceTests.release.xcconfig"; sourceTree = ""; }; 90AC1C0B391E04A837BDC64E /* Pods-WooCommerce.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WooCommerce.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-WooCommerce/Pods-WooCommerce.debug.xcconfig"; sourceTree = ""; }; 93BCF01E20DC2CE200EBF7A1 /* bash_secrets.tpl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = bash_secrets.tpl; sourceTree = ""; }; @@ -368,6 +370,7 @@ isa = PBXGroup; children = ( 74036CBF211B882100E462C2 /* PeriodDataViewController.swift */, + 74E0F440211C9AE600A79CCE /* PeriodDataViewController.xib */, 74AFF2E9211B9B1B0038153A /* StoreStatsViewController.swift */, ); path = MyStore; @@ -896,6 +899,7 @@ CE85FD6020F7BE8D0080B73E /* LogOutTableViewCell.xib in Resources */, CE583A0C2107937F00D73C1C /* TextViewTableViewCell.xib in Resources */, B5A8F8AF20B88DCC00D211DE /* LoginPrologueViewController.xib in Resources */, + 74E0F441211C9AE600A79CCE /* PeriodDataViewController.xib in Resources */, B5D1AFC820BC7B9600DB0E8C /* StorePickerViewController.xib in Resources */, B57C744320F54F1C00EEFC87 /* AccountHeaderView.xib in Resources */, CED6021E20B35FDF0032C639 /* NoResultsTableViewCell.xib in Resources */, From 379cdf12bba8db098ca930cb1d8ddb7868335c65 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Thu, 9 Aug 2018 13:15:23 -0500 Subject: [PATCH 018/116] Dashboard updates to period child VCs --- .../MyStore/PeriodDataViewController.swift | 40 ++++++--- .../MyStore/PeriodDataViewController.xib | 86 ++++++++++++++----- .../MyStore/StoreStatsViewController.swift | 12 +-- 3 files changed, 97 insertions(+), 41 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift index 1b39ead5001..97c39ae4c05 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift @@ -1,21 +1,39 @@ import UIKit import Yosemite import XLPagerTabStrip +import CocoaLumberjack class PeriodDataViewController: UIViewController, IndicatorInfoProvider { - @IBOutlet weak var visitorsTitle: UILabel! - @IBOutlet weak var visitorsData: UILabel! - @IBOutlet weak var ordersTitle: UILabel! - @IBOutlet weak var ordersData: UILabel! - @IBOutlet weak var revenueTitle: UILabel! - @IBOutlet weak var revenueData: UILabel! - @IBOutlet weak var lastUpdated: UILabel! - @IBOutlet weak var chartView: UIView! - @IBOutlet weak var borderView: UIView! + // MARK: Properties + + @IBOutlet private weak var visitorsTitle: UILabel! + @IBOutlet private weak var visitorsData: UILabel! + @IBOutlet private weak var ordersTitle: UILabel! + @IBOutlet private weak var ordersData: UILabel! + @IBOutlet private weak var revenueTitle: UILabel! + @IBOutlet private weak var revenueData: UILabel! + @IBOutlet private weak var lastUpdated: UILabel! + @IBOutlet private weak var chartView: UIView! + @IBOutlet private weak var borderView: UIView! - var tabTitle: String = "" + private var tabTitle: String = "" + + /// Designated Initializer + /// + init(tabTitle: String) { + self.tabTitle = tabTitle + super.init(nibName: type(of: self).nibName, bundle: nil) + } + + /// NSCoder Conformance + /// + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) is not supported") + } + + // MARK: View Lifecycle override func viewDidLoad() { super.viewDidLoad() @@ -56,6 +74,6 @@ private extension PeriodDataViewController { // Footer lastUpdated.font = UIFont.footnote - lastUpdated.textColor = StyleManager.wooGreyTextMin + lastUpdated.textColor = StyleManager.wooGreyMid } } diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.xib b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.xib index 32b72e2b3fe..2e4dcd8ca15 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.xib +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.xib @@ -32,73 +32,115 @@ - + - - + + + + + + + + + - - + - - + + + + + + + + + - - + - - + + + + + + + + + - - + - + @@ -126,13 +168,13 @@ - + - diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift index 4f3401d8d26..658abc6b4f8 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift @@ -10,7 +10,8 @@ class DashboardViewController: UIViewController { // MARK: Properties @IBOutlet private weak var scrollView: UIScrollView! - + private var storeStatsViewController: StoreStatsViewController! + private lazy var refreshControl: UIRefreshControl = { let refreshControl = UIRefreshControl() refreshControl.addTarget(self, action: #selector(pullToRefresh), for: .valueChanged) @@ -29,12 +30,23 @@ class DashboardViewController: UIViewController { configureNavigation() configureView() } + + override func viewDidAppear(_ animated: Bool) { + reloadData() + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + if let vc = segue.destination as? StoreStatsViewController, segue.identifier == Constants.storeStatsSegue { + self.storeStatsViewController = vc + } + } + } // MARK: - Configuration // -extension DashboardViewController { +private extension DashboardViewController { func configureView() { view.backgroundColor = StyleManager.tableViewBackgroundColor @@ -63,16 +75,27 @@ extension DashboardViewController { // MARK: - Action Handlers // -extension DashboardViewController { +private extension DashboardViewController { @objc func settingsTapped() { performSegue(withIdentifier: Constants.settingsSegue, sender: nil) } @objc func pullToRefresh() { - // TODO: Implement pull-to-refresh - self.refreshControl.endRefreshing() - DDLogDebug("Pulling to refresh!") + // FIXME: This code is just a WIP + reloadData() + refreshControl.endRefreshing() + DDLogInfo("Reloading dashboard data.") + } +} + + +// MARK: - Private Helpers +// +private extension DashboardViewController { + func reloadData() { + // FIXME: This code is just a WIP + storeStatsViewController.syncAllStats() } } @@ -81,6 +104,7 @@ extension DashboardViewController { // private extension DashboardViewController { struct Constants { - static let settingsSegue = "ShowSettingsViewController" + static let settingsSegue = "ShowSettingsViewController" + static let storeStatsSegue = "StoreStatsEmbedSeque" } } diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift index be425dffb56..655c0df8dd8 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift @@ -1,6 +1,7 @@ import UIKit import Yosemite import XLPagerTabStrip +import WordPressShared import CocoaLumberjack @@ -17,16 +18,30 @@ class PeriodDataViewController: UIViewController, IndicatorInfoProvider { @IBOutlet private weak var lastUpdated: UILabel! @IBOutlet private weak var chartView: UIView! @IBOutlet private weak var borderView: UIView! + private var lastUpdatedDate: Date? public let granularity: StatGranularity public var orderStats: OrderStats? { didSet { reloadOrderFields() + reloadLastUpdatedField() } } public var siteStats: SiteVisitStats? { didSet { reloadSiteFields() + reloadLastUpdatedField() + } + } + + // MARK: - Computed Properties + + private var summaryDateUpdated: String { + if let lastUpdatedDate = lastUpdatedDate { + return String.localizedStringWithFormat(NSLocalizedString("Updated %@.", + comment: "Stats summary date"), lastUpdatedDate.mediumString()) + } else { + return "" } } @@ -51,6 +66,11 @@ class PeriodDataViewController: UIViewController, IndicatorInfoProvider { super.viewDidLoad() configureView() } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + reloadLastUpdatedField() + } } @@ -99,11 +119,22 @@ private extension PeriodDataViewController { private extension PeriodDataViewController { func reloadOrderFields() { - // TODO: Refresh order stat fields + // FIXME: This is really just WIP code which puts data in the fields. Refactor please. + let totalOrders = orderStats?.totalOrders ?? 0 + if ordersData != nil { ordersData.text = String(totalOrders) } + let totalRevenue = orderStats?.totalGrossSales ?? 0 + if revenueData != nil { revenueData.text = "$\(totalRevenue)" } + lastUpdatedDate = Date() } func reloadSiteFields() { - // TODO: Refresh site stat fields + // FIXME: This is really just WIP code which puts data in the fields. Refactor please. + let totalVisitors = siteStats?.totalVisitors ?? 0 + if visitorsData != nil { visitorsData.text = String(totalVisitors) } + lastUpdatedDate = Date() } + func reloadLastUpdatedField() { + if lastUpdated != nil { lastUpdated.text = summaryDateUpdated } + } } diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.xib b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.xib index 2e4dcd8ca15..e2d4eaaa829 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.xib +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.xib @@ -25,11 +25,11 @@ - + - + @@ -168,14 +168,14 @@ - + - -