Bug 1440499 - Add payerName/Email/Phone contact picker. r?MattN
* WIP, tests to ensure the paymentOptions values propagate to the picker underway
* Add a field-names attribute to address-picker options, populated from the request paymentOptions
* Initial/placeholder CSS to selectively render address fields
MozReview-Commit-ID: Br8i5MVyeQ3
--- a/toolkit/components/payments/res/components/address-option.css
+++ b/toolkit/components/payments/res/components/address-option.css
@@ -12,17 +12,17 @@ address-option {
rich-select[open] > .rich-select-popup-box > address-option {
grid-template-areas:
"name name "
"street-address street-address"
"email tel ";
}
-address-option[hide-address] {
+address-picker.payer-related address-option {
grid-template-areas:
"name name"
"tel email";
}
address-option > .name {
grid-area: name;
}
@@ -34,20 +34,28 @@ address-option > .street-address {
address-option > .email {
grid-area: email;
}
address-option > .tel {
grid-area: tel;
}
+/* Hide all the fields by default, and enable them explicitly for each format case */
address-option > .name,
address-option > .street-address,
address-option > .email,
address-option > .tel {
white-space: nowrap;
+ display: none;
}
-address-option[hide-address] > .street-address,
-.rich-select-selected-clone:not([hide-address]) > .email,
-.rich-select-selected-clone:not([hide-address]) > .tel {
- display: none;
+address-option:not([address-fields]) > .name,
+address-option:not([address-fields]) > .street-address {
+ display: inline-block;
}
+
+address-option[address-fields~='name'] > .name,
+address-option[address-fields~='email'] > .email,
+address-option[address-fields~='tel'] > .tel {
+ display: inline-block;
+}
+
--- a/toolkit/components/payments/res/components/address-option.js
+++ b/toolkit/components/payments/res/components/address-option.js
@@ -21,17 +21,17 @@
/* global ObservedPropertiesMixin, RichOption */
class AddressOption extends ObservedPropertiesMixin(RichOption) {
static get observedAttributes() {
return RichOption.observedAttributes.concat([
"address-level1",
"address-level2",
"country",
- "hide-address",
+ "address-fields",
"email",
"guid",
"name",
"postal-code",
"street-address",
"tel",
]);
}
--- a/toolkit/components/payments/res/containers/address-picker.js
+++ b/toolkit/components/payments/res/containers/address-picker.js
@@ -21,28 +21,51 @@ class AddressPicker extends PaymentState
connectedCallback() {
this.appendChild(this.dropdown);
super.connectedCallback();
}
render(state) {
let {savedAddresses} = state;
- let hideAddress = this.hasAttribute("hide-address"); // TODO
+ let payerRelated = this.classList.contains("payer-related");
+ let fieldNames = new Set(["name", "tel", "email"]);
+ let useFieldNames = false;
+
+ if (payerRelated) {
+ let paymentOptions = state.request.paymentOptions;
+ fieldNames.clear();
+ if (paymentOptions.requestPayerName) {
+ fieldNames.add("name");
+ }
+ if (paymentOptions.requestPayerEmail) {
+ fieldNames.add("email");
+ }
+ if (paymentOptions.requestPayerPhone) {
+ fieldNames.add("tel");
+ }
+ useFieldNames = !!fieldNames.size;
+ }
+
let desiredOptions = [];
for (let [guid, address] of Object.entries(savedAddresses)) {
let optionEl = this.dropdown.getOptionByValue(guid);
if (!optionEl) {
optionEl = document.createElement("address-option");
optionEl.value = guid;
}
+
for (let [key, val] of Object.entries(address)) {
optionEl.setAttribute(key, val);
}
- optionEl.hideAddress = hideAddress;
+ if (useFieldNames && fieldNames.size) {
+ optionEl.setAttribute("address-fields", [...fieldNames].join(" "));
+ } else {
+ optionEl.removeAttribute("address-fields");
+ }
desiredOptions.push(optionEl);
}
let el = null;
while ((el = this.dropdown.popupBox.querySelector(":scope > address-option"))) {
el.remove();
}
for (let option of desiredOptions) {
this.dropdown.popupBox.appendChild(option);
--- a/toolkit/components/payments/res/containers/payment-dialog.js
+++ b/toolkit/components/payments/res/containers/payment-dialog.js
@@ -29,16 +29,18 @@ class PaymentDialog extends PaymentState
this._viewAllButton = contents.querySelector("#view-all");
this._viewAllButton.addEventListener("click", this);
this._orderDetailsOverlay = contents.querySelector("#order-details-overlay");
this._shippingTypeLabel = contents.querySelector("#shipping-type-label");
this._shippingRelatedEls = contents.querySelectorAll(".shipping-related");
this._payerRelatedEls = contents.querySelectorAll(".payer-related");
+ this._payerAddressPicker = contents.querySelector("address-picker.payer-related");
+
this._errorText = contents.querySelector("#error-text");
this._disabledOverlay = contents.getElementById("disabled-overlay");
this.appendChild(contents);
super.connectedCallback();
}
@@ -156,17 +158,16 @@ class PaymentDialog extends PaymentState
// Ensure `selectedPayerAddress` never refers to a deleted address and refers
// to an address if one exists.
if (!savedAddresses[selectedPayerAddress]) {
this.requestStore.setState({
selectedPayerAddress: Object.keys(savedAddresses)[0] || null,
});
}
-
}
_renderPayButton(state) {
this._payButton.disabled = state.changesPrevented;
switch (state.completionState) {
case "initial":
case "processing":
break;
@@ -203,24 +204,29 @@ class PaymentDialog extends PaymentState
let totalItem = paymentDetails.totalItem;
let totalAmountEl = this.querySelector("#total > currency-amount");
totalAmountEl.value = totalItem.amount.value;
totalAmountEl.currency = totalItem.amount.currency;
this._orderDetailsOverlay.hidden = !state.orderDetailsShowing;
this._errorText.textContent = paymentDetails.error;
+
let paymentOptions = request.paymentOptions;
for (let element of this._shippingRelatedEls) {
element.hidden = !paymentOptions.requestShipping;
}
- let payerRequested = paymentOptions.requestPayerName || paymentOptions.requestPayerEmail || paymentOptions.requestPayerPhone;
+
+ let payerRequested = paymentOptions.requestPayerName ||
+ paymentOptions.requestPayerEmail ||
+ paymentOptions.requestPayerPhone;
for (let element of this._payerRelatedEls) {
element.hidden = !payerRequested;
}
+
let shippingType = paymentOptions.shippingType || "shipping";
this._shippingTypeLabel.querySelector("label").textContent =
this._shippingTypeLabel.dataset[shippingType + "AddressLabel"];
this._renderPayButton(state);
let {
changesPrevented,
--- a/toolkit/components/payments/res/paymentRequest.xhtml
+++ b/toolkit/components/payments/res/paymentRequest.xhtml
@@ -78,17 +78,16 @@
<address-picker class="shipping-related" selected-state-key="selectedShippingAddress"></address-picker>
<div class="shipping-related"><label>&shippingOptionsLabel;</label></div>
<shipping-option-picker class="shipping-related"></shipping-option-picker>
<div><label>&paymentMethodsLabel;</label></div>
<payment-method-picker selected-state-key="selectedPaymentCard"></payment-method-picker>
<div class="payer-related"><label>&payerLabel;</label></div>
<address-picker class="payer-related"
- hide-address=""
selected-state-key="selectedPayerAddress"></address-picker>
</section>
<footer id="controls-container">
<button id="cancel">&cancelPaymentButton.label;</button>
<button id="pay"
data-initial-label="&approvePaymentButton.label;"
data-processing-label="&processingPaymentButton.label;"></button>