diff --git a/externals/javelin b/externals/javelin index c614793279..d9a1cb4c16 160000 --- a/externals/javelin +++ b/externals/javelin @@ -1 +1 @@ -Subproject commit c614793279a6b7fffed7b1fa40c005f7ad5effd6 +Subproject commit d9a1cb4c16866aec38f062eee9f3d2129c885b62 diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index 5e6a2f087a..1681077ab4 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -179,16 +179,6 @@ celerity_register_resource_map(array( ), 'disk' => '/rsrc/css/application/differential/revision-comment-list.css', ), - 0 => - array( - 'uri' => '/res/39de799e/rsrc/js/javelin/docs/Base.js', - 'type' => 'js', - 'requires' => - array( - 0 => 'javelin-install', - ), - 'disk' => '/rsrc/js/javelin/docs/Base.js', - ), 'differential-revision-detail-css' => array( 'uri' => '/res/ea9de420/rsrc/css/application/differential/revision-detail.css', @@ -225,15 +215,6 @@ celerity_register_resource_map(array( ), 'disk' => '/rsrc/css/application/diffusion/commit-view.css', ), - 'diffusion-source-css' => - array( - 'uri' => '/res/415aad1a/rsrc/css/application/diffusion/diffusion-source.css', - 'type' => 'css', - 'requires' => - array( - ), - 'disk' => '/rsrc/css/application/diffusion/diffusion-source.css', - ), 'herald-css' => array( 'uri' => '/res/5051f3ab/rsrc/css/application/herald/herald.css', @@ -475,6 +456,19 @@ celerity_register_resource_map(array( ), 'disk' => '/rsrc/js/application/maniphest/behavior-transaction-controls.js', ), + 'javelin-behavior-maniphest-transaction-expand' => + array( + 'uri' => '/res/966410de/rsrc/js/application/maniphest/behavior-transaction-expand.js', + 'type' => 'js', + 'requires' => + array( + 0 => 'javelin-behavior', + 1 => 'javelin-dom', + 2 => 'javelin-workflow', + 3 => 'javelin-stratcom', + ), + 'disk' => '/rsrc/js/application/maniphest/behavior-transaction-expand.js', + ), 'javelin-behavior-maniphest-transaction-preview' => array( 'uri' => '/res/44e86555/rsrc/js/application/maniphest/behavior-transaction-preview.js', @@ -539,6 +533,16 @@ celerity_register_resource_map(array( ), 'disk' => '/rsrc/js/javelin/lib/DOM.js', ), + 0 => + array( + 'uri' => '/res/39de799e/rsrc/js/javelin/docs/Base.js', + 'type' => 'js', + 'requires' => + array( + 0 => 'javelin-install', + ), + 'disk' => '/rsrc/js/javelin/docs/Base.js', + ), 'javelin-event' => array( 'uri' => '/res/25c7c9e8/rsrc/js/javelin/core/Event.js', @@ -562,7 +566,7 @@ celerity_register_resource_map(array( ), 'javelin-json' => array( - 'uri' => '/res/315c8b24/rsrc/js/javelin/lib/JSON.js', + 'uri' => '/res/1c4e3f6a/rsrc/js/javelin/lib/JSON.js', 'type' => 'js', 'requires' => array( @@ -607,7 +611,7 @@ celerity_register_resource_map(array( ), 'javelin-stratcom' => array( - 'uri' => '/res/d3f4599a/rsrc/js/javelin/core/Stratcom.js', + 'uri' => '/res/9e7eb62b/rsrc/js/javelin/core/Stratcom.js', 'type' => 'js', 'requires' => array( @@ -764,7 +768,7 @@ celerity_register_resource_map(array( ), 'maniphest-transaction-detail-css' => array( - 'uri' => '/res/8e196c52/rsrc/css/application/maniphest/transaction-detail.css', + 'uri' => '/res/0a35f731/rsrc/css/application/maniphest/transaction-detail.css', 'type' => 'css', 'requires' => array( @@ -998,7 +1002,7 @@ celerity_register_resource_map(array( 'uri' => '/res/pkg/33f413ef/typeahead.pkg.js', 'type' => 'js', ), - '7d23deb1' => + 'ce1d51a9' => array ( 'name' => 'javelin.pkg.js', 'symbols' => @@ -1014,7 +1018,7 @@ celerity_register_resource_map(array( 8 => 'javelin-json', 9 => 'javelin-uri', ), - 'uri' => '/res/pkg/7d23deb1/javelin.pkg.js', + 'uri' => '/res/pkg/ce1d51a9/javelin.pkg.js', 'type' => 'js', ), 'ed383f69' => @@ -1052,7 +1056,7 @@ celerity_register_resource_map(array( 'differential-revision-history-css' => '314934dc', 'differential-table-of-contents-css' => '314934dc', 'diffusion-commit-view-css' => '03ef179e', - 'javelin-behavior' => '7d23deb1', + 'javelin-behavior' => 'ce1d51a9', 'javelin-behavior-aphront-basic-tokenizer' => '33f413ef', 'javelin-behavior-differential-diff-radios' => 'ed383f69', 'javelin-behavior-differential-edit-inline-comments' => 'ed383f69', @@ -1060,22 +1064,22 @@ celerity_register_resource_map(array( 'javelin-behavior-differential-populate' => 'ed383f69', 'javelin-behavior-differential-show-more' => 'ed383f69', 'javelin-behavior-workflow' => '122a6b6d', - 'javelin-dom' => '7d23deb1', - 'javelin-event' => '7d23deb1', - 'javelin-install' => '7d23deb1', - 'javelin-json' => '7d23deb1', + 'javelin-dom' => 'ce1d51a9', + 'javelin-event' => 'ce1d51a9', + 'javelin-install' => 'ce1d51a9', + 'javelin-json' => 'ce1d51a9', 'javelin-mask' => '122a6b6d', - 'javelin-request' => '7d23deb1', - 'javelin-stratcom' => '7d23deb1', + 'javelin-request' => 'ce1d51a9', + 'javelin-stratcom' => 'ce1d51a9', 'javelin-tokenizer' => '33f413ef', 'javelin-typeahead' => '33f413ef', 'javelin-typeahead-normalizer' => '33f413ef', 'javelin-typeahead-ondemand-source' => '33f413ef', 'javelin-typeahead-preloaded-source' => '33f413ef', 'javelin-typeahead-source' => '33f413ef', - 'javelin-uri' => '7d23deb1', - 'javelin-util' => '7d23deb1', - 'javelin-vector' => '7d23deb1', + 'javelin-uri' => 'ce1d51a9', + 'javelin-util' => 'ce1d51a9', + 'javelin-vector' => 'ce1d51a9', 'javelin-workflow' => '122a6b6d', 'phabricator-core-buttons-css' => '1ef6c6f9', 'phabricator-core-css' => '1ef6c6f9', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 7ad09c5b74..d6ed7a22b5 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -250,6 +250,7 @@ phutil_register_library_map(array( 'ManiphestDAO' => 'applications/maniphest/storage/base', 'ManiphestReplyHandler' => 'applications/maniphest/replyhandler', 'ManiphestTask' => 'applications/maniphest/storage/task', + 'ManiphestTaskDescriptionChangeController' => 'applications/maniphest/controller/descriptionchange', 'ManiphestTaskDetailController' => 'applications/maniphest/controller/taskdetail', 'ManiphestTaskEditController' => 'applications/maniphest/controller/taskedit', 'ManiphestTaskListController' => 'applications/maniphest/controller/tasklist', @@ -692,6 +693,7 @@ phutil_register_library_map(array( 'ManiphestDAO' => 'PhabricatorLiskDAO', 'ManiphestReplyHandler' => 'PhabricatorMailReplyHandler', 'ManiphestTask' => 'ManiphestDAO', + 'ManiphestTaskDescriptionChangeController' => 'ManiphestController', 'ManiphestTaskDetailController' => 'ManiphestController', 'ManiphestTaskEditController' => 'ManiphestController', 'ManiphestTaskListController' => 'ManiphestController', diff --git a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php index fe9a116f8e..bb5532c9f8 100644 --- a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php +++ b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php @@ -157,6 +157,8 @@ class AphrontDefaultApplicationConfiguration 'task/' => array( 'create/$' => 'ManiphestTaskEditController', 'edit/(?P\d+)/$' => 'ManiphestTaskEditController', + 'descriptionchange/(?P\d+)/$' => + 'ManiphestTaskDescriptionChangeController', ), 'transaction/' => array( 'save/' => 'ManiphestTransactionSaveController', diff --git a/src/applications/diffusion/controller/history/__init__.php b/src/applications/diffusion/controller/history/__init__.php index c8589c78e6..02cc7325be 100644 --- a/src/applications/diffusion/controller/history/__init__.php +++ b/src/applications/diffusion/controller/history/__init__.php @@ -14,7 +14,6 @@ phutil_require_module('phabricator', 'view/control/pager'); phutil_require_module('phabricator', 'view/layout/panel'); phutil_require_module('phutil', 'markup'); -phutil_require_module('phutil', 'parser/uri'); phutil_require_module('phutil', 'utils'); diff --git a/src/applications/maniphest/controller/descriptionchange/ManiphestTaskDescriptionChangeController.php b/src/applications/maniphest/controller/descriptionchange/ManiphestTaskDescriptionChangeController.php new file mode 100644 index 0000000000..11c5909f26 --- /dev/null +++ b/src/applications/maniphest/controller/descriptionchange/ManiphestTaskDescriptionChangeController.php @@ -0,0 +1,60 @@ +transactionID = $data['id']; + } + + public function processRequest() { + + $request = $this->getRequest(); + $user = $request->getUser(); + + $transaction = id(new ManiphestTransaction())->load($this->transactionID); + if (!$transaction) { + return new Aphront404Response(); + } + + $transactions = array($transaction); + + $phids = array(); + foreach ($transactions as $transaction) { + foreach ($transaction->extractPHIDs() as $phid) { + $phids[$phid] = $phid; + } + } + $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); + + $factory = new DifferentialMarkupEngineFactory(); + $engine = $factory->newDifferentialCommentMarkupEngine(); + + $view = new ManiphestTransactionDetailView(); + $view->setTransactionGroup($transactions); + $view->setHandles($handles); + $view->setMarkupEngine($engine); + $view->setRenderSummaryOnly(true); + $view->setRenderFullSummary(true); + + return id(new AphrontAjaxResponse())->setContent($view->render()); + } + +} diff --git a/src/applications/maniphest/controller/descriptionchange/__init__.php b/src/applications/maniphest/controller/descriptionchange/__init__.php new file mode 100644 index 0000000000..fd7bbc1534 --- /dev/null +++ b/src/applications/maniphest/controller/descriptionchange/__init__.php @@ -0,0 +1,20 @@ +transactions = $transactions; return $this; @@ -44,6 +47,24 @@ class ManiphestTransactionDetailView extends AphrontView { return $this; } + public function setRenderSummaryOnly($render_summary_only) { + $this->renderSummaryOnly = $render_summary_only; + return $this; + } + + public function getRenderSummaryOnly() { + return $this->renderSummaryOnly; + } + + public function setRenderFullSummary($render_full_summary) { + $this->renderFullSummary = $render_full_summary; + return $this; + } + + public function getRenderFullSummary() { + return $this->renderFullSummary; + } + public function renderForEmail($with_date) { $this->forEmail = true; @@ -76,7 +97,7 @@ class ManiphestTransactionDetailView extends AphrontView { } foreach ($this->transactions as $transaction) { - $supplemental = $this->renderSupplementalLinksForEmail($transaction); + $supplemental = $this->renderSupplementalInfoForEmail($transaction); if ($supplemental) { $descs .= "\n\n".$supplemental; } @@ -108,9 +129,22 @@ class ManiphestTransactionDetailView extends AphrontView { foreach ($transactions as $transaction) { list($verb, $desc, $classes) = $this->describeAction($transaction); $more_classes = array_merge($more_classes, $classes); - $descs[] = $author->renderLink().' '.$desc.'.'; + $full_summary = null; + if ($this->getRenderFullSummary()) { + $full_summary = $this->renderFullSummary($transaction); + } + $descs[] = javelin_render_tag( + 'div', + array( + 'sigil' => 'maniphest-transaction-description', + ), + $author->renderLink().' '.$desc.'.'.$full_summary); + } + $descs = implode("\n", $descs); + + if ($this->getRenderSummaryOnly()) { + return $descs; } - $descs = implode('
', $descs); $more_classes = implode(' ', $more_classes); @@ -157,7 +191,7 @@ class ManiphestTransactionDetailView extends AphrontView { ''); } - private function renderSupplementalLinksForEmail($transaction) { + private function renderSupplementalInfoForEmail($transaction) { $handles = $this->handles; $type = $transaction->getTransactionType(); @@ -165,6 +199,9 @@ class ManiphestTransactionDetailView extends AphrontView { $old = $transaction->getOldValue(); switch ($type) { + case ManiphestTransactionType::TYPE_DESCRIPTION: + return "NEW DESCRIPTION\n ".trim($new)."\n\n". + "PREVIOUS DESCRIPTION\n ".trim($old); case ManiphestTransactionType::TYPE_ATTACH: $old_raw = nonempty($old, array()); $new_raw = nonempty($new, array()); @@ -228,9 +265,13 @@ class ManiphestTransactionDetailView extends AphrontView { ' to '.$this->renderString($new); break; case ManiphestTransactionType::TYPE_DESCRIPTION: - // TODO: show the changes somehow. $verb = 'Edited'; - $desc = 'updated the task description'; + if ($this->forEmail || $this->getRenderFullSummary()) { + $desc = 'updated the task description'; + } else { + $desc = 'updated the task description; '. + $this->renderExpandLink($transaction); + } break; case ManiphestTransactionType::TYPE_NONE: $verb = 'Commented On'; @@ -419,6 +460,46 @@ class ManiphestTransactionDetailView extends AphrontView { return array($verb, $desc, $classes); } + private function renderFullSummary($transaction) { + switch ($transaction->getTransactionType()) { + case ManiphestTransactionType::TYPE_DESCRIPTION: + $engine = $this->markupEngine; + + $old = $transaction->getOldValue(); + $new = $transaction->getNewValue(); + $table = + ' + + + + + + + + +
Previous DescriptionNew Description
'.$engine->markupText($old).''.$engine->markupText($new).'
'; + + return $table; + } + + return null; + } + + private function renderExpandLink($transaction) { + $id = $transaction->getID(); + + Javelin::initBehavior('maniphest-transaction-expand'); + + return javelin_render_tag( + 'a', + array( + 'href' => '/maniphest/task/descriptionchange/'.$id.'/', + 'sigil' => 'maniphest-expand-transaction', + 'mustcapture' => true, + ), + 'show details'); + } + private function renderHandles($phids) { $links = array(); foreach ($phids as $phid) { diff --git a/src/applications/maniphest/view/transactiondetail/__init__.php b/src/applications/maniphest/view/transactiondetail/__init__.php index a7da42d3a8..600b258bce 100644 --- a/src/applications/maniphest/view/transactiondetail/__init__.php +++ b/src/applications/maniphest/view/transactiondetail/__init__.php @@ -12,6 +12,8 @@ phutil_require_module('phabricator', 'applications/maniphest/constants/transacti phutil_require_module('phabricator', 'applications/phid/constants'); phutil_require_module('phabricator', 'infrastructure/celerity/api'); phutil_require_module('phabricator', 'infrastructure/env'); +phutil_require_module('phabricator', 'infrastructure/javelin/api'); +phutil_require_module('phabricator', 'infrastructure/javelin/markup'); phutil_require_module('phabricator', 'view/base'); phutil_require_module('phabricator', 'view/utils'); diff --git a/webroot/rsrc/css/application/maniphest/transaction-detail.css b/webroot/rsrc/css/application/maniphest/transaction-detail.css index 94661578d0..54b8d1eec9 100644 --- a/webroot/rsrc/css/application/maniphest/transaction-detail.css +++ b/webroot/rsrc/css/application/maniphest/transaction-detail.css @@ -71,3 +71,22 @@ padding: 4px 1em; background: #f3f3f3; } + +.maniphest-change-table { + width: 100%; + margin: .5em 0em; + border-collapse: separate; + border-spacing: 4px 0px; +} + +.maniphest-change-table td { + width: 50%; + padding: 0.25em 1em; + background: #f9f9f9; +} + +.maniphest-change-table th { + font-weight: bold; + padding: 0.25em; + border-bottom: 1px solid #cccccc; +} diff --git a/webroot/rsrc/js/application/maniphest/behavior-transaction-expand.js b/webroot/rsrc/js/application/maniphest/behavior-transaction-expand.js new file mode 100644 index 0000000000..dede9d942d --- /dev/null +++ b/webroot/rsrc/js/application/maniphest/behavior-transaction-expand.js @@ -0,0 +1,29 @@ +/** + * @provides javelin-behavior-maniphest-transaction-expand + * @requires javelin-behavior + * javelin-dom + * javelin-workflow + * javelin-stratcom + */ + +/** + * When the user clicks "show details" in a Maniphest transaction, replace the + * summary rendering with a detailed rendering. + */ +JX.behavior('maniphest-transaction-expand', function(config) { + + JX.Stratcom.listen( + 'click', + 'maniphest-expand-transaction', + function(e) { + e.kill(); + JX.Workflow.newFromLink(e.getTarget(), {}) + .setHandler(function(r) { + JX.DOM.setContent( + e.getNode('maniphest-transaction-description'), + JX.$H(r)); + }) + .start(); + }); + +});