2 column picker WIP
diff --git a/planetstack/core/xoslib/static/js/picker.js b/planetstack/core/xoslib/static/js/picker.js
new file mode 100644
index 0000000..0302cf4
--- /dev/null
+++ b/planetstack/core/xoslib/static/js/picker.js
@@ -0,0 +1,50 @@
+function init_picker(selector, ordered) {
+ //console.log("init_picker");
+ //console.log($(selector));
+
+ var addBtn = $(selector).find(".btn-picker-add");
+ var removeBtn = $(selector).find(".btn-picker-remove");
+ var upBtn = $(selector).find(".btn-picker-up");
+ var downBtn = $(selector).find(".btn-picker-down");
+ var from = $(selector).find(".select-picker-from");
+ var to = $(selector).find(".select-picker-to");
+
+ if (!ordered) {
+ upBtn.hide();
+ downBtn.hide();
+ }
+
+ addBtn.click(function(){
+ console.log("add");
+ from.find(":selected").each( function() {
+ to.append("<option value='"+$(this).val()+"'>"+$(this).text()+"</option>");
+ $(this).remove();
+ });
+ });
+ removeBtn.click(function(){
+ console.log("remove");
+ to.find(":selected").each( function() {
+ from.append("<option value='"+$(this).val()+"'>"+$(this).text()+"</option>");
+ $(this).remove();
+ });
+ });
+ upBtn.bind('click', function() {
+ to.find(":selected").each( function() {
+ var newPos = to.find('option').index(this) - 1;
+ if (newPos > -1) {
+ to.find("option").eq(newPos).before("<option value='"+$(this).val()+"' selected='selected'>"+$(this).text()+"</option>");
+ $(this).remove();
+ }
+ });
+ });
+ downBtn.bind('click', function() {
+ var countOptions = to.find("option").size();
+ to.find(":selected").each( function() {
+ var newPos = to.find("option").index(this) + 1;
+ if (newPos < countOptions) {
+ to.find("option").eq(newPos).after("<option value='"+$(this).val()+"' selected='selected'>"+$(this).text()+"</option>");
+ $(this).remove();
+ }
+ });
+ });
+};
diff --git a/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js b/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js
index 554ff5f..b0ee0dc 100644
--- a/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js
+++ b/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js
@@ -79,6 +79,20 @@
return Backbone.Model.prototype.save.call(this, attributes, options);
},
+ getChoices: function(fieldName, excludeChosen) {
+ choices=[];
+ if (fieldName in this.m2mFields) {
+ for (index in xos[this.m2mFields[fieldName]].models) {
+ candidate = xos[this.m2mFields[fieldName]].models[index];
+ if (excludeChosen && idInArray(candidate.id, this.attributes[fieldName])) {
+ continue;
+ }
+ choices.push(candidate.id);
+ }
+ }
+ return choices;
+ },
+
/* If a 'validate' method is supplied, then it will be called
automatically on save. Unfortunately, save calls neither the
'error' nor the 'success' callback if the validator fails.
@@ -324,6 +338,7 @@
attrs.inputType = attrs.inputType || {};
attrs.foreignFields = attrs.foreignFields || {};
+ attrs.m2mFields = attrs.m2mFields || {};
attrs.readOnlyFields = attrs.readOnlyFields || [];
attrs.detailLinkFields = attrs.detailLinkFields || ["id","name"];
@@ -473,9 +488,11 @@
define_model(this, { urlRoot: DEPLOYMENT_API,
relatedCollections: {"nodes": "deployment", "slivers": "deploymentNetwork", "networkDeployments": "deployment", "userDeployments": "deployment"},
+ m2mFields: {"flavors": "flavors", "sites": "sites", "images": "images"},
modelName: "deployment",
listFields: ["backend_status", "id", "name", "backend_type", "admin_tenant"],
- detailFields: ["backend_status", "name", "backend_type", "admin_tenant"],
+ detailFields: ["backend_status", "name", "backend_type", "admin_tenant", "flavors", "sites", "images"],
+ inputType: {"flavors": "picker", "sites": "picker", "images": "picker"},
});
define_model(this, {urlRoot: IMAGE_API,
@@ -529,9 +546,10 @@
define_model(this, {urlRoot: FLAVOR_API,
modelName: "flavor",
+ m2mFields: {"deployments": "deployments"},
listFields: ["backend_status", "id", "name", "flavor", "order", "default"],
- detailFields: ["backend_status", "name", "description", "flavor", "order", "default"],
- inputType: {"default": "checkbox"},
+ detailFields: ["backend_status", "name", "description", "flavor", "order", "default", "deployments"],
+ inputType: {"default": "checkbox", "deployments": "picker"},
});
// enhanced REST
diff --git a/planetstack/core/xoslib/static/js/xoslib/xos-util.js b/planetstack/core/xoslib/static/js/xoslib/xos-util.js
index 638ba9a..3fd597b 100644
--- a/planetstack/core/xoslib/static/js/xoslib/xos-util.js
+++ b/planetstack/core/xoslib/static/js/xoslib/xos-util.js
@@ -1,5 +1,15 @@
// misc utility functions
+function idInArray(id, arr) {
+ // because sometimes ids are strings and sometimes they're integers
+ for (index in arr) {
+ if (id.toString() == arr[index].toString()) {
+ return true;
+ }
+ }
+ return false;
+}
+
function assert(outcome, description) {
if (!outcome) {
console.log(description);
diff --git a/planetstack/core/xoslib/static/js/xoslib/xosHelper.js b/planetstack/core/xoslib/static/js/xoslib/xosHelper.js
index 65ccdbd..fe975aa 100644
--- a/planetstack/core/xoslib/static/js/xoslib/xosHelper.js
+++ b/planetstack/core/xoslib/static/js/xoslib/xosHelper.js
@@ -404,6 +404,8 @@
XOSDetailView = Marionette.ItemView.extend({
tagName: "div",
+ viewInitializers: [],
+
events: {"click button.btn-xos-save-continue": "submitContinueClicked",
"click button.btn-xos-save-leave": "submitLeaveClicked",
"click button.btn-xos-save-another": "submitAddAnotherClicked",
@@ -420,6 +422,12 @@
this.synchronous = false;
},
+ onShow: function() {
+ _.each(this.viewInitializers, function(initializer) {
+ initializer();
+ });
+ },
+
afterSave: function(e) {
},
@@ -574,7 +582,6 @@
onFormDataInvalid: function(errors) {
var self=this;
var markErrors = function(value, key) {
- console.log("name='" + key + "'");
var $inputElement = self.$el.find("[name='" + key + "']");
var $inputContainer = $inputElement.parent();
//$inputContainer.find(".help-inline").remove();
@@ -593,6 +600,7 @@
detailLinkFields: this.model.detailLinkFields,
inputType: this.model.inputType,
model: this.model,
+ detailView: this,
}},
});
@@ -972,6 +980,10 @@
return xos.idToName(id, collectionName, fieldName);
};
+makeIdToName = function(collectionName, fieldName) {
+ return function(id) { return idToName(id, collectionName, fieldName); }
+};
+
/* Constructs lists of <option> html blocks for items in a collection.
selectedId = the id of an object that should be selected, if any