Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php
index 852fe7f057..99b7e68be0 100644
--- a/src/__celerity_resource_map__.php
+++ b/src/__celerity_resource_map__.php
@@ -1,1208 +1,1223 @@
<?php
/**
* This file is automatically generated. Use 'celerity_mapper.php' to rebuild
* it.
* @generated
*/
celerity_register_resource_map(array(
'aphront-attached-file-view-css' =>
array(
'uri' => '/res/a6ca5487/rsrc/css/aphront/attached-file-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/attached-file-view.css',
),
'aphront-crumbs-view-css' =>
array(
'uri' => '/res/9009e6bd/rsrc/css/aphront/crumbs-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/crumbs-view.css',
),
'aphront-dark-console-css' =>
array(
'uri' => '/res/e7011594/rsrc/css/aphront/dark-console.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/dark-console.css',
),
'aphront-dialog-view-css' =>
array(
'uri' => '/res/79613f9b/rsrc/css/aphront/dialog-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/dialog-view.css',
),
'aphront-error-view-css' =>
array(
'uri' => '/res/98c5fc69/rsrc/css/aphront/error-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/error-view.css',
),
'aphront-form-view-css' =>
array(
'uri' => '/res/38a347da/rsrc/css/aphront/form-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/form-view.css',
),
'aphront-headsup-action-list-view-css' =>
array(
'uri' => '/res/71783633/rsrc/css/aphront/headsup-action-list-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/headsup-action-list-view.css',
),
'aphront-list-filter-view-css' =>
array(
'uri' => '/res/e6cff171/rsrc/css/aphront/list-filter-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/list-filter-view.css',
),
'aphront-pager-view-css' =>
array(
'uri' => '/res/43fb79f0/rsrc/css/aphront/pager-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/pager-view.css',
),
'aphront-panel-view-css' =>
array(
'uri' => '/res/e0139b9c/rsrc/css/aphront/panel-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/panel-view.css',
),
'aphront-request-failure-view-css' =>
array(
'uri' => '/res/c9a43002/rsrc/css/aphront/request-failure-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/request-failure-view.css',
),
'aphront-side-nav-view-css' =>
array(
'uri' => '/res/f92966bd/rsrc/css/aphront/side-nav-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/side-nav-view.css',
),
'aphront-table-view-css' =>
array(
'uri' => '/res/910e83ec/rsrc/css/aphront/table-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/table-view.css',
),
'aphront-tokenizer-control-css' =>
array(
'uri' => '/res/f530af47/rsrc/css/aphront/tokenizer.css',
'type' => 'css',
'requires' =>
array(
0 => 'aphront-typeahead-control-css',
),
'disk' => '/rsrc/css/aphront/tokenizer.css',
),
'aphront-typeahead-control-css' =>
array(
'uri' => '/res/a05236a6/rsrc/css/aphront/typeahead.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/typeahead.css',
),
'differential-changeset-view-css' =>
array(
- 'uri' => '/res/4cb57f5f/rsrc/css/application/differential/changeset-view.css',
+ 'uri' => '/res/313e96e9/rsrc/css/application/differential/changeset-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/changeset-view.css',
),
'differential-core-view-css' =>
array(
'uri' => '/res/d0ae90e5/rsrc/css/application/differential/core.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/core.css',
),
+ 'differential-inline-comment-editor' =>
+ array(
+ 'uri' => '/res/0ee4fd79/rsrc/js/application/differential/DifferentialInlineCommentEditor.js',
+ 'type' => 'js',
+ 'requires' =>
+ array(
+ 0 => 'javelin-dom',
+ 1 => 'javelin-workflow',
+ 2 => 'javelin-util',
+ 3 => 'javelin-stratcom',
+ 4 => 'javelin-install',
+ ),
+ 'disk' => '/rsrc/js/application/differential/DifferentialInlineCommentEditor.js',
+ ),
'differential-revision-add-comment-css' =>
array(
'uri' => '/res/849748d3/rsrc/css/application/differential/add-comment.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/add-comment.css',
),
'differential-revision-comment-css' =>
array(
'uri' => '/res/e3539439/rsrc/css/application/differential/revision-comment.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/revision-comment.css',
),
'differential-revision-comment-list-css' =>
array(
'uri' => '/res/3b31faa3/rsrc/css/application/differential/revision-comment-list.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/revision-comment-list.css',
),
'differential-revision-detail-css' =>
array(
'uri' => '/res/ea9de420/rsrc/css/application/differential/revision-detail.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/revision-detail.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-history-css' =>
array(
'uri' => '/res/0d7d515d/rsrc/css/application/differential/revision-history.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/revision-history.css',
),
'differential-table-of-contents-css' =>
array(
'uri' => '/res/d173445b/rsrc/css/application/differential/table-of-contents.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/table-of-contents.css',
),
'diffusion-commit-view-css' =>
array(
'uri' => '/res/bc39d876/rsrc/css/application/diffusion/commit-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/diffusion/commit-view.css',
),
'diffusion-source-css' =>
array(
'uri' => '/res/db4566b6/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',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/herald/herald.css',
),
'herald-rule-editor' =>
array(
'uri' => '/res/402e94d2/rsrc/js/application/herald/HeraldRuleEditor.js',
'type' => 'js',
'requires' =>
array(
0 => 'multirow-row-manager',
1 => 'javelin-install',
2 => 'javelin-typeahead',
3 => 'javelin-util',
4 => 'javelin-dom',
5 => 'javelin-tokenizer',
6 => 'javelin-typeahead-preloaded-source',
7 => 'javelin-stratcom',
8 => 'javelin-json',
),
'disk' => '/rsrc/js/application/herald/HeraldRuleEditor.js',
),
'herald-test-css' =>
array(
'uri' => '/res/c0cd6bdb/rsrc/css/application/herald/herald-test.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/herald/herald-test.css',
),
'javelin-behavior' =>
array(
'uri' => '/res/3c772c64/rsrc/js/javelin/lib/behavior.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-magical-init',
),
'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' =>
array(
'uri' => '/res/bce3961b/rsrc/js/application/core/behavior-tokenizer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-typeahead',
2 => 'javelin-tokenizer',
3 => 'javelin-typeahead-preloaded-source',
4 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-tokenizer.js',
),
'javelin-behavior-aphront-drag-and-drop' =>
array(
'uri' => '/res/170115f4/rsrc/js/application/core/behavior-drag-and-drop.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-drag-and-drop-file-upload',
),
'disk' => '/rsrc/js/application/core/behavior-drag-and-drop.js',
),
'javelin-behavior-aphront-form-disable-on-submit' =>
array(
'uri' => '/res/6c659ede/rsrc/js/application/core/behavior-form.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-form.js',
),
'javelin-behavior-dark-console' =>
array(
'uri' => '/res/c80156c4/rsrc/js/application/core/behavior-dark-console.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-request',
5 => 'phabricator-keyboard-shortcut',
),
'disk' => '/rsrc/js/application/core/behavior-dark-console.js',
),
'javelin-behavior-differential-add-reviewers' =>
array(
'uri' => '/res/dc79790c/rsrc/js/application/differential/behavior-add-reviewers.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-tokenizer',
3 => 'javelin-typeahead',
4 => 'javelin-typeahead-preloaded-source',
),
'disk' => '/rsrc/js/application/differential/behavior-add-reviewers.js',
),
'javelin-behavior-differential-comment-jump' =>
array(
'uri' => '/res/be77fced/rsrc/js/application/differential/behavior-comment-jump.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-util',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/differential/behavior-comment-jump.js',
),
'javelin-behavior-differential-diff-radios' =>
array(
'uri' => '/res/004cb66f/rsrc/js/application/differential/behavior-diff-radios.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/differential/behavior-diff-radios.js',
),
'javelin-behavior-differential-edit-inline-comments' =>
array(
- 'uri' => '/res/682d1a9c/rsrc/js/application/differential/behavior-edit-inline-comments.js',
+ 'uri' => '/res/e21bb634/rsrc/js/application/differential/behavior-edit-inline-comments.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
- 3 => 'javelin-workflow',
+ 3 => 'javelin-util',
4 => 'javelin-vector',
+ 5 => 'differential-inline-comment-editor',
),
'disk' => '/rsrc/js/application/differential/behavior-edit-inline-comments.js',
),
'javelin-behavior-differential-feedback-preview' =>
array(
'uri' => '/res/ab8a7d60/rsrc/js/application/differential/behavior-comment-preview.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-request',
4 => 'javelin-util',
5 => 'phabricator-shaped-request',
),
'disk' => '/rsrc/js/application/differential/behavior-comment-preview.js',
),
'javelin-behavior-differential-populate' =>
array(
'uri' => '/res/025171e1/rsrc/js/application/differential/behavior-populate.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-request',
2 => 'javelin-util',
3 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/differential/behavior-populate.js',
),
'javelin-behavior-differential-show-all-comments' =>
array(
'uri' => '/res/bcc990f0/rsrc/js/application/differential/behavior-show-all-comments.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/differential/behavior-show-all-comments.js',
),
'javelin-behavior-differential-show-more' =>
array(
- 'uri' => '/res/9cbf1c9c/rsrc/js/application/differential/behavior-show-more.js',
+ 'uri' => '/res/a766c717/rsrc/js/application/differential/behavior-show-more.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-request',
3 => 'javelin-util',
4 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/differential/behavior-show-more.js',
),
'javelin-behavior-diffusion-jump-to' =>
array(
'uri' => '/res/4b63e436/rsrc/js/application/diffusion/behavior-jump-to.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-util',
2 => 'javelin-vector',
3 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/diffusion/behavior-jump-to.js',
),
'javelin-behavior-diffusion-pull-lastmodified' =>
array(
'uri' => '/res/29fe2790/rsrc/js/application/diffusion/behavior-pull-lastmodified.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-request',
),
'disk' => '/rsrc/js/application/diffusion/behavior-pull-lastmodified.js',
),
'javelin-behavior-error-log' =>
array(
'uri' => '/res/a5cb42a5/rsrc/js/application/core/behavior-error-log.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-error-log.js',
),
'javelin-behavior-herald-rule-editor' =>
array(
'uri' => '/res/77a0c945/rsrc/js/application/herald/herald-rule-editor.js',
'type' => 'js',
'requires' =>
array(
0 => 'herald-rule-editor',
1 => 'javelin-behavior',
),
'disk' => '/rsrc/js/application/herald/herald-rule-editor.js',
),
'javelin-behavior-maniphest-transaction-controls' =>
array(
'uri' => '/res/94a2a395/rsrc/js/application/maniphest/behavior-transaction-controls.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-tokenizer',
3 => 'javelin-typeahead',
4 => 'javelin-typeahead-preloaded-source',
),
'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',
'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' =>
array(
'uri' => '/res/9cf78ffc/rsrc/js/application/owners/owners-path-editor.js',
'type' => 'js',
'requires' =>
array(
0 => 'owners-path-editor',
1 => 'javelin-behavior',
),
'disk' => '/rsrc/js/application/owners/owners-path-editor.js',
),
'javelin-behavior-phabricator-keyboard-shortcuts' =>
array(
'uri' => '/res/5a23bcc8/rsrc/js/application/core/behavior-keyboard-shortcuts.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-workflow',
2 => 'javelin-json',
3 => 'phabricator-keyboard-shortcut',
),
'disk' => '/rsrc/js/application/core/behavior-keyboard-shortcuts.js',
),
'javelin-behavior-phabricator-object-selector' =>
array(
'uri' => '/res/12d4d90d/rsrc/js/application/core/behavior-object-selector.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-request',
3 => 'javelin-util',
4 => 'javelin-stratcom',
),
'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' =>
array(
'uri' => '/res/079f49c3/rsrc/js/application/core/behavior-workflow.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-workflow',
),
'disk' => '/rsrc/js/application/core/behavior-workflow.js',
),
'javelin-dom' =>
array(
'uri' => '/res/43e9e2de/rsrc/js/javelin/lib/DOM.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-magical-init',
1 => 'javelin-install',
2 => 'javelin-util',
3 => 'javelin-vector',
4 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/javelin/lib/DOM.js',
),
'javelin-event' =>
array(
'uri' => '/res/25c7c9e8/rsrc/js/javelin/core/Event.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/core/Event.js',
),
'javelin-install' =>
array(
'uri' => '/res/f4d0e147/rsrc/js/javelin/core/install.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-util',
1 => 'javelin-magical-init',
),
'disk' => '/rsrc/js/javelin/core/install.js',
),
'javelin-json' =>
array(
'uri' => '/res/1c4e3f6a/rsrc/js/javelin/lib/JSON.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/lib/JSON.js',
),
'javelin-magical-init' =>
array(
'uri' => '/res/92e7f37e/rsrc/js/javelin/core/init.js',
'type' => 'js',
'requires' =>
array(
),
'disk' => '/rsrc/js/javelin/core/init.js',
),
'javelin-mask' =>
array(
'uri' => '/res/28e3bd9c/rsrc/js/javelin/lib/Mask.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-vector',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/javelin/lib/Mask.js',
),
'javelin-request' =>
array(
'uri' => '/res/1ed0d596/rsrc/js/javelin/lib/Request.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-stratcom',
2 => 'javelin-util',
3 => 'javelin-behavior',
),
'disk' => '/rsrc/js/javelin/lib/Request.js',
),
'javelin-stratcom' =>
array(
'uri' => '/res/9e7eb62b/rsrc/js/javelin/core/Stratcom.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-event',
2 => 'javelin-util',
3 => 'javelin-magical-init',
),
'disk' => '/rsrc/js/javelin/core/Stratcom.js',
),
'javelin-tokenizer' =>
array(
'uri' => '/res/83787676/rsrc/js/javelin/lib/control/tokenizer/Tokenizer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-dom',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/lib/control/tokenizer/Tokenizer.js',
),
'javelin-typeahead' =>
array(
'uri' => '/res/ae18ee16/rsrc/js/javelin/lib/control/typeahead/Typeahead.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-vector',
3 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/Typeahead.js',
),
'javelin-typeahead-normalizer' =>
array(
'uri' => '/res/a5d60e3c/rsrc/js/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js',
),
'javelin-typeahead-ondemand-source' =>
array(
'uri' => '/res/0015bbf5/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-request',
4 => 'javelin-typeahead-source',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js',
),
'javelin-typeahead-preloaded-source' =>
array(
'uri' => '/res/863a173c/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-request',
4 => 'javelin-typeahead-source',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js',
),
'javelin-typeahead-source' =>
array(
'uri' => '/res/58518dde/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadSource.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-typeahead-normalizer',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadSource.js',
),
'javelin-uri' =>
array(
'uri' => '/res/70c9d32b/rsrc/js/javelin/lib/URI.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/javelin/lib/URI.js',
),
'javelin-util' =>
array(
'uri' => '/res/be43fdba/rsrc/js/javelin/core/util.js',
'type' => 'js',
'requires' =>
array(
),
'disk' => '/rsrc/js/javelin/core/util.js',
),
'javelin-vector' =>
array(
'uri' => '/res/cd4721c4/rsrc/js/javelin/lib/Vector.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-event',
),
'disk' => '/rsrc/js/javelin/lib/Vector.js',
),
'javelin-workflow' =>
array(
'uri' => '/res/efe645f0/rsrc/js/javelin/lib/Workflow.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-stratcom',
1 => 'javelin-request',
2 => 'javelin-dom',
3 => 'javelin-vector',
4 => 'javelin-install',
5 => 'javelin-util',
6 => 'javelin-mask',
7 => 'javelin-uri',
),
'disk' => '/rsrc/js/javelin/lib/Workflow.js',
),
'mainphest-task-detail-css' =>
array(
'uri' => '/res/dbefc148/rsrc/css/application/maniphest/task-detail.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/maniphest/task-detail.css',
),
'maniphest-task-summary-css' =>
array(
'uri' => '/res/41624cb0/rsrc/css/application/maniphest/task-summary.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/maniphest/task-summary.css',
),
'maniphest-transaction-detail-css' =>
array(
'uri' => '/res/7ee02b5e/rsrc/css/application/maniphest/transaction-detail.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/maniphest/transaction-detail.css',
),
'multirow-row-manager' =>
array(
'uri' => '/res/0a9b3dee/rsrc/js/application/core/MultirowRowManager.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-util',
),
'disk' => '/rsrc/js/application/core/MultirowRowManager.js',
),
'owners-path-editor' =>
array(
'uri' => '/res/e6c51eb6/rsrc/js/application/owners/OwnersPathEditor.js',
'type' => 'js',
'requires' =>
array(
0 => 'multirow-row-manager',
1 => 'javelin-install',
2 => 'path-typeahead',
3 => 'javelin-dom',
4 => 'javelin-util',
),
'disk' => '/rsrc/js/application/owners/OwnersPathEditor.js',
),
'owners-path-editor-css' =>
array(
'uri' => '/res/9bc5332c/rsrc/css/application/owners/owners-path-editor.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/owners/owners-path-editor.css',
),
'path-typeahead' =>
array(
'uri' => '/res/1343345d/rsrc/js/application/herald/PathTypeahead.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-typeahead',
2 => 'javelin-dom',
3 => 'javelin-request',
4 => 'javelin-typeahead-ondemand-source',
5 => 'javelin-util',
),
'disk' => '/rsrc/js/application/herald/PathTypeahead.js',
),
'phabricator-core-buttons-css' =>
array(
'uri' => '/res/3059cf79/rsrc/css/core/buttons.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/core/buttons.css',
),
'phabricator-core-css' =>
array(
'uri' => '/res/78194d68/rsrc/css/core/core.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/core/core.css',
),
'phabricator-directory-css' =>
array(
'uri' => '/res/a3d307c5/rsrc/css/application/directory/phabricator-directory.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/directory/phabricator-directory.css',
),
'phabricator-drag-and-drop-file-upload' =>
array(
'uri' => '/res/63a06ad9/rsrc/js/application/core/DragAndDropFileUpload.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-request',
3 => 'javelin-dom',
4 => 'javelin-uri',
),
'disk' => '/rsrc/js/application/core/DragAndDropFileUpload.js',
),
'phabricator-keyboard-shortcut' =>
array(
'uri' => '/res/beed38cd/rsrc/js/application/core/KeyboardShortcut.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'phabricator-keyboard-shortcut-manager',
),
'disk' => '/rsrc/js/application/core/KeyboardShortcut.js',
),
'phabricator-keyboard-shortcut-manager' =>
array(
'uri' => '/res/b32845bd/rsrc/js/application/core/KeyboardShortcutManager.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/KeyboardShortcutManager.js',
),
'phabricator-object-selector-css' =>
array(
'uri' => '/res/ced4098a/rsrc/css/application/objectselector/object-selector.css',
'type' => 'css',
'requires' =>
array(
0 => 'aphront-dialog-view-css',
),
'disk' => '/rsrc/css/application/objectselector/object-selector.css',
),
'phabricator-profile-css' =>
array(
'uri' => '/res/adcdb5f3/rsrc/css/application/people/profile.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/people/profile.css',
),
'phabricator-remarkup-css' =>
array(
'uri' => '/res/774d4078/rsrc/css/core/remarkup.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/core/remarkup.css',
),
'phabricator-shaped-request' =>
array(
'uri' => '/res/d7ba774e/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' =>
array(
'uri' => '/res/02ae6920/rsrc/css/application/base/standard-page-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/base/standard-page-view.css',
),
'phabricator-ui-example-css' =>
array(
'uri' => '/res/0cef078b/rsrc/css/application/uiexample/example.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/uiexample/example.css',
),
'syntax-highlighting-css' =>
array(
'uri' => '/res/e5cc3d88/rsrc/css/core/syntax.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/core/syntax.css',
),
), array (
'packages' =>
array (
'03ef179e' =>
array (
'name' => 'diffusion.pkg.css',
'symbols' =>
array (
0 => 'diffusion-commit-view-css',
),
'uri' => '/res/pkg/03ef179e/diffusion.pkg.css',
'type' => 'css',
),
+ '234a821b' =>
+ 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/234a821b/differential.pkg.css',
+ 'type' => 'css',
+ ),
'33f413ef' =>
array (
'name' => 'typeahead.pkg.js',
'symbols' =>
array (
0 => 'javelin-typeahead',
1 => 'javelin-typeahead-normalizer',
2 => 'javelin-typeahead-source',
3 => 'javelin-typeahead-preloaded-source',
4 => 'javelin-typeahead-ondemand-source',
5 => 'javelin-tokenizer',
6 => 'javelin-behavior-aphront-basic-tokenizer',
),
'uri' => '/res/pkg/33f413ef/typeahead.pkg.js',
'type' => 'js',
),
'64383b02' =>
array (
'name' => 'core.pkg.css',
'symbols' =>
array (
0 => 'phabricator-core-css',
1 => 'phabricator-core-buttons-css',
2 => 'phabricator-standard-page-view',
3 => 'aphront-dialog-view-css',
4 => 'aphront-form-view-css',
5 => 'aphront-panel-view-css',
6 => 'aphront-side-nav-view-css',
7 => 'aphront-table-view-css',
8 => 'aphront-crumbs-view-css',
9 => 'aphront-tokenizer-control-css',
10 => 'aphront-typeahead-control-css',
11 => 'aphront-list-filter-view-css',
12 => 'phabricator-directory-css',
13 => 'phabricator-remarkup-css',
14 => 'syntax-highlighting-css',
),
'uri' => '/res/pkg/64383b02/core.pkg.css',
'type' => 'css',
),
- 'b1200c80' =>
- 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/b1200c80/differential.pkg.css',
- 'type' => 'css',
- ),
'db95a6d0' =>
array (
'name' => 'javelin.pkg.js',
'symbols' =>
array (
0 => 'javelin-util',
1 => 'javelin-install',
2 => 'javelin-event',
3 => 'javelin-stratcom',
4 => 'javelin-behavior',
5 => 'javelin-request',
6 => 'javelin-vector',
7 => 'javelin-dom',
8 => 'javelin-json',
9 => 'javelin-uri',
),
'uri' => '/res/pkg/db95a6d0/javelin.pkg.js',
'type' => 'js',
),
'e26c5e06' =>
array (
'name' => 'workflow.pkg.js',
'symbols' =>
array (
0 => 'javelin-mask',
1 => 'javelin-workflow',
2 => 'javelin-behavior-workflow',
3 => 'javelin-behavior-aphront-form-disable-on-submit',
4 => 'phabricator-keyboard-shortcut-manager',
5 => 'phabricator-keyboard-shortcut',
6 => 'javelin-behavior-phabricator-keyboard-shortcuts',
),
'uri' => '/res/pkg/e26c5e06/workflow.pkg.js',
'type' => 'js',
),
- 'ed383f69' =>
+ 'f292b274' =>
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/ed383f69/differential.pkg.js',
+ 'uri' => '/res/pkg/f292b274/differential.pkg.js',
'type' => 'js',
),
),
'reverse' =>
array (
'aphront-crumbs-view-css' => '64383b02',
'aphront-dialog-view-css' => '64383b02',
'aphront-form-view-css' => '64383b02',
'aphront-list-filter-view-css' => '64383b02',
'aphront-panel-view-css' => '64383b02',
'aphront-side-nav-view-css' => '64383b02',
'aphront-table-view-css' => '64383b02',
'aphront-tokenizer-control-css' => '64383b02',
'aphront-typeahead-control-css' => '64383b02',
- 'differential-changeset-view-css' => 'b1200c80',
- 'differential-core-view-css' => 'b1200c80',
- 'differential-revision-add-comment-css' => 'b1200c80',
- 'differential-revision-comment-css' => 'b1200c80',
- 'differential-revision-comment-list-css' => 'b1200c80',
- 'differential-revision-detail-css' => 'b1200c80',
- 'differential-revision-history-css' => 'b1200c80',
- 'differential-table-of-contents-css' => 'b1200c80',
+ 'differential-changeset-view-css' => '234a821b',
+ 'differential-core-view-css' => '234a821b',
+ 'differential-revision-add-comment-css' => '234a821b',
+ 'differential-revision-comment-css' => '234a821b',
+ 'differential-revision-comment-list-css' => '234a821b',
+ 'differential-revision-detail-css' => '234a821b',
+ 'differential-revision-history-css' => '234a821b',
+ 'differential-table-of-contents-css' => '234a821b',
'diffusion-commit-view-css' => '03ef179e',
'javelin-behavior' => 'db95a6d0',
'javelin-behavior-aphront-basic-tokenizer' => '33f413ef',
'javelin-behavior-aphront-form-disable-on-submit' => 'e26c5e06',
- 'javelin-behavior-differential-diff-radios' => 'ed383f69',
- 'javelin-behavior-differential-edit-inline-comments' => 'ed383f69',
- 'javelin-behavior-differential-feedback-preview' => 'ed383f69',
- 'javelin-behavior-differential-populate' => 'ed383f69',
- 'javelin-behavior-differential-show-more' => 'ed383f69',
+ 'javelin-behavior-differential-diff-radios' => 'f292b274',
+ 'javelin-behavior-differential-edit-inline-comments' => 'f292b274',
+ 'javelin-behavior-differential-feedback-preview' => 'f292b274',
+ 'javelin-behavior-differential-populate' => 'f292b274',
+ 'javelin-behavior-differential-show-more' => 'f292b274',
'javelin-behavior-phabricator-keyboard-shortcuts' => 'e26c5e06',
'javelin-behavior-workflow' => 'e26c5e06',
'javelin-dom' => 'db95a6d0',
'javelin-event' => 'db95a6d0',
'javelin-install' => 'db95a6d0',
'javelin-json' => 'db95a6d0',
'javelin-mask' => 'e26c5e06',
'javelin-request' => 'db95a6d0',
'javelin-stratcom' => 'db95a6d0',
'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' => 'db95a6d0',
'javelin-util' => 'db95a6d0',
'javelin-vector' => 'db95a6d0',
'javelin-workflow' => 'e26c5e06',
'phabricator-core-buttons-css' => '64383b02',
'phabricator-core-css' => '64383b02',
'phabricator-directory-css' => '64383b02',
'phabricator-keyboard-shortcut' => 'e26c5e06',
'phabricator-keyboard-shortcut-manager' => 'e26c5e06',
'phabricator-remarkup-css' => '64383b02',
'phabricator-standard-page-view' => '64383b02',
'syntax-highlighting-css' => '64383b02',
),
));
diff --git a/src/applications/differential/controller/inlinecommentedit/DifferentialInlineCommentEditController.php b/src/applications/differential/controller/inlinecommentedit/DifferentialInlineCommentEditController.php
index 7dc1731190..8bd919e124 100644
--- a/src/applications/differential/controller/inlinecommentedit/DifferentialInlineCommentEditController.php
+++ b/src/applications/differential/controller/inlinecommentedit/DifferentialInlineCommentEditController.php
@@ -1,201 +1,245 @@
<?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 DifferentialInlineCommentEditController extends DifferentialController {
private $revisionID;
public function willProcessRequest(array $data) {
$this->revisionID = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$changeset = $request->getInt('changeset');
$is_new = $request->getBool('is_new');
$on_right = $request->getBool('on_right');
$number = $request->getInt('number');
$length = $request->getInt('length');
$text = $request->getStr('text');
$op = $request->getStr('op');
$inline_id = $request->getInt('id');
$user = $request->getUser();
$submit_uri = '/differential/comment/inline/edit/'.$this->revisionID.'/';
$edit_dialog = new AphrontDialogView();
$edit_dialog->setUser($user);
$edit_dialog->setSubmitURI($submit_uri);
$edit_dialog->addHiddenInput('on_right', $on_right);
$edit_dialog->addSubmitButton();
$edit_dialog->addCancelButton('#');
- $inline = null;
- if ($inline_id) {
- $inline = id(new DifferentialInlineComment())
- ->load($inline_id);
-
- if (!$inline ||
- $inline->getAuthorPHID() != $user->getPHID() ||
- $inline->getCommentID() ||
- $inline->getRevisionID() != $this->revisionID) {
- throw new Exception("That comment is not editable!");
- }
- }
-
switch ($op) {
case 'delete':
- if (!$inline) {
- return new Aphront400Response();
- }
+ $inline = $this->loadInlineCommentForEditing($inline_id);
if ($request->isFormPost()) {
$inline->delete();
return $this->buildEmptyResponse();
}
$edit_dialog->setTitle('Really delete this comment?');
$edit_dialog->addHiddenInput('id', $inline_id);
$edit_dialog->addHiddenInput('op', 'delete');
$edit_dialog->appendChild(
'<p>Delete this inline comment?</p>');
return id(new AphrontDialogResponse())->setDialog($edit_dialog);
case 'edit':
- if (!$inline) {
- return new Aphront400Response();
- }
+ $inline = $this->loadInlineCommentForEditing($inline_id);
if ($request->isFormPost()) {
if (strlen($text)) {
$inline->setContent($text);
$inline->setCache(null);
$inline->save();
return $this->buildRenderedCommentResponse(
$inline,
$on_right);
} else {
$inline->delete();
return $this->buildEmptyResponse();
}
}
$edit_dialog->setTitle('Edit Inline Comment');
$edit_dialog->addHiddenInput('id', $inline_id);
$edit_dialog->addHiddenInput('op', 'edit');
$edit_dialog->appendChild(
$this->renderTextArea(
- $inline->getContent()));
+ nonempty($text, $inline->getContent())));
return id(new AphrontDialogResponse())->setDialog($edit_dialog);
case 'create':
if (!$request->isFormPost() || !strlen($text)) {
return $this->buildEmptyResponse();
}
// Verify revision and changeset correspond to actual objects.
$revision_obj = id(new DifferentialRevision())->load($this->revisionID);
$changeset_obj = id(new DifferentialChangeset())->load($changeset);
if (!$revision_obj || !$changeset_obj) {
throw new Exception("Invalid revision ID or changeset ID!");
}
$inline = id(new DifferentialInlineComment())
->setRevisionID($this->revisionID)
->setChangesetID($changeset)
->setCommentID(null)
->setAuthorPHID($user->getPHID())
->setLineNumber($number)
->setLineLength($length)
->setIsNewFile($on_right)
->setContent($text)
->save();
return $this->buildRenderedCommentResponse($inline, $on_right);
+
+ case 'reply':
default:
- $edit_dialog->setTitle('New Inline Comment');
+
+ if ($op == 'reply') {
+ $inline = $this->loadInlineComment($inline_id);
+ // Override defaults.
+ $changeset = $inline->getChangesetID();
+ $is_new = $inline->getIsNewFile();
+ $number = $inline->getLineNumber();
+ $length = $inline->getLineLength();
+ $edit_dialog->setTitle('Reply to Inline Comment');
+ } else {
+ $edit_dialog->setTitle('New Inline Comment');
+ }
$edit_dialog->addHiddenInput('op', 'create');
$edit_dialog->addHiddenInput('changeset', $changeset);
$edit_dialog->addHiddenInput('is_new', $is_new);
$edit_dialog->addHiddenInput('number', $number);
$edit_dialog->addHiddenInput('length', $length);
- $edit_dialog->appendChild($this->renderTextArea(''));
+ $edit_dialog->appendChild($this->renderTextArea($text));
return id(new AphrontDialogResponse())->setDialog($edit_dialog);
}
}
private function buildRenderedCommentResponse(
DifferentialInlineComment $inline,
$on_right) {
$request = $this->getRequest();
$user = $request->getUser();
$factory = new DifferentialMarkupEngineFactory();
$engine = $factory->newDifferentialCommentMarkupEngine();
$phids = array($user->getPHID());
$handles = id(new PhabricatorObjectHandleData($phids))
->loadHandles();
$view = new DifferentialInlineCommentView();
$view->setInlineComment($inline);
$view->setOnRight($on_right);
$view->setBuildScaffolding(true);
$view->setMarkupEngine($engine);
$view->setHandles($handles);
$view->setEditable(true);
return id(new AphrontAjaxResponse())
->setContent(
array(
'inlineCommentID' => $inline->getID(),
'markup' => $view->render(),
));
}
private function buildEmptyResponse() {
return id(new AphrontAjaxResponse())
->setContent(
array(
'markup' => '',
));
}
private function renderTextArea($text) {
- return phutil_render_tag(
+ return javelin_render_tag(
'textarea',
array(
'class' => 'differential-inline-comment-edit-textarea',
+ 'sigil' => 'differential-inline-comment-edit-textarea',
'name' => 'text',
),
phutil_escape_html($text));
}
+ private function loadInlineComment($id) {
+ $inline = null;
+
+ if ($id) {
+ $inline = id(new DifferentialInlineComment())->load($id);
+ }
+
+ if (!$inline) {
+ throw new Exception("No such inline comment!");
+ }
+
+ return $inline;
+ }
+
+ private function loadInlineCommentForEditing($id) {
+ $inline = $this->loadInlineComment($id);
+ $user = $this->getRequest()->getUser();
+
+ if (!$this->canEditInlineComment($user, $inline, $this->revisionID)) {
+ throw new Exception("That comment is not editable!");
+ }
+ return $inline;
+ }
+
+ private function canEditInlineComment(
+ PhabricatorUser $user,
+ DifferentialInlineComment $inline,
+ $revision_id) {
+
+ // Only the author may edit a comment.
+ if ($inline->getAuthorPHID() != $user->getPHID()) {
+ return false;
+ }
+
+ // Saved comments may not be edited.
+ if ($inline->getCommentID()) {
+ return false;
+ }
+
+ // Inline must be attached to the active revision.
+ if ($inline->getRevisionID() != $revision_id) {
+ return false;
+ }
+
+ return true;
+ }
+
}
diff --git a/src/applications/differential/controller/inlinecommentedit/__init__.php b/src/applications/differential/controller/inlinecommentedit/__init__.php
index 8df121645d..8cb908d5a2 100644
--- a/src/applications/differential/controller/inlinecommentedit/__init__.php
+++ b/src/applications/differential/controller/inlinecommentedit/__init__.php
@@ -1,25 +1,25 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
-phutil_require_module('phabricator', 'aphront/response/400');
phutil_require_module('phabricator', 'aphront/response/ajax');
phutil_require_module('phabricator', 'aphront/response/dialog');
phutil_require_module('phabricator', 'applications/differential/controller/base');
phutil_require_module('phabricator', 'applications/differential/parser/markup');
phutil_require_module('phabricator', 'applications/differential/storage/changeset');
phutil_require_module('phabricator', 'applications/differential/storage/inlinecomment');
phutil_require_module('phabricator', 'applications/differential/storage/revision');
phutil_require_module('phabricator', 'applications/differential/view/inlinecomment');
phutil_require_module('phabricator', 'applications/phid/handle/data');
+phutil_require_module('phabricator', 'infrastructure/javelin/markup');
phutil_require_module('phabricator', 'view/dialog');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('DifferentialInlineCommentEditController.php');
diff --git a/src/applications/differential/view/changesetdetailview/DifferentialChangesetDetailView.php b/src/applications/differential/view/changesetdetailview/DifferentialChangesetDetailView.php
index 61135cc71e..4dd6f8be2e 100644
--- a/src/applications/differential/view/changesetdetailview/DifferentialChangesetDetailView.php
+++ b/src/applications/differential/view/changesetdetailview/DifferentialChangesetDetailView.php
@@ -1,96 +1,89 @@
<?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 DifferentialChangesetDetailView extends AphrontView {
private $changeset;
private $buttons = array();
private $revisionID;
public function setChangeset($changeset) {
$this->changeset = $changeset;
return $this;
}
public function addButton($button) {
$this->buttons[] = $button;
return $this;
}
public function setRevisionID($revision_id) {
$this->revisionID = $revision_id;
return $this;
}
public function render() {
require_celerity_resource('differential-changeset-view-css');
require_celerity_resource('syntax-highlighting-css');
if ($this->revisionID) {
$edit = true;
} else {
$edit = false;
}
$changeset = $this->changeset;
$class = 'differential-changeset';
if (!$edit) {
$class .= ' differential-changeset-immutable';
}
$buttons = null;
if ($this->buttons) {
$buttons =
'<div class="differential-changeset-buttons">'.
implode('', $this->buttons).
'</div>';
}
$display_filename = $changeset->getDisplayFilename();
$output = javelin_render_tag(
'div',
array(
'sigil' => 'differential-changeset',
'meta' => array(
'left' => $this->changeset->getID(),
'right' => $this->changeset->getID(),
),
'class' => $class,
),
phutil_render_tag(
'a',
array(
'name' => $changeset->getAnchorName(),
),
'').
$buttons.
'<h1>'.phutil_escape_html($display_filename).'</h1>'.
'<div style="clear: both;"></div>'.
$this->renderChildren());
- if ($edit) {
- Javelin::initBehavior(
- 'differential-edit-inline-comments', array(
- 'uri' => '/differential/comment/inline/edit/'.$this->revisionID.'/',
- ));
- }
-
return $output;
}
}
diff --git a/src/applications/differential/view/changesetdetailview/__init__.php b/src/applications/differential/view/changesetdetailview/__init__.php
index 783a68af76..4e50ea0f06 100644
--- a/src/applications/differential/view/changesetdetailview/__init__.php
+++ b/src/applications/differential/view/changesetdetailview/__init__.php
@@ -1,17 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'infrastructure/celerity/api');
-phutil_require_module('phabricator', 'infrastructure/javelin/api');
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
phutil_require_module('phabricator', 'view/base');
phutil_require_module('phutil', 'markup');
phutil_require_source('DifferentialChangesetDetailView.php');
diff --git a/src/applications/differential/view/changesetlistview/DifferentialChangesetListView.php b/src/applications/differential/view/changesetlistview/DifferentialChangesetListView.php
index 4acc578a49..3dfef7f781 100644
--- a/src/applications/differential/view/changesetlistview/DifferentialChangesetListView.php
+++ b/src/applications/differential/view/changesetlistview/DifferentialChangesetListView.php
@@ -1,141 +1,176 @@
<?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 DifferentialChangesetListView extends AphrontView {
private $changesets = array();
private $editable;
private $revision;
private $renderURI = '/differential/changeset/';
private $whitespace;
private $standaloneViews;
public function setChangesets($changesets) {
$this->changesets = $changesets;
return $this;
}
public function setEditable($editable) {
$this->editable = $editable;
return $this;
}
public function setStandaloneViews($has_standalone_views) {
$this->standaloneViews = $has_standalone_views;
return $this;
}
public function setRevision(DifferentialRevision $revision) {
$this->revision = $revision;
return $this;
}
public function setRenderingReferences(array $references) {
$this->references = $references;
return $this;
}
public function setRenderURI($render_uri) {
$this->renderURI = $render_uri;
return $this;
}
public function setWhitespace($whitespace) {
$this->whitespace = $whitespace;
return $this;
}
public function render() {
require_celerity_resource('differential-changeset-view-css');
$changesets = $this->changesets;
$output = array();
$mapping = array();
foreach ($changesets as $key => $changeset) {
$file = $changeset->getFilename();
$class = 'differential-changeset';
if (!$this->editable) {
$class .= ' differential-changeset-noneditable';
}
$ref = $this->references[$key];
$detail_button = null;
if ($this->standaloneViews) {
$detail_uri = new PhutilURI($this->renderURI);
$detail_uri->setQueryParams(
array(
'ref' => $ref,
'whitespace' => $this->whitespace,
));
$detail_button = phutil_render_tag(
'a',
array(
'class' => 'button small grey',
'href' => $detail_uri,
'target' => '_blank',
),
'View Standalone / Raw');
}
$uniq_id = celerity_generate_unique_node_id();
$detail = new DifferentialChangesetDetailView();
$detail->setChangeset($changeset);
$detail->addButton($detail_button);
$detail->appendChild(
phutil_render_tag(
'div',
array(
'id' => $uniq_id,
),
'<div class="differential-loading">Loading...</div>'));
$output[] = $detail->render();
$mapping[$uniq_id] = $ref;
}
Javelin::initBehavior('differential-populate', array(
'registry' => $mapping,
'whitespace' => $this->whitespace,
'uri' => $this->renderURI,
));
Javelin::initBehavior('differential-show-more', array(
'uri' => $this->renderURI,
'whitespace' => $this->whitespace,
));
Javelin::initBehavior('differential-comment-jump', array());
if ($this->editable) {
+
+ $undo_templates = $this->renderUndoTemplates();
+
$revision = $this->revision;
Javelin::initBehavior('differential-edit-inline-comments', array(
'uri' => '/differential/comment/inline/edit/'.$revision->getID().'/',
+ 'undo_templates' => $undo_templates,
));
}
return
'<div class="differential-review-stage" id="differential-review-stage">'.
implode("\n", $output).
'</div>';
}
+ /**
+ * Render the "Undo" markup for the inline comment undo feature.
+ */
+ private function renderUndoTemplates() {
+ $link = javelin_render_tag(
+ 'a',
+ array(
+ 'href' => '#',
+ 'sigil' => 'differential-inline-comment-undo',
+ ),
+ 'Undo');
+
+ $div = phutil_render_tag(
+ 'div',
+ array(
+ 'class' => 'differential-inline-undo',
+ ),
+ 'Changes discarded. '.$link);
+
+ $content = '<th></th><td>'.$div.'</td>';
+ $empty = '<th></th><td></td>';
+
+ $left = array($content, $empty);
+ $right = array($empty, $content);
+
+ return array(
+ 'l' => '<table><tr>'.implode('', $left).'</tr></table>',
+ 'r' => '<table><tr>'.implode('', $right).'</tr></table>',
+ );
+ }
+
}
diff --git a/src/applications/differential/view/changesetlistview/__init__.php b/src/applications/differential/view/changesetlistview/__init__.php
index 3077c4f454..b8ca61df16 100644
--- a/src/applications/differential/view/changesetlistview/__init__.php
+++ b/src/applications/differential/view/changesetlistview/__init__.php
@@ -1,18 +1,19 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/differential/view/changesetdetailview');
phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'infrastructure/javelin/api');
+phutil_require_module('phabricator', 'infrastructure/javelin/markup');
phutil_require_module('phabricator', 'view/base');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'parser/uri');
phutil_require_source('DifferentialChangesetListView.php');
diff --git a/src/applications/differential/view/inlinecomment/DifferentialInlineCommentView.php b/src/applications/differential/view/inlinecomment/DifferentialInlineCommentView.php
index 8d92b79c3b..0a5ce04855 100644
--- a/src/applications/differential/view/inlinecomment/DifferentialInlineCommentView.php
+++ b/src/applications/differential/view/inlinecomment/DifferentialInlineCommentView.php
@@ -1,204 +1,198 @@
<?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.
*/
final class DifferentialInlineCommentView extends AphrontView {
private $inlineComment;
private $onRight;
private $buildScaffolding;
private $handles;
private $markupEngine;
private $editable;
public function setInlineComment(DifferentialInlineComment $comment) {
$this->inlineComment = $comment;
return $this;
}
public function setOnRight($on_right) {
$this->onRight = $on_right;
return $this;
}
public function setBuildScaffolding($scaffold) {
$this->buildScaffolding = $scaffold;
return $this;
}
public function setHandles(array $handles) {
$this->handles = $handles;
return $this;
}
public function setMarkupEngine(PhutilMarkupEngine $engine) {
$this->markupEngine = $engine;
return $this;
}
public function setEditable($editable) {
$this->editable = $editable;
return $this;
}
public function render() {
$inline = $this->inlineComment;
$start = $inline->getLineNumber();
$length = $inline->getLineLength();
if ($length) {
$end = $start + $length;
$line = 'Lines '.number_format($start).'-'.number_format($end);
} else {
$line = 'Line '.number_format($start);
}
$metadata = array(
'id' => $inline->getID(),
'number' => $inline->getLineNumber(),
'length' => $inline->getLineLength(),
'on_right' => $this->onRight,
+ 'original' => $inline->getContent(),
);
$sigil = 'differential-inline-comment';
$content = $inline->getContent();
$handles = $this->handles;
$links = array();
$links[] = javelin_render_tag(
'a',
array(
'href' => '#',
'mustcapture' => true,
'sigil' => 'differential-inline-prev',
),
'Previous');
$links[] = javelin_render_tag(
'a',
array(
'href' => '#',
'mustcapture' => true,
'sigil' => 'differential-inline-next',
),
'Next');
$links[] = javelin_render_tag(
'a',
array(
'href' => '#',
'mustcapture' => true,
'sigil' => 'differential-inline-reply',
- 'meta' => array(
- 'is_new' => true,
- 'changeset' => $inline->getChangesetID(),
- 'number' => $inline->getLineNumber(),
- 'length' => $inline->getLineLength(),
- 'on_right' => $this->onRight,
- )
),
'Reply');
if ($this->editable) {
$links[] = javelin_render_tag(
'a',
array(
'href' => '#',
'mustcapture' => true,
'sigil' => 'differential-inline-edit',
),
'Edit');
$links[] = javelin_render_tag(
'a',
array(
'href' => '#',
'mustcapture' => true,
'sigil' => 'differential-inline-delete',
),
'Delete');
}
if ($links) {
$links =
'<span class="differential-inline-comment-links">'.
implode(' &middot; ', $links).
'</span>';
} else {
$links = null;
}
$cache = $inline->getCache();
if (strlen($cache)) {
$content = $cache;
} else {
$content = $this->markupEngine->markupText($content);
if ($inline->getID()) {
$inline->setCache($content);
$inline->save();
}
}
$anchor = phutil_render_tag(
'a',
array(
'name' => 'inline-'.$inline->getID(),
),
'');
$markup = javelin_render_tag(
'div',
array(
'class' => 'differential-inline-comment',
'sigil' => $sigil,
'meta' => $metadata,
),
'<div class="differential-inline-comment-head">'.
$anchor.
$links.
'<span class="differential-inline-comment-line">'.$line.'</span>'.
phutil_escape_html($handles[$inline->getAuthorPHID()]->getName()).
'</div>'.
'<div class="phabricator-remarkup">'.
$content.
'</div>');
return $this->scaffoldMarkup($markup);
}
private function scaffoldMarkup($markup) {
if (!$this->buildScaffolding) {
return $markup;
}
$left_markup = !$this->onRight ? $markup : '';
$right_markup = $this->onRight ? $markup : '';
return
'<table>'.
'<tr class="inline">'.
'<th></th>'.
'<td>'.$left_markup.'</td>'.
'<th></th>'.
'<td>'.$right_markup.'</td>'.
'</tr>'.
'</table>';
}
}
diff --git a/src/infrastructure/lint/linter/javelin/PhabricatorJavelinLinter.php b/src/infrastructure/lint/linter/javelin/PhabricatorJavelinLinter.php
index 31cc60b589..4af3069773 100644
--- a/src/infrastructure/lint/linter/javelin/PhabricatorJavelinLinter.php
+++ b/src/infrastructure/lint/linter/javelin/PhabricatorJavelinLinter.php
@@ -1,247 +1,247 @@
<?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 PhabricatorJavelinLinter extends ArcanistLinter {
private $symbols = array();
private $haveSymbolsBinary;
private $haveWarnedAboutBinary;
const LINT_PRIVATE_ACCESS = 1;
const LINT_MISSING_DEPENDENCY = 2;
const LINT_UNNECESSARY_DEPENDENCY = 3;
const LINT_UNKNOWN_DEPENDENCY = 4;
const LINT_MISSING_BINARY = 5;
public function willLintPaths(array $paths) {
if ($this->haveSymbolsBinary === null) {
$binary = $this->getSymbolsBinaryPath();
$this->haveSymbolsBinary = Filesystem::pathExists($binary);
if (!$this->haveSymbolsBinary) {
return;
}
}
$futures = array();
foreach ($paths as $path) {
$future = $this->newSymbolsFuture($path);
$futures[$path] = $future;
}
foreach (Futures($futures)->limit(8) as $path => $future) {
$this->symbols[$path] = $future->resolvex();
}
}
public function getLinterName() {
return 'JAVELIN';
}
public function getLintSeverityMap() {
return array(
self::LINT_MISSING_BINARY => ArcanistLintSeverity::SEVERITY_WARNING,
);
}
public function getLintNameMap() {
return array(
self::LINT_PRIVATE_ACCESS => 'Private Method/Member Access',
self::LINT_MISSING_DEPENDENCY => 'Missing Javelin Dependency',
self::LINT_UNNECESSARY_DEPENDENCY => 'Unnecessary Javelin Dependency',
self::LINT_UNKNOWN_DEPENDENCY => 'Unknown Javelin Dependency',
self::LINT_MISSING_BINARY => '`javelinsymbols` Binary Not Built',
);
}
public function lintPath($path) {
if (!$this->haveSymbolsBinary) {
if (!$this->haveWarnedAboutBinary) {
$this->haveWarnedAboutBinary = true;
// TODO: Write build documentation for the Javelin binaries and point
// the user at it.
$this->raiseLintAtLine(
- 0,
+ 1,
0,
self::LINT_MISSING_BINARY,
"The 'javelinsymbols' binary in the Javelin project has not been ".
"built, so the Javelin linter can't run. This isn't a big concern, ".
"but means some Javelin problems can't be automatically detected.");
}
return;
}
list($uses, $installs) = $this->getUsedAndInstalledSymbolsForPath($path);
foreach ($uses as $symbol => $line) {
$parts = explode('.', $symbol);
foreach ($parts as $part) {
if ($part[0] == '_' && $part[1] != '_') {
$base = implode('.', array_slice($parts, 0, 2));
if (!array_key_exists($base, $installs)) {
$this->raiseLintAtLine(
$line,
0,
self::LINT_PRIVATE_ACCESS,
"This file accesses private symbol '{$symbol}' across file ".
"boundaries. You may only access private members and methods ".
"from the file where they are defined.");
}
break;
}
}
}
if ($this->getEngine()->getCommitHookMode()) {
// Don't do the dependency checks in commit-hook mode because we won't
// have an available working copy.
return;
}
$external_classes = array();
foreach ($uses as $symbol => $line) {
$parts = explode('.', $symbol);
$class = implode('.', array_slice($parts, 0, 2));
if (!array_key_exists($class, $external_classes) &&
!array_key_exists($class, $installs)) {
$external_classes[$class] = $line;
}
}
$celerity = CelerityResourceMap::getInstance();
$path = preg_replace(
'@^externals/javelin/src/@',
'webroot/rsrc/js/javelin/',
$path);
$info = $celerity->lookupFileInformation(substr($path, strlen('webroot')));
$need = $external_classes;
$requires = $info['requires'];
foreach ($requires as $key => $name) {
$symbol_info = $celerity->lookupSymbolInformation($name);
if (!$symbol_info) {
$this->raiseLintAtLine(
0,
0,
self::LINT_UNKNOWN_DEPENDENCY,
"This file @requires component '{$name}', but it does not ".
"exist. You may need to rebuild the Celerity map.");
unset($requires[$key]);
continue;
}
$symbol_path = 'webroot'.$symbol_info['disk'];
list($ignored, $req_install) = $this->getUsedAndInstalledSymbolsForPath(
$symbol_path);
if (array_intersect_key($req_install, $external_classes)) {
$need = array_diff_key($need, $req_install);
unset($requires[$key]);
}
}
foreach ($need as $class => $line) {
$this->raiseLintAtLine(
$line,
0,
self::LINT_MISSING_DEPENDENCY,
"This file uses '{$class}' but does not @requires the component ".
"which installs it. You may need to rebuild the Celerity map.");
}
foreach ($requires as $component) {
$this->raiseLintAtLine(
0,
0,
self::LINT_UNNECESSARY_DEPENDENCY,
"This file @requires component '{$component}' but does not use ".
"anything it provides.");
}
}
private function loadSymbols($path) {
if (empty($this->symbols[$path])) {
$this->symbols[$path] = $this->newSymbolsFuture($path)->resolvex();
}
return $this->symbols[$path];
}
private function newSymbolsFuture($path) {
$javelinsymbols = $this->getSymbolsBinaryPath();
$future = new ExecFuture($javelinsymbols.' # '.escapeshellarg($path));
$future->write($this->getData($path));
return $future;
}
private function getSymbolsBinaryPath() {
$root = dirname(phutil_get_library_root('phabricator'));
$support = $root.'/externals/javelin/support';
return $support.'/javelinsymbols/javelinsymbols';
}
private function getUsedAndInstalledSymbolsForPath($path) {
list($symbols) = $this->loadSymbols($path);
$symbols = explode("\n", trim($symbols));
$uses = array();
$installs = array();
foreach ($symbols as $line) {
$matches = null;
if (!preg_match('/^([?+])([^:]*):(\d+)$/', $line, $matches)) {
throw new Exception(
"Received malformed output from `javelinsymbols`.");
}
$type = $matches[1];
$symbol = $matches[2];
$line = $matches[3];
switch ($type) {
case '?':
$uses[$symbol] = $line;
break;
case '+':
$installs['JX.'.$symbol] = $line;
break;
}
}
$contents = $this->getData($path);
$matches = null;
$count = preg_match_all(
'/@javelin-installs\W+(\S+)/',
$contents,
$matches,
PREG_PATTERN_ORDER);
if ($count) {
foreach ($matches[1] as $symbol) {
$installs[$symbol] = 0;
}
}
return array($uses, $installs);
}
}
diff --git a/webroot/rsrc/css/application/differential/changeset-view.css b/webroot/rsrc/css/application/differential/changeset-view.css
index 9599b1f7a5..56aec58c7c 100644
--- a/webroot/rsrc/css/application/differential/changeset-view.css
+++ b/webroot/rsrc/css/application/differential/changeset-view.css
@@ -1,231 +1,243 @@
/**
* @provides differential-changeset-view-css
*/
.differential-diff {
background: #ffffff;
font-family: "Menlo", "Consolas", "Monaco", monospace;
font-size: 10px;
width: 100%;
}
.differential-diff td {
/* using monospace fonts makes ex/em most useful:
*
* Unfortunately, firefox 3.6 renders diffs columns for added and removed
* files "way-too-wide" when given em as the dimension measurement, so we
* use an eyeballed ex equivalent and reset it to the ch character width
* measurement for browsers that support that css3 measurement.
*/
width: 88ex;
width: 81ch;
/*
Disable ligatures in Firefox. Firefox 3 has fancypants ligature support, but
it gets applied to monospaced fonts, which sucks because it means that the
"fi" ligature only takes up one character, e.g. It's probably the font's
fault that it even specifies ligatures (seriously, what the hell?) but
that's hard to fix and this is "easy" to "fix": custom letter spacing
disables ligatures, as long as it's at least 0.008333-repeating pixels of
custom letter spacing. I have no idea where this number comes from, but note
that .83333.. = 5/6. -epriestley
*/
letter-spacing: 0.0083334px;
vertical-align: top;
white-space: pre;
padding: 0 8px 1px;
line-height: 16px;
overflow: hidden;
}
.differential-diff th {
text-align: right;
padding: 2px 6px;
width: 44px;
vertical-align: top;
background: #eeeeee;
color: #888888;
cursor: pointer;
border-style: solid;
border-width: 0px 1px;
border-color: #eeeeee #999999 #eeeeee #dddddd;
font-weight: bold;
font-family: "Verdana";
font-size: 11px;
overflow: hidden;
}
.differential-diff td.old {
background: #ffd0d0;
color: #161111;
}
.differential-diff td.new {
background: #d0ffd0;
color: #111611;
}
.differential-diff td.old-full,
.differential-diff td.old span.bright {
background: #ffaaaa;
color: #221111;
}
.differential-diff td.new-full,
.differential-diff td.new span.bright {
background: #aaffaa;
color: #112211;
}
.differential-diff td.show-more,
.differential-diff td.differential-shield {
background: #ffffee;
padding: 1em;
text-align: center;
font-family: "Verdana";
font-size: 11px;
border: 1px solid #ccccaa;
white-space: normal;
}
.differential-diff td.show-more {
color: #999966;
}
.differential-diff td.differential-shield {
text-align: center;
max-width: 1160px;
}
.differential-diff td.differential-shield a {
font-weight: bold;
}
.differential-meta-notice {
border: 1px solid #ffdd99;
background: #ffeeaa;
font-family: "Verdana";
font-size: 11px;
padding: 1em;
margin: 0 0 6px 0;
}
.differential-changeset h1 {
font-size: 14px;
font-weight: bold;
padding: 2px 0 8px;
}
.differential-changeset {
margin: 0.5em 0;
padding: 10px 0px 20px;
}
.differential-reticle {
background: #ffeeaa;
border: 1px solid #ffcc00;
position: absolute;
z-index: 2;
opacity: 0.5;
top: 0px;
left: 0px;
}
.differential-inline-comment {
background: #f9f9f1;
border: 1px solid #aaaa88;
font-family: Verdana;
font-size: 11px;
margin: 4px 0px;
padding: 8px 10px;
width: 100%;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
overflow: hidden;
max-width: 520px;
white-space: normal;
}
.differential-inline-comment-head {
font-weight: bold;
color: #333333;
border-bottom: 1px solid #ccccaa;
padding-bottom: 6px;
margin-bottom: 4px;
}
.differential-inline-comment-links,
.differential-inline-comment-line {
font-weight: normal;
font-style: italic;
color: #666666;
float: right;
white-space: nowrap;
}
.differential-inline-comment-links {
margin-left: 8px;
font-style: normal;
}
.differential-inline-comment-edit-textarea {
width: 100%;
height: 12em;
}
.differential-changeset-buttons {
float: right;
}
.differential-changeset-buttons a.button {
margin-left: 8px;
}
-
.differential-property-table {
width: auto;
margin: .75em auto;
background: #e3e3e3;
}
.differential-property-table th {
text-align: right;
width: 10em;
font-weight: bold;
color: #666666;
white-space: nowrap;
padding: 4px 8px;
border-right: 1px solid #666666;
}
.differential-property-table td {
padding: 4px 8px;
width: 35em;
}
.differential-property-table td em {
color: #888888;
}
.differential-property-table tr.property-table-header th,
.differential-property-table tr.property-table-header td {
text-align: center;
font-weight: bold;
border-bottom: 1px solid #666666;
}
.differential-property-table td.oval {
background: #ffd0d0;
}
.differential-property-table td.nval {
background: #d0ffd0;
}
.differential-property-table tr.property-table-header td.oval {
background: #ffaaaa;
}
.differential-property-table tr.property-table-header td.nval {
background: #aaffaa;
}
+
+.differential-inline-undo {
+ padding: 4px;
+ text-align: center;
+ background: #ffeeaa;
+ margin: 3px 0 1px;
+ font: 11px "Verdana";
+ color: 444444;
+}
+
+.differential-inline-undo a {
+ font-weight: bold;
+}
diff --git a/webroot/rsrc/js/application/differential/DifferentialInlineCommentEditor.js b/webroot/rsrc/js/application/differential/DifferentialInlineCommentEditor.js
new file mode 100644
index 0000000000..6ad3370793
--- /dev/null
+++ b/webroot/rsrc/js/application/differential/DifferentialInlineCommentEditor.js
@@ -0,0 +1,197 @@
+/**
+ * @provides differential-inline-comment-editor
+ * @requires javelin-dom
+ * javelin-workflow
+ * javelin-util
+ * javelin-stratcom
+ * javelin-install
+ */
+
+JX.install('DifferentialInlineCommentEditor', {
+
+ construct : function(uri) {
+ this._uri = uri;
+ },
+
+ events : ['done'],
+
+ members : {
+ _uri : null,
+ _undoText : null,
+ _skipOverInlineCommentRows : function(node) {
+ // TODO: Move this semantic information out of class names.
+ while (node && node.className.indexOf('inline') !== -1) {
+ node = node.nextSibling;
+ }
+ return node;
+ },
+ _buildRequestData : function() {
+ return {
+ op : this.getOperation(),
+ on_right : this.getOnRight(),
+ id : this.getID(),
+ number : this.getLineNumber(),
+ is_new : this.getIsNew(),
+ length : this.getLength(),
+ changeset : this.getChangeset(),
+ text : this.getText() || ''
+ };
+ },
+ _draw : function(content, exact_row) {
+ var row = this.getRow();
+ var table = row.parentNode;
+ var target = exact_row ? row : this._skipOverInlineCommentRows(row);
+
+ return copyRows(table, content, target);
+ },
+ _removeUndoLink : function() {
+ var rows = JX.DifferentialInlineCommentEditor._undoRows;
+ if (rows) {
+ for (var ii = 0; ii < rows.length; ii++) {
+ JX.DOM.remove(rows[ii]);
+ }
+ }
+ },
+ _undo : function() {
+ this._removeUndoLink();
+
+ this.setText(this._undoText);
+ this.start();
+ },
+ _registerUndoListener : function() {
+ if (!JX.DifferentialInlineCommentEditor._activeEditor) {
+ JX.Stratcom.listen(
+ 'click',
+ 'differential-inline-comment-undo',
+ function(e) {
+ JX.DifferentialInlineCommentEditor._activeEditor._undo();
+ e.kill();
+ });
+ }
+ JX.DifferentialInlineCommentEditor._activeEditor = this;
+ },
+ _didCompleteWorkflow : function(response) {
+ var op = this.getOperation();
+
+ // We don't get any markup back if the user deletes a comment, or saves
+ // an empty comment (which effects a delete).
+ if (response.markup) {
+ this._draw(JX.$N('div', JX.$H(response.markup)));
+ }
+
+ // These operations remove the old row (edit adds a new row first).
+ var remove_old = (op == 'edit' || op == 'delete');
+ if (remove_old) {
+ JX.DOM.remove(this.getRow());
+ }
+
+ // Once the user saves something, get rid of the 'undo' option. A
+ // particular case where we need this is saving a delete, when we might
+ // otherwise leave around an 'undo' for an earlier edit to the same
+ // comment.
+ this._removeUndoLink();
+
+ JX.Stratcom.invoke('differential-inline-comment-update');
+ this.invoke('done');
+ },
+ _didCancelWorkflow : function() {
+ this.invoke('done');
+
+ var op = this.getOperation();
+ if (op == 'delete') {
+ // No undo for delete, we prompt the user explicitly.
+ return;
+ }
+
+ try {
+ var textarea = JX.DOM.find(
+ document.body, // TODO: use getDialogRootNode() when available
+ 'textarea',
+ 'differential-inline-comment-edit-textarea');
+ } catch (ex) {
+ if (ex !== JX.$.NotFound) {
+ throw ex;
+ }
+ // The close handler is called whenever the dialog closes, even if the
+ // user closed it by completing the workflow with "Save". The
+ // JX.Workflow API should probably be refined to allow programmatic
+ // distinction of close caused by 'cancel' vs 'submit'. Testing for
+ // presence of the textarea serves as a proxy for detecting a 'cancel'.
+ return;
+ }
+
+ var text = textarea.value;
+
+ // If the user hasn't edited the text (i.e., no change from original for
+ // 'edit' or no text for 'new' or 'reply'), don't offer them an undo.
+ if (text == (this.getOriginalText() || '')) {
+ return;
+ }
+
+ // Save the text so we can 'undo' back to it.
+ this._undoText = text;
+
+ var template = this.getOnRight()
+ ? this.getTemplates().r
+ : this.getTemplates().l;
+ template = JX.$N('div', JX.$H(template));
+
+ // NOTE: Operation order matters here; we can't remove anything until
+ // after we draw the new rows because _draw uses the old rows to figure
+ // out where to place the comment.
+
+ // We use 'exact_row' to put the "undo" text directly above the affected
+ // comment.
+ var exact_row = true;
+ var rows = this._draw(template, exact_row);
+
+ this._removeUndoLink();
+
+ JX.DifferentialInlineCommentEditor._undoRows = rows;
+ },
+
+ start : function() {
+ this._registerUndoListener();
+
+ var data = this._buildRequestData();
+ var handler = JX.bind(this, this._didCompleteWorkflow);
+ var close_handler = JX.bind(this, this._didCancelWorkflow);
+
+ new JX.Workflow(this._uri, data)
+ .setHandler(handler)
+ .setCloseHandler(close_handler)
+ .start();
+
+ return this;
+ }
+ },
+
+ statics : {
+ /**
+ * Global refernece to the 'undo' rows currently rendered in the document.
+ */
+ _undoRows : null,
+
+ /**
+ * Global listener for the 'undo' click associated with the currently
+ * displayed 'undo' link. When an editor is start()ed, it becomes the active
+ * editor.
+ */
+ _activeEditor : null
+ },
+
+ properties : {
+ operation : null,
+ row : null,
+ onRight : null,
+ ID : null,
+ lineNumber : null,
+ changeset : null,
+ length : null,
+ isNew : null,
+ text : null,
+ templates : null,
+ originalText : null
+ }
+
+});
diff --git a/webroot/rsrc/js/application/differential/behavior-edit-inline-comments.js b/webroot/rsrc/js/application/differential/behavior-edit-inline-comments.js
index ecbd876d5e..067755e7d7 100644
--- a/webroot/rsrc/js/application/differential/behavior-edit-inline-comments.js
+++ b/webroot/rsrc/js/application/differential/behavior-edit-inline-comments.js
@@ -1,269 +1,207 @@
/**
* @provides javelin-behavior-differential-edit-inline-comments
* @requires javelin-behavior
* javelin-stratcom
* javelin-dom
- * javelin-workflow
+ * javelin-util
* javelin-vector
+ * differential-inline-comment-editor
*/
JX.behavior('differential-edit-inline-comments', function(config) {
var selecting = false;
var reticle = JX.$N('div', {className: 'differential-reticle'});
JX.DOM.hide(reticle);
document.body.appendChild(reticle);
var origin = null;
var target = null;
var root = null;
var changeset = null;
- var workflow = false;
- var is_new = false;
+
+ var editor = null;
function updateReticle() {
var top = origin;
var bot = target;
if (JX.$V(top).y > JX.$V(bot).y) {
var tmp = top;
top = bot;
bot = tmp;
}
var code = target.nextSibling;
var pos = JX.$V(top).add(1 + JX.Vector.getDim(target).x, 0);
var dim = JX.Vector.getDim(code).add(-4, 0);
dim.y = (JX.$V(bot).y - pos.y) + JX.Vector.getDim(bot).y;
pos.setPos(reticle);
dim.setDim(reticle);
JX.DOM.show(reticle);
}
function hideReticle() {
JX.DOM.hide(reticle);
}
- function finishSelect() {
+ JX.DifferentialInlineCommentEditor.listen('done', function() {
selecting = false;
- workflow = false;
+ editor = false;
hideReticle();
- }
-
- function drawInlineComment(table, anchor, r) {
- copyRows(table, JX.$N('div', JX.$H(r.markup)), anchor);
- finishSelect();
- }
+ });
function isOnRight(node) {
return node.parentNode.firstChild != node;
}
function isNewFile(node) {
var data = JX.Stratcom.getData(root);
return isOnRight(node) || (data.left != data.right);
}
function getRowNumber(th_node) {
try {
return parseInt(th_node.id.match(/^C\d+[ON]L(\d+)$/)[1], 10);
} catch (x) {
return undefined;
}
}
- function isInlineCommentNode(target) {
- return target &&
- (!JX.DOM.isType(target, 'tr')
- || target.className.indexOf('inline') !== -1);
-
- }
-
- function findInlineCommentTarget(target) {
- while (isInlineCommentNode(target)) {
- target = target.nextSibling;
- }
- return target;
- }
-
JX.Stratcom.listen(
'mousedown',
['differential-changeset', 'tag:th'],
function(e) {
- if (workflow ||
+ if (editor ||
selecting ||
getRowNumber(e.getTarget()) === undefined) {
return;
}
selecting = true;
root = e.getNode('differential-changeset');
origin = target = e.getTarget();
var data = e.getNodeData('differential-changeset');
if (isOnRight(target)) {
changeset = data.left;
} else {
changeset = data.right;
}
updateReticle();
e.kill();
});
JX.Stratcom.listen(
'mouseover',
['differential-changeset', 'tag:th'],
function(e) {
if (!selecting ||
- workflow ||
+ editor ||
(getRowNumber(e.getTarget()) === undefined) ||
(isOnRight(e.getTarget()) != isOnRight(origin)) ||
(e.getNode('differential-changeset') !== root)) {
return;
}
target = e.getTarget();
updateReticle();
});
JX.Stratcom.listen(
'mouseup',
null,
function(e) {
- if (workflow || !selecting) {
+ if (editor || !selecting) {
return;
}
var o = getRowNumber(origin);
var t = getRowNumber(target);
var insert;
var len;
if (t < o) {
len = (o - t);
o = t;
insert = origin.parentNode;
} else {
len = (t - o);
insert = target.parentNode;
}
- var data = {
- op: 'new',
- changeset: changeset,
- number: o,
- length: len,
- is_new: isNewFile(target) ? 1 : 0,
- on_right: isOnRight(target) ? 1 : 0
- };
-
- workflow = true;
-
- var w = new JX.Workflow(config.uri, data)
- .setHandler(function(r) {
- // Skip over any rows which contain inline feedback. Don't mimic this!
- // We're shipping around raw HTML here for performance reasons, but
- // normally you should use sigils to encode this kind of data on
- // the document.
- var target = findInlineCommentTarget(insert.nextSibling);
- drawInlineComment(insert.parentNode, target, r);
- finishSelect();
- JX.Stratcom.invoke('differential-inline-comment-update');
- })
- .setCloseHandler(finishSelect);
-
-
- w.listen('error', function(e) {
- // TODO: uh, tell the user I guess
- finishSelect();
- JX.Stratcom.context().stop();
- });
-
- w.start();
+ editor = new JX.DifferentialInlineCommentEditor(config.uri)
+ .setTemplates(config.undo_templates)
+ .setOperation('new')
+ .setChangeset(changeset)
+ .setLineNumber(o)
+ .setLength(len)
+ .setIsNew(isNewFile(target) ? 1 : 0)
+ .setOnRight(isOnRight(target) ? 1 : 0)
+ .setRow(insert.nextSibling)
+ .start();
e.kill();
});
JX.Stratcom.listen(
['mouseover', 'mouseout'],
'differential-inline-comment',
function(e) {
- if (selecting || workflow) {
+ if (selecting || editor) {
return;
}
if (e.getType() == 'mouseout') {
hideReticle();
} else {
root = e.getNode('differential-changeset');
var data = e.getNodeData('differential-inline-comment');
var change = e.getNodeData('differential-changeset');
var prefix;
if (data.on_right) {
prefix = 'C' + (change.left) + 'NL';
} else {
prefix = 'C' + (change.right) + 'OL';
}
origin = JX.$(prefix + data.number);
target = JX.$(prefix + (parseInt(data.number, 10) +
parseInt(data.length, 10)));
updateReticle();
}
});
- JX.Stratcom.listen(
- 'click',
- [['differential-inline-comment', 'differential-inline-reply']],
- function(e) {
- new JX.Workflow(config.uri, e.getNodeData('differential-inline-reply'))
- .setHandler(function(r) {
- var base_row =
- findInlineCommentTarget(
- e.getNode('differential-inline-comment')
- .parentNode
- .parentNode
- );
- drawInlineComment(base_row.parentNode, base_row, r);
- JX.Stratcom.invoke('differential-inline-comment-update');
- })
- .start();
+ var action_handler = function(op, e) {
+ var data = e.getNodeData('differential-inline-comment');
+ var node = e.getNode('differential-inline-comment');
- e.kill();
- }
- );
+ editor = new JX.DifferentialInlineCommentEditor(config.uri)
+ .setTemplates(config.undo_templates)
+ .setOperation(op)
+ .setID(data.id)
+ .setOnRight(data.on_right)
+ .setOriginalText(data.original)
+ .setRow(node.parentNode.parentNode)
+ .start();
- JX.Stratcom.listen(
- 'click',
- [['differential-inline-comment', 'differential-inline-delete'],
- ['differential-inline-comment', 'differential-inline-edit']],
- function(e) {
- var data = {
- op: e.getNode('differential-inline-edit') ? 'edit' : 'delete',
- id: e.getNodeData('differential-inline-comment').id,
- on_right: e.getNodeData('differential-inline-comment').on_right
- };
- new JX.Workflow(config.uri, data)
- .setHandler(function(r) {
- var base_row = e.getNode('differential-inline-comment')
- .parentNode
- .parentNode;
- if (data.op == 'edit' && r.markup) {
- drawInlineComment(base_row.parentNode, base_row, r);
- }
- JX.DOM.remove(base_row);
- JX.Stratcom.invoke('differential-inline-comment-update');
- })
- .start();
- e.kill();
- });
+ e.kill();
+ }
+
+ for (var op in {'edit' : 1, 'delete' : 1, 'reply' : 1}) {
+ JX.Stratcom.listen(
+ 'click',
+ ['differential-inline-comment', 'differential-inline-' + op],
+ JX.bind(null, action_handler, op));
+ }
});
+
diff --git a/webroot/rsrc/js/application/differential/behavior-show-more.js b/webroot/rsrc/js/application/differential/behavior-show-more.js
index 135276bb11..591c95e198 100644
--- a/webroot/rsrc/js/application/differential/behavior-show-more.js
+++ b/webroot/rsrc/js/application/differential/behavior-show-more.js
@@ -1,47 +1,48 @@
/**
* @provides javelin-behavior-differential-show-more
* @requires javelin-behavior
* javelin-dom
* javelin-request
* javelin-util
* javelin-stratcom
*/
JX.behavior('differential-show-more', function(config) {
function onresponse(origin, response) {
var div = JX.$N('div', {}, JX.$H(response));
var anchor = origin.getNode('context-target');
var root = anchor.parentNode;
copyRows(root, div, anchor);
root.removeChild(anchor);
}
JX.Stratcom.listen(
'click',
'show-more',
function(e) {
var context = e.getNodes()['context-target'];
var container = JX.DOM.find(context, 'td');
JX.DOM.setContent(container, 'Loading...');
JX.DOM.alterClass(context, 'differential-show-more-loading', true);
var data = e.getNodeData('show-more');
data['whitespace'] = config.whitespace;
new JX.Request(config.uri, JX.bind(null, onresponse, e))
.setData(data)
.send();
e.kill();
});
});
function copyRows(dst, src, before) {
var rows = JX.DOM.scry(src, 'tr');
for (var ii = 0; ii < rows.length; ii++) {
if (before) {
dst.insertBefore(rows[ii], before);
} else {
dst.appendChild(rows[ii]);
}
}
+ return rows;
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jun 10, 2:04 PM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
140399
Default Alt Text
(93 KB)

Event Timeline