From 2ca201dd4129b1bfb95b940d3b98148cc27d1e54 Mon Sep 17 00:00:00 2001 From: mpl Date: Mon, 20 May 2013 22:49:27 +0200 Subject: [PATCH] newui: index; select a current set, add members to it This change adds 2 buttons to the toolbar. 1) setAsCollecButton_ is enabled only when a single item (which has no content) is selected. When clicked, the button sets that item as the currently selected collection/set (BlobItemContainer.currentCollec_). 2) checkedItemsAddToSetButton_ is enabled when currentCollec_ is set and some items are selected. When clicked, it adds the selected item(s) to the current collection. Change-Id: Ib8dcfa308b03b114e54612cd790e4b24e60a9d53 --- server/camlistored/newui/blob_item.js | 15 ++++ .../camlistored/newui/blob_item_container.js | 16 +++- server/camlistored/newui/index.js | 89 +++++++++++++++++-- server/camlistored/newui/toolbar.js | 62 +++++++++++++ 4 files changed, 174 insertions(+), 8 deletions(-) diff --git a/server/camlistored/newui/blob_item.js b/server/camlistored/newui/blob_item.js index 34dcdb591..71b53bc3f 100644 --- a/server/camlistored/newui/blob_item.js +++ b/server/camlistored/newui/blob_item.js @@ -117,6 +117,21 @@ camlistore.BlobItem.resolve = function(blobRef, metaBag) { }; +/** + * @return {boolean} + */ +camlistore.BlobItem.prototype.isCollection = function() { + // TODO(mpl): for now disallow being a collection if it + // has members. What else to check? + if (!this.resolvedMetaData_ || + this.resolvedMetaData_.camliType != 'permanode' || + !this.resolvedMetaData_.permanode || + !this.resolvedMetaData_.permanode.attr || + !!this.resolvedMetaData_.permanode.attr.camliContent) { + return false; + } + return true; +}; /** * @return {string} diff --git a/server/camlistored/newui/blob_item_container.js b/server/camlistored/newui/blob_item_container.js index cdba7e94a..c8a77a79d 100644 --- a/server/camlistored/newui/blob_item_container.js +++ b/server/camlistored/newui/blob_item_container.js @@ -40,6 +40,15 @@ camlistore.BlobItemContainer = function(connection, opt_domHelper) { */ this.connection_ = connection; + /** + * BlobRef of the permanode defined as the current collection/set. + * Selected blobitems will be added as members of that collection + * upon relevant actions (e.g click on the 'Add to Set' toolbar button). + * @type {string} + * @private + */ + this.currentCollec_ = ""; + /** * @type {goog.events.EventHandler} * @private @@ -81,7 +90,8 @@ camlistore.BlobItemContainer.prototype.dragDepth_ = 0; * @enum {string} */ camlistore.BlobItemContainer.EventType = { - BLOB_ITEMS_CHOSEN: 'Camlistore_BlobItemContainer_BlobItems_Chosen' + BLOB_ITEMS_CHOSEN: 'Camlistore_BlobItemContainer_BlobItems_Chosen', + SINGLE_NODE_CHOSEN: 'Camlistore_BlobItemContainer_SingleNode_Chosen' }; @@ -368,6 +378,7 @@ camlistore.BlobItemContainer.prototype.handleBlobItemChecked_ = function(e) { this.checkedBlobItems_.push(item); } } + this.dispatchEvent(camlistore.BlobItemContainer.EventType.BLOB_ITEMS_CHOSEN); } else if (isCtrlMultiSelect) { if (isCheckingItem) { blobItem.setState(goog.ui.Component.State.CHECKED, true); @@ -395,6 +406,7 @@ camlistore.BlobItemContainer.prototype.handleBlobItemChecked_ = function(e) { } } } + this.dispatchEvent(camlistore.BlobItemContainer.EventType.BLOB_ITEMS_CHOSEN); } else { // unselect all chosen items. goog.array.forEach(this.checkedBlobItems_, function(item) { @@ -406,8 +418,8 @@ camlistore.BlobItemContainer.prototype.handleBlobItemChecked_ = function(e) { } else { this.checkedBlobItems_ = []; } + this.dispatchEvent(camlistore.BlobItemContainer.EventType.SINGLE_NODE_CHOSEN); } - this.dispatchEvent(camlistore.BlobItemContainer.EventType.BLOB_ITEMS_CHOSEN); }; /** diff --git a/server/camlistored/newui/index.js b/server/camlistored/newui/index.js index 2ee3a5dc2..c7f4e8859 100644 --- a/server/camlistored/newui/index.js +++ b/server/camlistored/newui/index.js @@ -132,12 +132,69 @@ camlistore.IndexPage.prototype.enterDocument = function() { this.createNewSetWithItems_(blobItems); }); + this.eh_.listen( + this.toolbar_, camlistore.Toolbar.EventType.CHECKED_ITEMS_ADDTO_SET, + function() { + var blobItems = this.blobItemContainer_.getCheckedBlobItems(); + this.addItemsToSet_(blobItems); + }); + + this.eh_.listen( + this.toolbar_, camlistore.Toolbar.EventType.SELECT_COLLEC, + function() { + var blobItems = this.blobItemContainer_.getCheckedBlobItems(); + // there should be only one item selected + if (blobItems.length != 1) { + alert("Cannet set multiple items as current collection"); + return; + } + this.blobItemContainer_.currentCollec_ = blobItems[0].blobRef_; + this.blobItemContainer_.unselectAll(); + this.toolbar_.setCheckedBlobItemCount(0); + this.toolbar_.toggleCollecButton(false); + this.toolbar_.toggleAddToSetButton(false); + }); + + // TODO(mpl): those are getting large. make dedicated funcs. this.eh_.listen( this.blobItemContainer_, camlistore.BlobItemContainer.EventType.BLOB_ITEMS_CHOSEN, function() { var blobItems = this.blobItemContainer_.getCheckedBlobItems(); this.toolbar_.setCheckedBlobItemCount(blobItems.length); + // set checkedItemsAddToSetButton_ + if (this.blobItemContainer_.currentCollec_ && + this.blobItemContainer_.currentCollec_ != "" && + blobItems.length > 0) { + this.toolbar_.toggleAddToSetButton(true); + } else { + this.toolbar_.toggleAddToSetButton(false); + } + // set setAsCollecButton_ + this.toolbar_.toggleCollecButton(false); + }); + + this.eh_.listen( + this.blobItemContainer_, + camlistore.BlobItemContainer.EventType.SINGLE_NODE_CHOSEN, + function() { + var blobItems = this.blobItemContainer_.getCheckedBlobItems(); + this.toolbar_.setCheckedBlobItemCount(blobItems.length); + // set checkedItemsAddToSetButton_ + if (this.blobItemContainer_.currentCollec_ && + this.blobItemContainer_.currentCollec_ != "" && + blobItems.length > 0) { + this.toolbar_.toggleAddToSetButton(true); + } else { + this.toolbar_.toggleAddToSetButton(false); + } + // set setAsCollecButton_ + if (blobItems.length == 1 && + blobItems[0].isCollection()) { + this.toolbar_.toggleCollecButton(true); + } else { + this.toolbar_.toggleCollecButton(false); + } }); this.blobItemContainer_.showRecent(); @@ -160,28 +217,44 @@ camlistore.IndexPage.prototype.exitDocument = function() { */ camlistore.IndexPage.prototype.createNewSetWithItems_ = function(blobItems) { this.connection_.createPermanode( - goog.bind(this.createPermanodeDone_, this, blobItems)); + goog.bind(this.addMembers_, this, true, blobItems)); }; +/** + * @param {Array.} blobItems Items to add to the permanode. + * @private + */ +camlistore.IndexPage.prototype.addItemsToSet_ = function(blobItems) { + if (!this.blobItemContainer_.currentCollec_ || + this.blobItemContainer_.currentCollec_ == "") { + alert("no destination collection selected"); + } + this.addMembers_(false, blobItems, this.blobItemContainer_.currentCollec_); +}; /** + * @param {boolean} newSet Whether the containing set has just been created. * @param {Array.} blobItems Items to add to the permanode. * @param {string} permanode Node to add the items to. * @private */ -camlistore.IndexPage.prototype.createPermanodeDone_ = - function(blobItems, permanode) { +camlistore.IndexPage.prototype.addMembers_ = + function(newSet, blobItems, permanode) { var deferredList = []; var complete = goog.bind(this.addItemsToSetDone_, this, permanode); var callback = function() { deferredList.push(1); - if (deferredList.length == blobItems.length + 1) { + if (deferredList.length == blobItems.length) { complete(); } }; - this.connection_.newAddAttributeClaim( - permanode, 'title', 'My new set', callback); + // TODO(mpl): newSet is a lame trick. Do better. + if (newSet) { + this.connection_.newSetAttributeClaim( + permanode, 'title', 'My new set', function() {} + ); + } goog.array.forEach(blobItems, function(blobItem, index) { this.connection_.newAddAttributeClaim( permanode, 'camliMember', blobItem.getBlobRef(), callback); @@ -194,5 +267,9 @@ camlistore.IndexPage.prototype.createPermanodeDone_ = * @private */ camlistore.IndexPage.prototype.addItemsToSetDone_ = function(permanode) { + this.blobItemContainer_.unselectAll(); + this.toolbar_.setCheckedBlobItemCount(0); + this.toolbar_.toggleCollecButton(false); + this.toolbar_.toggleAddToSetButton(false); this.blobItemContainer_.showRecent(); }; diff --git a/server/camlistored/newui/toolbar.js b/server/camlistored/newui/toolbar.js index 0b322df8d..9e8eed053 100644 --- a/server/camlistored/newui/toolbar.js +++ b/server/camlistored/newui/toolbar.js @@ -46,6 +46,25 @@ camlistore.Toolbar = function(opt_domHelper) { this.checkedItemsCreateSetButton_ = new goog.ui.ToolbarButton(''); this.checkedItemsCreateSetButton_.addClassName('cam-checked-items'); + /** + * Used only on the index page (for now) + * @type {goog.ui.ToolbarButton} + * @private + */ + this.checkedItemsAddToSetButton_ = new goog.ui.ToolbarButton('Add to Set'); + this.checkedItemsAddToSetButton_.addClassName('cam-checked-items'); + this.checkedItemsAddToSetButton_.setEnabled(false); + + /** + * Used only on the index page (for now) + * @type {goog.ui.ToolbarButton} + * @private + */ + this.setAsCollecButton_ = new goog.ui.ToolbarButton('Select as current Set'); + this.setAsCollecButton_.addClassName('cam-checked-items'); + this.setAsCollecButton_.setEnabled(false); + + /** * Used only on the search page * @type {goog.ui.ToolbarButton} @@ -102,6 +121,8 @@ camlistore.Toolbar.EventType = { ROOTS: 'Camlistore_Toolbar_SearchRoots', GOSEARCH: 'Camlistore_Toolbar_GoSearch', HELP: 'Camlistore_Toolbar_Help', + CHECKED_ITEMS_ADDTO_SET: 'Camlistore_Toolbar_Checked_Items_Addto_set', + SELECT_COLLEC: 'Camlistore_Toolbar_Select_collec', CHECKED_ITEMS_CREATE_SET: 'Camlistore_Toolbar_Checked_Items_Create_set' }; @@ -134,6 +155,8 @@ camlistore.Toolbar.prototype.decorateInternal = function(el) { this.addChild(this.rootsButton_, true); this.addChild(this.helpButton_, true); } else { + this.addChild(this.setAsCollecButton_, true); + this.addChild(this.checkedItemsAddToSetButton_, true); this.addChild(this.goSearchButton_, true); } }; @@ -163,6 +186,7 @@ camlistore.Toolbar.prototype.enterDocument = function() { goog.bind(this.dispatch_, this, camlistore.Toolbar.EventType.SMALLER)); if (this.isSearch == "true") { + this.eh_.listen( this.rootsButton_.getElement(), goog.events.EventType.CLICK, @@ -174,10 +198,24 @@ camlistore.Toolbar.prototype.enterDocument = function() { goog.bind(this.dispatch_, this, camlistore.Toolbar.EventType.HOME)); } else { + + this.eh_.listen( + this.setAsCollecButton_.getElement(), + goog.events.EventType.CLICK, + goog.bind(this.dispatch_, this, + camlistore.Toolbar.EventType.SELECT_COLLEC)); + + this.eh_.listen( + this.checkedItemsAddToSetButton_.getElement(), + goog.events.EventType.CLICK, + goog.bind(this.dispatch_, this, + camlistore.Toolbar.EventType.CHECKED_ITEMS_ADDTO_SET)); + this.eh_.listen( this.goSearchButton_.getElement(), goog.events.EventType.CLICK, goog.bind(this.dispatch_, this, camlistore.Toolbar.EventType.GOSEARCH)); + } this.eh_.listen( @@ -185,6 +223,7 @@ camlistore.Toolbar.prototype.enterDocument = function() { goog.events.EventType.CLICK, goog.bind(this.dispatch_, this, camlistore.Toolbar.EventType.CHECKED_ITEMS_CREATE_SET)); + }; @@ -221,3 +260,26 @@ camlistore.Toolbar.prototype.setCheckedBlobItemCount = function(count) { } }; +/** + * TODO: i18n. + * @param {boolean} enable + */ +camlistore.Toolbar.prototype.toggleCollecButton = function(enable) { + if (enable) { + this.setAsCollecButton_.setEnabled(true); + } else { + this.setAsCollecButton_.setEnabled(false); + } +}; + +/** + * TODO: i18n. + * @param {boolean} enable + */ +camlistore.Toolbar.prototype.toggleAddToSetButton = function(enable) { + if (enable) { + this.checkedItemsAddToSetButton_.setEnabled(true); + } else { + this.checkedItemsAddToSetButton_.setEnabled(false); + } +};