mirror of
https://github.com/google/nomulus.git
synced 2025-04-30 12:07:51 +02:00
Forward declares symbol. This is an indication to the compiler that the symbol may be used in the source yet is not required and may not be provided in compilation. The most common usage of forward declaration is code that takes a type as a function parameter but does not need to require it. By forward declaring instead of requiring, no hard dependency is made, and (if not required elsewhere) the namespace may never be required and thus, not be pulled into the JavaScript binary. If it is required elsewhere, it will be type checked as normal. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=127095620
296 lines
8.8 KiB
JavaScript
296 lines
8.8 KiB
JavaScript
// 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.EditItem');
|
|
|
|
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.Component');
|
|
goog.require('registry.soy.console');
|
|
goog.require('registry.util');
|
|
|
|
goog.forwardDeclare('registry.Console');
|
|
|
|
|
|
|
|
/**
|
|
* An editable item, with Edit and Save/Cancel buttons in the appbar.
|
|
* @param {!registry.Console} cons
|
|
* @param {function()} itemTmpl
|
|
* @constructor
|
|
* @extends {registry.Component}
|
|
*/
|
|
registry.EditItem = function(cons, itemTmpl) {
|
|
registry.EditItem.base(this, 'constructor', cons);
|
|
|
|
/**
|
|
* @type {!Function}
|
|
*/
|
|
this.itemTmpl = itemTmpl;
|
|
|
|
/**
|
|
* Optional current target resource id.
|
|
* @type {?string}
|
|
*/
|
|
this.id = null;
|
|
|
|
/**
|
|
* Transitional id for next resource during create.
|
|
* @type {?string}
|
|
*/
|
|
this.nextId = null;
|
|
};
|
|
goog.inherits(registry.EditItem, registry.Component);
|
|
|
|
|
|
/** @override */
|
|
registry.EditItem.prototype.bindToDom = function(id) {
|
|
registry.EditItem.base(this, 'bindToDom', id);
|
|
this.id = id;
|
|
this.nextId = null;
|
|
this.setupAppbar();
|
|
};
|
|
|
|
|
|
/** Setup appbar save/edit buttons. */
|
|
registry.EditItem.prototype.setupAppbar = function() {
|
|
goog.soy.renderElement(goog.dom.getRequiredElement('reg-appbar'),
|
|
registry.soy.console.appbarButtons);
|
|
goog.events.listen(goog.dom.getRequiredElement('reg-app-btn-add'),
|
|
goog.events.EventType.CLICK,
|
|
goog.bind(this.add, this));
|
|
goog.events.listen(goog.dom.getRequiredElement('reg-app-btn-edit'),
|
|
goog.events.EventType.CLICK,
|
|
goog.bind(this.edit, this));
|
|
goog.events.listen(goog.dom.getRequiredElement('reg-app-btn-save'),
|
|
goog.events.EventType.CLICK,
|
|
goog.bind(this.save, this));
|
|
goog.events.listen(goog.dom.getRequiredElement('reg-app-btn-cancel'),
|
|
goog.events.EventType.CLICK,
|
|
goog.bind(this.cancel, this));
|
|
goog.events.listen(goog.dom.getRequiredElement('reg-app-btn-back'),
|
|
goog.events.EventType.CLICK,
|
|
goog.bind(this.back, this));
|
|
if (this.id) {
|
|
registry.util.setVisible('reg-app-btns-edit', true);
|
|
} else {
|
|
registry.util.setVisible('reg-app-btn-add', true);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Retrieve item from server. Overrides should callback to {@code
|
|
* #handleFetchItem(string, !Object)}.
|
|
* @param {string} id item id.
|
|
*/
|
|
registry.EditItem.prototype.fetchItem = goog.abstractMethod;
|
|
|
|
|
|
/**
|
|
* Handle result decoding and display.
|
|
* @param {string} id The requested ID/name, for error message.
|
|
* @param {!Object} rsp The requested object.
|
|
*/
|
|
registry.EditItem.prototype.handleFetchItem = goog.abstractMethod;
|
|
|
|
|
|
/** Subclasses should override to continue processing after fetch. */
|
|
registry.EditItem.prototype.processItem = function() {};
|
|
|
|
|
|
/**
|
|
* Show the item.
|
|
* @param {!Object} objArgs
|
|
*/
|
|
registry.EditItem.prototype.renderItem = function(objArgs) {
|
|
goog.soy.renderElement(goog.dom.getRequiredElement('reg-content'),
|
|
this.itemTmpl,
|
|
objArgs);
|
|
};
|
|
|
|
|
|
/**
|
|
* @return {boolean} if the component is currently being edited.
|
|
*/
|
|
registry.EditItem.prototype.isEditing = function() {
|
|
return goog.dom.classlist.contains(
|
|
goog.dom.getElement('reg-app'), goog.getCssName('editing'));
|
|
};
|
|
|
|
|
|
/**
|
|
* Toggles the editing state of a component. This will first hide the
|
|
* elements of the {@code shown} class, then adds the {@code editing}
|
|
* style to the component, then shows the elements that had the {@code
|
|
* hidden} class.
|
|
*/
|
|
registry.EditItem.prototype.toggleEdit = function() {
|
|
// Toggle appbar buttons.
|
|
var addBtn = goog.dom.getRequiredElement('reg-app-btn-add');
|
|
var editBtns = goog.dom.getRequiredElement('reg-app-btns-edit');
|
|
var saveBtns = goog.dom.getRequiredElement('reg-app-btns-save');
|
|
var editing = goog.dom.classlist.contains(saveBtns,
|
|
registry.util.cssShown);
|
|
if (editing) {
|
|
registry.util.setVisible(saveBtns, false);
|
|
if (this.id) {
|
|
registry.util.setVisible(editBtns, true);
|
|
} else {
|
|
registry.util.setVisible(addBtn, true);
|
|
}
|
|
} else {
|
|
if (this.id) {
|
|
registry.util.setVisible(editBtns, false);
|
|
} else {
|
|
registry.util.setVisible(addBtn, false);
|
|
}
|
|
registry.util.setVisible(saveBtns, true);
|
|
}
|
|
// Then page contents.
|
|
var parentElt = goog.dom.getElement('reg-content');
|
|
var shownCssName = goog.getCssName('shown');
|
|
var hiddenCssName = goog.getCssName('hidden');
|
|
var shown = goog.dom.getElementsByClass(shownCssName, parentElt);
|
|
var hidden = goog.dom.getElementsByClass(hiddenCssName, parentElt);
|
|
|
|
for (var i = 0; i < shown.length; i++) {
|
|
goog.dom.classlist.addRemove(shown[i], shownCssName, hiddenCssName);
|
|
}
|
|
|
|
// Then add editing styles.
|
|
var editingCssName = goog.getCssName('editing');
|
|
var startingEdit = !goog.dom.classlist.contains(parentElt, editingCssName);
|
|
if (startingEdit) {
|
|
goog.dom.classlist.remove(parentElt, editingCssName);
|
|
} else {
|
|
goog.dom.classlist.add(parentElt, editingCssName);
|
|
}
|
|
|
|
// The show hiddens.
|
|
for (var i = 0; i < hidden.length; i++) {
|
|
goog.dom.classlist.addRemove(hidden[i], hiddenCssName, shownCssName);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Subclasses should override to enhance the default model.
|
|
* @return {!Object.<string, ?>}
|
|
*/
|
|
registry.EditItem.prototype.newModel = function() {
|
|
return {item: {}};
|
|
};
|
|
|
|
|
|
// N.B. setting these as abstract precludes their correct binding in
|
|
// setupAppbar.
|
|
/** Show add item panel. */
|
|
registry.EditItem.prototype.add = function() {};
|
|
|
|
|
|
/** Go back from item to collection view. */
|
|
registry.EditItem.prototype.back = function() {};
|
|
|
|
|
|
/** Sets up initial edit model state and then called edit(objArgs). */
|
|
registry.EditItem.prototype.edit = function() {
|
|
var objArgs = this.model;
|
|
if (objArgs == null) {
|
|
objArgs = this.newModel();
|
|
}
|
|
// XXX: This is vestigial. In the new msg format, this pollutes the
|
|
// server-model state. Should be carried elsewhere.
|
|
objArgs.readonly = false;
|
|
this.renderItem(objArgs);
|
|
this.setupEditor(objArgs);
|
|
this.toggleEdit();
|
|
};
|
|
|
|
|
|
/**
|
|
* Save the current item. Calls either create if creating a new
|
|
* object or update otherwise.
|
|
*/
|
|
registry.EditItem.prototype.save = function() {
|
|
if (this.model == null) {
|
|
this.sendCreate();
|
|
} else {
|
|
this.sendUpdate();
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Resets to non-editing, readonly state, or visits home screen if the
|
|
* page was in on a create panel.
|
|
*/
|
|
registry.EditItem.prototype.cancel = function() {
|
|
this.toggleEdit();
|
|
// XXX: The presence of a model is sufficent for non-collection pages, but an
|
|
// empty id also means go to the collection in collection pages. Should
|
|
// be simplified.
|
|
if (this.model && this.id != '') {
|
|
this.model.readonly = true;
|
|
this.renderItem(this.model);
|
|
} else {
|
|
this.bindToDom('');
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Called after this.renderItem(), to allow for further setup of
|
|
* editing.
|
|
* @param {!Object} objArgs
|
|
*/
|
|
registry.EditItem.prototype.setupEditor = function(objArgs) {};
|
|
|
|
|
|
// XXX: These should really take @param {object} which is the form. Alas the
|
|
// only override which doesn't work this way, ResourceComponent.sendCreate
|
|
// breaks this opportunity. Hmmm...
|
|
/** Subclasses should extract form values and send them to the server. */
|
|
registry.EditItem.prototype.sendCreate = goog.abstractMethod;
|
|
|
|
|
|
/** Subclasses should extract form values and send them to the server. */
|
|
registry.EditItem.prototype.sendUpdate = goog.abstractMethod;
|
|
|
|
|
|
/** Subclasses should extract form values and send them to the server. */
|
|
registry.EditItem.prototype.sendDelete = goog.abstractMethod;
|
|
|
|
|
|
/**
|
|
* Sublcasses should override to populate update queryParams with form
|
|
* fields as needed. {@code queryParams.nextId} MUST be set to the
|
|
* new object's ID.
|
|
* @param {!Object} queryParams
|
|
*/
|
|
registry.EditItem.prototype.prepareUpdate = goog.abstractMethod;
|
|
|
|
|
|
/**
|
|
* Subclasses should provide a funtion to parse either XML or JSON response
|
|
* from server and return a result object as described below.
|
|
* @param {!Object} rsp Decoded XML/JSON response from the server.
|
|
* @return {!Object} a result object describing next steps. On
|
|
* success, if next is defined, visit(ret.next) is called, otherwise
|
|
* if err is set, the butterbar message is set to it.
|
|
*/
|
|
registry.EditItem.prototype.handleUpdateResponse = goog.abstractMethod;
|