Skip to content

Commit 2e3d54d

Browse files
authored
Merge pull request #742 from woocommerce/issue/121-manual-status-change
Order status Mark IV: manual status change
2 parents fbfe870 + e3f9712 commit 2e3d54d

File tree

12 files changed

+641
-4
lines changed

12 files changed

+641
-4
lines changed

WooCommerce/Classes/Analytics/WooAnalyticsStat.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,13 @@ public enum WooAnalyticsStat: String {
137137
case orderDetailCustomerPhoneMenuTapped = "order_detail_customer_info_phone_menu_tapped"
138138
case orderDetailCustomerPhoneOptionTapped = "order_detail_customer_info_phone_menu_phone_tapped"
139139
case orderDetailCustomerSMSOptionTapped = "order_detail_customer_info_phone_menu_sms_tapped"
140+
case orderDetailOrderStatusEditButtonTapped = "order_detail_order_status_edit_button_tapped"
140141
case orderDetailProductDetailTapped = "order_detail_product_detail_button_tapped"
141142
case orderDetailTrackPackageButtonTapped = "order_detail_track_package_button_tapped"
142143
case orderFulfillmentCompleteButtonTapped = "order_fulfillment_mark_order_complete_button_tapped"
143144
case orderMarkedCompleteUndoButtonTapped = "snack_order_marked_complete_undo_button_tapped"
144145
case orderShareStoreButtonTapped = "orders_list_share_your_store_button_tapped"
146+
case orderStatusDialogApplyButtonTapped = "set_order_status_dialog_apply_button_tapped"
145147

146148
// Order Data/Action Events
147149
//

WooCommerce/Classes/Extensions/UIImage+Woo.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ extension UIImage {
3434
return UIImage(named: "gravatar")!
3535
}
3636

37+
/// Pencil Icon
38+
///
39+
static var pencilImage: UIImage {
40+
let tintColor = StyleManager.wooCommerceBrandColor
41+
return Gridicon.iconOfType(.pencil)
42+
.imageWithTintColor(tintColor)!
43+
.imageFlippedForRightToLeftLayoutDirection()
44+
}
45+
3746
/// Jetpack Logo Image
3847
///
3948
static var jetpackLogoImage: UIImage {

WooCommerce/Classes/ViewRelated/Orders/Cells/SummaryTableViewCell.swift

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import UIKit
22
import Yosemite
3+
import Gridicons
34

45

56
// MARK: - SummaryTableViewCell
67
//
7-
class SummaryTableViewCell: UITableViewCell {
8+
final class SummaryTableViewCell: UITableViewCell {
89

910
/// Label: Title
1011
///
@@ -18,6 +19,10 @@ class SummaryTableViewCell: UITableViewCell {
1819
///
1920
@IBOutlet private weak var paymentStatusLabel: PaddedLabel!
2021

22+
/// Button: Manually Update Order Status
23+
///
24+
@IBOutlet private var updateStatusButton: UIButton!
25+
2126
/// Title
2227
///
2328
var title: String? {
@@ -40,6 +45,10 @@ class SummaryTableViewCell: UITableViewCell {
4045
}
4146
}
4247

48+
/// Closure to be executed whenever the edit button is tapped.
49+
///
50+
var onEditTouchUp: (() -> Void)?
51+
4352
/// Displays the specified OrderStatus, and applies the right Label Style
4453
///
4554
func display(orderStatus: OrderStatus) {
@@ -53,6 +62,7 @@ class SummaryTableViewCell: UITableViewCell {
5362
override func awakeFromNib() {
5463
super.awakeFromNib()
5564
configureLabels()
65+
configureIcon()
5666
}
5767

5868
override func setSelected(_ selected: Bool, animated: Bool) {
@@ -97,4 +107,49 @@ private extension SummaryTableViewCell {
97107
createdLabel.applyFootnoteStyle()
98108
paymentStatusLabel.applyPaddedLabelDefaultStyles()
99109
}
110+
111+
func configureIcon() {
112+
updateStatusButton.setImage(.pencilImage, for: .normal)
113+
114+
updateStatusButton.addTarget(self, action: #selector(editWasTapped), for: .touchUpInside)
115+
116+
configureIconForVoiceOver()
117+
}
118+
119+
@objc func editWasTapped() {
120+
onEditTouchUp?()
121+
}
122+
}
123+
124+
125+
/// MARK: - VoiceOver
126+
///
127+
private extension SummaryTableViewCell {
128+
func configureIconForVoiceOver() {
129+
updateStatusButton.accessibilityLabel = NSLocalizedString("Update Order Status",
130+
comment: "Accessibility label for the button to update the order status in Order Details")
131+
updateStatusButton.accessibilityTraits = .button
132+
updateStatusButton.accessibilityHint = NSLocalizedString("Opens a list of available statuses.",
133+
comment: "Accessibility hint for the button to update the order status")
134+
}
135+
}
136+
137+
138+
/// MARK: - Testability
139+
extension SummaryTableViewCell {
140+
func getTitle() -> UILabel {
141+
return titleLabel
142+
}
143+
144+
func getCreatedLabel() -> UILabel {
145+
return createdLabel
146+
}
147+
148+
func getStatusLabel() -> UILabel {
149+
return paymentStatusLabel
150+
}
151+
152+
func getEditButton() -> UIButton {
153+
return updateStatusButton
154+
}
100155
}

WooCommerce/Classes/ViewRelated/Orders/Cells/SummaryTableViewCell.xib

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
33
<device id="retina4_7" orientation="portrait">
44
<adaptation id="fullscreen"/>
55
</device>
66
<dependencies>
77
<deployment identifier="iOS"/>
8-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
8+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
99
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
1010
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
1111
</dependencies>
@@ -37,15 +37,25 @@
3737
<nil key="textColor"/>
3838
<nil key="highlightedColor"/>
3939
</label>
40+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0jq-dU-DSt">
41+
<rect key="frame" x="284" y="73" width="20" height="20"/>
42+
<constraints>
43+
<constraint firstAttribute="width" secondItem="0jq-dU-DSt" secondAttribute="height" multiplier="1:1" id="JlF-NG-SGG"/>
44+
<constraint firstAttribute="width" constant="20" id="weV-me-Oj4"/>
45+
</constraints>
46+
<state key="normal" title="Button"/>
47+
</button>
4048
</subviews>
4149
<constraints>
50+
<constraint firstItem="0jq-dU-DSt" firstAttribute="centerY" secondItem="uIV-Sn-Yeh" secondAttribute="centerY" id="0cI-jv-Lbj"/>
4251
<constraint firstItem="Kz9-1h-fRY" firstAttribute="leading" secondItem="VuR-wG-Bbc" secondAttribute="leading" id="0iO-Eg-LvT"/>
4352
<constraint firstAttribute="bottomMargin" secondItem="uIV-Sn-Yeh" secondAttribute="bottom" constant="5" id="3OU-Nl-wcg"/>
4453
<constraint firstItem="Kz9-1h-fRY" firstAttribute="top" secondItem="VuR-wG-Bbc" secondAttribute="bottom" constant="8" id="4yW-xe-vMw"/>
4554
<constraint firstItem="VuR-wG-Bbc" firstAttribute="trailing" secondItem="H2p-sc-9uM" secondAttribute="trailingMargin" id="ALe-dT-Iae"/>
4655
<constraint firstItem="uIV-Sn-Yeh" firstAttribute="top" secondItem="Kz9-1h-fRY" secondAttribute="bottom" constant="8" id="B6Q-cI-ASJ"/>
4756
<constraint firstItem="Kz9-1h-fRY" firstAttribute="trailing" secondItem="VuR-wG-Bbc" secondAttribute="trailing" id="H8X-uc-vIl"/>
4857
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="uIV-Sn-Yeh" secondAttribute="trailing" constant="16" id="Iv2-nI-HgU"/>
58+
<constraint firstItem="0jq-dU-DSt" firstAttribute="trailing" secondItem="VuR-wG-Bbc" secondAttribute="trailing" id="Yrn-9W-9Dw"/>
4959
<constraint firstItem="uIV-Sn-Yeh" firstAttribute="leading" secondItem="VuR-wG-Bbc" secondAttribute="leading" id="h9K-qI-gKu"/>
5060
<constraint firstItem="VuR-wG-Bbc" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" id="mSL-pS-fig"/>
5161
<constraint firstItem="VuR-wG-Bbc" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" constant="5" id="oDH-pY-Emj"/>
@@ -56,6 +66,7 @@
5666
<outlet property="createdLabel" destination="Kz9-1h-fRY" id="lxU-eQ-lCc"/>
5767
<outlet property="paymentStatusLabel" destination="uIV-Sn-Yeh" id="7Go-fW-UgK"/>
5868
<outlet property="titleLabel" destination="VuR-wG-Bbc" id="d7c-2Y-FFD"/>
69+
<outlet property="updateStatusButton" destination="0jq-dU-DSt" id="f15-0P-cBB"/>
5970
</connections>
6071
<point key="canvasLocation" x="71" y="123"/>
6172
</tableViewCell>

WooCommerce/Classes/ViewRelated/Orders/OrderDetailsViewController.swift

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ class OrderDetailsViewController: UIViewController {
4747
return EntityListener(storageManager: AppDelegate.shared.storageManager, readOnlyEntity: viewModel.order)
4848
}()
4949

50+
/// ResultsController: Surrounds us. Binds the galaxy together. And also, keeps the UITableView <> (Stored) OrderStatuses in sync.
51+
///
52+
private lazy var statusResultsController: ResultsController<StorageOrderStatus> = {
53+
let storageManager = AppDelegate.shared.storageManager
54+
let predicate = NSPredicate(format: "siteID == %lld", StoresManager.shared.sessionManager.defaultStoreID ?? Int.min)
55+
let descriptor = NSSortDescriptor(key: "slug", ascending: true)
56+
57+
return ResultsController<StorageOrderStatus>(storageManager: storageManager, matching: predicate, sortedBy: [descriptor])
58+
}()
59+
5060
/// Sections to be rendered
5161
///
5262
private var sections = [Section]()
@@ -73,6 +83,12 @@ class OrderDetailsViewController: UIViewController {
7383
return trackingResultsController.fetchedObjects
7484
}
7585

86+
/// Order statuses list
87+
///
88+
private var currentSiteStatuses: [OrderStatus] {
89+
return statusResultsController.fetchedObjects
90+
}
91+
7692
/// Haptic Feedback!
7793
///
7894
private let hapticGenerator = UINotificationFeedbackGenerator()
@@ -87,6 +103,7 @@ class OrderDetailsViewController: UIViewController {
87103
registerTableViewCells()
88104
registerTableViewHeaderFooters()
89105
configureEntityListener()
106+
configureResultsController()
90107
configureTrackingResultsController()
91108
}
92109

@@ -132,7 +149,8 @@ private extension OrderDetailsViewController {
132149
return
133150
}
134151

135-
self.viewModel = OrderDetailsViewModel(order: order)
152+
let orderStatus = self.lookUpOrderStatus(for: order)
153+
self.viewModel = OrderDetailsViewModel(order: order, orderStatus: orderStatus)
136154
}
137155

138156
entityListener.onDelete = { [weak self] in
@@ -147,6 +165,10 @@ private extension OrderDetailsViewController {
147165

148166
/// Setup: Results Controller
149167
///
168+
private func configureResultsController() {
169+
try? statusResultsController.performFetch()
170+
}
171+
150172
func configureTrackingResultsController() {
151173
trackingResultsController.onDidChangeContent = { [weak self] in
152174
self?.reloadTableViewSectionsAndData()
@@ -575,6 +597,9 @@ private extension OrderDetailsViewController {
575597
func configureSummary(cell: SummaryTableViewCell) {
576598
cell.title = viewModel.summaryTitle
577599
cell.dateCreated = viewModel.summaryDateCreated
600+
cell.onEditTouchUp = { [weak self] in
601+
self?.displayOrderStatusList()
602+
}
578603

579604
if let orderStatus = viewModel.orderStatus {
580605
cell.display(orderStatus: orderStatus)
@@ -635,6 +660,14 @@ private extension OrderDetailsViewController {
635660

636661
StoresManager.shared.dispatch(action)
637662
}
663+
664+
func lookUpOrderStatus(for order: Order) -> OrderStatus? {
665+
for orderStatus in currentSiteStatuses where orderStatus.slug == order.statusKey {
666+
return orderStatus
667+
}
668+
669+
return nil
670+
}
638671
}
639672

640673

@@ -963,6 +996,20 @@ private extension OrderDetailsViewController {
963996
}
964997

965998

999+
// MARK: - Present Order Status List
1000+
//
1001+
private extension OrderDetailsViewController {
1002+
private func displayOrderStatusList() {
1003+
WooAnalytics.shared.track(.orderDetailOrderStatusEditButtonTapped,
1004+
withProperties: ["status": viewModel.order.statusKey])
1005+
let statusList = OrderStatusListViewController(order: viewModel.order)
1006+
let navigationController = UINavigationController(rootViewController: statusList)
1007+
1008+
present(navigationController, animated: true)
1009+
}
1010+
}
1011+
1012+
9661013
// MARK: - MFMessageComposeViewControllerDelegate Conformance
9671014
//
9681015
extension OrderDetailsViewController: MFMessageComposeViewControllerDelegate {
@@ -1041,6 +1088,7 @@ private extension OrderDetailsViewController {
10411088
static let rowHeight = CGFloat(38)
10421089
static let sectionHeight = CGFloat(44)
10431090
static let productDetailsSegue = "ShowProductListViewController"
1091+
static let orderStatusListSegue = "ShowOrderStatusListViewController"
10441092
}
10451093

10461094
enum Title {

0 commit comments

Comments
 (0)