From 5520dbfac6ccbb46b68fc1fdd2101102e09badcc Mon Sep 17 00:00:00 2001 From: Bob Trahan Date: Thu, 7 May 2015 10:42:07 -0700 Subject: [PATCH] Quicksand and Pholio - make mock edit work Summary: Fixes T8036. In addition to making the mock edit work, this tightens quicksand code such that the correct page id is returned even if start() has not been called yet. It also tightens mock view where some functions should respect statics.enabled a bit more. Test Plan: clicked edit mock, mock crumb, edit mock, mock crum, edit mock, made edits and they worked! clicked edit mock, mock crumb, edit mock, mock crumb, edit mock, profile icon, hit browser back to edit mock, made edits and they worked! also observed mock view page not occasionally wigging out from image_onload race not having statics.enabled respect during the above Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin, epriestley Maniphest Tasks: T8036 Differential Revision: https://secure.phabricator.com/D12739 --- resources/celerity/map.php | 67 +++++------ .../controller/PholioMockEditController.php | 2 + .../rsrc/externals/javelin/lib/Quicksand.js | 8 +- .../pholio/behavior-pholio-mock-edit.js | 104 +++++++++++++----- .../pholio/behavior-pholio-mock-view.js | 8 ++ 5 files changed, 124 insertions(+), 65 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 53b5069337..d4e992531b 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -8,7 +8,7 @@ return array( 'names' => array( 'core.pkg.css' => 'ca3f6a60', - 'core.pkg.js' => '74e57ea0', + 'core.pkg.js' => 'ff529dc7', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => 'bb338e4b', 'differential.pkg.js' => '3cfa26f9', @@ -205,7 +205,7 @@ return array( 'rsrc/externals/javelin/lib/JSON.js' => '69adf288', 'rsrc/externals/javelin/lib/Leader.js' => '331b1611', 'rsrc/externals/javelin/lib/Mask.js' => '8a41885b', - 'rsrc/externals/javelin/lib/Quicksand.js' => '977e1f47', + 'rsrc/externals/javelin/lib/Quicksand.js' => '4cebc641', 'rsrc/externals/javelin/lib/Request.js' => '94b750d2', 'rsrc/externals/javelin/lib/Resource.js' => '44959b73', 'rsrc/externals/javelin/lib/Routable.js' => 'b3e7d692', @@ -397,8 +397,8 @@ return array( 'rsrc/js/application/owners/owners-path-editor.js' => '7a68dda3', 'rsrc/js/application/passphrase/passphrase-credential-control.js' => '3cb0b2fc', 'rsrc/js/application/phame/phame-post-preview.js' => 'be807912', - 'rsrc/js/application/pholio/behavior-pholio-mock-edit.js' => '9c2623f4', - 'rsrc/js/application/pholio/behavior-pholio-mock-view.js' => 'a4fc6fe5', + 'rsrc/js/application/pholio/behavior-pholio-mock-edit.js' => '246dc085', + 'rsrc/js/application/pholio/behavior-pholio-mock-view.js' => 'fbe497e7', 'rsrc/js/application/phortune/behavior-stripe-payment-form.js' => '3f5d6dbf', 'rsrc/js/application/phortune/behavior-test-payment-form.js' => 'fc91ab6c', 'rsrc/js/application/phortune/phortune-credit-card-form.js' => '2290aeef', @@ -626,8 +626,8 @@ return array( 'javelin-behavior-phabricator-transaction-list' => '13c739ea', 'javelin-behavior-phabricator-watch-anchor' => '9f36c42d', 'javelin-behavior-phame-post-preview' => 'be807912', - 'javelin-behavior-pholio-mock-edit' => '9c2623f4', - 'javelin-behavior-pholio-mock-view' => 'a4fc6fe5', + 'javelin-behavior-pholio-mock-edit' => '246dc085', + 'javelin-behavior-pholio-mock-view' => 'fbe497e7', 'javelin-behavior-phui-object-box-tabs' => '2bfa2836', 'javelin-behavior-phui-timeline-dropdown-menu' => '4d94d9c3', 'javelin-behavior-policy-control' => '9a340b3d', @@ -668,7 +668,7 @@ return array( 'javelin-leader' => '331b1611', 'javelin-magical-init' => '3010e992', 'javelin-mask' => '8a41885b', - 'javelin-quicksand' => '977e1f47', + 'javelin-quicksand' => '4cebc641', 'javelin-reactor' => '2b8de964', 'javelin-reactor-dom' => 'c90a04fc', 'javelin-reactor-node-calmer' => '76f4ebed', @@ -972,6 +972,16 @@ return array( 'javelin-workflow', 'javelin-util', ), + '246dc085' => array( + 'javelin-behavior', + 'javelin-stratcom', + 'javelin-dom', + 'javelin-workflow', + 'javelin-quicksand', + 'phabricator-phtize', + 'phabricator-drag-and-drop-file-upload', + 'phabricator-draggable-list', + ), '2529c82d' => array( 'javelin-dom', 'javelin-util', @@ -1117,6 +1127,9 @@ return array( 'javelin-request', 'javelin-util', ), + '4cebc641' => array( + 'javelin-install', + ), '4d94d9c3' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1578,9 +1591,6 @@ return array( 'javelin-resource', 'javelin-routable', ), - '977e1f47' => array( - 'javelin-install', - ), '988040b4' => array( 'javelin-install', 'javelin-dom', @@ -1595,15 +1605,6 @@ return array( 'phuix-action-view', 'javelin-workflow', ), - '9c2623f4' => array( - 'javelin-behavior', - 'javelin-stratcom', - 'javelin-dom', - 'javelin-workflow', - 'phabricator-phtize', - 'phabricator-drag-and-drop-file-upload', - 'phabricator-draggable-list', - ), '9f36c42d' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1650,20 +1651,6 @@ return array( 'javelin-uri', 'phabricator-notification', ), - 'a4fc6fe5' => array( - 'javelin-behavior', - 'javelin-util', - 'javelin-stratcom', - 'javelin-dom', - 'javelin-vector', - 'javelin-magical-init', - 'javelin-request', - 'javelin-history', - 'javelin-workflow', - 'javelin-mask', - 'javelin-behavior-device', - 'phabricator-keyboard-shortcut', - ), 'a80d0378' => array( 'javelin-behavior', 'javelin-stratcom', @@ -2022,6 +2009,20 @@ return array( 'javelin-vector', 'javelin-magical-init', ), + 'fbe497e7' => array( + 'javelin-behavior', + 'javelin-util', + 'javelin-stratcom', + 'javelin-dom', + 'javelin-vector', + 'javelin-magical-init', + 'javelin-request', + 'javelin-history', + 'javelin-workflow', + 'javelin-mask', + 'javelin-behavior-device', + 'phabricator-keyboard-shortcut', + ), 'fc91ab6c' => array( 'javelin-behavior', 'javelin-dom', diff --git a/src/applications/pholio/controller/PholioMockEditController.php b/src/applications/pholio/controller/PholioMockEditController.php index 357f4e49da..7cfa0b35b4 100644 --- a/src/applications/pholio/controller/PholioMockEditController.php +++ b/src/applications/pholio/controller/PholioMockEditController.php @@ -383,6 +383,8 @@ final class PholioMockEditController extends PholioController { $form_box, ); + $this->addExtraQuicksandConfig( + array('mockEditConfig' => true)); return $this->buildApplicationPage( $content, array( diff --git a/webroot/rsrc/externals/javelin/lib/Quicksand.js b/webroot/rsrc/externals/javelin/lib/Quicksand.js index f72eb23cbc..adf451ac44 100644 --- a/webroot/rsrc/externals/javelin/lib/Quicksand.js +++ b/webroot/rsrc/externals/javelin/lib/Quicksand.js @@ -25,7 +25,7 @@ JX.install('Quicksand', { statics: { - _id: 0, + _id: null, _onpage: 0, _cursor: 0, _current: 0, @@ -71,7 +71,11 @@ JX.install('Quicksand', { getCurrentPageID: function() { - return JX.Quicksand._id; + var self = JX.Quicksand; + if (self._id === null) { + self._id = window.history.state || 0; + } + return self._id; }, /** diff --git a/webroot/rsrc/js/application/pholio/behavior-pholio-mock-edit.js b/webroot/rsrc/js/application/pholio/behavior-pholio-mock-edit.js index 4977bf0a13..8a62f7d0db 100644 --- a/webroot/rsrc/js/application/pholio/behavior-pholio-mock-edit.js +++ b/webroot/rsrc/js/application/pholio/behavior-pholio-mock-edit.js @@ -4,19 +4,13 @@ * javelin-stratcom * javelin-dom * javelin-workflow + * javelin-quicksand * phabricator-phtize * phabricator-drag-and-drop-file-upload * phabricator-draggable-list */ -JX.behavior('pholio-mock-edit', function(config) { +JX.behavior('pholio-mock-edit', function(config, statics) { var pht = JX.phtize(config.pht); - - var nodes = { - list: JX.$(config.listID), - drop: JX.$(config.dropID), - order: JX.$(config.orderID) - }; - var uploading = []; @@ -26,7 +20,7 @@ JX.behavior('pholio-mock-edit', function(config) { // When the user clicks the "X" on an image, we replace it with a "click to // undo" element. If they click to undo, we put the original node back in the // DOM. - JX.Stratcom.listen('click', 'pholio-drop-remove', function(e) { + var pholio_drop_remove = function(e) { e.kill(); var node = e.getNode('pholio-drop-image'); @@ -40,37 +34,39 @@ JX.behavior('pholio-mock-edit', function(config) { JX.DOM.replace(node, undo); synchronize_order(); - }); + }; /* -( Reordering Images )-------------------------------------------------- */ - var draglist = new JX.DraggableList('pholio-drop-image', nodes.list) - .setGhostNode(JX.$N('div', {className: 'drag-ghost'})) - .setFindItemsHandler(function() { - return JX.DOM.scry(nodes.list, 'div', 'pholio-drop-image'); - }); - - // Only let the user drag images by the handle, not the whole entry. - draglist.listen('shouldBeginDrag', function(e) { - if (!e.getNode('pholio-drag-handle')) { - JX.Stratcom.context().prevent(); - } - }); - // Reflect the display order in a hidden input. var synchronize_order = function() { - var items = draglist.findItems(); + var items = statics.draglist.findItems(); var order = []; for (var ii = 0; ii < items.length; ii++) { order.push(JX.Stratcom.getData(items[ii]).filePHID); } - nodes.order.value = order.join(','); + statics.nodes.order.value = order.join(','); }; - draglist.listen('didDrop', synchronize_order); - synchronize_order(); + + var build_draglist = function(node) { + var draglist = new JX.DraggableList('pholio-drop-image', node) + .setGhostNode(JX.$N('div', {className: 'drag-ghost'})) + .setFindItemsHandler(function() { + return JX.DOM.scry(node, 'div', 'pholio-drop-image'); + }); + + // Only let the user drag images by the handle, not the whole entry. + draglist.listen('shouldBeginDrag', function(e) { + if (!e.getNode('pholio-drag-handle')) { + JX.Stratcom.context().prevent(); + } + }); + draglist.listen('didDrop', synchronize_order); + return draglist; + }; /* -( Build )-------------------------------------------------------------- */ @@ -97,7 +93,7 @@ JX.behavior('pholio-mock-edit', function(config) { drop.listen('willUpload', function(file) { var node = render_uploading(); uploading.push({node: node, file: file}); - nodes.list.appendChild(node); + statics.nodes.list.appendChild(node); }); drop.listen('didUpload', function(file) { @@ -191,7 +187,55 @@ JX.behavior('pholio-mock-edit', function(config) { /* -( Init )--------------------------------------------------------------- */ - build_add_control(nodes.drop); - build_list_controls(nodes.list); + function update_statics(data, page_id, no_build) { + statics.nodes = { + list: JX.$(data.listID), + drop: JX.$(data.dropID), + order: JX.$(data.orderID) + }; + + if (!statics.mockEditCache[page_id]) { + statics.mockEditCache[page_id] = {}; + } + statics.mockEditCache[page_id].config = config; + statics.mockEditCache[page_id].nodes = statics.nodes; + + if (no_build !== true) { + build_add_control(statics.nodes.drop); + build_list_controls(statics.nodes.list); + statics.draglist = build_draglist(statics.nodes.list); + statics.mockEditCache[page_id].draglist = statics.draglist; + } else { + statics.draglist = statics.mockEditCache[page_id].draglist; + } + synchronize_order(); + } + + function install() { + statics.mockEditCache = {}; + JX.Stratcom.listen('click', 'pholio-drop-remove', pholio_drop_remove); + JX.Stratcom.listen( + 'quicksand-redraw', + null, + function (e) { + e.kill(); + + var data = e.getData(); + if (!data.newResponse.mockEditConfig) { + return; + } + if (data.fromServer) { + // we ran update_statics(config) below already + } else { + var page_id = data.newResponseID; + var new_config = statics.mockEditCache[page_id].config; + update_statics(new_config, page_id, true); + } + }); + return true; + } + + statics.installed = statics.installed || install(); + update_statics(config, JX.Quicksand.getCurrentPageID(), false); }); diff --git a/webroot/rsrc/js/application/pholio/behavior-pholio-mock-view.js b/webroot/rsrc/js/application/pholio/behavior-pholio-mock-view.js index d873ea060e..3991f4cc4e 100644 --- a/webroot/rsrc/js/application/pholio/behavior-pholio-mock-view.js +++ b/webroot/rsrc/js/application/pholio/behavior-pholio-mock-view.js @@ -233,6 +233,10 @@ JX.behavior('pholio-mock-view', function(config, statics) { } function redraw_inlines(id) { + if (!statics.enabled) { + return; + } + if (!active_image) { return; } @@ -306,6 +310,10 @@ JX.behavior('pholio-mock-view', function(config, statics) { } function redraw_selection() { + if (!statics.enabled) { + return; + } + var classes = ['pholio-mock-reticle-selection']; selection_reticle = selection_reticle || render_reticle(classes, '');