mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-30 02:32:42 +01:00
Add comment linking to Maniphest and Differential
Summary: Allows you to link to comments with "D123#3" or "T123#3", then adds a pile of JS to try to make it not terrible. :/ The thing I'm trying to avoid here is when someone says "look at this! http://blog.com/#comment-239291" and you click and your browser jumps somewhere random and you have no idea which comment they meant. Since I really hate this, I've tried to avoid it by making sure the comment is always highlighted. Test Plan: Put T1#1 and D1#1 in remarkup and verified they linked properly. Clicked anchors on individual comments. Faked all comments hidden in Differential and verified they expanded on anchor or anchor change. Reviewed By: aran Reviewers: aran, tomo, mroch, jungejason, tuomaspelkonen CC: aran, epriestley Differential Revision: 383
This commit is contained in:
parent
ead9bbfeb1
commit
d96d515cc2
22 changed files with 343 additions and 116 deletions
2
externals/javelin
vendored
2
externals/javelin
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 7ac64cd03d89d6d5f8c7f85b32c9611d3866ea2b
|
Subproject commit c714cff45db83fc8c34e82b7ec1155b7c442dc7b
|
|
@ -172,7 +172,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'differential-revision-comment-css' =>
|
'differential-revision-comment-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/e3ea8c34/rsrc/css/application/differential/revision-comment.css',
|
'uri' => '/res/e3539439/rsrc/css/application/differential/revision-comment.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -188,6 +188,16 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/css/application/differential/revision-comment-list.css',
|
'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' =>
|
'differential-revision-detail-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/ea9de420/rsrc/css/application/differential/revision-detail.css',
|
'uri' => '/res/ea9de420/rsrc/css/application/differential/revision-detail.css',
|
||||||
|
@ -279,16 +289,6 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/js/javelin/lib/behavior.js',
|
'disk' => '/rsrc/js/javelin/lib/behavior.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-aphront-basic-tokenizer' =>
|
'javelin-behavior-aphront-basic-tokenizer' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/bce3961b/rsrc/js/application/core/behavior-tokenizer.js',
|
'uri' => '/res/bce3961b/rsrc/js/application/core/behavior-tokenizer.js',
|
||||||
|
@ -424,7 +424,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'javelin-behavior-differential-show-all-comments' =>
|
'javelin-behavior-differential-show-all-comments' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/b7c7e1ee/rsrc/js/application/differential/behavior-show-all-comments.js',
|
'uri' => '/res/bcc990f0/rsrc/js/application/differential/behavior-show-all-comments.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -560,6 +560,19 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/js/application/core/behavior-object-selector.js',
|
'disk' => '/rsrc/js/application/core/behavior-object-selector.js',
|
||||||
),
|
),
|
||||||
|
'javelin-behavior-phabricator-watch-anchor' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/bb6fa5b2/rsrc/js/application/core/behavior-watch-anchor.js',
|
||||||
|
'type' => 'js',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
0 => 'javelin-behavior',
|
||||||
|
1 => 'javelin-stratcom',
|
||||||
|
2 => 'javelin-util',
|
||||||
|
3 => 'javelin-dom',
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/js/application/core/behavior-watch-anchor.js',
|
||||||
|
),
|
||||||
'javelin-behavior-workflow' =>
|
'javelin-behavior-workflow' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/079f49c3/rsrc/js/application/core/behavior-workflow.js',
|
'uri' => '/res/079f49c3/rsrc/js/application/core/behavior-workflow.js',
|
||||||
|
@ -574,7 +587,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'javelin-dom' =>
|
'javelin-dom' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/770d72cd/rsrc/js/javelin/lib/DOM.js',
|
'uri' => '/res/43e9e2de/rsrc/js/javelin/lib/DOM.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -620,7 +633,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'javelin-magical-init' =>
|
'javelin-magical-init' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/ce002e50/rsrc/js/javelin/core/init.js',
|
'uri' => '/res/92e7f37e/rsrc/js/javelin/core/init.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -641,7 +654,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'javelin-request' =>
|
'javelin-request' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/72a23e59/rsrc/js/javelin/lib/Request.js',
|
'uri' => '/res/1ed0d596/rsrc/js/javelin/lib/Request.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -811,7 +824,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'maniphest-transaction-detail-css' =>
|
'maniphest-transaction-detail-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/14758b00/rsrc/css/application/maniphest/transaction-detail.css',
|
'uri' => '/res/7ee02b5e/rsrc/css/application/maniphest/transaction-detail.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -1002,23 +1015,6 @@ celerity_register_resource_map(array(
|
||||||
'uri' => '/res/pkg/122a6b6d/workflow.pkg.js',
|
'uri' => '/res/pkg/122a6b6d/workflow.pkg.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
),
|
),
|
||||||
'1ac25e8a' =>
|
|
||||||
array (
|
|
||||||
'name' => 'differential.pkg.css',
|
|
||||||
'symbols' =>
|
|
||||||
array (
|
|
||||||
0 => 'differential-core-view-css',
|
|
||||||
1 => 'differential-changeset-view-css',
|
|
||||||
2 => 'differential-revision-detail-css',
|
|
||||||
3 => 'differential-revision-history-css',
|
|
||||||
4 => 'differential-table-of-contents-css',
|
|
||||||
5 => 'differential-revision-comment-css',
|
|
||||||
6 => 'differential-revision-add-comment-css',
|
|
||||||
7 => 'differential-revision-comment-list-css',
|
|
||||||
),
|
|
||||||
'uri' => '/res/pkg/1ac25e8a/differential.pkg.css',
|
|
||||||
'type' => 'css',
|
|
||||||
),
|
|
||||||
'33f413ef' =>
|
'33f413ef' =>
|
||||||
array (
|
array (
|
||||||
'name' => 'typeahead.pkg.js',
|
'name' => 'typeahead.pkg.js',
|
||||||
|
@ -1035,6 +1031,23 @@ celerity_register_resource_map(array(
|
||||||
'uri' => '/res/pkg/33f413ef/typeahead.pkg.js',
|
'uri' => '/res/pkg/33f413ef/typeahead.pkg.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
),
|
),
|
||||||
|
'613cf273' =>
|
||||||
|
array (
|
||||||
|
'name' => 'differential.pkg.css',
|
||||||
|
'symbols' =>
|
||||||
|
array (
|
||||||
|
0 => 'differential-core-view-css',
|
||||||
|
1 => 'differential-changeset-view-css',
|
||||||
|
2 => 'differential-revision-detail-css',
|
||||||
|
3 => 'differential-revision-history-css',
|
||||||
|
4 => 'differential-table-of-contents-css',
|
||||||
|
5 => 'differential-revision-comment-css',
|
||||||
|
6 => 'differential-revision-add-comment-css',
|
||||||
|
7 => 'differential-revision-comment-list-css',
|
||||||
|
),
|
||||||
|
'uri' => '/res/pkg/613cf273/differential.pkg.css',
|
||||||
|
'type' => 'css',
|
||||||
|
),
|
||||||
'a6102fe7' =>
|
'a6102fe7' =>
|
||||||
array (
|
array (
|
||||||
'name' => 'core.pkg.css',
|
'name' => 'core.pkg.css',
|
||||||
|
@ -1059,7 +1072,7 @@ celerity_register_resource_map(array(
|
||||||
'uri' => '/res/pkg/a6102fe7/core.pkg.css',
|
'uri' => '/res/pkg/a6102fe7/core.pkg.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
),
|
),
|
||||||
'd985d27a' =>
|
'db95a6d0' =>
|
||||||
array (
|
array (
|
||||||
'name' => 'javelin.pkg.js',
|
'name' => 'javelin.pkg.js',
|
||||||
'symbols' =>
|
'symbols' =>
|
||||||
|
@ -1075,7 +1088,7 @@ celerity_register_resource_map(array(
|
||||||
8 => 'javelin-json',
|
8 => 'javelin-json',
|
||||||
9 => 'javelin-uri',
|
9 => 'javelin-uri',
|
||||||
),
|
),
|
||||||
'uri' => '/res/pkg/d985d27a/javelin.pkg.js',
|
'uri' => '/res/pkg/db95a6d0/javelin.pkg.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
),
|
),
|
||||||
'ed383f69' =>
|
'ed383f69' =>
|
||||||
|
@ -1104,16 +1117,16 @@ celerity_register_resource_map(array(
|
||||||
'aphront-table-view-css' => 'a6102fe7',
|
'aphront-table-view-css' => 'a6102fe7',
|
||||||
'aphront-tokenizer-control-css' => 'a6102fe7',
|
'aphront-tokenizer-control-css' => 'a6102fe7',
|
||||||
'aphront-typeahead-control-css' => 'a6102fe7',
|
'aphront-typeahead-control-css' => 'a6102fe7',
|
||||||
'differential-changeset-view-css' => '1ac25e8a',
|
'differential-changeset-view-css' => '613cf273',
|
||||||
'differential-core-view-css' => '1ac25e8a',
|
'differential-core-view-css' => '613cf273',
|
||||||
'differential-revision-add-comment-css' => '1ac25e8a',
|
'differential-revision-add-comment-css' => '613cf273',
|
||||||
'differential-revision-comment-css' => '1ac25e8a',
|
'differential-revision-comment-css' => '613cf273',
|
||||||
'differential-revision-comment-list-css' => '1ac25e8a',
|
'differential-revision-comment-list-css' => '613cf273',
|
||||||
'differential-revision-detail-css' => '1ac25e8a',
|
'differential-revision-detail-css' => '613cf273',
|
||||||
'differential-revision-history-css' => '1ac25e8a',
|
'differential-revision-history-css' => '613cf273',
|
||||||
'differential-table-of-contents-css' => '1ac25e8a',
|
'differential-table-of-contents-css' => '613cf273',
|
||||||
'diffusion-commit-view-css' => '03ef179e',
|
'diffusion-commit-view-css' => '03ef179e',
|
||||||
'javelin-behavior' => 'd985d27a',
|
'javelin-behavior' => 'db95a6d0',
|
||||||
'javelin-behavior-aphront-basic-tokenizer' => '33f413ef',
|
'javelin-behavior-aphront-basic-tokenizer' => '33f413ef',
|
||||||
'javelin-behavior-differential-diff-radios' => 'ed383f69',
|
'javelin-behavior-differential-diff-radios' => 'ed383f69',
|
||||||
'javelin-behavior-differential-edit-inline-comments' => 'ed383f69',
|
'javelin-behavior-differential-edit-inline-comments' => 'ed383f69',
|
||||||
|
@ -1121,22 +1134,22 @@ celerity_register_resource_map(array(
|
||||||
'javelin-behavior-differential-populate' => 'ed383f69',
|
'javelin-behavior-differential-populate' => 'ed383f69',
|
||||||
'javelin-behavior-differential-show-more' => 'ed383f69',
|
'javelin-behavior-differential-show-more' => 'ed383f69',
|
||||||
'javelin-behavior-workflow' => '122a6b6d',
|
'javelin-behavior-workflow' => '122a6b6d',
|
||||||
'javelin-dom' => 'd985d27a',
|
'javelin-dom' => 'db95a6d0',
|
||||||
'javelin-event' => 'd985d27a',
|
'javelin-event' => 'db95a6d0',
|
||||||
'javelin-install' => 'd985d27a',
|
'javelin-install' => 'db95a6d0',
|
||||||
'javelin-json' => 'd985d27a',
|
'javelin-json' => 'db95a6d0',
|
||||||
'javelin-mask' => '122a6b6d',
|
'javelin-mask' => '122a6b6d',
|
||||||
'javelin-request' => 'd985d27a',
|
'javelin-request' => 'db95a6d0',
|
||||||
'javelin-stratcom' => 'd985d27a',
|
'javelin-stratcom' => 'db95a6d0',
|
||||||
'javelin-tokenizer' => '33f413ef',
|
'javelin-tokenizer' => '33f413ef',
|
||||||
'javelin-typeahead' => '33f413ef',
|
'javelin-typeahead' => '33f413ef',
|
||||||
'javelin-typeahead-normalizer' => '33f413ef',
|
'javelin-typeahead-normalizer' => '33f413ef',
|
||||||
'javelin-typeahead-ondemand-source' => '33f413ef',
|
'javelin-typeahead-ondemand-source' => '33f413ef',
|
||||||
'javelin-typeahead-preloaded-source' => '33f413ef',
|
'javelin-typeahead-preloaded-source' => '33f413ef',
|
||||||
'javelin-typeahead-source' => '33f413ef',
|
'javelin-typeahead-source' => '33f413ef',
|
||||||
'javelin-uri' => 'd985d27a',
|
'javelin-uri' => 'db95a6d0',
|
||||||
'javelin-util' => 'd985d27a',
|
'javelin-util' => 'db95a6d0',
|
||||||
'javelin-vector' => 'd985d27a',
|
'javelin-vector' => 'db95a6d0',
|
||||||
'javelin-workflow' => '122a6b6d',
|
'javelin-workflow' => '122a6b6d',
|
||||||
'phabricator-core-buttons-css' => 'a6102fe7',
|
'phabricator-core-buttons-css' => 'a6102fe7',
|
||||||
'phabricator-core-css' => 'a6102fe7',
|
'phabricator-core-css' => 'a6102fe7',
|
||||||
|
|
|
@ -410,6 +410,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorRemarkupRuleDiffusion' => 'infrastructure/markup/remarkup/markuprule/diffusion',
|
'PhabricatorRemarkupRuleDiffusion' => 'infrastructure/markup/remarkup/markuprule/diffusion',
|
||||||
'PhabricatorRemarkupRuleImageMacro' => 'infrastructure/markup/remarkup/markuprule/imagemacro',
|
'PhabricatorRemarkupRuleImageMacro' => 'infrastructure/markup/remarkup/markuprule/imagemacro',
|
||||||
'PhabricatorRemarkupRuleManiphest' => 'infrastructure/markup/remarkup/markuprule/maniphest',
|
'PhabricatorRemarkupRuleManiphest' => 'infrastructure/markup/remarkup/markuprule/maniphest',
|
||||||
|
'PhabricatorRemarkupRuleObjectName' => 'infrastructure/markup/remarkup/markuprule/objectname',
|
||||||
'PhabricatorRemarkupRuleProxyImage' => 'infrastructure/markup/remarkup/markuprule/proxyimage',
|
'PhabricatorRemarkupRuleProxyImage' => 'infrastructure/markup/remarkup/markuprule/proxyimage',
|
||||||
'PhabricatorRemarkupRuleYoutube' => 'infrastructure/markup/remarkup/markuprule/youtube',
|
'PhabricatorRemarkupRuleYoutube' => 'infrastructure/markup/remarkup/markuprule/youtube',
|
||||||
'PhabricatorRepository' => 'applications/repository/storage/repository',
|
'PhabricatorRepository' => 'applications/repository/storage/repository',
|
||||||
|
@ -841,10 +842,11 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorProjectProfile' => 'PhabricatorProjectDAO',
|
'PhabricatorProjectProfile' => 'PhabricatorProjectDAO',
|
||||||
'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
|
'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
|
||||||
'PhabricatorRedirectController' => 'PhabricatorController',
|
'PhabricatorRedirectController' => 'PhabricatorController',
|
||||||
'PhabricatorRemarkupRuleDifferential' => 'PhutilRemarkupRule',
|
'PhabricatorRemarkupRuleDifferential' => 'PhabricatorRemarkupRuleObjectName',
|
||||||
'PhabricatorRemarkupRuleDiffusion' => 'PhutilRemarkupRule',
|
'PhabricatorRemarkupRuleDiffusion' => 'PhutilRemarkupRule',
|
||||||
'PhabricatorRemarkupRuleImageMacro' => 'PhutilRemarkupRule',
|
'PhabricatorRemarkupRuleImageMacro' => 'PhutilRemarkupRule',
|
||||||
'PhabricatorRemarkupRuleManiphest' => 'PhutilRemarkupRule',
|
'PhabricatorRemarkupRuleManiphest' => 'PhabricatorRemarkupRuleObjectName',
|
||||||
|
'PhabricatorRemarkupRuleObjectName' => 'PhutilRemarkupRule',
|
||||||
'PhabricatorRemarkupRuleProxyImage' => 'PhutilRemarkupRule',
|
'PhabricatorRemarkupRuleProxyImage' => 'PhutilRemarkupRule',
|
||||||
'PhabricatorRemarkupRuleYoutube' => 'PhutilRemarkupRule',
|
'PhabricatorRemarkupRuleYoutube' => 'PhutilRemarkupRule',
|
||||||
'PhabricatorRepository' => 'PhabricatorRepositoryDAO',
|
'PhabricatorRepository' => 'PhabricatorRepositoryDAO',
|
||||||
|
|
|
@ -42,7 +42,7 @@ class PhabricatorLoginController extends PhabricatorAuthController {
|
||||||
$error_view = null;
|
$error_view = null;
|
||||||
if ($password_auth) {
|
if ($password_auth) {
|
||||||
$error = false;
|
$error = false;
|
||||||
$username = $request->getCookie('phusr');
|
$username_or_email = $request->getCookie('phusr');
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
$username_or_email = $request->getStr('username_or_email');
|
$username_or_email = $request->getStr('username_or_email');
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ final class DifferentialRevisionCommentView extends AphrontView {
|
||||||
private $inlines;
|
private $inlines;
|
||||||
private $changesets;
|
private $changesets;
|
||||||
private $target;
|
private $target;
|
||||||
|
private $commentNumber;
|
||||||
|
|
||||||
public function setComment($comment) {
|
public function setComment($comment) {
|
||||||
$this->comment = $comment;
|
$this->comment = $comment;
|
||||||
|
@ -61,6 +62,11 @@ final class DifferentialRevisionCommentView extends AphrontView {
|
||||||
$this->target = $target;
|
$this->target = $target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setCommentNumber($comment_number) {
|
||||||
|
$this->commentNumber = $comment_number;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function render() {
|
public function render() {
|
||||||
|
|
||||||
require_celerity_resource('phabricator-remarkup-css');
|
require_celerity_resource('phabricator-remarkup-css');
|
||||||
|
@ -78,6 +84,24 @@ final class DifferentialRevisionCommentView extends AphrontView {
|
||||||
$date = date('F jS, Y g:i:s A', $comment->getDateCreated());
|
$date = date('F jS, Y g:i:s A', $comment->getDateCreated());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$info = array($date);
|
||||||
|
|
||||||
|
$comment_anchor = null;
|
||||||
|
$num = $this->commentNumber;
|
||||||
|
if ($num) {
|
||||||
|
Javelin::initBehavior('phabricator-watch-anchor');
|
||||||
|
$info[] = phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'name' => 'comment-'.$num,
|
||||||
|
'href' => '#comment-'.$num,
|
||||||
|
),
|
||||||
|
'Comment D'.$comment->getRevisionID().'#'.$num);
|
||||||
|
$comment_anchor = 'anchor-comment-'.$num;
|
||||||
|
}
|
||||||
|
|
||||||
|
$info = implode(' · ', $info);
|
||||||
|
|
||||||
$author = $this->handles[$comment->getAuthorPHID()];
|
$author = $this->handles[$comment->getAuthorPHID()];
|
||||||
$author_link = $author->renderLink();
|
$author_link = $author->renderLink();
|
||||||
|
|
||||||
|
@ -189,11 +213,16 @@ final class DifferentialRevisionCommentView extends AphrontView {
|
||||||
$background = "background-image: url('{$uri}');";
|
$background = "background-image: url('{$uri}');";
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return phutil_render_tag(
|
||||||
'<div class="differential-comment '.$action_class.'">'.
|
'div',
|
||||||
|
array(
|
||||||
|
'class' => "differential-comment {$action_class}",
|
||||||
|
'id' => $comment_anchor,
|
||||||
|
),
|
||||||
'<div class="differential-comment-head">'.
|
'<div class="differential-comment-head">'.
|
||||||
'<div class="differential-comment-date">'.$date.'</div>'.
|
'<span class="differential-comment-info">'.$info.'</span>'.
|
||||||
'<div class="differential-comment-title">'.$title.'</div>'.
|
'<span class="differential-comment-title">'.$title.'</span>'.
|
||||||
|
'<div style="clear: both;"></div>'.
|
||||||
'</div>'.
|
'</div>'.
|
||||||
'<div class="differential-comment-body" style="'.$background.'">'.
|
'<div class="differential-comment-body" style="'.$background.'">'.
|
||||||
'<div class="differential-comment-content">'.
|
'<div class="differential-comment-content">'.
|
||||||
|
@ -202,8 +231,7 @@ final class DifferentialRevisionCommentView extends AphrontView {
|
||||||
'</div>'.
|
'</div>'.
|
||||||
$inline_render.
|
$inline_render.
|
||||||
'</div>'.
|
'</div>'.
|
||||||
'</div>'.
|
'</div>');
|
||||||
'</div>';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'applications/differential/constants/action');
|
phutil_require_module('phabricator', 'applications/differential/constants/action');
|
||||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||||
|
phutil_require_module('phabricator', 'infrastructure/javelin/api');
|
||||||
phutil_require_module('phabricator', 'view/base');
|
phutil_require_module('phabricator', 'view/base');
|
||||||
|
|
||||||
phutil_require_module('phutil', 'markup');
|
phutil_require_module('phutil', 'markup');
|
||||||
|
|
|
@ -63,7 +63,7 @@ final class DifferentialRevisionCommentListView extends AphrontView {
|
||||||
|
|
||||||
$inlines = mgroup($this->inlines, 'getCommentID');
|
$inlines = mgroup($this->inlines, 'getCommentID');
|
||||||
|
|
||||||
|
$num = 1;
|
||||||
$html = array();
|
$html = array();
|
||||||
foreach ($this->comments as $comment) {
|
foreach ($this->comments as $comment) {
|
||||||
$view = new DifferentialRevisionCommentView();
|
$view = new DifferentialRevisionCommentView();
|
||||||
|
@ -73,6 +73,7 @@ final class DifferentialRevisionCommentListView extends AphrontView {
|
||||||
$view->setInlineComments(idx($inlines, $comment->getID(), array()));
|
$view->setInlineComments(idx($inlines, $comment->getID(), array()));
|
||||||
$view->setChangesets($this->changesets);
|
$view->setChangesets($this->changesets);
|
||||||
$view->setTargetDiff($this->target);
|
$view->setTargetDiff($this->target);
|
||||||
|
$view->setCommentNumber($num++);
|
||||||
|
|
||||||
$html[] = $view->render();
|
$html[] = $view->render();
|
||||||
}
|
}
|
||||||
|
@ -158,7 +159,7 @@ final class DifferentialRevisionCommentListView extends AphrontView {
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
'<div>'.
|
'<div class="differential-comment-list">'.
|
||||||
implode("\n", $header).
|
implode("\n", $header).
|
||||||
$hidden.
|
$hidden.
|
||||||
implode("\n", $visible).
|
implode("\n", $visible).
|
||||||
|
|
|
@ -23,6 +23,7 @@ class ManiphestTransactionDetailView extends AphrontView {
|
||||||
private $markupEngine;
|
private $markupEngine;
|
||||||
private $forEmail;
|
private $forEmail;
|
||||||
private $preview;
|
private $preview;
|
||||||
|
private $commentNumber;
|
||||||
|
|
||||||
private $renderSummaryOnly;
|
private $renderSummaryOnly;
|
||||||
private $renderFullSummary;
|
private $renderFullSummary;
|
||||||
|
@ -65,6 +66,11 @@ class ManiphestTransactionDetailView extends AphrontView {
|
||||||
return $this->renderFullSummary;
|
return $this->renderFullSummary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setCommentNumber($comment_number) {
|
||||||
|
$this->commentNumber = $comment_number;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function renderForEmail($with_date) {
|
public function renderForEmail($with_date) {
|
||||||
$this->forEmail = true;
|
$this->forEmail = true;
|
||||||
|
|
||||||
|
@ -174,16 +180,37 @@ class ManiphestTransactionDetailView extends AphrontView {
|
||||||
$timestamp = phabricator_format_timestamp($transaction->getDateCreated());
|
$timestamp = phabricator_format_timestamp($transaction->getDateCreated());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$info = array();
|
||||||
|
$info[] = $timestamp;
|
||||||
|
|
||||||
|
|
||||||
|
$comment_anchor = null;
|
||||||
|
$num = $this->commentNumber;
|
||||||
|
if ($num) {
|
||||||
|
Javelin::initBehavior('phabricator-watch-anchor');
|
||||||
|
$info[] = javelin_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'name' => 'comment-'.$num,
|
||||||
|
'href' => '#comment-'.$num,
|
||||||
|
),
|
||||||
|
'Comment T'.$any_transaction->getTaskID().'#'.$num);
|
||||||
|
$comment_anchor = 'anchor-comment-'.$num;
|
||||||
|
}
|
||||||
|
|
||||||
|
$info = implode(' · ', $info);
|
||||||
|
|
||||||
return phutil_render_tag(
|
return phutil_render_tag(
|
||||||
'div',
|
'div',
|
||||||
array(
|
array(
|
||||||
'class' => "maniphest-transaction-detail-container",
|
'class' => "maniphest-transaction-detail-container",
|
||||||
'style' => "background-image: url('".$author->getImageURI()."')",
|
'style' => "background-image: url('".$author->getImageURI()."')",
|
||||||
|
'id' => $comment_anchor,
|
||||||
),
|
),
|
||||||
'<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">'.
|
||||||
$timestamp.
|
$info.
|
||||||
'</div>'.
|
'</div>'.
|
||||||
$descs.
|
$descs.
|
||||||
'</div>'.
|
'</div>'.
|
||||||
|
|
|
@ -77,17 +77,19 @@ class ManiphestTransactionListView extends AphrontView {
|
||||||
$groups[] = $group;
|
$groups[] = $group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$sequence = 1;
|
||||||
foreach ($groups as $group) {
|
foreach ($groups as $group) {
|
||||||
$view = new ManiphestTransactionDetailView();
|
$view = new ManiphestTransactionDetailView();
|
||||||
$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);
|
$view->setPreview($this->preview);
|
||||||
|
$view->setCommentNumber($sequence++);
|
||||||
$views[] = $view->render();
|
$views[] = $view->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
'<div style="padding: .5em 1.5em;">'.
|
'<div class="maniphest-transaction-list-view">'.
|
||||||
implode("\n", $views).
|
implode("\n", $views).
|
||||||
'</div>';
|
'</div>';
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,10 @@ by mentioning the name of an object:
|
||||||
# You must specify at least 7 characters of the hash.
|
# You must specify at least 7 characters of the hash.
|
||||||
T123 # Link to Maniphest task T123
|
T123 # Link to Maniphest task T123
|
||||||
|
|
||||||
|
You can also link directly to a comment in Maniphest and Differential:
|
||||||
|
|
||||||
|
T123#4 # Link to comment #4 of T123
|
||||||
|
|
||||||
= Quoting Text =
|
= Quoting Text =
|
||||||
|
|
||||||
To quote text, preface it with an ">":
|
To quote text, preface it with an ">":
|
||||||
|
|
|
@ -43,9 +43,22 @@ final class CelerityStaticResourceResponse {
|
||||||
return $this->metadataBlock;
|
return $this->metadataBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a behavior for initialization. NOTE: if $config is empty,
|
||||||
|
* a behavior will execute only once even if it is initialized multiple times.
|
||||||
|
* If $config is nonempty, the behavior will be invoked once for each config.
|
||||||
|
*/
|
||||||
public function initBehavior($behavior, array $config = array()) {
|
public function initBehavior($behavior, array $config = array()) {
|
||||||
$this->requireResource('javelin-behavior-'.$behavior);
|
$this->requireResource('javelin-behavior-'.$behavior);
|
||||||
|
|
||||||
|
if (empty($this->behaviors[$behavior])) {
|
||||||
|
$this->behaviors[$behavior] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($config) {
|
||||||
$this->behaviors[$behavior][] = $config;
|
$this->behaviors[$behavior][] = $config;
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,18 +20,10 @@
|
||||||
* @group markup
|
* @group markup
|
||||||
*/
|
*/
|
||||||
class PhabricatorRemarkupRuleDifferential
|
class PhabricatorRemarkupRuleDifferential
|
||||||
extends PhutilRemarkupRule {
|
extends PhabricatorRemarkupRuleObjectName {
|
||||||
|
|
||||||
public function apply($text) {
|
protected function getObjectNamePrefix() {
|
||||||
return preg_replace_callback(
|
return 'D';
|
||||||
'@\bD(\d+)\b@',
|
|
||||||
array($this, 'markupDifferentialLink'),
|
|
||||||
$text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function markupDifferentialLink($matches) {
|
|
||||||
return $this->getEngine()->storeText(
|
|
||||||
'<a href="/D'.$matches[1].'">D'.$matches[1].'</a>');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
phutil_require_module('phutil', 'markup/engine/remarkup/markuprule/base');
|
phutil_require_module('phabricator', 'infrastructure/markup/remarkup/markuprule/objectname');
|
||||||
|
|
||||||
|
|
||||||
phutil_require_source('PhabricatorRemarkupRuleDifferential.php');
|
phutil_require_source('PhabricatorRemarkupRuleDifferential.php');
|
||||||
|
|
|
@ -20,18 +20,10 @@
|
||||||
* @group markup
|
* @group markup
|
||||||
*/
|
*/
|
||||||
class PhabricatorRemarkupRuleManiphest
|
class PhabricatorRemarkupRuleManiphest
|
||||||
extends PhutilRemarkupRule {
|
extends PhabricatorRemarkupRuleObjectName {
|
||||||
|
|
||||||
public function apply($text) {
|
protected function getObjectNamePrefix() {
|
||||||
return preg_replace_callback(
|
return 'T';
|
||||||
'@\bT(\d+)\b@',
|
|
||||||
array($this, 'markupManiphestLink'),
|
|
||||||
$text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function markupManiphestLink($matches) {
|
|
||||||
return $this->getEngine()->storeText(
|
|
||||||
'<a href="/T'.$matches[1].'">T'.$matches[1].'</a>');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
phutil_require_module('phutil', 'markup/engine/remarkup/markuprule/base');
|
phutil_require_module('phabricator', 'infrastructure/markup/remarkup/markuprule/objectname');
|
||||||
|
|
||||||
|
|
||||||
phutil_require_source('PhabricatorRemarkupRuleManiphest.php');
|
phutil_require_source('PhabricatorRemarkupRuleManiphest.php');
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group markup
|
||||||
|
*/
|
||||||
|
abstract class PhabricatorRemarkupRuleObjectName
|
||||||
|
extends PhutilRemarkupRule {
|
||||||
|
|
||||||
|
abstract protected function getObjectNamePrefix();
|
||||||
|
|
||||||
|
public function apply($text) {
|
||||||
|
$prefix = $this->getObjectNamePrefix();
|
||||||
|
return preg_replace_callback(
|
||||||
|
"@\b{$prefix}(\d+)(?:#(\d+))?\b@",
|
||||||
|
array($this, 'markupObjectNameLink'),
|
||||||
|
$text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function markupObjectNameLink($matches) {
|
||||||
|
$prefix = $this->getObjectNamePrefix();
|
||||||
|
$id = $matches[1];
|
||||||
|
|
||||||
|
if (isset($matches[2])) {
|
||||||
|
$comment_id = $matches[2];
|
||||||
|
$href = "/{$prefix}{$id}#comment-{$comment_id}";
|
||||||
|
$text = "{$prefix}{$id}#{$comment_id}";
|
||||||
|
} else {
|
||||||
|
$href = "/{$prefix}{$id}";
|
||||||
|
$text = "{$prefix}{$id}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getEngine()->storeText(
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => $href,
|
||||||
|
),
|
||||||
|
$text));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'markup');
|
||||||
|
phutil_require_module('phutil', 'markup/engine/remarkup/markuprule/base');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhabricatorRemarkupRuleObjectName.php');
|
|
@ -65,14 +65,7 @@ final class AphrontFormView extends AphrontView {
|
||||||
public function render() {
|
public function render() {
|
||||||
require_celerity_resource('aphront-form-view-css');
|
require_celerity_resource('aphront-form-view-css');
|
||||||
|
|
||||||
static $initialized_behavior;
|
Javelin::initBehavior('aphront-form-disable-on-submit');
|
||||||
if (!$initialized_behavior) {
|
|
||||||
// TODO: This is sort of a yucky hack.
|
|
||||||
$initialized_behavior = true;
|
|
||||||
Javelin::initBehavior(
|
|
||||||
'aphront-form-disable-on-submit',
|
|
||||||
array());
|
|
||||||
}
|
|
||||||
|
|
||||||
return javelin_render_tag(
|
return javelin_render_tag(
|
||||||
'form',
|
'form',
|
||||||
|
|
|
@ -3,14 +3,29 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
.differential-comment-date {
|
.differential-comment {
|
||||||
|
padding: 3px 6px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.differential-comment-list .anchor-target {
|
||||||
|
background-color: #ffffdd;
|
||||||
|
border-color: #ffff00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.differential-comment-info {
|
||||||
color: #666666;
|
color: #666666;
|
||||||
float: right;
|
float: right;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
margin: 0em;
|
margin: 0 0 3px;
|
||||||
padding-top: 6px;
|
padding-top: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.differential-comment-info a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.differential-comment-title {
|
.differential-comment-title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
|
@ -24,7 +39,6 @@
|
||||||
padding-left: 62px;
|
padding-left: 62px;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: 6px 0px;
|
background-position: 6px 0px;
|
||||||
margin-bottom: 14px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.differential-comment-content {
|
.differential-comment-content {
|
||||||
|
|
|
@ -2,10 +2,21 @@
|
||||||
* @provides maniphest-transaction-detail-css
|
* @provides maniphest-transaction-detail-css
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.maniphest-trnasaction-list-view {
|
||||||
|
padding: .5em 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.maniphest-transaction-detail-container {
|
.maniphest-transaction-detail-container {
|
||||||
margin: 1em 1em 1.5em;
|
margin: 1em 1em 1.25em;
|
||||||
background: 0px 0px no-repeat;
|
background: 2px 2px no-repeat;
|
||||||
min-height: 50px;
|
min-height: 50px;
|
||||||
|
padding: 2px 2px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.maniphest-transaction-list-view .anchor-target {
|
||||||
|
background-color: #ffffdd;
|
||||||
|
border-color: #ffff00;
|
||||||
}
|
}
|
||||||
|
|
||||||
.maniphest-transaction-detail-container .upforgrab {
|
.maniphest-transaction-detail-container .upforgrab {
|
||||||
|
|
34
webroot/rsrc/js/application/core/behavior-watch-anchor.js
Normal file
34
webroot/rsrc/js/application/core/behavior-watch-anchor.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* @provides javelin-behavior-phabricator-watch-anchor
|
||||||
|
* @requires javelin-behavior
|
||||||
|
* javelin-stratcom
|
||||||
|
* javelin-util
|
||||||
|
* javelin-dom
|
||||||
|
*/
|
||||||
|
|
||||||
|
JX.behavior('phabricator-watch-anchor', function() {
|
||||||
|
|
||||||
|
var highlighted;
|
||||||
|
|
||||||
|
function highlight() {
|
||||||
|
highlighted && JX.DOM.alterClass(highlighted, 'anchor-target', false);
|
||||||
|
try {
|
||||||
|
highlighted = JX.$('anchor-' + window.location.hash.replace('#', ''));
|
||||||
|
JX.DOM.alterClass(highlighted, 'anchor-target', true);
|
||||||
|
} catch (ex) {
|
||||||
|
if (ex === JX.$.NotFound) {
|
||||||
|
highlighted = null;
|
||||||
|
} else {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JX.Stratcom.listen(
|
||||||
|
'hashchange',
|
||||||
|
null,
|
||||||
|
// Defer invocation so other listeners can update the document.
|
||||||
|
function() { JX.defer(highlight); });
|
||||||
|
|
||||||
|
JX.defer(highlight);
|
||||||
|
});
|
|
@ -7,13 +7,43 @@
|
||||||
|
|
||||||
JX.behavior('differential-show-all-comments', function(config) {
|
JX.behavior('differential-show-all-comments', function(config) {
|
||||||
|
|
||||||
|
var shown = false;
|
||||||
|
function reveal(node) {
|
||||||
|
if (shown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
shown = true;
|
||||||
|
node = node || JX.DOM.find(
|
||||||
|
document.body,
|
||||||
|
'div',
|
||||||
|
'differential-all-comments-container');
|
||||||
|
if (node) {
|
||||||
|
JX.DOM.setContent(node, JX.$H(config.markup));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reveal the hidden comments if the user clicks "Show All Comments", or if
|
||||||
|
// there's an anchor in the URL, since we don't want to link to "#comment-3"
|
||||||
|
// and have it collapsed.
|
||||||
|
|
||||||
|
if (window.location.hash) {
|
||||||
|
reveal();
|
||||||
|
} else {
|
||||||
|
JX.Stratcom.listen(
|
||||||
|
'hashchange',
|
||||||
|
null,
|
||||||
|
function(e) {
|
||||||
|
if (window.location.hash.match(/comment/)) {
|
||||||
|
reveal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
JX.Stratcom.listen(
|
JX.Stratcom.listen(
|
||||||
'click',
|
'click',
|
||||||
'differential-show-all-comments',
|
'differential-show-all-comments',
|
||||||
function(e) {
|
function(e) {
|
||||||
JX.DOM.setContent(
|
reveal(e.getNode('differential-all-comments-container'));
|
||||||
e.getNode('differential-all-comments-container'),
|
|
||||||
JX.$H(config.markup));
|
|
||||||
e.kill();
|
e.kill();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue