mirror of
https://github.com/google/nomulus.git
synced 2025-07-25 12:08:36 +02:00
mv com/google/domain/registry google/registry
This change renames directories in preparation for the great package rename. The repository is now in a broken state because the code itself hasn't been updated. However this should ensure that git correctly preserves history for each file.
This commit is contained in:
parent
a41677aea1
commit
5012893c1d
2396 changed files with 0 additions and 0 deletions
31
java/google/registry/ui/js/registrar/BUILD
Normal file
31
java/google/registry/ui/js/registrar/BUILD
Normal file
|
@ -0,0 +1,31 @@
|
|||
package(default_visibility = ["//java/com/google/domain/registry:registry_project"])
|
||||
|
||||
load("//third_party/closure/compiler:closure_js_library.bzl", "closure_js_library")
|
||||
|
||||
|
||||
filegroup(
|
||||
name = "js_files",
|
||||
srcs = glob(["*.js"]),
|
||||
)
|
||||
|
||||
closure_js_library(
|
||||
name = "registrar",
|
||||
srcs = [":js_files"],
|
||||
deps = [
|
||||
"//java/com/google/domain/registry/ui/js",
|
||||
"//java/com/google/domain/registry/ui/soy:Forms",
|
||||
"//java/com/google/domain/registry/ui/soy/registrar:Console",
|
||||
"//java/com/google/domain/registry/ui/soy/registrar:Contact",
|
||||
"//java/com/google/domain/registry/ui/soy/registrar:ContactEpp",
|
||||
"//java/com/google/domain/registry/ui/soy/registrar:ContactSettings",
|
||||
"//java/com/google/domain/registry/ui/soy/registrar:Domain",
|
||||
"//java/com/google/domain/registry/ui/soy/registrar:DomainEpp",
|
||||
"//java/com/google/domain/registry/ui/soy/registrar:Epp",
|
||||
"//java/com/google/domain/registry/ui/soy/registrar:Host",
|
||||
"//java/com/google/domain/registry/ui/soy/registrar:HostEpp",
|
||||
"//java/com/google/domain/registry/ui/soy/registrar:Payment",
|
||||
"//java/com/google/domain/registry/ui/soy/registrar:SecuritySettings",
|
||||
"//java/com/google/domain/registry/ui/soy/registrar:WhoisSettings",
|
||||
"//javascript/closure",
|
||||
],
|
||||
)
|
265
java/google/registry/ui/js/registrar/brainframe.js
Normal file
265
java/google/registry/ui/js/registrar/brainframe.js
Normal file
|
@ -0,0 +1,265 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.BrainFrame');
|
||||
goog.provide('registry.registrar.BrainFrame.main');
|
||||
|
||||
goog.require('goog.Timer');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events.EventHandler');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.json');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.style');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sandboxed iframe for Braintree JS SDK v2 iframe.
|
||||
*
|
||||
* <p>This class adds an additional layer of security between the Registrar
|
||||
* Console and JavaScript loaded from Braintree's web server.
|
||||
*
|
||||
* <p>The main function for this class is compiled into a separate binary,
|
||||
* which is loaded within an iframe that's hosted on a different domain than
|
||||
* the production environment. This ensures that cross origin browser security
|
||||
* policies take effect.
|
||||
*
|
||||
* @param {string} origin FQDN of production environment.
|
||||
* @param {string} containerId ID of Braintree container element.
|
||||
* @constructor
|
||||
* @extends {goog.events.EventHandler}
|
||||
* @final
|
||||
*/
|
||||
registry.registrar.BrainFrame = function(origin, containerId) {
|
||||
registry.registrar.BrainFrame.base(this, 'constructor');
|
||||
|
||||
/**
|
||||
* Hostname of production registry, e.g. domain-registry.appspot.com.
|
||||
* @private {string}
|
||||
* @const
|
||||
*/
|
||||
this.origin_ = origin;
|
||||
|
||||
/**
|
||||
* Div that wraps Braintree iframe.
|
||||
* @private {!Element}
|
||||
* @const
|
||||
*/
|
||||
this.container_ = goog.dom.getRequiredElement(containerId);
|
||||
|
||||
/**
|
||||
* Last known height of {@code container_}.
|
||||
* @private {number}
|
||||
*/
|
||||
this.containerHeight_ = 0;
|
||||
|
||||
/**
|
||||
* Timer polling for changes in Braintree iframe height.
|
||||
* @private {!goog.Timer}
|
||||
* @const
|
||||
*/
|
||||
this.resizeTimer_ = new goog.Timer(1000 / 30);
|
||||
this.registerDisposable(this.resizeTimer_);
|
||||
this.listen(this.resizeTimer_, goog.Timer.TICK, this.onResizeTimer_);
|
||||
|
||||
/**
|
||||
* Form that wraps {@code container_}.
|
||||
* @private {?Element}
|
||||
* @const
|
||||
*/
|
||||
this.form_ = goog.dom.getAncestorByTagNameAndClass(this.container_,
|
||||
goog.dom.TagName.FORM);
|
||||
goog.asserts.assert(this.form_ != null);
|
||||
|
||||
/**
|
||||
* State indicating if we're submitting at behest of parent.
|
||||
* @private {boolean}
|
||||
*/
|
||||
this.isSubmitting_ = false;
|
||||
|
||||
this.listen(goog.global.window,
|
||||
goog.events.EventType.MESSAGE,
|
||||
this.onMessage_);
|
||||
};
|
||||
goog.inherits(registry.registrar.BrainFrame, goog.events.EventHandler);
|
||||
|
||||
|
||||
/**
|
||||
* Runs Braintree sandbox environment.
|
||||
*/
|
||||
registry.registrar.BrainFrame.prototype.run = function() {
|
||||
this.send_(
|
||||
'type', registry.registrar.BrainFrame.MessageType.TOKEN_REQUEST);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles message from parent iframe which sends Braintree token.
|
||||
* @param {!goog.events.BrowserEvent} e
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.BrainFrame.prototype.onMessage_ = function(e) {
|
||||
var msg = /** @type {!MessageEvent.<string>} */ (e.getBrowserEvent());
|
||||
if (msg.source != goog.global.window.parent) {
|
||||
return;
|
||||
}
|
||||
if (this.origin_ != '*' && this.origin_ != msg.origin) {
|
||||
throw new Error(
|
||||
'Message origin is "' + msg.origin + '" but wanted: ' + this.origin_);
|
||||
}
|
||||
var data = goog.json.parse(msg.data);
|
||||
switch (goog.object.get(data, 'type')) {
|
||||
case registry.registrar.BrainFrame.MessageType.TOKEN_RESPONSE:
|
||||
goog.global.braintree.setup(goog.object.get(data, 'token'), 'dropin', {
|
||||
container: this.container_,
|
||||
onPaymentMethodReceived: goog.bind(this.onPaymentMethod_, this),
|
||||
onReady: goog.bind(this.onReady_, this),
|
||||
onError: goog.bind(this.onError_, this)
|
||||
});
|
||||
this.resizeTimer_.start();
|
||||
break;
|
||||
case registry.registrar.BrainFrame.MessageType.SUBMIT_REQUEST:
|
||||
this.isSubmitting_ = true;
|
||||
// Trigger Braintree JS SDK submit event listener. It does not appear to
|
||||
// be possible to do this using the Closure Library. This is IE 9+ only.
|
||||
this.form_.dispatchEvent(new Event(goog.events.EventType.SUBMIT));
|
||||
break;
|
||||
default:
|
||||
throw Error('Unexpected message: ' + msg.data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Polls for resizes of Braintree iframe and propagates them to the parent
|
||||
* frame which will then use it to resize this iframe.
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.BrainFrame.prototype.onResizeTimer_ = function() {
|
||||
var height = goog.style.getSize(this.container_).height;
|
||||
if (height != this.containerHeight_) {
|
||||
this.send_(
|
||||
'type', registry.registrar.BrainFrame.MessageType.RESIZE_REQUEST,
|
||||
'height', height);
|
||||
this.containerHeight_ = height;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Callback Braintree iframe has fully loaded.
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.BrainFrame.prototype.onReady_ = function() {
|
||||
this.send_('type', registry.registrar.BrainFrame.MessageType.READY);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Callback Braintree says an error happened.
|
||||
* @param {!braintreepayments.Error} error
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.BrainFrame.prototype.onError_ = function(error) {
|
||||
this.isSubmitting_ = false;
|
||||
this.send_('type', registry.registrar.BrainFrame.MessageType.SUBMIT_ERROR,
|
||||
'message', error.message);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Callback when user successfully gave Braintree payment details.
|
||||
* @param {!braintreepayments.PaymentMethod} pm
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.BrainFrame.prototype.onPaymentMethod_ = function(pm) {
|
||||
// TODO(b/26829319): The Braintree JS SDK does not seem to recognize the
|
||||
// enter key while embedded inside our sandbox iframe. So
|
||||
// at this time, this callback will only be invoked after
|
||||
// we've submitted the form manually at the behest of
|
||||
// payment.js, which means isSubmitting_ will be true.
|
||||
this.send_(
|
||||
'type', registry.registrar.BrainFrame.MessageType.PAYMENT_METHOD,
|
||||
'submit', this.isSubmitting_,
|
||||
'method', pm);
|
||||
this.isSubmitting_ = false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sends message to parent iframe.
|
||||
* @param {...*} var_args Passed along to {@code goog.object.create}.
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.BrainFrame.prototype.send_ = function(var_args) {
|
||||
goog.asserts.assert(arguments[0] == 'type');
|
||||
registry.registrar.BrainFrame.postMessage_(
|
||||
goog.json.serialize(goog.object.create.apply(null, arguments)),
|
||||
this.origin_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Delegates to {@code window.parent.postMessage}. This method exists because
|
||||
* IE will not allow us to mock methods on the window object.
|
||||
* @param {string} message
|
||||
* @param {string} origin
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.BrainFrame.postMessage_ = function(message, origin) {
|
||||
goog.global.window.parent.postMessage(message, origin);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Message types passed between brainframe and payment page.
|
||||
* @enum {string}
|
||||
*/
|
||||
registry.registrar.BrainFrame.MessageType = {
|
||||
|
||||
/** Brainframe asks payment page for Braintree token. */
|
||||
TOKEN_REQUEST: 'token_request',
|
||||
|
||||
/** Payment page sends brainframe Braintree token. */
|
||||
TOKEN_RESPONSE: 'token_response',
|
||||
|
||||
/** Brainframe asks payment page to be resized. */
|
||||
RESIZE_REQUEST: 'resize_request',
|
||||
|
||||
/** Brainframe tells payment page it finished loading. */
|
||||
READY: 'ready',
|
||||
|
||||
/** Payment page asks brainframe to submit Braintree payment method form. */
|
||||
SUBMIT_REQUEST: 'submit_request',
|
||||
|
||||
/** Brainframe tells payment page it failed to submit. */
|
||||
SUBMIT_ERROR: 'submit_error',
|
||||
|
||||
/** Brainframe gives payment method info and nonce to payment page. */
|
||||
PAYMENT_METHOD: 'payment_method'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Entrypoint for {@link registry.registrar.BrainFrame}.
|
||||
* @param {string} origin
|
||||
* @param {string} containerId
|
||||
* @export
|
||||
*/
|
||||
registry.registrar.BrainFrame.main = function(origin, containerId) {
|
||||
new registry.registrar.BrainFrame(origin, containerId).run();
|
||||
};
|
167
java/google/registry/ui/js/registrar/console.js
Normal file
167
java/google/registry/ui/js/registrar/console.js
Normal file
|
@ -0,0 +1,167 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.Console');
|
||||
|
||||
goog.require('goog.dispose');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.classlist');
|
||||
goog.require('goog.net.XhrIo');
|
||||
goog.require('registry.Console');
|
||||
goog.require('registry.registrar.Contact');
|
||||
goog.require('registry.registrar.ContactSettings');
|
||||
goog.require('registry.registrar.ContactUs');
|
||||
goog.require('registry.registrar.Dashboard');
|
||||
goog.require('registry.registrar.Domain');
|
||||
goog.require('registry.registrar.EppSession');
|
||||
goog.require('registry.registrar.Host');
|
||||
goog.require('registry.registrar.Payment');
|
||||
goog.require('registry.registrar.Resources');
|
||||
goog.require('registry.registrar.SecuritySettings');
|
||||
goog.require('registry.registrar.WhoisSettings');
|
||||
goog.require('registry.util');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The Registrar Console.
|
||||
* @param {string} xsrfToken Populated by server-side soy template.
|
||||
* @param {string} clientId The logged in GAE user.
|
||||
* @constructor
|
||||
* @extends {registry.Console}
|
||||
* @final
|
||||
*/
|
||||
registry.registrar.Console = function(xsrfToken, clientId) {
|
||||
registry.registrar.Console.base(
|
||||
this, 'constructor',
|
||||
new registry.registrar.EppSession(this, xsrfToken, clientId));
|
||||
|
||||
/**
|
||||
* Component that's currently embedded in the page.
|
||||
* @type {?registry.Component}
|
||||
* @private
|
||||
*/
|
||||
this.component_ = null;
|
||||
|
||||
// XXX: This was in parent ctor but was triggering event dispatching before
|
||||
// ready here.
|
||||
this.history.setEnabled(true);
|
||||
|
||||
/**
|
||||
* @type {!string}
|
||||
* @private
|
||||
*/
|
||||
this.xsrfToken_ = xsrfToken;
|
||||
|
||||
/**
|
||||
* Last active nav element.
|
||||
* @type {Element}
|
||||
*/
|
||||
this.lastActiveNavElt;
|
||||
|
||||
/**
|
||||
* @type {!Object.<string, function(new:registry.Component,
|
||||
* !registry.registrar.Console,
|
||||
* string)>}
|
||||
*/
|
||||
this.pageMap = {};
|
||||
this.pageMap['security-settings'] = registry.registrar.SecuritySettings;
|
||||
this.pageMap['contact-settings'] = registry.registrar.ContactSettings;
|
||||
this.pageMap['whois-settings'] = registry.registrar.WhoisSettings;
|
||||
this.pageMap['contact-us'] = registry.registrar.ContactUs;
|
||||
this.pageMap['resources'] = registry.registrar.Resources;
|
||||
this.pageMap['contact'] = registry.registrar.Contact;
|
||||
this.pageMap['payment'] = registry.registrar.Payment;
|
||||
this.pageMap['domain'] = registry.registrar.Domain;
|
||||
this.pageMap['host'] = registry.registrar.Host;
|
||||
this.pageMap[''] = registry.registrar.Dashboard;
|
||||
};
|
||||
goog.inherits(registry.registrar.Console, registry.Console);
|
||||
|
||||
|
||||
/**
|
||||
* Changes the content area depending on hash path.
|
||||
*
|
||||
* <p>Hash path is expected to be of the form:
|
||||
*
|
||||
* <pre>
|
||||
* #type/id
|
||||
* </pre>
|
||||
*
|
||||
* <p>The {@code id} part may be appended by {@code ()} to specify the target
|
||||
* should be a resource create page.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
registry.registrar.Console.prototype.handleHashChange = function() {
|
||||
var hashToken = this.history.getToken();
|
||||
// On page reloads, opening a new tab, etc. it's possible that the
|
||||
// session cookie for a logged-in session exists, but the
|
||||
// this.session is not yet aware, so come back here after syncing.
|
||||
//
|
||||
// XXX: Method should be refactored to avoid this 2-stage behavior.
|
||||
if (!this.session.isEppLoggedIn()) {
|
||||
this.session.login(goog.bind(this.handleHashChange, this));
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, a resource operation.
|
||||
var parts = hashToken.split('/');
|
||||
var type = '';
|
||||
var id = '';
|
||||
if (parts.length >= 1) {
|
||||
type = parts[0];
|
||||
}
|
||||
if (parts.length == 2) {
|
||||
id = parts[1];
|
||||
}
|
||||
|
||||
goog.net.XhrIo.cleanup();
|
||||
|
||||
var componentCtor = this.pageMap[type];
|
||||
if (componentCtor == undefined) {
|
||||
componentCtor = this.pageMap[''];
|
||||
}
|
||||
var oldComponent = this.component_;
|
||||
this.component_ = new componentCtor(this, this.xsrfToken_);
|
||||
this.registerDisposable(this.component_);
|
||||
this.component_.basePath = type;
|
||||
this.component_.bindToDom(id);
|
||||
|
||||
this.changeNavStyle();
|
||||
|
||||
goog.dispose(oldComponent);
|
||||
};
|
||||
|
||||
|
||||
/** Change nav style. */
|
||||
registry.registrar.Console.prototype.changeNavStyle = function() {
|
||||
var hashToken = this.history.getToken();
|
||||
// Path except id
|
||||
var slashNdx = hashToken.lastIndexOf('/');
|
||||
slashNdx = slashNdx == -1 ? hashToken.length : slashNdx;
|
||||
var regNavlist = goog.dom.getRequiredElement('reg-navlist');
|
||||
var path = hashToken.substring(0, slashNdx);
|
||||
var active = regNavlist.querySelector('a[href="/registrar#' + path + '"]');
|
||||
if (goog.isNull(active)) {
|
||||
registry.util.log('Unknown path or path form in changeNavStyle.');
|
||||
return;
|
||||
}
|
||||
if (this.lastActiveNavElt) {
|
||||
goog.dom.classlist.remove(
|
||||
this.lastActiveNavElt, goog.getCssName('domain-active-nav'));
|
||||
}
|
||||
goog.dom.classlist.add(active, goog.getCssName('domain-active-nav'));
|
||||
this.lastActiveNavElt = active;
|
||||
};
|
125
java/google/registry/ui/js/registrar/contact.js
Normal file
125
java/google/registry/ui/js/registrar/contact.js
Normal file
|
@ -0,0 +1,125 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.Contact');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('registry.registrar.XmlResourceComponent');
|
||||
goog.require('registry.soy.registrar.contact');
|
||||
goog.require('registry.soy.registrar.contactepp');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The {@code Contact} class respresents a registry contact object and
|
||||
* binds UI CRUD operations to it.
|
||||
* @param {!registry.registrar.Console} console the
|
||||
* console singleton.
|
||||
* @constructor
|
||||
* @extends {registry.registrar.XmlResourceComponent}
|
||||
* @final
|
||||
*/
|
||||
registry.registrar.Contact = function(console) {
|
||||
registry.registrar.Contact.base(
|
||||
this, 'constructor',
|
||||
registry.soy.registrar.contact.item,
|
||||
registry.soy.registrar.contactepp,
|
||||
console);
|
||||
};
|
||||
goog.inherits(registry.registrar.Contact,
|
||||
registry.registrar.XmlResourceComponent);
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Contact.prototype.processItem = function() {
|
||||
this.model.item = this.model['epp']['response']['resData']['contact:infData'];
|
||||
if (!goog.isArray(this.model.item['contact:postalInfo'])) {
|
||||
this.model.item['contact:postalInfo'] =
|
||||
[this.model.item['contact:postalInfo']];
|
||||
}
|
||||
|
||||
// XXX: Is this code necessary?
|
||||
var fixPlus = function(val) {
|
||||
var str = (val || '') + '';
|
||||
if (str == '' || str.match(/\+.*/)) {
|
||||
return str;
|
||||
} else {
|
||||
return '+' + str;
|
||||
}
|
||||
};
|
||||
|
||||
// Both of these are optional.
|
||||
if (this.model.item['contact:voice']) {
|
||||
this.model.item['contact:voice']['keyValue'] =
|
||||
fixPlus(this.model.item['contact:voice']['keyValue']);
|
||||
}
|
||||
if (this.model.item['contact:voice']) {
|
||||
this.model.item['contact:fax']['keyValue'] =
|
||||
fixPlus(this.model.item['contact:fax']['keyValue']);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Contact.prototype.setupEditor = function(objArgs) {
|
||||
// For now always keep the first contact and make it i18n. Toggle button
|
||||
// disables to enforce state.
|
||||
//
|
||||
// XXX: Should be simplified to make more modular.
|
||||
var postalElt = goog.dom.getRequiredElement('contact-postalInfo');
|
||||
var addPostalInfoBtn = goog.dom.getRequiredElement(
|
||||
'domain-contact-postalInfo-add-button');
|
||||
this.typeCounts['contact-postalInfo'] = postalElt.childNodes.length;
|
||||
// 4 child nodes means both addresses are present:
|
||||
// 2 data tables, the footer id elt and a hidden input.
|
||||
var setupRemoveBtns = this.typeCounts['contact-postalInfo'] == 4;
|
||||
if (setupRemoveBtns) {
|
||||
this.appendRemoveBtn(/** @type {!Element} */ (postalElt.childNodes[0]));
|
||||
this.appendRemoveBtn(/** @type {!Element} */ (postalElt.childNodes[1]));
|
||||
} else {
|
||||
addPostalInfoBtn.removeAttribute('disabled');
|
||||
}
|
||||
|
||||
this.addRemBtnHandlers(
|
||||
'contact-postalInfo',
|
||||
function() {
|
||||
return 'contact:postalInfo[1].contact:';
|
||||
},
|
||||
function() {
|
||||
addPostalInfoBtn.setAttribute('disabled', true);
|
||||
return null;
|
||||
},
|
||||
registry.soy.registrar.contact.postalInfo,
|
||||
{
|
||||
item: {},
|
||||
localized: true,
|
||||
itemPrefix: 'contact:',
|
||||
namePrefix: 'contact:postalInfo[1].contact:'
|
||||
},
|
||||
setupRemoveBtns);
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Contact.prototype.prepareCreate = function(params) {
|
||||
params.nextId = params.item['contact:id'];
|
||||
return registry.soy.registrar.contactepp.create(params).toString();
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Contact.prototype.prepareUpdate = function(params) {
|
||||
params.nextId = params.item['contact:id'];
|
||||
return registry.soy.registrar.contactepp.update(params).toString();
|
||||
};
|
240
java/google/registry/ui/js/registrar/contact_settings.js
Normal file
240
java/google/registry/ui/js/registrar/contact_settings.js
Normal file
|
@ -0,0 +1,240 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.ContactSettings');
|
||||
|
||||
goog.require('goog.Uri');
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.json');
|
||||
goog.require('goog.soy');
|
||||
goog.require('registry.Resource');
|
||||
goog.require('registry.ResourceComponent');
|
||||
goog.require('registry.soy.registrar.contacts');
|
||||
goog.require('registry.util');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Contact Settings page. Registrar Contacts are not really a proper
|
||||
* REST resource as they're still passed from the server as a member
|
||||
* field of Registrar, so this class behaves like an item page,
|
||||
* updating only that field of the Registrar object and not
|
||||
* implementing the create action from edit_item.
|
||||
* @param {!registry.registrar.Console} console
|
||||
* @param {string} xsrfToken Security token to pass back to the server.
|
||||
* @constructor
|
||||
* @extends {registry.ResourceComponent}
|
||||
* @final
|
||||
*/
|
||||
registry.registrar.ContactSettings = function(console, xsrfToken) {
|
||||
registry.registrar.ContactSettings.base(
|
||||
this, 'constructor',
|
||||
console,
|
||||
new registry.Resource(new goog.Uri('/registrar-settings'), xsrfToken),
|
||||
registry.soy.registrar.contacts.contact,
|
||||
null);
|
||||
};
|
||||
goog.inherits(registry.registrar.ContactSettings, registry.ResourceComponent);
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.ContactSettings.prototype.setupAppbar = function() {
|
||||
registry.registrar.ContactSettings.base(this, 'setupAppbar');
|
||||
// Setup delete only on existing items, not on creates.
|
||||
if (goog.isDefAndNotNull(this.model)) {
|
||||
var deleteBtn = goog.dom.createDom('button', {
|
||||
type: 'button',
|
||||
id: 'reg-app-btn-delete',
|
||||
className: goog.getCssName('kd-button')
|
||||
},
|
||||
'Delete');
|
||||
goog.events.listen(deleteBtn, goog.events.EventType.CLICK,
|
||||
goog.bind(this.sendDelete, this));
|
||||
goog.dom.insertSiblingBefore(deleteBtn,
|
||||
goog.dom.getRequiredElement('reg-app-btn-cancel'));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.ContactSettings.prototype.renderItem = function(rspObj) {
|
||||
var contentElt = goog.dom.getRequiredElement('reg-content');
|
||||
/** @type {!registry.json.RegistrarContact} */
|
||||
var contacts = rspObj.contacts;
|
||||
if (this.id) {
|
||||
var targetContactNdx;
|
||||
var targetContact;
|
||||
for (var c in contacts) {
|
||||
var ct = contacts[c];
|
||||
if (ct.emailAddress == this.id) {
|
||||
targetContactNdx = c;
|
||||
targetContact = ct;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!targetContact) {
|
||||
registry.util.butter('No contact with the given email.');
|
||||
return;
|
||||
}
|
||||
var typesList = targetContact.types.toLowerCase().split(',');
|
||||
var actualTypesLookup = {};
|
||||
for (var t in typesList) {
|
||||
actualTypesLookup[typesList[t]] = true;
|
||||
}
|
||||
goog.soy.renderElement(
|
||||
contentElt,
|
||||
registry.soy.registrar.contacts.contact,
|
||||
{
|
||||
item: targetContact,
|
||||
namePrefix: 'contacts[' + targetContactNdx + '].',
|
||||
actualTypesLookup: actualTypesLookup,
|
||||
readonly: (rspObj.readonly || false)
|
||||
});
|
||||
this.setupAppbar();
|
||||
} else {
|
||||
var contactsByType = {};
|
||||
for (var c in contacts) {
|
||||
var contact = contacts[c];
|
||||
var types = contact.types;
|
||||
if (!types) {
|
||||
continue;
|
||||
}
|
||||
types = types.split(',');
|
||||
for (var t in types) {
|
||||
var type = types[t].toLowerCase();
|
||||
var contactsList = contactsByType[type];
|
||||
if (!contactsList) {
|
||||
contactsByType[type] = contactsList = [];
|
||||
}
|
||||
contactsList.push(contact);
|
||||
}
|
||||
}
|
||||
goog.soy.renderElement(
|
||||
contentElt,
|
||||
registry.soy.registrar.contacts.set,
|
||||
{contactsByType: contactsByType });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.ContactSettings.prototype.add = function() {
|
||||
var newContactNdx = this.model.contacts.length;
|
||||
goog.soy.renderElement(goog.dom.getRequiredElement('reg-content'),
|
||||
registry.soy.registrar.contacts.contact,
|
||||
{
|
||||
item: {},
|
||||
namePrefix: 'contacts[' + newContactNdx + '].',
|
||||
actualTypesLookup: {},
|
||||
readonly: false
|
||||
});
|
||||
this.toggleEdit();
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.ContactSettings.prototype.sendDelete = function() {
|
||||
var ndxToDel = null;
|
||||
for (var i = 0; i < this.model.contacts.length; i++) {
|
||||
var contact = this.model.contacts[i];
|
||||
if (contact.emailAddress == this.id) {
|
||||
ndxToDel = i;
|
||||
}
|
||||
}
|
||||
if (goog.isNull(ndxToDel)) {
|
||||
throw new Error('Email to delete does not match model.');
|
||||
}
|
||||
var modelCopy = /** @type {!Object}
|
||||
*/ (goog.json.parse(goog.json.serialize(this.model)));
|
||||
goog.array.removeAt(modelCopy.contacts, ndxToDel);
|
||||
this.resource.update(modelCopy, goog.bind(this.handleDeleteResponse, this));
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.ContactSettings.prototype.prepareUpdate =
|
||||
function(modelCopy) {
|
||||
var form = registry.util.parseForm('item');
|
||||
var contact;
|
||||
// Handle update/create.
|
||||
if (this.id) {
|
||||
// Update contact, so overwrite it in the model before sending
|
||||
// back to server.
|
||||
var once = false;
|
||||
for (var c in form.contacts) {
|
||||
if (once) {
|
||||
throw new Error('More than one contact parsed from form: ' + c);
|
||||
}
|
||||
contact = form.contacts[c];
|
||||
modelCopy.contacts[c] = contact;
|
||||
once = true;
|
||||
}
|
||||
} else {
|
||||
// Add contact.
|
||||
contact = form.contacts.pop();
|
||||
modelCopy.contacts.push(contact);
|
||||
}
|
||||
contact.visibleInWhoisAsAdmin = contact.visibleInWhoisAsAdmin == 'true';
|
||||
contact.visibleInWhoisAsTech = contact.visibleInWhoisAsTech == 'true';
|
||||
contact.types = '';
|
||||
for (var tNdx in contact.type) {
|
||||
if (contact.type[tNdx]) {
|
||||
if (contact.types.length > 0) {
|
||||
contact.types += ',';
|
||||
}
|
||||
contact.types += ('' + tNdx).toUpperCase();
|
||||
}
|
||||
}
|
||||
delete contact['type'];
|
||||
this.nextId = contact.emailAddress;
|
||||
};
|
||||
|
||||
|
||||
// XXX: Should be hoisted up.
|
||||
/**
|
||||
* Handler for contact save that navigates to that item on success.
|
||||
* Does nothing on failure as UI will be left with error messages for
|
||||
* the user to resolve.
|
||||
* @param {!Object} rsp Decoded XML/JSON response from the server.
|
||||
* @override
|
||||
*/
|
||||
registry.registrar.ContactSettings.prototype.handleCreateResponse =
|
||||
function(rsp) {
|
||||
this.handleUpdateResponse(rsp);
|
||||
if (rsp.status == 'SUCCESS') {
|
||||
this.console.view('contact-settings/' + this.nextId);
|
||||
}
|
||||
return rsp;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for contact delete that navigates back to the collection on success.
|
||||
* Does nothing on failure as UI will be left with error messages for
|
||||
* the user to resolve.
|
||||
* @param {!Object} rsp Decoded XML/JSON response from the server.
|
||||
* @override
|
||||
*/
|
||||
registry.registrar.ContactSettings.prototype.handleDeleteResponse =
|
||||
function(rsp) {
|
||||
this.handleUpdateResponse(rsp);
|
||||
if (rsp.status == 'SUCCESS') {
|
||||
this.id = null;
|
||||
this.console.view('contact-settings');
|
||||
}
|
||||
return rsp;
|
||||
};
|
49
java/google/registry/ui/js/registrar/contact_us.js
Normal file
49
java/google/registry/ui/js/registrar/contact_us.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.ContactUs');
|
||||
|
||||
goog.require('goog.Uri');
|
||||
goog.require('goog.dom');
|
||||
goog.require('registry.Resource');
|
||||
goog.require('registry.ResourceComponent');
|
||||
goog.require('registry.soy.registrar.console');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Contact Us page.
|
||||
* @param {!registry.registrar.Console} console
|
||||
* @param {string} xsrfToken Security token to pass back to the server.
|
||||
* @constructor
|
||||
* @extends {registry.ResourceComponent}
|
||||
* @final
|
||||
*/
|
||||
registry.registrar.ContactUs = function(console, xsrfToken) {
|
||||
registry.registrar.ContactUs.base(
|
||||
this,
|
||||
'constructor',
|
||||
console,
|
||||
new registry.Resource(new goog.Uri('/registrar-settings'), xsrfToken),
|
||||
registry.soy.registrar.console.contactUs,
|
||||
null);
|
||||
};
|
||||
goog.inherits(registry.registrar.ContactUs, registry.ResourceComponent);
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.ContactUs.prototype.bindToDom = function(id) {
|
||||
registry.registrar.ContactUs.base(this, 'bindToDom', '');
|
||||
goog.dom.removeChildren(goog.dom.getRequiredElement('reg-app-buttons'));
|
||||
};
|
94
java/google/registry/ui/js/registrar/dashboard.js
Normal file
94
java/google/registry/ui/js/registrar/dashboard.js
Normal file
|
@ -0,0 +1,94 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.Dashboard');
|
||||
|
||||
goog.require('goog.Timer');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.soy');
|
||||
goog.require('goog.style');
|
||||
goog.require('registry.Component');
|
||||
goog.require('registry.soy.registrar.console');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Dashboard for Registrar Console.
|
||||
* @param {!registry.registrar.Console} console
|
||||
* @constructor
|
||||
* @extends {registry.Component}
|
||||
* @final
|
||||
*/
|
||||
registry.registrar.Dashboard = function(console) {
|
||||
registry.registrar.Dashboard.base(this, 'constructor', console);
|
||||
|
||||
/** @private {number} */
|
||||
this.x_ = 0;
|
||||
|
||||
/** @private {Element} */
|
||||
this.gear_ = null;
|
||||
|
||||
/** @private {goog.Timer} */
|
||||
this.timer_ = null;
|
||||
};
|
||||
goog.inherits(registry.registrar.Dashboard, registry.Component);
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Dashboard.prototype.bindToDom = function(id) {
|
||||
registry.registrar.Dashboard.base(this, 'bindToDom', '');
|
||||
goog.dom.removeChildren(goog.dom.getRequiredElement('reg-appbar'));
|
||||
goog.soy.renderElement(goog.dom.getElement('reg-content'),
|
||||
registry.soy.registrar.console.dashboard);
|
||||
goog.events.listen(goog.dom.getElement('rotate'),
|
||||
goog.events.EventType.CLICK,
|
||||
goog.bind(this.rotate_, this));
|
||||
this.gear_ = goog.dom.getRequiredElement('gear');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Do EPP logout.
|
||||
*/
|
||||
registry.registrar.Dashboard.prototype.doEppLogout = function() {
|
||||
this.console.session.logout();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Let's do the twist.
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.Dashboard.prototype.rotate_ = function() {
|
||||
this.timer_ = new goog.Timer(10);
|
||||
this.registerDisposable(this.timer_);
|
||||
goog.events.listen(this.timer_, goog.Timer.TICK,
|
||||
goog.bind(this.rotateCall_, this));
|
||||
this.timer_.start();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* No really this time!
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.Dashboard.prototype.rotateCall_ = function() {
|
||||
this.x_++;
|
||||
goog.style.setStyle(this.gear_, 'transform', 'rotate(' + this.x_ + 'deg)');
|
||||
if (this.x_ == 360) {
|
||||
this.timer_.stop();
|
||||
}
|
||||
};
|
202
java/google/registry/ui/js/registrar/domain.js
Normal file
202
java/google/registry/ui/js/registrar/domain.js
Normal file
|
@ -0,0 +1,202 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.Domain');
|
||||
|
||||
goog.require('goog.json');
|
||||
goog.require('registry.registrar.XmlResourceComponent');
|
||||
goog.require('registry.soy.forms');
|
||||
goog.require('registry.soy.registrar.domain');
|
||||
goog.require('registry.soy.registrar.domainepp');
|
||||
goog.require('registry.util');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* CRUD for EPP domain objects.
|
||||
* @param {!registry.registrar.Console} console
|
||||
* @constructor
|
||||
* @extends {registry.registrar.XmlResourceComponent}
|
||||
* @final
|
||||
*/
|
||||
registry.registrar.Domain = function(console) {
|
||||
registry.registrar.Domain.base(
|
||||
this, 'constructor',
|
||||
registry.soy.registrar.domain.item,
|
||||
registry.soy.registrar.domainepp,
|
||||
console);
|
||||
};
|
||||
goog.inherits(registry.registrar.Domain,
|
||||
registry.registrar.XmlResourceComponent);
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Launch phase flag. If not SUNRUSH then GA.
|
||||
*/
|
||||
goog.define('registry.registrar.Domain.SUNRUSH', false);
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Domain.prototype.newModel = function() {
|
||||
var newModel = {item: {'domain:period': ''}};
|
||||
if (registry.registrar.Domain.SUNRUSH) {
|
||||
newModel.allowSmd = true;
|
||||
}
|
||||
return newModel;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Prepare a fetch query for the domain by its domain application id.
|
||||
* @param {!Object} params should have a name field with a
|
||||
* possibly extended domain name id of the form "example.tld:1234"
|
||||
* where the 1234 is the domain application id assigned by the
|
||||
* backend flows.
|
||||
* @override
|
||||
*/
|
||||
registry.registrar.Domain.prototype.prepareFetch = function(params) {
|
||||
var xml;
|
||||
if (registry.registrar.Domain.SUNRUSH) {
|
||||
var idParts = params.id.split(':');
|
||||
if (idParts.length != 2) {
|
||||
registry.util.butter(
|
||||
'Domain queries during sunrush have the form: ' +
|
||||
'"example.tld:1234", where 1234 is the application ID.');
|
||||
throw Error('Invalid domain name for SUNRUSH, lacking application ID');
|
||||
}
|
||||
params.name = idParts[0];
|
||||
params.applicationID = idParts[1];
|
||||
xml = registry.soy.registrar.domainepp.infoSunrush(params);
|
||||
} else {
|
||||
xml = registry.soy.registrar.domainepp.info(params);
|
||||
}
|
||||
return xml.toString();
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Domain.prototype.processItem = function() {
|
||||
this.model.item = this.model['epp']['response']['resData']['domain:infData'];
|
||||
// Hoist extensions for easy soy access.
|
||||
var extension = this.model['epp']['response']['extension'];
|
||||
if (extension && extension['launch:infData']) {
|
||||
var extendedInfData = extension['launch:infData'];
|
||||
|
||||
var applicationID = extendedInfData['launch:applicationID'];
|
||||
if (applicationID) {
|
||||
this.model.item['launch:applicationID'] = applicationID;
|
||||
}
|
||||
|
||||
var mark = extendedInfData['mark:mark'];
|
||||
if (mark) {
|
||||
this.model.item['mark:mark'] = {'keyValue': goog.json.serialize(mark)};
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap single item into an array.
|
||||
if (this.model.item['domain:ns'] &&
|
||||
this.model.item['domain:ns']['domain:hostObj']) {
|
||||
var hostObj = this.model.item['domain:ns']['domain:hostObj'];
|
||||
if (!goog.isArray(hostObj)) {
|
||||
this.model.item['domain:ns']['domain:hostObj'] = [hostObj];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Domain.prototype.setupEditor = function(objArgs) {
|
||||
this.typeCounts['contact'] = objArgs.item['domain:contact'] ?
|
||||
objArgs.item['domain:contact'].length : 0;
|
||||
|
||||
var ji = objArgs.item['domain:ns'];
|
||||
this.typeCounts['host'] =
|
||||
ji && ji['domain:hostObj'] ? ji['domain:hostObj'].length : 0;
|
||||
|
||||
this.formInputRowRemovable(
|
||||
document.querySelectorAll('input.domain-hostObj[readonly]'));
|
||||
|
||||
this.formInputRowRemovable(
|
||||
document.querySelectorAll('input.domain-contact[readonly]'));
|
||||
|
||||
this.addRemBtnHandlers(
|
||||
'contact',
|
||||
goog.bind(function() {
|
||||
return 'domain:contact[' + this.typeCounts['contact'] + ']';
|
||||
}, this),
|
||||
goog.bind(function(newFieldName) {
|
||||
return registry.util.renderBeforeRow(
|
||||
'domain-contacts-footer',
|
||||
registry.soy.forms.selectRow, {
|
||||
label: 'Type',
|
||||
name: newFieldName + '.@type',
|
||||
options: ['admin', 'tech', 'billing']
|
||||
});
|
||||
}, this));
|
||||
|
||||
this.addRemBtnHandlers('host', goog.bind(function() {
|
||||
return 'domain:ns.domain:hostObj[' + this.typeCounts['host'] + ']';
|
||||
}, this));
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Domain.prototype.prepareCreate = function(params) {
|
||||
var form = params.item;
|
||||
params.nextId = form['domain:name'];
|
||||
|
||||
// The presence of this field is used to signal extended template, so remove
|
||||
// if not used.
|
||||
if (form['smd:encodedSignedMark'] == '') {
|
||||
delete form['smd:encodedSignedMark'];
|
||||
}
|
||||
var xml;
|
||||
if (registry.registrar.Domain.SUNRUSH) {
|
||||
xml = registry.soy.registrar.domainepp.createSunrush(params);
|
||||
} else {
|
||||
xml = registry.soy.registrar.domainepp.create(params);
|
||||
}
|
||||
return xml.toString();
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Domain.prototype.prepareUpdate =
|
||||
function(params) {
|
||||
var form = params.item;
|
||||
var nextId = form['domain:name'];
|
||||
params.nextId = nextId;
|
||||
|
||||
if (form['domain:contact']) {
|
||||
this.addRem(form['domain:contact'], 'Contacts', params);
|
||||
}
|
||||
|
||||
if (form['domain:ns'] && form['domain:ns']['domain:hostObj']) {
|
||||
this.addRem(form['domain:ns']['domain:hostObj'], 'Hosts', params);
|
||||
}
|
||||
|
||||
var xml;
|
||||
if (registry.registrar.Domain.SUNRUSH) {
|
||||
xml = registry.soy.registrar.domainepp.updateSunrush(params);
|
||||
nextId += ':' + form['launch:applicationID'];
|
||||
} else {
|
||||
if (form['domain:ns'] && form['domain:ns']['domain:hostObj']) {
|
||||
this.addRem(form['domain:ns']['domain:hostObj'], 'Hosts', params);
|
||||
}
|
||||
this.addRem(form['domain:contact'], 'Contacts', params);
|
||||
xml = registry.soy.registrar.domainepp.update(params);
|
||||
}
|
||||
|
||||
return xml.toString();
|
||||
};
|
131
java/google/registry/ui/js/registrar/epp_session.js
Normal file
131
java/google/registry/ui/js/registrar/epp_session.js
Normal file
|
@ -0,0 +1,131 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.EppSession');
|
||||
|
||||
goog.require('goog.Uri');
|
||||
goog.require('registry.Session');
|
||||
goog.require('registry.soy.registrar.epp');
|
||||
goog.require('registry.util');
|
||||
goog.require('registry.xml');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Session state for console.
|
||||
* @param {!registry.registrar.Console} console
|
||||
* @param {string} xsrfToken Populated by server-side soy template.
|
||||
* @param {string} clientId The logged in GAE user.
|
||||
* @constructor
|
||||
* @extends {registry.Session}
|
||||
* @final
|
||||
*/
|
||||
registry.registrar.EppSession = function(console, xsrfToken, clientId) {
|
||||
registry.registrar.EppSession.base(
|
||||
this, 'constructor', new goog.Uri('/registrar-xhr'), xsrfToken,
|
||||
registry.Session.ContentType.EPP);
|
||||
|
||||
/**
|
||||
* @type {!registry.registrar.Console}
|
||||
*/
|
||||
this.console = console;
|
||||
|
||||
/**
|
||||
* @type {!boolean}
|
||||
* @private
|
||||
*/
|
||||
this.isEppLoggedIn_ = false;
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.clientId_ = clientId;
|
||||
};
|
||||
goog.inherits(registry.registrar.EppSession, registry.Session);
|
||||
|
||||
|
||||
/**
|
||||
* Whether the session has received an EPP success response to an EPP
|
||||
* login attempt.
|
||||
* @return {boolean} Whether the user is logged into an EPP session.
|
||||
*/
|
||||
registry.registrar.EppSession.prototype.isEppLoggedIn = function() {
|
||||
return this.isEppLoggedIn_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the clientId if the user is logged in, or throw Error.
|
||||
* @throws Error if the user is not logged in.
|
||||
* @return {string} the clientId.
|
||||
*/
|
||||
registry.registrar.EppSession.prototype.getClientId = function() {
|
||||
return this.clientId_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Login or display butterbar info about error.
|
||||
* @param {function()} successCb to be called on success.
|
||||
*/
|
||||
registry.registrar.EppSession.prototype.login = function(successCb) {
|
||||
var eppArgs = {clId: this.clientId_, clTrid: 'asdf-1235'};
|
||||
this.send(
|
||||
registry.soy.registrar.epp.login(eppArgs).getContent(),
|
||||
goog.bind(function(xml) {
|
||||
var result = xml['epp']['response']['result'];
|
||||
var eppCode = result['@code'];
|
||||
if (eppCode == '1000' || eppCode == '2002') {
|
||||
// Success || Already logged in.
|
||||
this.isEppLoggedIn_ = true;
|
||||
successCb();
|
||||
} else {
|
||||
// Failure.
|
||||
this.isEppLoggedIn_ = false;
|
||||
registry.util.butter('login error: ' + eppCode);
|
||||
}
|
||||
}, this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Logout or display butterbar info about error.
|
||||
*/
|
||||
registry.registrar.EppSession.prototype.logout = function() {
|
||||
this.send(
|
||||
registry.soy.registrar.epp.logout(
|
||||
{clTrid: 'asdf-1235'}).getContent(),
|
||||
goog.bind(function(xml) {
|
||||
var result = xml['epp']['response']['result'];
|
||||
var eppCode = result['@code'];
|
||||
registry.util.butter(
|
||||
'logout ' + eppCode + ': ' + result['msg']['keyValue']);
|
||||
// Going to be safe here and force a login either way.
|
||||
this.isEppLoggedIn_ = false;
|
||||
}, this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Send xml to the server.
|
||||
* @param {string} xml Request document.
|
||||
* @param {function(!Object)} callback For XhrIo result throws.
|
||||
*/
|
||||
registry.registrar.EppSession.prototype.send = function(xml, callback) {
|
||||
var toXmlJsonCb = function(rspXml) {
|
||||
callback(registry.xml.convertToJson(rspXml));
|
||||
};
|
||||
this.sendXhrIo(xml, toXmlJsonCb);
|
||||
};
|
103
java/google/registry/ui/js/registrar/host.js
Normal file
103
java/google/registry/ui/js/registrar/host.js
Normal file
|
@ -0,0 +1,103 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.Host');
|
||||
|
||||
goog.require('registry.registrar.XmlResourceComponent');
|
||||
goog.require('registry.soy.registrar.host');
|
||||
goog.require('registry.soy.registrar.hostepp');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* CRUD for EPP host objects.
|
||||
* @param {!registry.registrar.Console} console
|
||||
* @constructor
|
||||
* @extends {registry.registrar.XmlResourceComponent}
|
||||
* @final
|
||||
*/
|
||||
registry.registrar.Host = function(console) {
|
||||
registry.registrar.Host.base(
|
||||
this, 'constructor',
|
||||
registry.soy.registrar.host.item,
|
||||
registry.soy.registrar.hostepp,
|
||||
console);
|
||||
};
|
||||
goog.inherits(registry.registrar.Host,
|
||||
registry.registrar.XmlResourceComponent);
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Host.prototype.processItem = function() {
|
||||
this.model.item = this.model['epp']['response']['resData']['host:infData'];
|
||||
if (this.model.item['host:addr']) {
|
||||
if (!goog.isArray(this.model.item['host:addr'])) {
|
||||
this.model.item['host:addr'] = [this.model.item['host:addr']];
|
||||
}
|
||||
} else {
|
||||
this.model.item['host:addr'] = [];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Host.prototype.setupEditor = function(objArgs) {
|
||||
this.typeCounts['host-addr'] =
|
||||
objArgs.item['host:addr'] ? objArgs.item['host:addr'].length : 0;
|
||||
this.addRemBtnHandlers('host-addr', goog.bind(function() {
|
||||
return 'host:addr[' + this.typeCounts['host-addr'] + ']';
|
||||
}, this));
|
||||
|
||||
this.formInputRowRemovable(document.querySelectorAll('input[readonly]'));
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Host.prototype.prepareCreate = function(params) {
|
||||
params.nextId = params.item['host:name'];
|
||||
return registry.soy.registrar.hostepp.create(params).toString();
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Host.prototype.prepareUpdate = function(params) {
|
||||
var form = params.item;
|
||||
var addAddrs = [];
|
||||
var remAddrs = [];
|
||||
if (form['host:addr']) {
|
||||
var oldAddrs = form['host:oldAddr'] || [];
|
||||
var newAddrs = form['host:addr'];
|
||||
var length = Math.max(oldAddrs.length, newAddrs.length);
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (i >= oldAddrs.length) {
|
||||
addAddrs.push(newAddrs[i]['value']);
|
||||
} else if (i >= newAddrs.length) {
|
||||
remAddrs.push(oldAddrs[i]['value']);
|
||||
} else {
|
||||
if (newAddrs[i]['value'] == oldAddrs[i]['value']) {
|
||||
// Do nothing.
|
||||
} else if (newAddrs[i]['value'] == '') {
|
||||
remAddrs.push(oldAddrs[i]['value']);
|
||||
} else {
|
||||
remAddrs.push(oldAddrs[i]['value']);
|
||||
addAddrs.push(newAddrs[i]['value']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
params.addAddrs = addAddrs;
|
||||
params.remAddrs = remAddrs;
|
||||
params.nextId = form['host:chgName'];
|
||||
return registry.soy.registrar.hostepp.update(params).toString();
|
||||
};
|
35
java/google/registry/ui/js/registrar/main.js
Normal file
35
java/google/registry/ui/js/registrar/main.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview Entry point for the registrar console.
|
||||
*/
|
||||
|
||||
goog.provide('registry.registrar.main');
|
||||
|
||||
goog.require('registry.registrar.Console');
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates a registry object, which syncs with the server.
|
||||
* Sub-templates are invoked based on location/pathname, to choose
|
||||
* either Registry or Registrar pages.
|
||||
*
|
||||
* @param {string} xsrfToken populated by server-side soy template.
|
||||
* @param {string} clientId The registrar clientId.
|
||||
* @export
|
||||
*/
|
||||
registry.registrar.main = function(xsrfToken, clientId) {
|
||||
new registry.registrar.Console(xsrfToken, clientId);
|
||||
};
|
412
java/google/registry/ui/js/registrar/payment.js
Normal file
412
java/google/registry/ui/js/registrar/payment.js
Normal file
|
@ -0,0 +1,412 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.Payment');
|
||||
|
||||
goog.require('goog.Uri');
|
||||
goog.require('goog.asserts');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.json');
|
||||
goog.require('goog.object');
|
||||
goog.require('goog.soy');
|
||||
goog.require('registry.Component');
|
||||
goog.require('registry.MenuButton');
|
||||
goog.require('registry.Session');
|
||||
goog.require('registry.forms');
|
||||
goog.require('registry.registrar.BrainFrame');
|
||||
goog.require('registry.soy.registrar.console');
|
||||
goog.require('registry.soy.registrar.payment');
|
||||
goog.require('registry.util');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Page allowing registrar to send money to registry.
|
||||
*
|
||||
* <p>This page contains a form that asks the user to enter an arbitrary amount
|
||||
* and a payment method, which can be credit card or PayPal. Multiple
|
||||
* currencies are supported.
|
||||
*
|
||||
* <h3>PCI Compliance</h3>
|
||||
*
|
||||
* <p>We don't have any access whatsoever to the credit card information. We
|
||||
* embed an iframe run by Braintree Payments. The user can then provide his
|
||||
* credit card (or PayPal) details directly to Braintree. Braintree then gives
|
||||
* us a nonce value representing the payment method, which we can use to issue
|
||||
* the transaction.
|
||||
*
|
||||
* <h3>Bidirectional Protection</h3>
|
||||
*
|
||||
* <p>To use Braintree's iframe, we need to load a script from their server. We
|
||||
* don't want that script to have access to the Registrar Console. If Braintree
|
||||
* got pwnd, the attacker would be able to issue EPP commands as a registrar.
|
||||
*
|
||||
* <p>We fix this problem by embedding the Braintree iframe inside another
|
||||
* sandbox iframe that's hosted from a Cloud Storage bucket. This frame is
|
||||
* defined by {@code brainframe.html}. It's basically an empty shell that sends
|
||||
* a request back to the production environment for {@code brainframe.js}.
|
||||
*
|
||||
* <p>The importance of the Cloud Storage bucket is that it is served from a
|
||||
* separate domain. This causes the browser to forbid the iframe from accessing
|
||||
* the contents of the parent frame. The HTML5 {@code sandbox} attribute does
|
||||
* this too, but we can't use it, because the Venmo functionality in the
|
||||
* Braintree JS SDK needs to be able to access {@code document.cookie}, which
|
||||
* is forbidden in a sandbox environment. This HTML5 {@code sandbox} feature is
|
||||
* also not available in older versions of Internet Explorer.
|
||||
*
|
||||
* <h3>Business Logic</h3>
|
||||
*
|
||||
* <p>This page starts off as a loading glyph, while we issue an RPC to the
|
||||
* backend. We ask for a Braintree token, which currencies are available, and
|
||||
* the location of the brainframe HTML file. Once we get that data, we render
|
||||
* the form.
|
||||
*
|
||||
* <p>Once the sandbox iframe inside that form has loaded, it'll send us a
|
||||
* message asking for the token. We give it the token, which it uses to load
|
||||
* the Braintree iframe.
|
||||
*
|
||||
* <p>To make sure the sandbox iframe is the same size as the Braintree iframe,
|
||||
* the sandbox iframe will send us messages on occasion asking to be resized.
|
||||
*
|
||||
* <p>The disabled state of the submit button is managed judiciously. It's
|
||||
* disabled initially, until we get a READY message from the sandbox iframe,
|
||||
* indicating that the Braintree iframe is fully loaded. We also disable the
|
||||
* submit button during the submit process.
|
||||
*
|
||||
* <p>When the user presses the submit button, we send a message to the sandbox
|
||||
* iframe asking it to submit the Braintree iframe. When the Braintree iframe
|
||||
* is submitted, it gives the sandbox iframe the the payment method nonce,
|
||||
* which it passes along to us. Then we pass the form data to the backend via
|
||||
* the payment RPC, which invokes the Braintree Java API to issue the
|
||||
* transaction.
|
||||
*
|
||||
* <p>If the payment RPC fails, we'll either show an error on a field, or in a
|
||||
* bloody butterbar. If it succeeds, then the backend will give us the
|
||||
* transaction ID assigned by Braintree, which we then render on a success
|
||||
* page.
|
||||
*
|
||||
* <p>The success page contains a "Make Another Payment" button which, if
|
||||
* clicked, will reset the state of this page back to the beginning.
|
||||
*
|
||||
* @param {!registry.registrar.Console} console
|
||||
* @param {string} xsrfToken Security token to pass back to the server.
|
||||
* @constructor
|
||||
* @extends {registry.Component}
|
||||
* @final
|
||||
*/
|
||||
registry.registrar.Payment = function(console, xsrfToken) {
|
||||
registry.registrar.Payment.base(this, 'constructor', console);
|
||||
|
||||
/**
|
||||
* Element in which this page is rendered.
|
||||
* @private {!Element}
|
||||
* @const
|
||||
*/
|
||||
this.content_ = goog.dom.getRequiredElement('reg-content');
|
||||
|
||||
/**
|
||||
* Braintree API nonce token generated by the backend. This value is a
|
||||
* prerequisite to rendering the Braintree iframe.
|
||||
* @private {string}
|
||||
*/
|
||||
this.token_ = '';
|
||||
|
||||
/**
|
||||
* Braintree API nonce value for payment method selected by user.
|
||||
* @private {string}
|
||||
*/
|
||||
this.paymentMethodNonce_ = '';
|
||||
|
||||
/**
|
||||
* Currency drop-down widget in form.
|
||||
* @private {?registry.MenuButton}
|
||||
*/
|
||||
this.currencyMenu_ = null;
|
||||
|
||||
/**
|
||||
* XHR client to {@code RegistrarPaymentSetupAction}.
|
||||
* @private {!registry.Session.<!registry.rpc.PaymentSetup.Request,
|
||||
* !registry.rpc.PaymentSetup.Response>}
|
||||
* @const
|
||||
*/
|
||||
this.setupRpc_ =
|
||||
new registry.Session(new goog.Uri('/registrar-payment-setup'),
|
||||
xsrfToken,
|
||||
registry.Session.ContentType.JSON);
|
||||
|
||||
/**
|
||||
* XHR client to {@code RegistrarPaymentAction}.
|
||||
* @private {!registry.Session.<!registry.rpc.Payment.Request,
|
||||
* !registry.rpc.Payment.Response>}
|
||||
* @const
|
||||
*/
|
||||
this.paymentRpc_ =
|
||||
new registry.Session(new goog.Uri('/registrar-payment'),
|
||||
xsrfToken,
|
||||
registry.Session.ContentType.JSON);
|
||||
|
||||
this.listen(goog.global.window,
|
||||
goog.events.EventType.MESSAGE,
|
||||
this.onMessage_);
|
||||
};
|
||||
goog.inherits(registry.registrar.Payment, registry.Component);
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Payment.prototype.bindToDom = function(id) {
|
||||
registry.registrar.Payment.base(this, 'bindToDom', id);
|
||||
if (!goog.isNull(goog.dom.getElement('reg-app-buttons'))) {
|
||||
goog.dom.removeChildren(goog.dom.getElement('reg-app-buttons'));
|
||||
}
|
||||
if (!registry.registrar.Payment.isBrowserSupported_()) {
|
||||
goog.soy.renderElement(this.content_,
|
||||
registry.soy.registrar.payment.unsupported);
|
||||
return;
|
||||
}
|
||||
goog.soy.renderElement(this.content_, registry.soy.registrar.console.loading);
|
||||
this.setupRpc_.sendXhrIo({}, goog.bind(this.onSetup_, this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler invoked when we receive information from our backend, such as a
|
||||
* Braintree token, which is necessary for us to render the payment form.
|
||||
* @param {!registry.rpc.PaymentSetup.Response} response
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.Payment.prototype.onSetup_ = function(response) {
|
||||
if (response.status != 'SUCCESS') {
|
||||
if (response.message == 'not-using-cc-billing') {
|
||||
goog.soy.renderElement(this.content_,
|
||||
registry.soy.registrar.payment.notUsingCcBilling);
|
||||
} else {
|
||||
registry.forms.displayError(response.message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
var result = response.results[0];
|
||||
this.token_ = result.token;
|
||||
this.paymentMethodNonce_ = '';
|
||||
goog.soy.renderElement(this.content_,
|
||||
registry.soy.registrar.payment.form,
|
||||
result);
|
||||
this.listen(
|
||||
goog.dom.getRequiredElementByClass(goog.getCssName('reg-payment-form')),
|
||||
goog.events.EventType.SUBMIT,
|
||||
this.onSubmit_);
|
||||
this.currencyMenu_ =
|
||||
new registry.MenuButton(goog.dom.getRequiredElement('currency'));
|
||||
this.registerDisposable(this.currencyMenu_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler invoked when payment form is submitted.
|
||||
* @param {!goog.events.BrowserEvent} e
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.Payment.prototype.onSubmit_ = function(e) {
|
||||
e.preventDefault();
|
||||
this.submit_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Submits payment form.
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.Payment.prototype.submit_ = function() {
|
||||
registry.forms.resetErrors();
|
||||
registry.registrar.Payment.setEnabled_(false);
|
||||
if (this.paymentMethodNonce_ == '') {
|
||||
this.send_(
|
||||
'type', registry.registrar.BrainFrame.MessageType.SUBMIT_REQUEST);
|
||||
return;
|
||||
}
|
||||
this.paymentRpc_.sendXhrIo(
|
||||
{
|
||||
amount: goog.dom.getRequiredElement('amount').value,
|
||||
currency: this.currencyMenu_.getValue(),
|
||||
paymentMethodNonce: this.paymentMethodNonce_
|
||||
},
|
||||
goog.bind(this.onPayment_, this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Callback for backend payment RPC that issues the transaction.
|
||||
* @param {!registry.rpc.Payment.Response} response
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.Payment.prototype.onPayment_ = function(response) {
|
||||
registry.registrar.Payment.setEnabled_(true);
|
||||
if (response.status != 'SUCCESS') {
|
||||
registry.forms.displayError(response.message, response.field);
|
||||
return;
|
||||
}
|
||||
goog.soy.renderElement(this.content_,
|
||||
registry.soy.registrar.payment.success,
|
||||
response.results[0]);
|
||||
this.listenOnce(
|
||||
goog.dom.getRequiredElementByClass(goog.getCssName('reg-payment-again')),
|
||||
goog.events.EventType.CLICK,
|
||||
this.bindToDom);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler invoked when {@code brainframe.js} sends us a message.
|
||||
* @param {!goog.events.BrowserEvent} e
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.Payment.prototype.onMessage_ = function(e) {
|
||||
var msg = /** @type {!MessageEvent.<string>} */ (e.getBrowserEvent());
|
||||
var brainframe =
|
||||
goog.dom.getElementByClass(goog.getCssName('reg-payment-form-method'));
|
||||
if (brainframe == null ||
|
||||
msg.source != goog.dom.getFrameContentWindow(brainframe)) {
|
||||
return;
|
||||
}
|
||||
var data;
|
||||
try {
|
||||
data = goog.json.parse(msg.data);
|
||||
} catch (ex) {
|
||||
// TODO(b/26876003): Figure out why it's possible that the Braintree iframe
|
||||
// is able to propagate messages up to our level.
|
||||
registry.util.log(ex, msg.source, msg.data);
|
||||
return;
|
||||
}
|
||||
switch (goog.object.get(data, 'type')) {
|
||||
case registry.registrar.BrainFrame.MessageType.TOKEN_REQUEST:
|
||||
goog.asserts.assert(this.token_ != '');
|
||||
this.send_(
|
||||
'type', registry.registrar.BrainFrame.MessageType.TOKEN_RESPONSE,
|
||||
'token', this.token_);
|
||||
break;
|
||||
case registry.registrar.BrainFrame.MessageType.RESIZE_REQUEST:
|
||||
brainframe.height = goog.object.get(data, 'height');
|
||||
break;
|
||||
case registry.registrar.BrainFrame.MessageType.READY:
|
||||
registry.registrar.Payment.setEnabled_(true);
|
||||
break;
|
||||
case registry.registrar.BrainFrame.MessageType.SUBMIT_ERROR:
|
||||
registry.registrar.Payment.setEnabled_(true);
|
||||
registry.forms.displayError(goog.object.get(data, 'message'), 'method');
|
||||
break;
|
||||
case registry.registrar.BrainFrame.MessageType.PAYMENT_METHOD:
|
||||
registry.registrar.Payment.setEnabled_(true);
|
||||
this.setPaymentMethod_(
|
||||
/** @type {!braintreepayments.PaymentMethod} */ (
|
||||
goog.object.get(data, 'method')));
|
||||
if (goog.object.get(data, 'submit')) {
|
||||
this.submit_();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw Error('Unexpected message: ' + msg.data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Updates UI to display selected payment method.
|
||||
*
|
||||
* <p>We remove the iframe from the page as soon as this happens, because the
|
||||
* UI would be busted otherwise. The Braintree UI for changing the payment
|
||||
* method (after it's been entered) does not appear to stop respond to submit
|
||||
* events. It also causes ugly scroll bars to appear inside the iframe.
|
||||
*
|
||||
* <p>This approach is also advantageous for screenshot testing. We do not want
|
||||
* our continuous integration testing system to talk to Braintree's servers. So
|
||||
* we mock out the brainframe with {@code integration-test-brainframe.html}
|
||||
* which <i>only</i> sends us a METHOD message, which we then render ourselves.
|
||||
*
|
||||
* @param {!braintreepayments.PaymentMethod} pm
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.Payment.prototype.setPaymentMethod_ = function(pm) {
|
||||
registry.forms.resetErrors();
|
||||
goog.dom.removeNode(
|
||||
goog.dom.getElementByClass(goog.getCssName('reg-payment-form-method')));
|
||||
var paymentMethodInfoBox =
|
||||
goog.dom.getRequiredElementByClass(
|
||||
goog.getCssName('reg-payment-form-method-info'));
|
||||
switch (pm.type) {
|
||||
case 'CreditCard':
|
||||
goog.soy.renderElement(
|
||||
paymentMethodInfoBox,
|
||||
registry.soy.registrar.payment.methodInfoCard,
|
||||
{cardType: pm.details.cardType, lastTwo: pm.details.lastTwo});
|
||||
break;
|
||||
case 'PayPalAccount':
|
||||
goog.soy.renderElement(
|
||||
paymentMethodInfoBox,
|
||||
registry.soy.registrar.payment.methodInfoPaypal,
|
||||
{email: pm.details.email});
|
||||
break;
|
||||
default:
|
||||
throw Error('Unknown payment method: ' + pm.type);
|
||||
}
|
||||
registry.util.setVisible(paymentMethodInfoBox, true);
|
||||
this.paymentMethodNonce_ = pm.nonce;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sends message to brainframe.
|
||||
* @param {...*} var_args Passed along to {@code goog.object.create}.
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.Payment.prototype.send_ = function(var_args) {
|
||||
goog.asserts.assert(arguments[0] == 'type');
|
||||
var brainframeWindow =
|
||||
goog.dom.getFrameContentWindow(
|
||||
goog.dom.getRequiredElementByClass(
|
||||
goog.getCssName('reg-payment-form-method')));
|
||||
// We send a string value to support older versions of IE.
|
||||
brainframeWindow.postMessage(
|
||||
goog.json.serialize(goog.object.create.apply(null, arguments)),
|
||||
'*');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Enables submit button and hides mini loading glyph.
|
||||
* @param {boolean} enabled
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.Payment.setEnabled_ = function(enabled) {
|
||||
registry.forms.setEnabled(
|
||||
goog.dom.getRequiredElementByClass(
|
||||
goog.getCssName('reg-payment-form-submit')), enabled);
|
||||
registry.util.setVisible(
|
||||
goog.dom.getRequiredElementByClass(
|
||||
goog.getCssName('reg-payment-form-loader')), !enabled);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns {@code true} if browser has all the features we need.
|
||||
* @return {boolean}
|
||||
* @private
|
||||
* @see "http://caniuse.com/#feat=dispatchevent"
|
||||
*/
|
||||
registry.registrar.Payment.isBrowserSupported_ = function() {
|
||||
// dispatchEvent is used by brainframe.js and is IE 9+.
|
||||
return goog.object.containsKey(
|
||||
goog.dom.createElement(goog.dom.TagName.FORM),
|
||||
'dispatchEvent');
|
||||
};
|
50
java/google/registry/ui/js/registrar/resources.js
Normal file
50
java/google/registry/ui/js/registrar/resources.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.Resources');
|
||||
|
||||
goog.require('goog.Uri');
|
||||
goog.require('goog.dom');
|
||||
goog.require('registry.Resource');
|
||||
goog.require('registry.ResourceComponent');
|
||||
goog.require('registry.soy.registrar.console');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Resources and billing page.
|
||||
* @param {!registry.registrar.Console} console
|
||||
* @param {string} xsrfToken Security token to pass back to the server.
|
||||
* @constructor
|
||||
* @extends {registry.ResourceComponent}
|
||||
* @final
|
||||
*/
|
||||
registry.registrar.Resources = function(console, xsrfToken) {
|
||||
registry.registrar.Resources.base(
|
||||
this,
|
||||
'constructor',
|
||||
console,
|
||||
new registry.Resource(new goog.Uri('/registrar-settings'), xsrfToken),
|
||||
registry.soy.registrar.console.resources,
|
||||
null);
|
||||
};
|
||||
goog.inherits(registry.registrar.Resources,
|
||||
registry.ResourceComponent);
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.Resources.prototype.bindToDom = function(id) {
|
||||
registry.registrar.Resources.base(this, 'bindToDom', '');
|
||||
goog.dom.removeChildren(goog.dom.getRequiredElement('reg-app-buttons'));
|
||||
};
|
110
java/google/registry/ui/js/registrar/security_settings.js
Normal file
110
java/google/registry/ui/js/registrar/security_settings.js
Normal file
|
@ -0,0 +1,110 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.SecuritySettings');
|
||||
|
||||
goog.require('goog.Uri');
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.classlist');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.events.EventType');
|
||||
goog.require('goog.soy');
|
||||
goog.require('registry.Resource');
|
||||
goog.require('registry.ResourceComponent');
|
||||
goog.require('registry.soy.registrar.security');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Security Settings page.
|
||||
* @param {!registry.registrar.Console} console
|
||||
* @param {string} xsrfToken Security token to pass back to the server.
|
||||
* @constructor
|
||||
* @extends {registry.ResourceComponent}
|
||||
* @final
|
||||
*/
|
||||
registry.registrar.SecuritySettings = function(console, xsrfToken) {
|
||||
registry.registrar.SecuritySettings.base(
|
||||
this,
|
||||
'constructor',
|
||||
console,
|
||||
new registry.Resource(new goog.Uri('/registrar-settings'), xsrfToken),
|
||||
registry.soy.registrar.security.settings,
|
||||
null);
|
||||
};
|
||||
goog.inherits(registry.registrar.SecuritySettings, registry.ResourceComponent);
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.SecuritySettings.prototype.bindToDom = function(id) {
|
||||
registry.registrar.SecuritySettings.base(this, 'bindToDom', 'fake');
|
||||
goog.dom.removeNode(goog.dom.getRequiredElement('reg-app-btn-back'));
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.SecuritySettings.prototype.setupEditor =
|
||||
function(objArgs) {
|
||||
goog.dom.classlist.add(goog.dom.getRequiredElement('ips'),
|
||||
goog.getCssName('editing'));
|
||||
var ips = goog.dom.getElementsByClass(goog.getCssName('ip'),
|
||||
goog.dom.getRequiredElement('ips'));
|
||||
goog.array.forEach(ips, function(ip) {
|
||||
var remBtn = goog.dom.getChildren(ip)[0];
|
||||
goog.events.listen(remBtn,
|
||||
goog.events.EventType.CLICK,
|
||||
goog.bind(this.onIpRemove_, this, remBtn));
|
||||
}, this);
|
||||
this.typeCounts['reg-ips'] = objArgs.ipAddressWhitelist ?
|
||||
objArgs.ipAddressWhitelist.length : 0;
|
||||
|
||||
goog.events.listen(goog.dom.getRequiredElement('btn-add-ip'),
|
||||
goog.events.EventType.CLICK,
|
||||
this.onIpAdd_,
|
||||
false,
|
||||
this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Click handler for IP add button.
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.SecuritySettings.prototype.onIpAdd_ = function() {
|
||||
var ipInputElt = goog.dom.getRequiredElement('newIp');
|
||||
var ipElt = goog.soy.renderAsFragment(registry.soy.registrar.security.ip, {
|
||||
name: 'ipAddressWhitelist[' + this.typeCounts['reg-ips'] + ']',
|
||||
ip: ipInputElt.value
|
||||
});
|
||||
goog.dom.appendChild(goog.dom.getRequiredElement('ips'), ipElt);
|
||||
var remBtn = goog.dom.getFirstElementChild(ipElt);
|
||||
goog.dom.classlist.remove(remBtn, goog.getCssName('hidden'));
|
||||
goog.events.listen(remBtn, goog.events.EventType.CLICK,
|
||||
goog.bind(this.onIpRemove_, this, remBtn));
|
||||
this.typeCounts['reg-ips']++;
|
||||
ipInputElt.value = '';
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Click handler for IP remove button.
|
||||
* @param {!Element} remBtn The remove button.
|
||||
* @private
|
||||
*/
|
||||
registry.registrar.SecuritySettings.prototype.onIpRemove_ =
|
||||
function(remBtn) {
|
||||
goog.dom.removeNode(goog.dom.getParentElement(remBtn));
|
||||
this.typeCounts['reg-ips']--;
|
||||
};
|
49
java/google/registry/ui/js/registrar/whois_settings.js
Normal file
49
java/google/registry/ui/js/registrar/whois_settings.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.WhoisSettings');
|
||||
|
||||
goog.require('goog.Uri');
|
||||
goog.require('goog.dom');
|
||||
goog.require('registry.Resource');
|
||||
goog.require('registry.ResourceComponent');
|
||||
goog.require('registry.soy.registrar.whois');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* WHOIS Settings page.
|
||||
* @param {!registry.registrar.Console} console
|
||||
* @param {string} xsrfToken Cross-site request forgery protection token.
|
||||
* @constructor
|
||||
* @extends {registry.ResourceComponent}
|
||||
* @final
|
||||
*/
|
||||
registry.registrar.WhoisSettings = function(console, xsrfToken) {
|
||||
registry.registrar.WhoisSettings.base(
|
||||
this,
|
||||
'constructor',
|
||||
console,
|
||||
new registry.Resource(new goog.Uri('/registrar-settings'), xsrfToken),
|
||||
registry.soy.registrar.whois.settings,
|
||||
null);
|
||||
};
|
||||
goog.inherits(registry.registrar.WhoisSettings, registry.ResourceComponent);
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.WhoisSettings.prototype.bindToDom = function(id) {
|
||||
registry.registrar.WhoisSettings.base(this, 'bindToDom', 'fake');
|
||||
goog.dom.removeNode(goog.dom.getRequiredElement('reg-app-btn-back'));
|
||||
};
|
217
java/google/registry/ui/js/registrar/xml_resource_component.js
Normal file
217
java/google/registry/ui/js/registrar/xml_resource_component.js
Normal file
|
@ -0,0 +1,217 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('registry.registrar.XmlResourceComponent');
|
||||
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.dom.classlist');
|
||||
goog.require('registry.EditItem');
|
||||
goog.require('registry.util');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The ResourceComponent class respresents server state for a named
|
||||
* resource and binds UI CRUD operations on it, or its constituent
|
||||
* collection.
|
||||
* @param {function()} itemTmpl
|
||||
* @param {!Object} eppTmpls Epp xml templates for info requests.
|
||||
* @param {!registry.registrar.Console} console
|
||||
* @constructor
|
||||
* @extends {registry.EditItem}
|
||||
*/
|
||||
registry.registrar.XmlResourceComponent = function(
|
||||
itemTmpl, eppTmpls, console) {
|
||||
registry.registrar.XmlResourceComponent.base(
|
||||
this, 'constructor', console, itemTmpl);
|
||||
|
||||
/** @type {!Object} */
|
||||
this.eppTmpls = eppTmpls;
|
||||
};
|
||||
goog.inherits(registry.registrar.XmlResourceComponent, registry.EditItem);
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.XmlResourceComponent.prototype.bindToDom =
|
||||
function(id) {
|
||||
// XXX: EPP resources still use null state.
|
||||
registry.registrar.XmlResourceComponent.base(
|
||||
this, 'bindToDom', (id || ''));
|
||||
if (id) {
|
||||
this.fetchItem(id);
|
||||
} else {
|
||||
// Start edit of empty object.
|
||||
this.edit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.XmlResourceComponent.prototype.fetchItem = function(id) {
|
||||
var queryParams = {id: id, clTrid: 'abc-1234'};
|
||||
var xml = this.prepareFetch(queryParams);
|
||||
this.console.session.send(xml, goog.bind(this.handleFetchItem, this, id));
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.XmlResourceComponent.prototype.handleFetchItem =
|
||||
function(id, rsp) {
|
||||
this.model = rsp;
|
||||
var result = rsp['epp']['response']['result'];
|
||||
var resCode = result['@code'];
|
||||
// XXX: Should use enum.
|
||||
if (resCode == 1000) { // OK
|
||||
this.model.readonly = true;
|
||||
this.processItem();
|
||||
this.renderItem(this.model);
|
||||
} else if (resCode == 2303) { // Missing
|
||||
registry.util.butter(
|
||||
'Could not find: "' + id + '". Please enter as "type/id"');
|
||||
} else {
|
||||
// includes general failure.
|
||||
registry.util.butter(resCode + ':' + result['msg']['keyValue']);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sublcasses should override to populate create queryParams with form
|
||||
* fields as needed. {@code queryParams.nextId} MUST be set to the
|
||||
* new object's ID.
|
||||
* @param {!Object} queryParams
|
||||
*/
|
||||
registry.registrar.XmlResourceComponent.prototype.prepareCreate =
|
||||
goog.abstractMethod;
|
||||
|
||||
|
||||
/**
|
||||
* Calls prepareCreate with template params and then send the returned
|
||||
* XML to the server
|
||||
* @override
|
||||
*/
|
||||
registry.registrar.XmlResourceComponent.prototype.sendCreate = function() {
|
||||
var form = registry.util.parseForm('item');
|
||||
var queryParams = {item: form, clTrid: 'abc-1234'};
|
||||
var xml = this.prepareCreate(queryParams);
|
||||
this.nextId = queryParams.nextId;
|
||||
this.console.session.send(xml, goog.bind(this.handleUpdateResponse, this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls prepareUpdate with template params and then send the returned
|
||||
* XML to the server.
|
||||
* @override
|
||||
*/
|
||||
registry.registrar.XmlResourceComponent.prototype.sendUpdate = function() {
|
||||
var form = registry.util.parseForm('item');
|
||||
var queryParams = {item: form, clTrid: 'abc-1234'};
|
||||
var xml = this.prepareUpdate(queryParams);
|
||||
this.nextId = queryParams.nextId;
|
||||
this.console.session.send(xml, goog.bind(this.handleUpdateResponse, this));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sublcasses should override to populate fetch queryParams with form
|
||||
* fields as needed.
|
||||
* @param {!Object} queryParams
|
||||
* @return {string} EPP xml string
|
||||
*/
|
||||
registry.registrar.XmlResourceComponent.prototype.prepareFetch =
|
||||
function(queryParams) {
|
||||
return this.eppTmpls.info(queryParams).toString();
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
registry.registrar.XmlResourceComponent.prototype.handleUpdateResponse =
|
||||
function(rsp) {
|
||||
var result = rsp['epp']['response']['result'];
|
||||
if (result['@code'] == 1000) {
|
||||
// XXX: Consider timer, probably just as a seconds arg with impl in butter.
|
||||
registry.util.butter('Saved.');
|
||||
this.fetchItem(this.nextId || '');
|
||||
this.nextId = null;
|
||||
this.toggleEdit();
|
||||
} else {
|
||||
registry.util.butter(result['msg']['keyValue']);
|
||||
}
|
||||
return rsp;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper to add add/remove hosts/contacts on queryParams:
|
||||
*
|
||||
* queryParams[op + fieldType] = formFields.
|
||||
*
|
||||
* @param {Array.<Object>} formFields named form item representations
|
||||
* that have an associated {op: (add|rem)} attribute.
|
||||
* @param {string} fieldType capitalized pluralized type name, e.g. "Contacts".
|
||||
* @param {!Object} queryParams
|
||||
*/
|
||||
registry.registrar.XmlResourceComponent.prototype.addRem =
|
||||
function(formFields, fieldType, queryParams) {
|
||||
var add = [];
|
||||
var rem = [];
|
||||
for (var i = 0; i < formFields.length; i++) {
|
||||
var formField = formFields[i];
|
||||
var op = formField['op'];
|
||||
switch (op) {
|
||||
case 'add':
|
||||
add.push(formField);
|
||||
break;
|
||||
case 'rem':
|
||||
rem.push(formField);
|
||||
break;
|
||||
default:
|
||||
registry.util.log(
|
||||
'Unknown op attribute ' + op + ' on form field:',
|
||||
formField);
|
||||
}
|
||||
}
|
||||
if (add.length > 0) {
|
||||
queryParams['add' + fieldType] = add;
|
||||
}
|
||||
if (rem.length > 0) {
|
||||
queryParams['rem' + fieldType] = rem;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Make the given form input rows removable.
|
||||
* @param {NodeList} elts array of input elements.
|
||||
* @param {function()=} opt_onclickCb called when remove button is clicked.
|
||||
*/
|
||||
registry.registrar.XmlResourceComponent.prototype.formInputRowRemovable =
|
||||
function(elts, opt_onclickCb) {
|
||||
for (var i = 0; i < elts.length; i++) {
|
||||
var parent = goog.dom.getParentElement(elts[i]);
|
||||
this.appendRemoveBtn(parent, goog.partial(function(elt) {
|
||||
var eppRemInput = goog.dom.createDom(goog.dom.TagName.INPUT, {
|
||||
'name': elt.name.replace(/\.value/, '.op'),
|
||||
'value': 'rem',
|
||||
'type': 'hidden'
|
||||
});
|
||||
goog.dom.appendChild(goog.dom.getParentElement(elt), eppRemInput);
|
||||
goog.dom.classlist.add(
|
||||
goog.dom.getParentElement(
|
||||
goog.dom.getParentElement(elt)), goog.getCssName('hidden'));
|
||||
}, elts[i]));
|
||||
}
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue