Skip to content

Commit fbfe870

Browse files
authored
Merge pull request #721 from woocommerce/issue/250-tracking-ui
Shipment Tracking Mark 4: UI
2 parents ccf9aad + 16ca782 commit fbfe870

File tree

11 files changed

+613
-10
lines changed

11 files changed

+613
-10
lines changed

RELEASE-NOTES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
1.4
22
-----
3+
- improvement: Add shipment tracking to Order Details screen
34
- improvement: The store switcher now allows you to go back to the previous screen without logging you out
45
- improvement: Custom order status labels are now supported! Instead of just displaying the order status slug and capitalizing the slug, the custom order status label will now be fetched from the server and properly displayed.
56
- improvement: Filtering by custom order status now supported!

WooCommerce/Classes/Analytics/WooAnalyticsStat.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ public enum WooAnalyticsStat: String {
138138
case orderDetailCustomerPhoneOptionTapped = "order_detail_customer_info_phone_menu_phone_tapped"
139139
case orderDetailCustomerSMSOptionTapped = "order_detail_customer_info_phone_menu_sms_tapped"
140140
case orderDetailProductDetailTapped = "order_detail_product_detail_button_tapped"
141+
case orderDetailTrackPackageButtonTapped = "order_detail_track_package_button_tapped"
141142
case orderFulfillmentCompleteButtonTapped = "order_fulfillment_mark_order_complete_button_tapped"
142143
case orderMarkedCompleteUndoButtonTapped = "snack_order_marked_complete_undo_button_tapped"
143144
case orderShareStoreButtonTapped = "orders_list_share_your_store_button_tapped"
@@ -156,6 +157,7 @@ public enum WooAnalyticsStat: String {
156157
case orderStatusChangeSuccess = "order_status_change_success"
157158
case orderStatusChangeFailed = "order_status_change_failed"
158159
case orderStatusChangeUndo = "order_status_change_undo"
160+
case orderTrackingLoaded = "order_tracking_loaded"
159161

160162
// Push Notifications Events
161163
//

WooCommerce/Classes/Extensions/String+Woo.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,16 @@ extension String {
1717
return " "
1818
}
1919
}
20+
21+
22+
/// String: URL manipulation
23+
///
24+
extension String {
25+
func addHTTPSSchemeIfNecessary() -> String {
26+
if self.hasPrefix("http://") || self.hasPrefix("https://") {
27+
return self
28+
}
29+
30+
return "https://\(self)"
31+
}
32+
}

WooCommerce/Classes/Extensions/UIButton+Helpers.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ extension UIButton {
1717
titleLabel?.applyHeadlineStyle()
1818
}
1919

20-
/// Applies the Primary Button Style: Clear BG / Bordered Outline
20+
/// Applies the Secondary Button Style: Clear BG / Bordered Outline
2121
///
2222
func applySecondaryButtonStyle() {
2323
backgroundColor = .clear
@@ -28,6 +28,17 @@ extension UIButton {
2828
layer.cornerRadius = Style.defaultCornerRadius
2929
titleLabel?.applyHeadlineStyle()
3030
}
31+
32+
/// Applies the Terciary Button Style: Clear BG / Top Outline
33+
///
34+
func applyTertiaryButtonStyle() {
35+
backgroundColor = .clear
36+
contentEdgeInsets = Style.noMarginEdgeInsets
37+
tintColor = StyleManager.wooCommerceBrandColor
38+
layer.borderColor = StyleManager.wooCommerceBrandColor.cgColor
39+
titleLabel?.applySubheadlineStyle()
40+
titleLabel?.textAlignment = .natural
41+
}
3142
}
3243

3344

@@ -39,5 +50,6 @@ private extension UIButton {
3950
static let defaultCornerRadius = CGFloat(8.0)
4051
static let defaultBorderWidth = CGFloat(1.0)
4152
static let defaultEdgeInsets = UIEdgeInsets(top: 12, left: 22, bottom: 12, right: 22)
53+
static let noMarginEdgeInsets = UIEdgeInsets(top: 12, left: 0, bottom: 12, right: 0)
4254
}
4355
}

WooCommerce/Classes/ViewModels/OrderDetailsViewModel.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class OrderDetailsViewModel {
4242

4343
let fulfillTitle = NSLocalizedString("Fulfill order", comment: "Fulfill order button title")
4444

45+
let trackTitle = NSLocalizedString("Track package", comment: "Track package button title")
46+
4547
var isProcessingPayment: Bool {
4648
return order.statusKey == OrderStatusEnum.processing.rawValue
4749
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import UIKit
2+
3+
/// Displays shipment tracking information associated to an Order.
4+
///
5+
final class OrderTrackingTableViewCell: UITableViewCell {
6+
@IBOutlet private var topLine: UILabel!
7+
@IBOutlet private var middleLine: UILabel!
8+
@IBOutlet private var bottomLine: UILabel!
9+
@IBOutlet private var topBorder: UIView!
10+
@IBOutlet private var actionButton: UIButton!
11+
@IBOutlet private var internalSeparator: UIView!
12+
13+
var onActionTouchUp: (() -> Void)?
14+
15+
var topText: String? {
16+
get {
17+
return topLine.text
18+
}
19+
set {
20+
topLine.text = newValue
21+
configureTopLineForVoiceOver()
22+
}
23+
}
24+
25+
var middleText: String? {
26+
get {
27+
return middleLine.text
28+
}
29+
set {
30+
middleLine.text = newValue
31+
configureMiddleLineForVoiceOver()
32+
}
33+
}
34+
35+
var bottomText: String? {
36+
get {
37+
return bottomLine.text
38+
}
39+
set {
40+
bottomLine.text = newValue
41+
configureBottonLineForVoiceOver()
42+
}
43+
}
44+
45+
var actionButtonNormalText: String? {
46+
get {
47+
return actionButton.title(for: .normal)
48+
}
49+
set {
50+
actionButton.setTitle(newValue, for: .normal)
51+
configureActionButtonForVoiceOver()
52+
}
53+
}
54+
55+
func showActionButton() {
56+
actionButton.isHidden = false
57+
internalSeparator.isHidden = false
58+
}
59+
60+
func hideActionButton() {
61+
actionButton.isHidden = true
62+
internalSeparator.isHidden = true
63+
}
64+
65+
override func awakeFromNib() {
66+
super.awakeFromNib()
67+
configureButtonSeparator()
68+
configureTopLine()
69+
configureMiddleLine()
70+
configureBottomLine()
71+
configureActionButton()
72+
}
73+
74+
private func configureButtonSeparator() {
75+
topBorder.backgroundColor = StyleManager.wooGreyBorder
76+
}
77+
78+
private func configureTopLine() {
79+
topLine.applySubheadlineStyle()
80+
}
81+
82+
private func configureMiddleLine() {
83+
middleLine.applyHeadlineStyle()
84+
}
85+
86+
private func configureBottomLine() {
87+
bottomLine.applySubheadlineStyle()
88+
}
89+
90+
private func configureActionButton() {
91+
actionButton.applyTertiaryButtonStyle()
92+
configureActionButtonForVoiceOver()
93+
}
94+
}
95+
96+
extension OrderTrackingTableViewCell {
97+
@IBAction func actionButtonPressed(_ sender: Any) {
98+
onActionTouchUp?()
99+
}
100+
}
101+
102+
/// MARK: - Accessibility
103+
///
104+
private extension OrderTrackingTableViewCell {
105+
func configureTopLineForVoiceOver() {
106+
topLine.accessibilityLabel = String.localizedStringWithFormat(
107+
NSLocalizedString("Shipment Company %@",
108+
comment: "Accessibility label for Shipment tracking company in Order details screen." +
109+
" Reads like: Shipment Company USPS"),
110+
topText ?? "")
111+
}
112+
113+
func configureMiddleLineForVoiceOver() {
114+
middleLine.accessibilityLabel = String.localizedStringWithFormat(
115+
NSLocalizedString("Tracking number %@",
116+
comment: "Accessibility label for Shipment tracking number in Order details screen. Reads like: Tracking Number 1AZ234567890"),
117+
middleText ?? "")
118+
}
119+
120+
func configureBottonLineForVoiceOver() {
121+
bottomLine.accessibilityLabel = String.localizedStringWithFormat(
122+
NSLocalizedString("Shipped %@",
123+
comment: "Accessibility label for Shipment date in Order details screen. Shipped: February 27, 2018."),
124+
bottomText ?? "")
125+
}
126+
127+
func configureActionButtonForVoiceOver() {
128+
actionButton.accessibilityLabel = actionButtonNormalText
129+
actionButton.accessibilityTraits = .button
130+
actionButton.accessibilityHint = NSLocalizedString("Tracks a shipment.",
131+
comment:
132+
"Accessibility hint for Track Package button in Order details screen")
133+
}
134+
}
135+
136+
/// MARK: - Expose private outlets for tests
137+
///
138+
extension OrderTrackingTableViewCell {
139+
func getTopLabel() -> UILabel {
140+
return topLine
141+
}
142+
143+
func getMiddleLabel() -> UILabel {
144+
return middleLine
145+
}
146+
147+
func getBottomLabel() -> UILabel {
148+
return bottomLine
149+
}
150+
151+
func getActionButton() -> UIButton {
152+
return actionButton
153+
}
154+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
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">
3+
<device id="retina4_7" orientation="portrait">
4+
<adaptation id="fullscreen"/>
5+
</device>
6+
<dependencies>
7+
<deployment identifier="iOS"/>
8+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
9+
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
10+
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
11+
</dependencies>
12+
<objects>
13+
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
14+
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
15+
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="OrderTrackingTableViewCell" rowHeight="188" id="KGk-i7-Jjw" customClass="OrderTrackingTableViewCell" customModule="WooCommerce" customModuleProvider="target">
16+
<rect key="frame" x="0.0" y="0.0" width="331" height="150"/>
17+
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
18+
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
19+
<rect key="frame" x="0.0" y="0.0" width="331" height="149.5"/>
20+
<autoresizingMask key="autoresizingMask"/>
21+
<subviews>
22+
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="nKR-kp-PKq">
23+
<rect key="frame" x="16" y="8" width="299" height="141.5"/>
24+
<subviews>
25+
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="MBb-Vp-3eh">
26+
<rect key="frame" x="0.0" y="0.0" width="299" height="69.5"/>
27+
<subviews>
28+
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kb4-pd-pEb">
29+
<rect key="frame" x="0.0" y="0.0" width="299" height="20.5"/>
30+
<fontDescription key="fontDescription" type="system" pointSize="17"/>
31+
<nil key="textColor"/>
32+
<nil key="highlightedColor"/>
33+
</label>
34+
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5Tp-fv-Tte">
35+
<rect key="frame" x="0.0" y="24.5" width="299" height="20.5"/>
36+
<fontDescription key="fontDescription" type="system" pointSize="17"/>
37+
<nil key="textColor"/>
38+
<nil key="highlightedColor"/>
39+
</label>
40+
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QPn-Oj-khc">
41+
<rect key="frame" x="0.0" y="49" width="299" height="20.5"/>
42+
<fontDescription key="fontDescription" type="system" pointSize="17"/>
43+
<nil key="textColor"/>
44+
<nil key="highlightedColor"/>
45+
</label>
46+
</subviews>
47+
</stackView>
48+
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="SIM-Wl-ZSt">
49+
<rect key="frame" x="0.0" y="77.5" width="299" height="64"/>
50+
<subviews>
51+
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Mav-Sc-Nqa">
52+
<rect key="frame" x="0.0" y="0.0" width="299" height="1"/>
53+
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
54+
<constraints>
55+
<constraint firstAttribute="height" constant="1" id="Pfr-XS-Lqh"/>
56+
</constraints>
57+
</view>
58+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="leading" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="q04-tu-Hwj">
59+
<rect key="frame" x="0.0" y="1" width="299" height="63"/>
60+
<state key="normal" title="Button"/>
61+
<connections>
62+
<action selector="actionButtonPressed:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="vJf-Pe-OWy"/>
63+
</connections>
64+
</button>
65+
</subviews>
66+
</stackView>
67+
</subviews>
68+
</stackView>
69+
</subviews>
70+
<constraints>
71+
<constraint firstAttribute="bottom" secondItem="nKR-kp-PKq" secondAttribute="bottom" id="OVJ-2E-eJY"/>
72+
<constraint firstItem="nKR-kp-PKq" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" id="Tkb-Wi-nOp"/>
73+
<constraint firstItem="nKR-kp-PKq" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="8" id="cF4-8H-16y"/>
74+
<constraint firstAttribute="trailingMargin" secondItem="nKR-kp-PKq" secondAttribute="trailing" id="fA5-E1-lrn"/>
75+
</constraints>
76+
</tableViewCellContentView>
77+
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
78+
<connections>
79+
<outlet property="actionButton" destination="q04-tu-Hwj" id="yfI-P3-JyX"/>
80+
<outlet property="bottomLine" destination="QPn-Oj-khc" id="TQ5-DT-vlI"/>
81+
<outlet property="internalSeparator" destination="Mav-Sc-Nqa" id="Tu8-Dw-dRl"/>
82+
<outlet property="middleLine" destination="5Tp-fv-Tte" id="0Kp-r9-HEk"/>
83+
<outlet property="topBorder" destination="Mav-Sc-Nqa" id="fen-Nr-OeV"/>
84+
<outlet property="topLine" destination="kb4-pd-pEb" id="eC2-Xc-JAH"/>
85+
</connections>
86+
<point key="canvasLocation" x="39.200000000000003" y="125.93703148425789"/>
87+
</tableViewCell>
88+
</objects>
89+
</document>

0 commit comments

Comments
 (0)