Bug 1440504 - Basic Payment Request Contact/Payer Add/Edit page (wip)
MozReview-Commit-ID: 8JK10dBimf2
new file mode 100644
--- /dev/null
+++ b/toolkit/components/payments/res/containers/address-form.js
@@ -0,0 +1,162 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* import-globals-from ../../../../../browser/extensions/formautofill/content/autofillEditForms.js*/
+/* import-globals-from ../mixins/PaymentStateSubscriberMixin.js */
+/* import-globals-from ../unprivileged-fallbacks.js */
+/* import-globals-from ../paymentRequest.js */
+
+"use strict";
+
+/**
+ * <address-form></address-form>
+ *
+ * XXX: Bug 1446164 - This form isn't localized when used via this custom element
+ * as it will be much easier to share the logic once we switch to Fluent.
+ */
+
+class AddressForm extends PaymentStateSubscriberMixin(HTMLElement) {
+ constructor() {
+ super();
+
+ this.genericErrorText = document.createElement("div");
+
+ this.backButton = document.createElement("button");
+ this.backButton.addEventListener("click", this);
+
+ this.saveButton = document.createElement("button");
+ this.saveButton.addEventListener("click", this);
+
+ // The markup is shared with form autofill preferences.
+ let url = "formautofill/editAddress.xhtml";
+ this.promiseReady = this._fetchMarkup(url).then(doc => {
+ this.form = doc.getElementById("form");
+ return this.form;
+ });
+ }
+
+ _fetchMarkup(url) {
+ return new Promise((resolve, reject) => {
+ let xhr = new XMLHttpRequest();
+ xhr.responseType = "document";
+ xhr.addEventListener("error", reject);
+ xhr.addEventListener("load", evt => {
+ resolve(xhr.response);
+ });
+ xhr.open("GET", url);
+ xhr.send();
+ });
+ }
+
+ connectedCallback() {
+ this.promiseReady.then(form => {
+ this.appendChild(form);
+
+ let record = {};
+ this.formHandler = new EditAddress({
+ form,
+ }, record, {
+ DEFAULT_REGION: ["US"],
+ supportedCountries: ["US", "CA"],
+ });
+
+ this.appendChild(this.genericErrorText);
+ this.appendChild(this.backButton);
+ this.appendChild(this.saveButton);
+ // Only call the connected super callback(s) once our markup is fully
+ // connected, including the shared form fetched asynchronously.
+ super.connectedCallback();
+ });
+ }
+
+ render(state) {
+ this.backButton.textContent = this.dataset.backButtonLabel;
+ this.saveButton.textContent = this.dataset.saveButtonLabel;
+
+ let record = {};
+ let {
+ page,
+ savedAddresses,
+ } = state;
+
+ this.genericErrorText.textContent = page.error;
+
+ let editing = !!page.guid;
+
+ // If a card is selected we want to edit it.
+ if (editing) {
+ record = savedAddresses[page.guid];
+ if (!record) {
+ throw new Error("Trying to edit a non-existing address: " + page.guid);
+ }
+ }
+
+ this.formHandler.loadRecord(record);
+ }
+
+ handleEvent(event) {
+ switch (event.type) {
+ case "click": {
+ this.onClick(event);
+ break;
+ }
+ }
+ }
+
+ onClick(evt) {
+ switch (evt.target) {
+ case this.backButton: {
+ this.requestStore.setState({
+ page: {
+ id: "payment-summary",
+ },
+ });
+ break;
+ }
+ case this.saveButton: {
+ this.saveRecord();
+ break;
+ }
+ default: {
+ throw new Error("Unexpected click target");
+ }
+ }
+ }
+
+ saveRecord() {
+ let record = this.formHandler.buildFormObject();
+ let {
+ page,
+ } = this.requestStore.getState();
+
+
+ for (let editableFieldName of ["cc-name", "cc-exp-month", "cc-exp-year"]) {
+ record[editableFieldName] = record[editableFieldName] || "";
+ }
+
+ // Only save the card number if we're saving a new record, otherwise we'd
+ // overwrite the unmasked card number with the masked one.
+ if (!page.guid) {
+ record["cc-number"] = record["cc-number"] || "";
+ }
+
+ paymentRequest.updateAutofillRecord("creditCards", record, page.guid, {
+ errorStateChange: {
+ page: {
+ id: "basic-card-page",
+ error: this.dataset.errorGenericSave,
+ },
+ },
+ preserveOldProperties: true,
+ selectedStateKey: "selectedPaymentCard",
+ successStateChange: {
+ page: {
+ id: "payment-summary",
+ },
+ },
+ });
+ }
+}
+
+customElements.define("address-form", AddressForm);
--- a/toolkit/components/payments/res/paymentRequest.xhtml
+++ b/toolkit/components/payments/res/paymentRequest.xhtml
@@ -23,16 +23,19 @@
<!ENTITY failPaymentButton.label "Fail">
<!ENTITY unknownPaymentButton.label "Unknown">
<!ENTITY orderDetailsLabel "Order Details">
<!ENTITY orderTotalLabel "Total">
<!ENTITY useSameAsShipping.label "Use shipping address as payment address">
<!ENTITY basicCardPage.error.genericSave "There was an error saving the payment card.">
<!ENTITY basicCardPage.backButton.label "Back">
<!ENTITY basicCardPage.saveButton.label "Save">
+ <!ENTITY addressPage.error.genericSave "There was an error saving the contact information.">
+ <!ENTITY addressPage.backButton.label "Back">
+ <!ENTITY addressPage.saveButton.label "Save">
]>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>&paymentSummaryTitle;</title>
<!-- chrome: is needed for global.dtd -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self' chrome:"/>
@@ -62,16 +65,17 @@
<script src="components/rich-option.js"></script>
<script src="components/address-option.js"></script>
<script src="components/shipping-option.js"></script>
<script src="containers/address-picker.js"></script>
<script src="components/basic-card-option.js"></script>
<script src="containers/shipping-option-picker.js"></script>
<script src="containers/payment-method-picker.js"></script>
<script src="containers/basic-card-form.js"></script>
+ <script src="containers/address-form.js"></script>
<script src="containers/payment-dialog.js"></script>
<script src="paymentRequest.js"></script>
<template id="payment-dialog-template">
<header>
<div id="total">
<h2 class="label"></h2>
@@ -133,16 +137,23 @@
</section>
<basic-card-form id="basic-card-page"
class="page"
data-error-generic-save="&basicCardPage.error.genericSave;"
data-back-button-label="&basicCardPage.backButton.label;"
data-save-button-label="&basicCardPage.saveButton.label;"
hidden="hidden"></basic-card-form>
+
+ <address-form id="address-form"
+ class="page"
+ data-error-generic-save="&addressPage.error.genericSave;"
+ data-back-button-label="&addressPage.backButton.label;"
+ data-save-button-label="&addressPage.saveButton.label;"
+ hidden="hidden"></address-form>
</div>
<div id="disabled-overlay" hidden="hidden">
<!-- overlay to prevent changes while waiting for a response from the merchant -->
</div>
</template>
<template id="order-details-template">