mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 14:52:41 +01:00
Add comment previews to Maniphest
Summary: Moves shared code from Differential and Maniphest comment previews into PhabricatorShapedRequest, and then implements Maniphest previews. This doesn't implement comment drafts, I'll follow up with that but it requires this and is completely separable. This also always shows the preview as "commented" rather than previewing the actual transaction. I'll follow up with that but I think it will require a little factoring and this is useful even without transaction details. I need to tweak the styling a bit too. Test Plan: Typed text in Maniphest and Differential. Toggled Differential action. Made comments. Reviewed By: rm Reviewers: rm, tuomaspelkonen, jungejason, aran CC: aran, rm Differential Revision: 258
This commit is contained in:
parent
e27c5f26e5
commit
90364cafdc
12 changed files with 323 additions and 68 deletions
|
@ -61,6 +61,16 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/css/aphront/headsup-action-list-view.css',
|
'disk' => '/rsrc/css/aphront/headsup-action-list-view.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',
|
||||||
|
),
|
||||||
'aphront-list-filter-view-css' =>
|
'aphront-list-filter-view-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/e6cff171/rsrc/css/aphront/list-filter-view.css',
|
'uri' => '/res/e6cff171/rsrc/css/aphront/list-filter-view.css',
|
||||||
|
@ -284,16 +294,6 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/js/application/core/behavior-tokenizer.js',
|
'disk' => '/rsrc/js/application/core/behavior-tokenizer.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-behavior-dark-console' =>
|
'javelin-behavior-dark-console' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/044c171f/rsrc/js/application/core/behavior-dark-console.js',
|
'uri' => '/res/044c171f/rsrc/js/application/core/behavior-dark-console.js',
|
||||||
|
@ -350,7 +350,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'javelin-behavior-differential-feedback-preview' =>
|
'javelin-behavior-differential-feedback-preview' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/79e7f18d/rsrc/js/application/differential/behavior-comment-preview.js',
|
'uri' => '/res/ab8a7d60/rsrc/js/application/differential/behavior-comment-preview.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -359,6 +359,7 @@ celerity_register_resource_map(array(
|
||||||
2 => 'javelin-dom',
|
2 => 'javelin-dom',
|
||||||
3 => 'javelin-request',
|
3 => 'javelin-request',
|
||||||
4 => 'javelin-util',
|
4 => 'javelin-util',
|
||||||
|
5 => 'phabricator-shaped-request',
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/js/application/differential/behavior-comment-preview.js',
|
'disk' => '/rsrc/js/application/differential/behavior-comment-preview.js',
|
||||||
),
|
),
|
||||||
|
@ -462,6 +463,19 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/js/application/maniphest/behavior-transaction-controls.js',
|
'disk' => '/rsrc/js/application/maniphest/behavior-transaction-controls.js',
|
||||||
),
|
),
|
||||||
|
'javelin-behavior-maniphest-transaction-preview' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/b211faf2/rsrc/js/application/maniphest/behavior-transaction-preview.js',
|
||||||
|
'type' => 'js',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
0 => 'javelin-behavior',
|
||||||
|
1 => 'javelin-dom',
|
||||||
|
2 => 'javelin-util',
|
||||||
|
3 => 'phabricator-shaped-request',
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/js/application/maniphest/behavior-transaction-preview.js',
|
||||||
|
),
|
||||||
'javelin-behavior-owners-path-editor' =>
|
'javelin-behavior-owners-path-editor' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/9cf78ffc/rsrc/js/application/owners/owners-path-editor.js',
|
'uri' => '/res/9cf78ffc/rsrc/js/application/owners/owners-path-editor.js',
|
||||||
|
@ -720,7 +734,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'mainphest-task-detail-css' =>
|
'mainphest-task-detail-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/dbefc148/rsrc/css/application/maniphest/task-detail.css',
|
'uri' => '/res/fa248d0b/rsrc/css/application/maniphest/task-detail.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -851,6 +865,18 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/css/core/remarkup.css',
|
'disk' => '/rsrc/css/core/remarkup.css',
|
||||||
),
|
),
|
||||||
|
'phabricator-shaped-request' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/1f0ef02b/rsrc/js/application/core/ShapedRequest.js',
|
||||||
|
'type' => 'js',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
0 => 'javelin-install',
|
||||||
|
1 => 'javelin-util',
|
||||||
|
2 => 'javelin-request',
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/js/application/core/ShapedRequest.js',
|
||||||
|
),
|
||||||
'phabricator-standard-page-view' =>
|
'phabricator-standard-page-view' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/9c468a70/rsrc/css/application/base/standard-page-view.css',
|
'uri' => '/res/9c468a70/rsrc/css/application/base/standard-page-view.css',
|
||||||
|
@ -936,20 +962,6 @@ celerity_register_resource_map(array(
|
||||||
'uri' => '/res/pkg/33f413ef/typeahead.pkg.js',
|
'uri' => '/res/pkg/33f413ef/typeahead.pkg.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
),
|
),
|
||||||
'711616db' =>
|
|
||||||
array (
|
|
||||||
'name' => 'differential.pkg.js',
|
|
||||||
'symbols' =>
|
|
||||||
array (
|
|
||||||
0 => 'javelin-behavior-differential-feedback-preview',
|
|
||||||
1 => 'javelin-behavior-differential-edit-inline-comments',
|
|
||||||
2 => 'javelin-behavior-differential-populate',
|
|
||||||
3 => 'javelin-behavior-differential-show-more',
|
|
||||||
4 => 'javelin-behavior-differential-diff-radios',
|
|
||||||
),
|
|
||||||
'uri' => '/res/pkg/711616db/differential.pkg.js',
|
|
||||||
'type' => 'js',
|
|
||||||
),
|
|
||||||
'7d23deb1' =>
|
'7d23deb1' =>
|
||||||
array (
|
array (
|
||||||
'name' => 'javelin.pkg.js',
|
'name' => 'javelin.pkg.js',
|
||||||
|
@ -993,6 +1005,20 @@ celerity_register_resource_map(array(
|
||||||
'uri' => '/res/pkg/ac70e6b7/core.pkg.css',
|
'uri' => '/res/pkg/ac70e6b7/core.pkg.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
),
|
),
|
||||||
|
'b17926e1' =>
|
||||||
|
array (
|
||||||
|
'name' => 'differential.pkg.js',
|
||||||
|
'symbols' =>
|
||||||
|
array (
|
||||||
|
0 => 'javelin-behavior-differential-feedback-preview',
|
||||||
|
1 => 'javelin-behavior-differential-edit-inline-comments',
|
||||||
|
2 => 'javelin-behavior-differential-populate',
|
||||||
|
3 => 'javelin-behavior-differential-show-more',
|
||||||
|
4 => 'javelin-behavior-differential-diff-radios',
|
||||||
|
),
|
||||||
|
'uri' => '/res/pkg/b17926e1/differential.pkg.js',
|
||||||
|
'type' => 'js',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
'reverse' =>
|
'reverse' =>
|
||||||
array (
|
array (
|
||||||
|
@ -1016,11 +1042,11 @@ celerity_register_resource_map(array(
|
||||||
'diffusion-commit-view-css' => '03ef179e',
|
'diffusion-commit-view-css' => '03ef179e',
|
||||||
'javelin-behavior' => '7d23deb1',
|
'javelin-behavior' => '7d23deb1',
|
||||||
'javelin-behavior-aphront-basic-tokenizer' => '33f413ef',
|
'javelin-behavior-aphront-basic-tokenizer' => '33f413ef',
|
||||||
'javelin-behavior-differential-diff-radios' => '711616db',
|
'javelin-behavior-differential-diff-radios' => 'b17926e1',
|
||||||
'javelin-behavior-differential-edit-inline-comments' => '711616db',
|
'javelin-behavior-differential-edit-inline-comments' => 'b17926e1',
|
||||||
'javelin-behavior-differential-feedback-preview' => '711616db',
|
'javelin-behavior-differential-feedback-preview' => 'b17926e1',
|
||||||
'javelin-behavior-differential-populate' => '711616db',
|
'javelin-behavior-differential-populate' => 'b17926e1',
|
||||||
'javelin-behavior-differential-show-more' => '711616db',
|
'javelin-behavior-differential-show-more' => 'b17926e1',
|
||||||
'javelin-behavior-workflow' => '122a6b6d',
|
'javelin-behavior-workflow' => '122a6b6d',
|
||||||
'javelin-dom' => '7d23deb1',
|
'javelin-dom' => '7d23deb1',
|
||||||
'javelin-event' => '7d23deb1',
|
'javelin-event' => '7d23deb1',
|
||||||
|
|
|
@ -261,6 +261,7 @@ phutil_register_library_map(array(
|
||||||
'ManiphestTransactionDetailView' => 'applications/maniphest/view/transactiondetail',
|
'ManiphestTransactionDetailView' => 'applications/maniphest/view/transactiondetail',
|
||||||
'ManiphestTransactionEditor' => 'applications/maniphest/editor/transaction',
|
'ManiphestTransactionEditor' => 'applications/maniphest/editor/transaction',
|
||||||
'ManiphestTransactionListView' => 'applications/maniphest/view/transactionlist',
|
'ManiphestTransactionListView' => 'applications/maniphest/view/transactionlist',
|
||||||
|
'ManiphestTransactionPreviewController' => 'applications/maniphest/controller/transactionpreview',
|
||||||
'ManiphestTransactionSaveController' => 'applications/maniphest/controller/transactionsave',
|
'ManiphestTransactionSaveController' => 'applications/maniphest/controller/transactionsave',
|
||||||
'ManiphestTransactionType' => 'applications/maniphest/constants/transactiontype',
|
'ManiphestTransactionType' => 'applications/maniphest/constants/transactiontype',
|
||||||
'Phabricator404Controller' => 'applications/base/controller/404',
|
'Phabricator404Controller' => 'applications/base/controller/404',
|
||||||
|
@ -684,6 +685,7 @@ phutil_register_library_map(array(
|
||||||
'ManiphestTransaction' => 'ManiphestDAO',
|
'ManiphestTransaction' => 'ManiphestDAO',
|
||||||
'ManiphestTransactionDetailView' => 'AphrontView',
|
'ManiphestTransactionDetailView' => 'AphrontView',
|
||||||
'ManiphestTransactionListView' => 'AphrontView',
|
'ManiphestTransactionListView' => 'AphrontView',
|
||||||
|
'ManiphestTransactionPreviewController' => 'ManiphestController',
|
||||||
'ManiphestTransactionSaveController' => 'ManiphestController',
|
'ManiphestTransactionSaveController' => 'ManiphestController',
|
||||||
'Phabricator404Controller' => 'PhabricatorController',
|
'Phabricator404Controller' => 'PhabricatorController',
|
||||||
'PhabricatorAuthController' => 'PhabricatorController',
|
'PhabricatorAuthController' => 'PhabricatorController',
|
||||||
|
|
|
@ -159,6 +159,7 @@ class AphrontDefaultApplicationConfiguration
|
||||||
),
|
),
|
||||||
'transaction/' => array(
|
'transaction/' => array(
|
||||||
'save/' => 'ManiphestTransactionSaveController',
|
'save/' => 'ManiphestTransactionSaveController',
|
||||||
|
'preview/(?P<id>\d+)/$' => 'ManiphestTransactionPreviewController',
|
||||||
),
|
),
|
||||||
'select/search/$' => 'ManiphestTaskSelectorSearchController',
|
'select/search/$' => 'ManiphestTaskSelectorSearchController',
|
||||||
),
|
),
|
||||||
|
|
|
@ -268,7 +268,7 @@ class ManiphestTaskDetailController extends ManiphestController {
|
||||||
id(new AphrontFormTextAreaControl())
|
id(new AphrontFormTextAreaControl())
|
||||||
->setLabel('Comments')
|
->setLabel('Comments')
|
||||||
->setName('comments')
|
->setName('comments')
|
||||||
->setValue(''))
|
->setID('transaction-comments'))
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormSubmitControl())
|
id(new AphrontFormSubmitControl())
|
||||||
->setValue('Avast!'));
|
->setValue('Avast!'));
|
||||||
|
@ -301,10 +301,27 @@ class ManiphestTaskDetailController extends ManiphestController {
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
|
Javelin::initBehavior('maniphest-transaction-preview', array(
|
||||||
|
'uri' => '/maniphest/transaction/preview/'.$task->getID().'/',
|
||||||
|
'preview' => 'transaction-preview',
|
||||||
|
'comments' => 'transaction-comments',
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
$comment_panel = new AphrontPanelView();
|
$comment_panel = new AphrontPanelView();
|
||||||
$comment_panel->appendChild($comment_form);
|
$comment_panel->appendChild($comment_form);
|
||||||
$comment_panel->setHeader('Leap Into Action');
|
$comment_panel->setHeader('Leap Into Action');
|
||||||
|
|
||||||
|
$preview_panel =
|
||||||
|
'<div class="maniphest-transaction-preview">
|
||||||
|
<div id="transaction-preview">
|
||||||
|
<div class="maniphest-loading-text">
|
||||||
|
Loading preview...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>';
|
||||||
|
|
||||||
$transaction_view = new ManiphestTransactionListView();
|
$transaction_view = new ManiphestTransactionListView();
|
||||||
$transaction_view->setTransactions($transactions);
|
$transaction_view->setTransactions($transactions);
|
||||||
$transaction_view->setHandles($handles);
|
$transaction_view->setHandles($handles);
|
||||||
|
@ -316,6 +333,7 @@ class ManiphestTaskDetailController extends ManiphestController {
|
||||||
$panel,
|
$panel,
|
||||||
$transaction_view,
|
$transaction_view,
|
||||||
$comment_panel,
|
$comment_panel,
|
||||||
|
$preview_panel,
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'title' => 'T'.$task->getID().' '.$task->getTitle(),
|
'title' => 'T'.$task->getID().' '.$task->getTitle(),
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ManiphestTransactionPreviewController extends ManiphestController {
|
||||||
|
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->id = $data['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
|
||||||
|
$comments = $request->getStr('comments');
|
||||||
|
|
||||||
|
$handles = id(new PhabricatorObjectHandleData(array($user->getPHID())))
|
||||||
|
->loadHandles();
|
||||||
|
|
||||||
|
$transaction = new ManiphestTransaction();
|
||||||
|
$transaction->setAuthorPHID($user->getPHID());
|
||||||
|
$transaction->setComments($comments);
|
||||||
|
$transaction->setTransactionType(ManiphestTransactionType::TYPE_NONE);
|
||||||
|
|
||||||
|
$transactions = array();
|
||||||
|
$transactions[] = $transaction;
|
||||||
|
|
||||||
|
$factory = new DifferentialMarkupEngineFactory();
|
||||||
|
$engine = $factory->newDifferentialCommentMarkupEngine();
|
||||||
|
|
||||||
|
$transaction_view = new ManiphestTransactionListView();
|
||||||
|
$transaction_view->setTransactions($transactions);
|
||||||
|
$transaction_view->setHandles($handles);
|
||||||
|
$transaction_view->setUser($user);
|
||||||
|
$transaction_view->setMarkupEngine($engine);
|
||||||
|
$transaction_view->setPreview(true);
|
||||||
|
|
||||||
|
return id(new AphrontAjaxResponse())
|
||||||
|
->setContent($transaction_view->render());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/ajax');
|
||||||
|
phutil_require_module('phabricator', 'applications/differential/parser/markup');
|
||||||
|
phutil_require_module('phabricator', 'applications/maniphest/constants/transactiontype');
|
||||||
|
phutil_require_module('phabricator', 'applications/maniphest/controller/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/maniphest/storage/transaction');
|
||||||
|
phutil_require_module('phabricator', 'applications/maniphest/view/transactionlist');
|
||||||
|
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('ManiphestTransactionPreviewController.php');
|
|
@ -22,6 +22,7 @@ class ManiphestTransactionDetailView extends AphrontView {
|
||||||
private $handles;
|
private $handles;
|
||||||
private $markupEngine;
|
private $markupEngine;
|
||||||
private $forEmail;
|
private $forEmail;
|
||||||
|
private $preview;
|
||||||
|
|
||||||
public function setTransactionGroup(array $transactions) {
|
public function setTransactionGroup(array $transactions) {
|
||||||
$this->transactions = $transactions;
|
$this->transactions = $transactions;
|
||||||
|
@ -38,6 +39,11 @@ class ManiphestTransactionDetailView extends AphrontView {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setPreview($preview) {
|
||||||
|
$this->preview = $preview;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function renderForEmail($with_date) {
|
public function renderForEmail($with_date) {
|
||||||
$this->forEmail = true;
|
$this->forEmail = true;
|
||||||
|
|
||||||
|
@ -107,7 +113,7 @@ class ManiphestTransactionDetailView extends AphrontView {
|
||||||
if (strlen($comments)) {
|
if (strlen($comments)) {
|
||||||
$comments = $this->markupEngine->markupText($comments);
|
$comments = $this->markupEngine->markupText($comments);
|
||||||
$comment_transaction->setCache($comments);
|
$comment_transaction->setCache($comments);
|
||||||
if ($comment_transaction->getID()) {
|
if ($comment_transaction->getID() && !$this->preview) {
|
||||||
$comment_transaction->save();
|
$comment_transaction->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,6 +126,12 @@ class ManiphestTransactionDetailView extends AphrontView {
|
||||||
$comment_block = null;
|
$comment_block = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->preview) {
|
||||||
|
$timestamp = 'COMMENT PREVIEW';
|
||||||
|
} else {
|
||||||
|
$timestamp = phabricator_format_timestamp($transaction->getDateCreated());
|
||||||
|
}
|
||||||
|
|
||||||
return phutil_render_tag(
|
return phutil_render_tag(
|
||||||
'div',
|
'div',
|
||||||
array(
|
array(
|
||||||
|
@ -129,7 +141,7 @@ class ManiphestTransactionDetailView extends AphrontView {
|
||||||
'<div class="maniphest-transaction-detail-view '.$more_classes.'">'.
|
'<div class="maniphest-transaction-detail-view '.$more_classes.'">'.
|
||||||
'<div class="maniphest-transaction-header">'.
|
'<div class="maniphest-transaction-header">'.
|
||||||
'<div class="maniphest-transaction-timestamp">'.
|
'<div class="maniphest-transaction-timestamp">'.
|
||||||
phabricator_format_timestamp($transaction->getDateCreated()).
|
$timestamp.
|
||||||
'</div>'.
|
'</div>'.
|
||||||
$descs.
|
$descs.
|
||||||
'</div>'.
|
'</div>'.
|
||||||
|
|
|
@ -22,6 +22,7 @@ class ManiphestTransactionListView extends AphrontView {
|
||||||
private $handles;
|
private $handles;
|
||||||
private $user;
|
private $user;
|
||||||
private $markupEngine;
|
private $markupEngine;
|
||||||
|
private $preview;
|
||||||
|
|
||||||
public function setTransactions(array $transactions) {
|
public function setTransactions(array $transactions) {
|
||||||
$this->transactions = $transactions;
|
$this->transactions = $transactions;
|
||||||
|
@ -43,6 +44,11 @@ class ManiphestTransactionListView extends AphrontView {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setPreview($preview) {
|
||||||
|
$this->preview = $preview;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function render() {
|
public function render() {
|
||||||
|
|
||||||
$views = array();
|
$views = array();
|
||||||
|
@ -76,6 +82,7 @@ class ManiphestTransactionListView extends AphrontView {
|
||||||
$view->setTransactionGroup($group);
|
$view->setTransactionGroup($group);
|
||||||
$view->setHandles($this->handles);
|
$view->setHandles($this->handles);
|
||||||
$view->setMarkupEngine($this->markupEngine);
|
$view->setMarkupEngine($this->markupEngine);
|
||||||
|
$view->setPreview($this->preview);
|
||||||
$views[] = $view->render();
|
$views[] = $view->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,3 +42,15 @@
|
||||||
.maniphest-task-detail-core {
|
.maniphest-task-detail-core {
|
||||||
margin-right: 265px;
|
margin-right: 265px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.maniphest-transaction-preview {
|
||||||
|
background: #f0f0f0;
|
||||||
|
border-top: 1px solid #dddddd;
|
||||||
|
border-bottom: 1px solid #aaaaaa;
|
||||||
|
margin: -1em 2em 2em;
|
||||||
|
padding: 15px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maniphest-loading-text {
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
88
webroot/rsrc/js/application/core/ShapedRequest.js
Normal file
88
webroot/rsrc/js/application/core/ShapedRequest.js
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/**
|
||||||
|
* @requires javelin-install
|
||||||
|
* javelin-util
|
||||||
|
* javelin-request
|
||||||
|
* @provides phabricator-shaped-request
|
||||||
|
* @javelin
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send requests with rate limiting and retries, in response to some application
|
||||||
|
* trigger. This is used to implement comment previews in Differential and
|
||||||
|
* Maniphest.
|
||||||
|
*/
|
||||||
|
JX.install('PhabricatorShapedRequest', {
|
||||||
|
|
||||||
|
construct : function(uri, callback, data_callback) {
|
||||||
|
this._uri = uri;
|
||||||
|
this._callback = callback;
|
||||||
|
this._dataCallback = data_callback;
|
||||||
|
},
|
||||||
|
|
||||||
|
members : {
|
||||||
|
_callback : null,
|
||||||
|
_dataCallback : null,
|
||||||
|
_request : null,
|
||||||
|
_min : null,
|
||||||
|
_defer : null,
|
||||||
|
_last : null,
|
||||||
|
start : function() {
|
||||||
|
this.trigger();
|
||||||
|
},
|
||||||
|
|
||||||
|
trigger : function() {
|
||||||
|
|
||||||
|
if (this._request) {
|
||||||
|
// Waiting on a request, rate-limit.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._min && (new Date().getTime() < this._min)) {
|
||||||
|
// Just got a request back, rate-limit.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._defer && this._defer.stop();
|
||||||
|
|
||||||
|
var data = this._dataCallback();
|
||||||
|
|
||||||
|
if (this.shouldSendRequest(this._last, data)) {
|
||||||
|
this._last = data;
|
||||||
|
var request = new JX.Request(this._uri, JX.bind(this, function(r) {
|
||||||
|
this._callback(r);
|
||||||
|
|
||||||
|
this._min = new Date().getTime() + this._rateLimit;
|
||||||
|
this._defer && this._defer.stop();
|
||||||
|
this._defer = JX.defer(JX.bind(this, this.trigger), this._rateLimit);
|
||||||
|
}));
|
||||||
|
request.listen('finally', JX.bind(this, function() {
|
||||||
|
this._request = null;
|
||||||
|
}));
|
||||||
|
request.setData(data);
|
||||||
|
request.setTimeout(this.getFrequency());
|
||||||
|
request.send();
|
||||||
|
} else {
|
||||||
|
this._defer = JX.defer(JX.bind(this, this.trigger), this._frequency);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
shouldSendRequest : function(last, data) {
|
||||||
|
if (last === null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var k in last) {
|
||||||
|
if (data[k] !== last[k]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
properties : {
|
||||||
|
rateLimit : 250,
|
||||||
|
frequency : 750
|
||||||
|
}
|
||||||
|
});
|
|
@ -5,52 +5,33 @@
|
||||||
* javelin-dom
|
* javelin-dom
|
||||||
* javelin-request
|
* javelin-request
|
||||||
* javelin-util
|
* javelin-util
|
||||||
|
* phabricator-shaped-request
|
||||||
*/
|
*/
|
||||||
|
|
||||||
JX.behavior('differential-feedback-preview', function(config) {
|
JX.behavior('differential-feedback-preview', function(config) {
|
||||||
|
|
||||||
var action = JX.$(config.action);
|
var action = JX.$(config.action);
|
||||||
var content = JX.$(config.content);
|
var content = JX.$(config.content);
|
||||||
var preview = JX.$(config.preview);
|
|
||||||
|
|
||||||
var aval = null;//action.value;
|
var callback = function(r) {
|
||||||
var cval = null;//content.value;
|
JX.DOM.setContent(JX.$(config.preview), JX.$H(r));
|
||||||
var defer = null;
|
};
|
||||||
var min = null;
|
|
||||||
var request = null;
|
|
||||||
|
|
||||||
function check() {
|
var getdata = function() {
|
||||||
if (request || (min && (new Date().getTime() < min))) {
|
return {
|
||||||
// Waiting on an async or just got one back, rate-limit.
|
content : content.value,
|
||||||
return;
|
action : action.value
|
||||||
}
|
};
|
||||||
|
};
|
||||||
|
|
||||||
defer && defer.stop();
|
var request = new JX.PhabricatorShapedRequest(config.uri, callback, getdata);
|
||||||
|
var trigger = JX.bind(request, request.trigger);
|
||||||
|
|
||||||
if (action.value !== aval || content.value !== cval) {
|
JX.DOM.listen(content, 'keydown', null, trigger);
|
||||||
aval = action.value;
|
JX.DOM.listen(action, 'change', null, trigger);
|
||||||
cval = content.value;
|
|
||||||
|
|
||||||
request = new JX.Request(config.uri, function(r) {
|
request.start();
|
||||||
preview && JX.DOM.setContent(preview, JX.$H(r));
|
|
||||||
min = new Date().getTime() + 500;
|
|
||||||
defer && defer.stop();
|
|
||||||
defer = JX.defer(check, 500);
|
|
||||||
});
|
|
||||||
request.listen('finally', function() { request = null; });
|
|
||||||
request.setData({action : aval, content : cval});
|
|
||||||
// If we don't get a response back soon, retry on the next action.
|
|
||||||
request.setTimeout(2000);
|
|
||||||
request.send();
|
|
||||||
} else {
|
|
||||||
defer = JX.defer(check, 2000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JX.DOM.listen(content, 'keydown', null, check);
|
|
||||||
JX.DOM.listen(action, 'change', null, check);
|
|
||||||
|
|
||||||
check();
|
|
||||||
|
|
||||||
|
|
||||||
function refreshInlinePreview() {
|
function refreshInlinePreview() {
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
* @provides javelin-behavior-maniphest-transaction-preview
|
||||||
|
* @requires javelin-behavior
|
||||||
|
* javelin-dom
|
||||||
|
* javelin-util
|
||||||
|
* phabricator-shaped-request
|
||||||
|
*/
|
||||||
|
|
||||||
|
JX.behavior('maniphest-transaction-preview', function(config) {
|
||||||
|
|
||||||
|
var comments = JX.$(config.comments);
|
||||||
|
|
||||||
|
var callback = function(r) {
|
||||||
|
JX.DOM.setContent(JX.$(config.preview), JX.$H(r));
|
||||||
|
};
|
||||||
|
|
||||||
|
var getdata = function() {
|
||||||
|
return {
|
||||||
|
comments : comments.value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = new JX.PhabricatorShapedRequest(config.uri, callback, getdata);
|
||||||
|
var trigger = JX.bind(request, request.trigger);
|
||||||
|
|
||||||
|
JX.DOM.listen(comments, 'keydown', null, trigger);
|
||||||
|
|
||||||
|
request.start();
|
||||||
|
});
|
Loading…
Reference in a new issue