Page MenuHomePhorge

No OneTemporary

diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php
index 2c299dd4c8..3903571d0d 100644
--- a/src/__celerity_resource_map__.php
+++ b/src/__celerity_resource_map__.php
@@ -1,1282 +1,1282 @@
<?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/61a58113/rsrc/css/aphront/dialog-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/dialog-view.css',
),
'aphront-error-view-css' =>
array(
'uri' => '/res/e4c5e4ed/rsrc/css/aphront/error-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/error-view.css',
),
'aphront-form-view-css' =>
array(
'uri' => '/res/8ee16aba/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/af3dff49/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/d2923406/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/438fe316/rsrc/css/application/differential/core.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/core.css',
),
'differential-inline-comment-editor' =>
array(
'uri' => '/res/5e4f0aa4/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/9dcbc5a2/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/015e5995/rsrc/css/application/differential/revision-detail.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/revision-detail.css',
),
'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',
),
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' =>
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',
),
'javelin-behavior-aphront-basic-tokenizer' =>
array(
'uri' => '/res/5e183bd5/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',
5 => 'javelin-stratcom',
),
'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-countdown-timer' =>
array(
'uri' => '/res/9eef8193/rsrc/js/application/countdown/timer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
),
'disk' => '/rsrc/js/application/countdown/timer.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-accept-with-errors' =>
array(
'uri' => '/res/41c4685b/rsrc/js/application/differential/behavior-accept-with-errors.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/differential/behavior-accept-with-errors.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/9d4ca5d7/rsrc/js/application/differential/behavior-edit-inline-comments.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
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-keyboard-navigation' =>
array(
'uri' => '/res/08ad535c/rsrc/js/application/differential/behavior-keyboard-nav.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'phabricator-keyboard-shortcut',
),
'disk' => '/rsrc/js/application/differential/behavior-keyboard-nav.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/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-project-create' =>
array(
'uri' => '/res/85a0eaf9/rsrc/js/application/maniphest/behavior-project-create.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-workflow',
),
'disk' => '/rsrc/js/application/maniphest/behavior-project-create.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/7aed0604/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/34f9a11e/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/28a267b3/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',
+ 'uri' => '/res/0bacdd7f/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/149fccab/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/bd20d04b/rsrc/css/core/core.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/core/core.css',
),
'phabricator-countdown-css' =>
array(
'uri' => '/res/0f646281/rsrc/css/application/countdown/timer.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/countdown/timer.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/04767571/rsrc/js/application/core/KeyboardShortcutManager.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-dom',
4 => 'javelin-vector',
),
'disk' => '/rsrc/js/application/core/KeyboardShortcutManager.js',
),
'phabricator-object-selector-css' =>
array(
'uri' => '/res/608461d2/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/4cb0251e/rsrc/css/application/profile/profile-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/profile/profile-view.css',
),
'phabricator-remarkup-css' =>
array(
- 'uri' => '/res/d7e98209/rsrc/css/core/remarkup.css',
+ 'uri' => '/res/e0c44a00/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/e8238633/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',
),
'2892314d' =>
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/2892314d/typeahead.pkg.js',
'type' => 'js',
),
- 'd752b5da' =>
+ 'cfafcff7' =>
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/d752b5da/core.pkg.css',
+ 'uri' => '/res/pkg/cfafcff7/core.pkg.css',
'type' => 'css',
),
'da416e1c' =>
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/da416e1c/differential.pkg.js',
'type' => 'js',
),
'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',
),
'f1d27e2a' =>
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/f1d27e2a/workflow.pkg.js',
'type' => 'js',
),
55967526 =>
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/55967526/differential.pkg.css',
'type' => 'css',
),
),
'reverse' =>
array (
- 'aphront-crumbs-view-css' => 'd752b5da',
- 'aphront-dialog-view-css' => 'd752b5da',
- 'aphront-form-view-css' => 'd752b5da',
- 'aphront-list-filter-view-css' => 'd752b5da',
- 'aphront-panel-view-css' => 'd752b5da',
- 'aphront-side-nav-view-css' => 'd752b5da',
- 'aphront-table-view-css' => 'd752b5da',
- 'aphront-tokenizer-control-css' => 'd752b5da',
- 'aphront-typeahead-control-css' => 'd752b5da',
+ 'aphront-crumbs-view-css' => 'cfafcff7',
+ 'aphront-dialog-view-css' => 'cfafcff7',
+ 'aphront-form-view-css' => 'cfafcff7',
+ 'aphront-list-filter-view-css' => 'cfafcff7',
+ 'aphront-panel-view-css' => 'cfafcff7',
+ 'aphront-side-nav-view-css' => 'cfafcff7',
+ 'aphront-table-view-css' => 'cfafcff7',
+ 'aphront-tokenizer-control-css' => 'cfafcff7',
+ 'aphront-typeahead-control-css' => 'cfafcff7',
'differential-changeset-view-css' => '55967526',
'differential-core-view-css' => '55967526',
'differential-revision-add-comment-css' => '55967526',
'differential-revision-comment-css' => '55967526',
'differential-revision-comment-list-css' => '55967526',
'differential-revision-detail-css' => '55967526',
'differential-revision-history-css' => '55967526',
'differential-table-of-contents-css' => '55967526',
'diffusion-commit-view-css' => '03ef179e',
'javelin-behavior' => 'db95a6d0',
'javelin-behavior-aphront-basic-tokenizer' => '2892314d',
'javelin-behavior-aphront-form-disable-on-submit' => 'f1d27e2a',
'javelin-behavior-differential-diff-radios' => 'da416e1c',
'javelin-behavior-differential-edit-inline-comments' => 'da416e1c',
'javelin-behavior-differential-feedback-preview' => 'da416e1c',
'javelin-behavior-differential-populate' => 'da416e1c',
'javelin-behavior-differential-show-more' => 'da416e1c',
'javelin-behavior-phabricator-keyboard-shortcuts' => 'f1d27e2a',
'javelin-behavior-workflow' => 'f1d27e2a',
'javelin-dom' => 'db95a6d0',
'javelin-event' => 'db95a6d0',
'javelin-install' => 'db95a6d0',
'javelin-json' => 'db95a6d0',
'javelin-mask' => 'f1d27e2a',
'javelin-request' => 'db95a6d0',
'javelin-stratcom' => 'db95a6d0',
'javelin-tokenizer' => '2892314d',
'javelin-typeahead' => '2892314d',
'javelin-typeahead-normalizer' => '2892314d',
'javelin-typeahead-ondemand-source' => '2892314d',
'javelin-typeahead-preloaded-source' => '2892314d',
'javelin-typeahead-source' => '2892314d',
'javelin-uri' => 'db95a6d0',
'javelin-util' => 'db95a6d0',
'javelin-vector' => 'db95a6d0',
'javelin-workflow' => 'f1d27e2a',
- 'phabricator-core-buttons-css' => 'd752b5da',
- 'phabricator-core-css' => 'd752b5da',
- 'phabricator-directory-css' => 'd752b5da',
+ 'phabricator-core-buttons-css' => 'cfafcff7',
+ 'phabricator-core-css' => 'cfafcff7',
+ 'phabricator-directory-css' => 'cfafcff7',
'phabricator-keyboard-shortcut' => 'f1d27e2a',
'phabricator-keyboard-shortcut-manager' => 'f1d27e2a',
- 'phabricator-remarkup-css' => 'd752b5da',
- 'phabricator-standard-page-view' => 'd752b5da',
- 'syntax-highlighting-css' => 'd752b5da',
+ 'phabricator-remarkup-css' => 'cfafcff7',
+ 'phabricator-standard-page-view' => 'cfafcff7',
+ 'syntax-highlighting-css' => 'cfafcff7',
),
));
diff --git a/src/applications/daemon/controller/combined/PhabricatorDaemonCombinedLogController.php b/src/applications/daemon/controller/combined/PhabricatorDaemonCombinedLogController.php
index 1b237b23da..6d0409ac25 100644
--- a/src/applications/daemon/controller/combined/PhabricatorDaemonCombinedLogController.php
+++ b/src/applications/daemon/controller/combined/PhabricatorDaemonCombinedLogController.php
@@ -1,54 +1,55 @@
<?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 PhabricatorDaemonCombinedLogController
extends PhabricatorDaemonController {
public function processRequest() {
$request = $this->getRequest();
$pager = new AphrontPagerView();
$pager->setOffset($request->getInt('page'));
$pager->setPageSize(1000);
$events = id(new PhabricatorDaemonLogEvent())->loadAllWhere(
'1 = 1 ORDER BY id DESC LIMIT %d, %d',
$pager->getOffset(),
$pager->getPageSize() + 1);
$events = $pager->sliceResults($events);
$pager->setURI($request->getRequestURI(), 'page');
$event_view = new PhabricatorDaemonLogEventsView();
$event_view->setEvents($events);
+ $event_view->setUser($request->getUser());
$event_view->setCombinedLog(true);
$log_panel = new AphrontPanelView();
$log_panel->setHeader('Combined Daemon Logs');
$log_panel->appendChild($event_view);
$log_panel->appendChild($pager);
return $this->buildStandardPageResponse(
$log_panel,
array(
'title' => 'Combined Daemon Log',
));
}
}
diff --git a/src/applications/daemon/controller/console/PhabricatorDaemonConsoleController.php b/src/applications/daemon/controller/console/PhabricatorDaemonConsoleController.php
index c9b5d8960d..b9f88b4c59 100644
--- a/src/applications/daemon/controller/console/PhabricatorDaemonConsoleController.php
+++ b/src/applications/daemon/controller/console/PhabricatorDaemonConsoleController.php
@@ -1,166 +1,170 @@
<?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 PhabricatorDaemonConsoleController extends PhabricatorDaemonController {
public function processRequest() {
$logs = id(new PhabricatorDaemonLog())->loadAllWhere(
'1 = 1 ORDER BY id DESC LIMIT 15');
+ $request = $this->getRequest();
+ $user = $request->getUser();
+
$daemon_table = new PhabricatorDaemonLogListView();
+ $daemon_table->setUser($user);
$daemon_table->setDaemonLogs($logs);
$daemon_panel = new AphrontPanelView();
$daemon_panel->setHeader(
'Recently Launched Daemons'.
' &middot; '.
phutil_render_tag(
'a',
array(
'href' => '/daemon/log/',
),
'View All Daemons').
' &middot; '.
phutil_render_tag(
'a',
array(
'href' => '/daemon/log/combined/',
),
'View Combined Log'));
$daemon_panel->appendChild($daemon_table);
$tasks = id(new PhabricatorWorkerTask())->loadAllWhere(
'leaseOwner IS NOT NULL');
$rows = array();
foreach ($tasks as $task) {
$rows[] = array(
$task->getID(),
$task->getTaskClass(),
$task->getLeaseOwner(),
$task->getLeaseExpires() - time(),
$task->getFailureCount(),
phutil_render_tag(
'a',
array(
'href' => '/daemon/task/'.$task->getID().'/',
'class' => 'button small grey',
),
'View Task'),
);
}
$leased_table = new AphrontTableView($rows);
$leased_table->setHeaders(
array(
'ID',
'Class',
'Owner',
'Expries',
'Failures',
'',
));
$leased_table->setColumnClasses(
array(
'n',
'wide',
'',
'',
'n',
'action',
));
$leased_table->setNoDataString('No tasks are leased by workers.');
$leased_panel = new AphrontPanelView();
$leased_panel->setHeader('Leased Tasks');
$leased_panel->appendChild($leased_table);
$task_table = new PhabricatorWorkerTask();
$queued = queryfx_all(
$task_table->establishConnection('r'),
'SELECT taskClass, count(*) N FROM %T GROUP BY taskClass
ORDER BY N DESC',
$task_table->getTableName());
$rows = array();
foreach ($queued as $row) {
$rows[] = array(
phutil_escape_html($row['taskClass']),
number_format($row['N']),
);
}
$queued_table = new AphrontTableView($rows);
$queued_table->setHeaders(
array(
'Class',
'Count',
));
$queued_table->setColumnClasses(
array(
'wide',
'n',
));
$queued_table->setNoDataString('Task queue is empty.');
$queued_panel = new AphrontPanelView();
$queued_panel->setHeader('Queued Tasks');
$queued_panel->appendChild($queued_table);
$cursors = id(new PhabricatorTimelineCursor())
->loadAll();
$rows = array();
foreach ($cursors as $cursor) {
$rows[] = array(
phutil_escape_html($cursor->getName()),
number_format($cursor->getPosition()),
);
}
$cursor_table = new AphrontTableView($rows);
$cursor_table->setHeaders(
array(
'Name',
'Position',
));
$cursor_table->setColumnClasses(
array(
'wide',
'n',
));
$cursor_table->setNoDataString('No timeline cursors exist.');
$cursor_panel = new AphrontPanelView();
$cursor_panel->setHeader('Timeline Cursors');
$cursor_panel->appendChild($cursor_table);
return $this->buildStandardPageResponse(
array(
$daemon_panel,
$leased_panel,
$queued_panel,
$cursor_panel,
),
array(
'title' => 'Console',
'tab' => 'console',
));
}
}
diff --git a/src/applications/daemon/controller/loglist/PhabricatorDaemonLogListController.php b/src/applications/daemon/controller/loglist/PhabricatorDaemonLogListController.php
index 1d44639026..eb69979409 100644
--- a/src/applications/daemon/controller/loglist/PhabricatorDaemonLogListController.php
+++ b/src/applications/daemon/controller/loglist/PhabricatorDaemonLogListController.php
@@ -1,50 +1,51 @@
<?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 PhabricatorDaemonLogListController extends PhabricatorDaemonController {
public function processRequest() {
$request = $this->getRequest();
$pager = new AphrontPagerView();
$pager->setOffset($request->getInt('page'));
$logs = id(new PhabricatorDaemonLog())->loadAllWhere(
'1 = 1 ORDER BY id DESC LIMIT %d, %d',
$pager->getOffset(),
$pager->getPageSize() + 1);
$logs = $pager->sliceResults($logs);
$pager->setURI($request->getRequestURI(), 'page');
$daemon_table = new PhabricatorDaemonLogListView();
+ $daemon_table->setUser($request->getUser());
$daemon_table->setDaemonLogs($logs);
$daemon_panel = new AphrontPanelView();
$daemon_panel->setHeader('Launched Daemons');
$daemon_panel->appendChild($daemon_table);
$daemon_panel->appendChild($pager);
return $this->buildStandardPageResponse(
$daemon_panel,
array(
'title' => 'All Daemons',
));
}
}
diff --git a/src/applications/daemon/controller/logview/PhabricatorDaemonLogViewController.php b/src/applications/daemon/controller/logview/PhabricatorDaemonLogViewController.php
index 8d46e21b98..ffb95ecd9e 100644
--- a/src/applications/daemon/controller/logview/PhabricatorDaemonLogViewController.php
+++ b/src/applications/daemon/controller/logview/PhabricatorDaemonLogViewController.php
@@ -1,91 +1,93 @@
<?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 PhabricatorDaemonLogViewController extends PhabricatorDaemonController {
private $id;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$log = id(new PhabricatorDaemonLog())->load($this->id);
if (!$log) {
return new Aphront404Response();
}
$events = id(new PhabricatorDaemonLogEvent())->loadAllWhere(
'logID = %d ORDER BY id DESC LIMIT 1000',
$log->getID());
$content = array();
$argv = $log->getArgv();
$argv = implode("\n", $argv);
$form = id(new AphrontFormView())
->setUser($user)
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Daemon')
->setValue($log->getDaemon()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Host')
->setValue($log->getHost()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('PID')
->setValue($log->getPID()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Started')
- ->setValue(date('F jS, Y g:i:s A', $log->getDateCreated())))
+ ->setValue(
+ phabricator_datetime($log->getDateCreated(), $user)))
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Argv')
->setValue($argv));
$panel = new AphrontPanelView();
$panel->setHeader('Daemon Details');
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->appendChild($form);
$content[] = $panel;
$event_view = new PhabricatorDaemonLogEventsView();
+ $event_view->setUser($user);
$event_view->setEvents($events);
$log_panel = new AphrontPanelView();
$log_panel->setHeader('Daemon Logs');
$log_panel->appendChild($event_view);
$content[] = $log_panel;
return $this->buildStandardPageResponse(
$content,
array(
'title' => 'Daemon Log',
));
}
}
diff --git a/src/applications/daemon/controller/logview/__init__.php b/src/applications/daemon/controller/logview/__init__.php
index 8ddc17864a..5d234e47e1 100644
--- a/src/applications/daemon/controller/logview/__init__.php
+++ b/src/applications/daemon/controller/logview/__init__.php
@@ -1,22 +1,23 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/404');
phutil_require_module('phabricator', 'applications/daemon/controller/base');
phutil_require_module('phabricator', 'applications/daemon/view/daemonlogevents');
phutil_require_module('phabricator', 'infrastructure/daemon/storage/event');
phutil_require_module('phabricator', 'infrastructure/daemon/storage/log');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/static');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/layout/panel');
+phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorDaemonLogViewController.php');
diff --git a/src/applications/daemon/view/daemonlogevents/PhabricatorDaemonLogEventsView.php b/src/applications/daemon/view/daemonlogevents/PhabricatorDaemonLogEventsView.php
index a8c0a72814..dd09781683 100644
--- a/src/applications/daemon/view/daemonlogevents/PhabricatorDaemonLogEventsView.php
+++ b/src/applications/daemon/view/daemonlogevents/PhabricatorDaemonLogEventsView.php
@@ -1,83 +1,93 @@
<?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 PhabricatorDaemonLogEventsView extends AphrontView {
private $events;
private $combinedLog;
+ private $user;
public function setEvents(array $events) {
$this->events = $events;
}
public function setCombinedLog($is_combined) {
$this->combinedLog = $is_combined;
}
+ public function setUser(PhabricatorUser $user) {
+ $this->user = $user;
+ return $this;
+ }
+
public function render() {
$rows = array();
+ if (!$this->user) {
+ throw new Exception("Call setUser() before rendering!");
+ }
+
foreach ($this->events as $event) {
$row = array(
phutil_escape_html($event->getLogType()),
- date('M j, Y', $event->getEpoch()),
- date('g:i:s A', $event->getEpoch()),
+ phabricator_date($event->getEpoch(), $this->user),
+ phabricator_time($event->getEpoch(), $this->user),
str_replace("\n", '<br />', phutil_escape_html($event->getMessage())),
);
if ($this->combinedLog) {
array_unshift(
$row,
phutil_render_tag(
'a',
array(
'href' => '/daemon/log/'.$event->getLogID().'/',
),
phutil_escape_html('Daemon '.$event->getLogID())));
}
$rows[] = $row;
}
$classes = array(
'',
'',
'right',
'wide wrap',
);
$headers = array(
'Type',
'Date',
'Time',
'Message',
);
if ($this->combinedLog) {
array_unshift($classes, 'pri');
array_unshift($headers, 'Daemon');
}
$log_table = new AphrontTableView($rows);
$log_table->setHeaders($headers);
$log_table->setColumnClasses($classes);
return $log_table->render();
}
}
diff --git a/src/applications/daemon/view/daemonlogevents/__init__.php b/src/applications/daemon/view/daemonlogevents/__init__.php
index 29eecc7ec3..dd4e977647 100644
--- a/src/applications/daemon/view/daemonlogevents/__init__.php
+++ b/src/applications/daemon/view/daemonlogevents/__init__.php
@@ -1,15 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'view/base');
phutil_require_module('phabricator', 'view/control/table');
+phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_source('PhabricatorDaemonLogEventsView.php');
diff --git a/src/applications/daemon/view/daemonloglist/PhabricatorDaemonLogListView.php b/src/applications/daemon/view/daemonloglist/PhabricatorDaemonLogListView.php
index d0c882ef0c..1a4481ab48 100644
--- a/src/applications/daemon/view/daemonloglist/PhabricatorDaemonLogListView.php
+++ b/src/applications/daemon/view/daemonloglist/PhabricatorDaemonLogListView.php
@@ -1,113 +1,123 @@
<?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 PhabricatorDaemonLogListView extends AphrontView {
private $daemonLogs;
+ private $user;
public function setDaemonLogs(array $daemon_logs) {
$this->daemonLogs = $daemon_logs;
}
+ public function setUser(PhabricatorUser $user) {
+ $this->user = $user;
+ return $this;
+ }
+
public function render() {
$rows = array();
+ if (!$this->user) {
+ throw new Exception("Call setUser() before rendering!");
+ }
+
foreach ($this->daemonLogs as $log) {
$epoch = $log->getDateCreated();
if ($log->getHost() == php_uname('n')) {
// This will probably fail since apache can't signal the process, but
// we can check the error code to figure out if the process exists.
$is_running = posix_kill($log->getPID(), 0);
if (posix_get_last_error() == 1) {
// "Operation Not Permitted", indicates that the PID exists. If it
// doesn't, we'll get an error 3 ("No such process") instead.
$is_running = true;
}
if ($is_running) {
$running = phutil_render_tag(
'span',
array(
'style' => 'color: #00cc00',
'title' => 'Running',
),
'&bull;');
} else {
$running = phutil_render_tag(
'span',
array(
'style' => 'color: #cc0000',
'title' => 'Not running',
),
'&bull;');
}
} else {
$running = phutil_render_tag(
'span',
array(
'style' => 'color: #888888',
'title' => 'Not on this host',
),
'?');
}
$rows[] = array(
$running,
phutil_escape_html($log->getDaemon()),
phutil_escape_html($log->getHost()),
$log->getPID(),
- date('M j, Y', $epoch),
- date('g:i A', $epoch),
+ phabricator_date($epoch, $this->user),
+ phabricator_time($epoch, $this->user),
phutil_render_tag(
'a',
array(
'href' => '/daemon/log/'.$log->getID().'/',
'class' => 'button small grey',
),
'View Log'),
);
}
$daemon_table = new AphrontTableView($rows);
$daemon_table->setHeaders(
array(
'',
'Daemon',
'Host',
'PID',
'Date',
'Time',
'View',
));
$daemon_table->setColumnClasses(
array(
'',
'wide wrap',
'',
'',
'',
'right',
'action',
));
return $daemon_table->render();
}
}
diff --git a/src/applications/daemon/view/daemonloglist/__init__.php b/src/applications/daemon/view/daemonloglist/__init__.php
index 3be004735f..0cb14d1492 100644
--- a/src/applications/daemon/view/daemonloglist/__init__.php
+++ b/src/applications/daemon/view/daemonloglist/__init__.php
@@ -1,15 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'view/base');
phutil_require_module('phabricator', 'view/control/table');
+phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_source('PhabricatorDaemonLogListView.php');
diff --git a/src/applications/differential/controller/commentpreview/DifferentialCommentPreviewController.php b/src/applications/differential/controller/commentpreview/DifferentialCommentPreviewController.php
index 96b04844ab..74b57a6211 100644
--- a/src/applications/differential/controller/commentpreview/DifferentialCommentPreviewController.php
+++ b/src/applications/differential/controller/commentpreview/DifferentialCommentPreviewController.php
@@ -1,62 +1,63 @@
<?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 DifferentialCommentPreviewController extends DifferentialController {
private $id;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$author_phid = $request->getUser()->getPHID();
$handles = id(new PhabricatorObjectHandleData(array($author_phid)))
->loadHandles();
$factory = new DifferentialMarkupEngineFactory();
$engine = $factory->newDifferentialCommentMarkupEngine();
$comment = new DifferentialComment();
$comment->setContent($request->getStr('content'));
$comment->setAction($request->getStr('action'));
$comment->setAuthorPHID($author_phid);
$view = new DifferentialRevisionCommentView();
+ $view->setUser($request->getUser());
$view->setComment($comment);
$view->setHandles($handles);
$view->setMarkupEngine($engine);
$view->setPreview(true);
$view->setTargetDiff(null);
$draft = new PhabricatorDraft();
$draft
->setAuthorPHID($author_phid)
->setDraftKey('differential-comment-'.$this->id)
->setDraft($comment->getContent())
->replace();
return id(new AphrontAjaxResponse())
->setContent($view->render());
}
}
diff --git a/src/applications/differential/view/revisioncomment/DifferentialRevisionCommentView.php b/src/applications/differential/view/revisioncomment/DifferentialRevisionCommentView.php
index 73f07f0973..7b08c5d85d 100644
--- a/src/applications/differential/view/revisioncomment/DifferentialRevisionCommentView.php
+++ b/src/applications/differential/view/revisioncomment/DifferentialRevisionCommentView.php
@@ -1,264 +1,274 @@
<?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 DifferentialRevisionCommentView extends AphrontView {
private $comment;
private $handles;
private $markupEngine;
private $preview;
private $inlines;
private $changesets;
private $target;
private $commentNumber;
+ private $user;
public function setComment($comment) {
$this->comment = $comment;
return $this;
}
public function setHandles(array $handles) {
$this->handles = $handles;
return $this;
}
public function setMarkupEngine($markup_engine) {
$this->markupEngine = $markup_engine;
return $this;
}
public function setPreview($preview) {
$this->preview = $preview;
return $this;
}
public function setInlineComments(array $inline_comments) {
$this->inlines = $inline_comments;
return $this;
}
public function setChangesets(array $changesets) {
// Ship these in sorted by getSortKey() and keyed by ID... or else!
$this->changesets = $changesets;
return $this;
}
public function setTargetDiff($target) {
$this->target = $target;
}
public function setCommentNumber($comment_number) {
$this->commentNumber = $comment_number;
return $this;
}
+ public function setUser(PhabricatorUser $user) {
+ $this->user = $user;
+ return $this;
+ }
+
public function render() {
+ if (!$this->user) {
+ throw new Exception("Call setUser() before rendering!");
+ }
+
require_celerity_resource('phabricator-remarkup-css');
require_celerity_resource('differential-revision-comment-css');
$comment = $this->comment;
$action = $comment->getAction();
$action_class = 'differential-comment-action-'.phutil_escape_html($action);
if ($this->preview) {
$date = 'COMMENT PREVIEW';
} else {
- $date = date('F jS, Y g:i:s A', $comment->getDateCreated());
+ $date = phabricator_datetime($comment->getDateCreated(), $this->user);
}
$info = array($date);
$comment_anchor = null;
$num = $this->commentNumber;
if ($num && !$this->preview) {
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(' &middot; ', $info);
$author = $this->handles[$comment->getAuthorPHID()];
$author_link = $author->renderLink();
$verb = DifferentialAction::getActionPastTenseVerb($comment->getAction());
$verb = phutil_escape_html($verb);
$content = $comment->getContent();
$head_content = null;
if (strlen(rtrim($content))) {
$title = "{$author_link} {$verb} this revision:";
$cache = $comment->getCache();
if (strlen($cache)) {
$content = $cache;
} else {
$content = $this->markupEngine->markupText($content);
if ($comment->getID()) {
$comment->setCache($content);
$comment->save();
}
}
$content =
'<div class="phabricator-remarkup">'.
$content.
'</div>';
} else {
$title = null;
$head_content =
'<div class="differential-comment-nocontent">'.
"<p>{$author_link} {$verb} this revision.</p>".
'</div>';
$content = null;
}
if ($this->inlines) {
$inline_render = array();
$inlines = $this->inlines;
$changesets = $this->changesets;
$inlines_by_changeset = mgroup($inlines, 'getChangesetID');
$inlines_by_changeset = array_select_keys(
$inlines_by_changeset,
array_keys($this->changesets));
$inline_render[] = '<table class="differential-inline-summary">';
foreach ($inlines_by_changeset as $changeset_id => $inlines) {
$changeset = $changesets[$changeset_id];
$inlines = msort($inlines, 'getLineNumber');
$inline_render[] =
'<tr>'.
'<th colspan="2">'.
phutil_escape_html($changeset->getFileName()).
'</th>'.
'</tr>';
foreach ($inlines as $inline) {
if (!$inline->getLineLength()) {
$lines = $inline->getLineNumber();
} else {
$lines = $inline->getLineNumber()."\xE2\x80\x93".
($inline->getLineNumber() + $inline->getLineLength());
}
if (!$this->target ||
$changeset->getDiffID() === $this->target->getID()) {
$lines = phutil_render_tag(
'a',
array(
'href' => '#inline-'.$inline->getID(),
'class' => 'num',
),
$lines);
}
$inline_content = $inline->getContent();
if (strlen($inline_content)) {
$inline_cache = $inline->getCache();
if ($inline_cache) {
$inline_content = $inline_cache;
} else {
$inline_content = $this->markupEngine->markupText(
$inline_content);
if ($inline->getID()) {
$inline->setCache($inline_content);
$inline->save();
}
}
}
$inline_render[] =
'<tr>'.
'<td class="inline-line-number">'.$lines.'</td>'.
'<td>'.
'<div class="phabricator-remarkup">'.
$inline_content.
'</div>'.
'</td>'.
'</tr>';
}
}
$inline_render[] = '</table>';
$inline_render = implode("\n", $inline_render);
$inline_render =
'<div class="differential-inline-summary-section">'.
'Inline Comments'.
'</div>'.
$inline_render;
} else {
$inline_render = null;
}
$background = null;
$uri = $author->getImageURI();
if ($uri) {
$background = "background-image: url('{$uri}');";
}
$metadata_blocks = array();
$metadata = $comment->getMetadata();
$added_reviewers = idx(
$metadata,
DifferentialComment::METADATA_ADDED_REVIEWERS);
if ($added_reviewers) {
$reviewers = array();
foreach ($added_reviewers as $phid) {
$reviewers[] = $this->handles[$phid]->renderLink();
}
$reviewers = 'Added reviewers: '.implode(', ', $reviewers);
$metadata_blocks[] = $reviewers;
}
if ($metadata_blocks) {
$metadata_blocks =
'<div class="differential-comment-metadata">'.
implode("\n", $metadata_blocks).
'</div>';
} else {
$metadata_blocks = null;
}
return phutil_render_tag(
'div',
array(
'class' => "differential-comment {$action_class}",
'id' => $comment_anchor,
),
'<div class="differential-comment-head">'.
'<span class="differential-comment-info">'.$info.'</span>'.
'<span class="differential-comment-title">'.$title.'</span>'.
'<div style="clear: both;"></div>'.
'</div>'.
'<div class="differential-comment-body" style="'.$background.'">'.
'<div class="differential-comment-content">'.
$head_content.
$metadata_blocks.
'<div class="differential-comment-core">'.
$content.
'</div>'.
$inline_render.
'</div>'.
'</div>');
}
}
diff --git a/src/applications/differential/view/revisioncomment/__init__.php b/src/applications/differential/view/revisioncomment/__init__.php
index d240fa85ca..f105a69222 100644
--- a/src/applications/differential/view/revisioncomment/__init__.php
+++ b/src/applications/differential/view/revisioncomment/__init__.php
@@ -1,19 +1,20 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/differential/constants/action');
phutil_require_module('phabricator', 'applications/differential/storage/comment');
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/utils');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('DifferentialRevisionCommentView.php');
diff --git a/src/applications/differential/view/revisioncommentlist/DifferentialRevisionCommentListView.php b/src/applications/differential/view/revisioncommentlist/DifferentialRevisionCommentListView.php
index 23a24b0141..4ca1901a58 100644
--- a/src/applications/differential/view/revisioncommentlist/DifferentialRevisionCommentListView.php
+++ b/src/applications/differential/view/revisioncommentlist/DifferentialRevisionCommentListView.php
@@ -1,168 +1,169 @@
<?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 DifferentialRevisionCommentListView extends AphrontView {
private $comments;
private $handles;
private $inlines;
private $changesets;
private $user;
private $target;
public function setComments(array $comments) {
$this->comments = $comments;
return $this;
}
public function setInlineComments(array $inline_comments) {
$this->inlines = $inline_comments;
return $this;
}
public function setHandles(array $handles) {
$this->handles = $handles;
return $this;
}
public function setChangesets(array $changesets) {
$this->changesets = $changesets;
return $this;
}
public function setUser(PhabricatorUser $user) {
$this->user = $user;
return $this;
}
public function setTargetDiff(DifferentialDiff $target) {
$this->target = $target;
}
public function render() {
require_celerity_resource('differential-revision-comment-list-css');
$factory = new DifferentialMarkupEngineFactory();
$engine = $factory->newDifferentialCommentMarkupEngine();
$inlines = mgroup($this->inlines, 'getCommentID');
$num = 1;
$html = array();
foreach ($this->comments as $comment) {
$view = new DifferentialRevisionCommentView();
$view->setComment($comment);
+ $view->setUser($this->user);
$view->setHandles($this->handles);
$view->setMarkupEngine($engine);
$view->setInlineComments(idx($inlines, $comment->getID(), array()));
$view->setChangesets($this->changesets);
$view->setTargetDiff($this->target);
$view->setCommentNumber($num++);
$html[] = $view->render();
}
$objs = array_reverse(array_values($this->comments));
$html = array_reverse(array_values($html));
$user = $this->user;
$last_comment = null;
// Find the most recent comment by the viewer.
foreach ($objs as $position => $comment) {
if ($user && ($comment->getAuthorPHID() == $user->getPHID())) {
if ($last_comment === null) {
$last_comment = $position;
} else if ($last_comment == $position - 1) {
// If the viewer made several comments in a row, show them all. This
// is a spaz rule for epriestley.
$last_comment = $position;
}
}
}
$header = array();
$hidden = array();
if ($last_comment !== null) {
foreach ($objs as $position => $comment) {
if (!$comment->getID()) {
// These are synthetic comments with summary/test plan information.
$header[] = $html[$position];
unset($html[$position]);
continue;
}
if ($position <= $last_comment) {
// Always show comments after the viewer's last comment.
continue;
}
if ($position < 3) {
// Always show the 3 most recent comments.
continue;
}
$hidden[] = $position;
}
}
if (count($hidden) <= 3) {
// Don't hide if there's not much to hide.
$hidden = array();
}
$header = array_reverse($header);
$hidden = array_select_keys($html, $hidden);
$visible = array_diff_key($html, $hidden);
$hidden = array_reverse($hidden);
$visible = array_reverse($visible);
if ($hidden) {
Javelin::initBehavior(
'differential-show-all-comments',
array(
'markup' => implode("\n", $hidden),
));
$hidden = javelin_render_tag(
'div',
array(
'sigil' => "differential-all-comments-container",
),
'<div class="differential-older-comments-are-hidden">'.
number_format(count($hidden)).' older comments are hidden. '.
javelin_render_tag(
'a',
array(
'href' => '#',
'mustcapture' => true,
'sigil' => 'differential-show-all-comments',
),
'Show all comments.').
'</div>');
} else {
$hidden = null;
}
return
'<div class="differential-comment-list">'.
implode("\n", $header).
$hidden.
implode("\n", $visible).
'</div>';
}
}
diff --git a/src/applications/files/controller/view/PhabricatorFileViewController.php b/src/applications/files/controller/view/PhabricatorFileViewController.php
index 7a75e26ff3..b13acb5b19 100644
--- a/src/applications/files/controller/view/PhabricatorFileViewController.php
+++ b/src/applications/files/controller/view/PhabricatorFileViewController.php
@@ -1,167 +1,170 @@
<?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 PhabricatorFileViewController extends PhabricatorFileController {
private $phid;
private $view;
public function willProcessRequest(array $data) {
$this->phid = $data['phid'];
$this->view = $data['view'];
}
public function processRequest() {
+ $request = $this->getRequest();
+ $user = $request->getUser();
+
$file = id(new PhabricatorFile())->loadOneWhere(
'phid = %s',
$this->phid);
if (!$file) {
return new Aphront404Response();
}
switch ($this->view) {
case 'download':
case 'view':
$data = $file->loadFileData();
$response = new AphrontFileResponse();
$response->setContent($data);
$response->setCacheDurationInSeconds(60 * 60 * 24 * 30);
if ($this->view == 'view') {
if (!$file->isViewableInBrowser()) {
return new Aphront400Response();
}
$download = false;
} else {
$download = true;
}
if ($download) {
$mime_type = $file->getMimeType();
} else {
$mime_type = $file->getViewableMimeType();
}
$response->setMimeType($mime_type);
if ($download) {
$response->setDownload($file->getName());
}
return $response;
default:
break;
}
$form = new AphrontFormView();
if ($file->isViewableInBrowser()) {
$form->setAction('/file/view/'.$file->getPHID().'/');
$button_name = 'View File';
} else {
$form->setAction('/file/download/'.$file->getPHID().'/');
$button_name = 'Download File';
}
$form->setUser($this->getRequest()->getUser());
$form
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Name')
->setName('name')
->setValue($file->getName()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('PHID')
->setName('phid')
->setValue($file->getPHID()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Created')
->setName('created')
- ->setValue(date('Y-m-d g:i:s A', $file->getDateCreated())))
+ ->setValue(phabricator_datetime($file->getDateCreated(), $user)))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Mime Type')
->setName('mime')
->setValue($file->getMimeType()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Size')
->setName('size')
->setValue($file->getByteSize().' bytes'))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Engine')
->setName('storageEngine')
->setValue($file->getStorageEngine()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Format')
->setName('storageFormat')
->setValue($file->getStorageFormat()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Handle')
->setName('storageHandle')
->setValue($file->getStorageHandle()))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue($button_name));
$panel = new AphrontPanelView();
$panel->setHeader('File Info - '.$file->getName());
$panel->appendChild($form);
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
$transformations = id(new PhabricatorTransformedFile())->loadAllWhere(
'originalPHID = %s',
$file->getPHID());
$rows = array();
foreach ($transformations as $transformed) {
$phid = $transformed->getTransformedPHID();
$rows[] = array(
phutil_escape_html($transformed->getTransform()),
phutil_render_tag(
'a',
array(
'href' => PhabricatorFileURI::getViewURIForPHID($phid),
),
$phid));
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
'Transform',
'File',
));
$xform_panel = new AphrontPanelView();
$xform_panel->appendChild($table);
$xform_panel->setWidth(AphrontPanelView::WIDTH_FORM);
$xform_panel->setHeader('Transformations');
return $this->buildStandardPageResponse(
array($panel, $xform_panel),
array(
'title' => 'File Info - '.$file->getName(),
));
}
}
diff --git a/src/applications/files/controller/view/__init__.php b/src/applications/files/controller/view/__init__.php
index 6f1fdac61b..36cba91615 100644
--- a/src/applications/files/controller/view/__init__.php
+++ b/src/applications/files/controller/view/__init__.php
@@ -1,26 +1,27 @@
<?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/404');
phutil_require_module('phabricator', 'aphront/response/file');
phutil_require_module('phabricator', 'applications/files/controller/base');
phutil_require_module('phabricator', 'applications/files/storage/file');
phutil_require_module('phabricator', 'applications/files/storage/transformed');
phutil_require_module('phabricator', 'applications/files/uri');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/static');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/layout/panel');
+phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorFileViewController.php');
diff --git a/src/applications/maniphest/controller/descriptionchange/ManiphestTaskDescriptionChangeController.php b/src/applications/maniphest/controller/descriptionchange/ManiphestTaskDescriptionChangeController.php
index 11c5909f26..4c8f5004a1 100644
--- a/src/applications/maniphest/controller/descriptionchange/ManiphestTaskDescriptionChangeController.php
+++ b/src/applications/maniphest/controller/descriptionchange/ManiphestTaskDescriptionChangeController.php
@@ -1,60 +1,61 @@
<?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 ManiphestTaskDescriptionChangeController extends ManiphestController {
private $transactionID;
public function willProcessRequest(array $data) {
$this->transactionID = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$transaction = id(new ManiphestTransaction())->load($this->transactionID);
if (!$transaction) {
return new Aphront404Response();
}
$transactions = array($transaction);
$phids = array();
foreach ($transactions as $transaction) {
foreach ($transaction->extractPHIDs() as $phid) {
$phids[$phid] = $phid;
}
}
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
$factory = new DifferentialMarkupEngineFactory();
$engine = $factory->newDifferentialCommentMarkupEngine();
$view = new ManiphestTransactionDetailView();
$view->setTransactionGroup($transactions);
$view->setHandles($handles);
+ $view->setUser($user);
$view->setMarkupEngine($engine);
$view->setRenderSummaryOnly(true);
$view->setRenderFullSummary(true);
return id(new AphrontAjaxResponse())->setContent($view->render());
}
}
diff --git a/src/applications/maniphest/controller/tasklist/ManiphestTaskListController.php b/src/applications/maniphest/controller/tasklist/ManiphestTaskListController.php
index 1d0e5f2135..7d008a13cd 100644
--- a/src/applications/maniphest/controller/tasklist/ManiphestTaskListController.php
+++ b/src/applications/maniphest/controller/tasklist/ManiphestTaskListController.php
@@ -1,403 +1,404 @@
<?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 ManiphestTaskListController extends ManiphestController {
private $view;
public function willProcessRequest(array $data) {
$this->view = idx($data, 'view');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$uri = $request->getRequestURI();
if ($request->isFormPost()) {
$phid_arr = $request->getArr('view_user');
$view_target = head($phid_arr);
return id(new AphrontRedirectResponse())
->setURI($request->getRequestURI()->alter('phid', $view_target));
}
$views = array(
'User Tasks',
'action' => 'Assigned',
'created' => 'Created',
'triage' => 'Need Triage',
// 'touched' => 'Touched',
'<hr />',
'All Tasks',
'alltriage' => 'Need Triage',
'unassigned' => 'Unassigned',
'all' => 'All Tasks',
);
if (empty($views[$this->view])) {
$this->view = 'action';
}
$has_filter = array(
'action' => true,
'created' => true,
'triage' => true,
);
$nav = new AphrontSideNavView();
foreach ($views as $view => $name) {
if (is_integer($view)) {
$nav->addNavItem(
phutil_render_tag(
'span',
array(),
$name));
} else {
$uri->setPath('/maniphest/view/'.$view.'/');
$nav->addNavItem(
phutil_render_tag(
'a',
array(
'href' => $uri,
'class' => ($this->view == $view)
? 'aphront-side-nav-selected'
: null,
),
phutil_escape_html($name)));
}
}
list($status_map, $status_links) = $this->renderStatusLinks();
list($grouping, $group_links) = $this->renderGroupLinks();
list($order, $order_links) = $this->renderOrderLinks();
$view_phid = nonempty($request->getStr('phid'), $user->getPHID());
list($tasks, $handles) = $this->loadTasks(
$view_phid,
array(
'status' => $status_map,
'group' => $grouping,
'order' => $order,
));
$form = id(new AphrontFormView())
->setUser($user);
if (isset($has_filter[$this->view])) {
$form->appendChild(
id(new AphrontFormTokenizerControl())
->setLimit(1)
->setDatasource('/typeahead/common/users/')
->setName('view_user')
->setLabel('View User')
->setValue(
array(
$view_phid => $handles[$view_phid]->getFullName(),
)));
}
$form
->appendChild(
id(new AphrontFormToggleButtonsControl())
->setLabel('Status')
->setValue($status_links))
->appendChild(
id(new AphrontFormToggleButtonsControl())
->setLabel('Group')
->setValue($group_links))
->appendChild(
id(new AphrontFormToggleButtonsControl())
->setLabel('Order')
->setValue($order_links));
$filter = new AphrontListFilterView();
$filter->addButton(
phutil_render_tag(
'a',
array(
'href' => '/maniphest/task/create/',
'class' => 'green button',
),
'Create New Task'));
$filter->appendChild($form);
$nav->appendChild($filter);
$have_tasks = false;
foreach ($tasks as $group => $list) {
if (count($list)) {
$have_tasks = true;
break;
}
}
require_celerity_resource('maniphest-task-summary-css');
if (!$have_tasks) {
$nav->appendChild(
'<h1 class="maniphest-task-group-header">'.
'No matching tasks.'.
'</h1>');
} else {
foreach ($tasks as $group => $list) {
$task_list = new ManiphestTaskListView();
+ $task_list->setUser($user);
$task_list->setTasks($list);
$task_list->setHandles($handles);
$count = number_format(count($list));
$nav->appendChild(
'<h1 class="maniphest-task-group-header">'.
phutil_escape_html($group).' ('.$count.')'.
'</h1>');
$nav->appendChild($task_list);
}
}
return $this->buildStandardPageResponse(
$nav,
array(
'title' => 'Task List',
));
}
private function loadTasks($view_phid, array $dict) {
$phids = array($view_phid);
$task = new ManiphestTask();
$argv = array();
$status = $dict['status'];
if (!empty($status['open']) && !empty($status['closed'])) {
$status_clause = '1 = 1';
} else if (!empty($status['open'])) {
$status_clause = 'status = %d';
$argv[] = 0;
} else {
$status_clause = 'status > %d';
$argv[] = 0;
}
$extra_clause = '1 = 1';
switch ($this->view) {
case 'action':
$extra_clause = 'ownerPHID in (%Ls)';
$argv[] = $phids;
break;
case 'created':
$extra_clause = 'authorPHID in (%Ls)';
$argv[] = $phids;
break;
case 'triage':
$extra_clause = 'ownerPHID in (%Ls) AND priority = %d';
$argv[] = $phids;
$argv[] = ManiphestTaskPriority::PRIORITY_TRIAGE;
break;
case 'alltriage':
$extra_clause = 'priority = %d';
$argv[] = ManiphestTaskPriority::PRIORITY_TRIAGE;
break;
case 'unassigned':
$extra_clause = 'ownerPHID is NULL';
break;
case 'all':
break;
}
switch ($dict['order']) {
case 'priority':
$order = 'priority DESC, dateModified DESC';
break;
case 'created':
$order = 'id DESC';
break;
default:
$order = 'dateModified DESC';
break;
}
$sql = "({$status_clause}) AND ({$extra_clause}) ORDER BY {$order}";
array_unshift($argv, $sql);
$data = call_user_func_array(array($task, 'loadAllWhere'), $argv);
$handle_phids = mpull($data, 'getOwnerPHID');
$handle_phids[] = $view_phid;
$handles = id(new PhabricatorObjectHandleData($handle_phids))
->loadHandles();
switch ($dict['group']) {
case 'priority':
$data = mgroup($data, 'getPriority');
krsort($data);
$out = array();
foreach ($data as $pri => $tasks) {
$out[ManiphestTaskPriority::getTaskPriorityName($pri)] = $tasks;
}
$data = $out;
break;
case 'status':
$data = mgroup($data, 'getStatus');
ksort($data);
$out = array();
foreach ($data as $status => $tasks) {
$out[ManiphestTaskStatus::getTaskStatusFullName($status)] = $tasks;
}
$data = $out;
break;
case 'owner':
$data = mgroup($data, 'getOwnerPHID');
$out = array();
foreach ($data as $phid => $tasks) {
if ($phid) {
$out[$handles[$phid]->getFullName()] = $tasks;
} else {
$out['Unassigned'] = $tasks;
}
}
if (isset($out['Unassigned'])) {
// If any tasks are unassigned, move them to the front of the list.
$data = array('Unassigned' => $out['Unassigned']) + $out;
} else {
$data = $out;
}
ksort($data);
break;
default:
$data = array(
'Tasks' => $data,
);
break;
}
return array($data, $handles);
}
public function renderStatusLinks() {
$request = $this->getRequest();
$statuses = array(
'o' => array('open' => true),
'c' => array('closed' => true),
'oc' => array('open' => true, 'closed' => true),
);
$status = $request->getStr('s');
if (empty($statuses[$status])) {
$status = 'o';
}
$button_names = array(
'Open' => 'o',
'Closed' => 'c',
'All' => 'oc',
);
$status_links = $this->renderFilterLinks($button_names, $status, 's');
return array($statuses[$status], $status_links);
}
public function renderOrderLinks() {
$request = $this->getRequest();
$order = $request->getStr('o');
$orders = array(
'u' => 'updated',
'c' => 'created',
'p' => 'priority',
);
if (empty($orders[$order])) {
$order = 'p';
}
$order_by = $orders[$order];
$order_names = array(
'Priority' => 'p',
'Updated' => 'u',
'Created' => 'c',
);
$order_links = $this->renderFilterLinks($order_names, $order, 'o');
return array($order_by, $order_links);
}
public function renderGroupLinks() {
$request = $this->getRequest();
$group = $request->getStr('g');
$groups = array(
'n' => 'none',
'p' => 'priority',
's' => 'status',
'o' => 'owner',
);
if (empty($groups[$group])) {
$group = 'p';
}
$group_by = $groups[$group];
$group_names = array(
'Priority' => 'p',
'Owner' => 'o',
'Status' => 's',
'None' => 'n',
);
$group_links = $this->renderFilterLinks($group_names, $group, 'g');
return array($group_by, $group_links);
}
private function renderFilterLinks($filter_map, $selected, $uri_param) {
$request = $this->getRequest();
$uri = $request->getRequestURI();
$links = array();
foreach ($filter_map as $name => $value) {
if ($value == $selected) {
$more = ' toggle-selected toggle-fixed';
$href = null;
} else {
$more = null;
$href = $uri->alter($uri_param, $value);
}
$links[] = phutil_render_tag(
'a',
array(
'class' => 'toggle'.$more,
'href' => $href,
),
$name);
}
return implode("\n", $links);
}
}
diff --git a/src/applications/maniphest/view/tasklist/ManiphestTaskListView.php b/src/applications/maniphest/view/tasklist/ManiphestTaskListView.php
index 8234ad3967..0e01aefb96 100644
--- a/src/applications/maniphest/view/tasklist/ManiphestTaskListView.php
+++ b/src/applications/maniphest/view/tasklist/ManiphestTaskListView.php
@@ -1,50 +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.
*/
class ManiphestTaskListView extends AphrontView {
private $tasks;
private $handles;
+ private $user;
public function setTasks(array $tasks) {
$this->tasks = $tasks;
return $this;
}
public function setHandles(array $handles) {
$this->handles = $handles;
return $this;
}
+ public function setUser(PhabricatorUser $user) {
+ $this->user = $user;
+ return $this;
+ }
+
public function render() {
$views = array();
foreach ($this->tasks as $task) {
$view = new ManiphestTaskSummaryView();
$view->setTask($task);
+ $view->setUser($this->user);
$view->setHandles($this->handles);
$views[] = $view->render();
}
return
'<div style="padding: 1em;">'.
implode("\n", $views).
'</div>';
}
}
diff --git a/src/applications/maniphest/view/tasksummary/ManiphestTaskSummaryView.php b/src/applications/maniphest/view/tasksummary/ManiphestTaskSummaryView.php
index b1ea5352b7..7cad3d02a8 100644
--- a/src/applications/maniphest/view/tasksummary/ManiphestTaskSummaryView.php
+++ b/src/applications/maniphest/view/tasksummary/ManiphestTaskSummaryView.php
@@ -1,85 +1,96 @@
<?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 ManiphestTaskSummaryView extends AphrontView {
private $task;
private $handles;
+ private $user;
public function setTask(ManiphestTask $task) {
$this->task = $task;
return $this;
}
public function setHandles(array $handles) {
$this->handles = $handles;
return $this;
}
+ public function setUser(PhabricatorUser $user) {
+ $this->user = $user;
+ return $this;
+ }
+
public function render() {
+
+ if (!$this->user) {
+ throw new Exception("Call setUser() before rendering!");
+ }
+
$task = $this->task;
$handles = $this->handles;
require_celerity_resource('maniphest-task-summary-css');
$classes = array(
ManiphestTaskPriority::PRIORITY_UNBREAK_NOW => 'pri-unbreak',
ManiphestTaskPriority::PRIORITY_TRIAGE => 'pri-triage',
ManiphestTaskPriority::PRIORITY_HIGH => 'pri-high',
ManiphestTaskPriority::PRIORITY_NORMAL => 'pri-normal',
ManiphestTaskPriority::PRIORITY_LOW => 'pri-low',
ManiphestTaskPriority::PRIORITY_WISH => 'pri-wish',
);
$pri_class = idx($classes, $task->getPriority());
return
'<table class="maniphest-task-summary">'.
'<tr>'.
'<td class="maniphest-task-number '.$pri_class.'">'.
'T'.$task->getID().
'</td>'.
'<td class="maniphest-task-status">'.
($task->getStatus() == ManiphestTaskStatus::STATUS_OPEN
? 'Open'
: 'Closed').
'</td>'.
'<td class="maniphest-task-owner">'.
($task->getOwnerPHID()
? $handles[$task->getOwnerPHID()]->renderLink()
: '<em>None</em>').
'</td>'.
'<td class="maniphest-task-name">'.
phutil_render_tag(
'a',
array(
'href' => '/T'.$task->getID(),
),
phutil_escape_html($task->getTitle())).
'</td>'.
'<td class="maniphest-task-priority">'.
ManiphestTaskPriority::getTaskPriorityName($task->getPriority()).
'</td>'.
'<td class="maniphest-task-updated">'.
- phabricator_format_timestamp($task->getDateModified()).
+ phabricator_datetime($task->getDateModified(), $this->user).
'</td>'.
'</tr>'.
'</table>';
}
}
diff --git a/src/applications/maniphest/view/transactiondetail/ManiphestTransactionDetailView.php b/src/applications/maniphest/view/transactiondetail/ManiphestTransactionDetailView.php
index f702a04125..243ee7eae9 100644
--- a/src/applications/maniphest/view/transactiondetail/ManiphestTransactionDetailView.php
+++ b/src/applications/maniphest/view/transactiondetail/ManiphestTransactionDetailView.php
@@ -1,561 +1,577 @@
<?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 ManiphestTransactionDetailView extends AphrontView {
private $transactions;
private $handles;
private $markupEngine;
private $forEmail;
private $preview;
private $commentNumber;
private $renderSummaryOnly;
private $renderFullSummary;
+ private $user;
public function setTransactionGroup(array $transactions) {
$this->transactions = $transactions;
return $this;
}
public function setHandles(array $handles) {
$this->handles = $handles;
return $this;
}
public function setMarkupEngine(PhutilMarkupEngine $engine) {
$this->markupEngine = $engine;
return $this;
}
public function setPreview($preview) {
$this->preview = $preview;
return $this;
}
public function setRenderSummaryOnly($render_summary_only) {
$this->renderSummaryOnly = $render_summary_only;
return $this;
}
public function getRenderSummaryOnly() {
return $this->renderSummaryOnly;
}
public function setRenderFullSummary($render_full_summary) {
$this->renderFullSummary = $render_full_summary;
return $this;
}
public function getRenderFullSummary() {
return $this->renderFullSummary;
}
public function setCommentNumber($comment_number) {
$this->commentNumber = $comment_number;
return $this;
}
+ public function setUser(PhabricatorUser $user) {
+ $this->user = $user;
+ return $this;
+ }
+
public function renderForEmail($with_date) {
$this->forEmail = true;
$transaction = reset($this->transactions);
$author = $this->renderHandles(array($transaction->getAuthorPHID()));
$action = null;
$descs = array();
$comments = null;
foreach ($this->transactions as $transaction) {
list($verb, $desc, $classes) = $this->describeAction($transaction);
if ($action === null) {
$action = $verb;
}
$desc = $author.' '.$desc.'.';
if ($with_date) {
- $desc = 'On '.date('M jS \a\t g:i A', $transaction->getDateCreated()).
- ', '.$desc;
+ // NOTE: This is going into a (potentially multi-recipient) email so
+ // we can't use a single user's timezone preferences. Use the server's
+ // instead, but make the timezone explicit.
+ $datetime = date('M jS \a\t g:i A T', $transaction->getDateCreated());
+ $desc = "On {$datetime}, {$desc}";
}
$descs[] = $desc;
if ($transaction->hasComments()) {
$comments = $transaction->getComments();
}
}
$descs = implode("\n", $descs);
if ($comments) {
$descs .= "\n".$comments;
}
foreach ($this->transactions as $transaction) {
$supplemental = $this->renderSupplementalInfoForEmail($transaction);
if ($supplemental) {
$descs .= "\n\n".$supplemental;
}
}
$this->forEmail = false;
return array($action, $descs);
}
public function render() {
+
+ if (!$this->user) {
+ throw new Exception("Call setUser() before render()!");
+ }
+
$handles = $this->handles;
$transactions = $this->transactions;
require_celerity_resource('maniphest-transaction-detail-css');
$comment_transaction = null;
foreach ($this->transactions as $transaction) {
if ($transaction->hasComments()) {
$comment_transaction = $transaction;
break;
}
}
$any_transaction = reset($transactions);
$author = $this->handles[$any_transaction->getAuthorPHID()];
$more_classes = array();
$descs = array();
foreach ($transactions as $transaction) {
list($verb, $desc, $classes) = $this->describeAction($transaction);
$more_classes = array_merge($more_classes, $classes);
$full_summary = null;
if ($this->getRenderFullSummary()) {
$full_summary = $this->renderFullSummary($transaction);
}
$descs[] = javelin_render_tag(
'div',
array(
'sigil' => 'maniphest-transaction-description',
),
$author->renderLink().' '.$desc.'.'.$full_summary);
}
$descs = implode("\n", $descs);
if ($this->getRenderSummaryOnly()) {
return $descs;
}
$more_classes = implode(' ', $more_classes);
if ($comment_transaction && $comment_transaction->hasComments()) {
$comments = $comment_transaction->getCache();
if (!strlen($comments)) {
$comments = $comment_transaction->getComments();
if (strlen($comments)) {
$comments = $this->markupEngine->markupText($comments);
$comment_transaction->setCache($comments);
if ($comment_transaction->getID() && !$this->preview) {
$comment_transaction->save();
}
}
}
$comment_block =
'<div class="maniphest-transaction-comments phabricator-remarkup">'.
$comments.
'</div>';
} else {
$comment_block = null;
}
if ($this->preview) {
$timestamp = 'COMMENT PREVIEW';
} else {
- $timestamp = phabricator_format_timestamp($transaction->getDateCreated());
+ $timestamp = phabricator_datetime(
+ $transaction->getDateCreated(),
+ $this->user);
}
$info = array();
$info[] = $timestamp;
$comment_anchor = null;
$num = $this->commentNumber;
if ($num && !$this->preview) {
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(' &middot; ', $info);
return phutil_render_tag(
'div',
array(
'class' => "maniphest-transaction-detail-container",
'style' => "background-image: url('".$author->getImageURI()."')",
'id' => $comment_anchor,
),
'<div class="maniphest-transaction-detail-view '.$more_classes.'">'.
'<div class="maniphest-transaction-header">'.
'<div class="maniphest-transaction-timestamp">'.
$info.
'</div>'.
$descs.
'</div>'.
$comment_block.
'</div>');
}
private function renderSupplementalInfoForEmail($transaction) {
$handles = $this->handles;
$type = $transaction->getTransactionType();
$new = $transaction->getNewValue();
$old = $transaction->getOldValue();
switch ($type) {
case ManiphestTransactionType::TYPE_DESCRIPTION:
return "NEW DESCRIPTION\n ".trim($new)."\n\n".
"PREVIOUS DESCRIPTION\n ".trim($old);
case ManiphestTransactionType::TYPE_ATTACH:
$old_raw = nonempty($old, array());
$new_raw = nonempty($new, array());
$attach_types = array(
PhabricatorPHIDConstants::PHID_TYPE_DREV,
PhabricatorPHIDConstants::PHID_TYPE_FILE,
);
foreach ($attach_types as $type) {
$old = array_keys(idx($old_raw, $type, array()));
$new = array_keys(idx($new_raw, $type, array()));
if ($old != $new) {
break;
}
}
$added = array_diff($new, $old);
if (!$added) {
break;
}
$links = array();
foreach (array_select_keys($handles, $added) as $handle) {
$links[] = ' '.PhabricatorEnv::getProductionURI($handle->getURI());
}
$links = implode("\n", $links);
switch ($type) {
case PhabricatorPHIDConstants::PHID_TYPE_DREV:
$title = 'ATTACHED REVISIONS';
break;
case PhabricatorPHIDConstants::PHID_TYPE_FILE:
$title = 'ATTACHED FILES';
break;
}
return $title."\n".$links;
default:
break;
}
return null;
}
private function describeAction($transaction) {
$verb = null;
$desc = null;
$classes = array();
$handles = $this->handles;
$type = $transaction->getTransactionType();
$author_phid = $transaction->getAuthorPHID();
$new = $transaction->getNewValue();
$old = $transaction->getOldValue();
switch ($type) {
case ManiphestTransactionType::TYPE_TITLE:
$verb = 'Retitled';
$desc = 'changed the title from '.$this->renderString($old).
' to '.$this->renderString($new);
break;
case ManiphestTransactionType::TYPE_DESCRIPTION:
$verb = 'Edited';
if ($this->forEmail || $this->getRenderFullSummary()) {
$desc = 'updated the task description';
} else {
$desc = 'updated the task description; '.
$this->renderExpandLink($transaction);
}
break;
case ManiphestTransactionType::TYPE_NONE:
$verb = 'Commented On';
$desc = 'added a comment';
break;
case ManiphestTransactionType::TYPE_OWNER:
if ($transaction->getAuthorPHID() == $new) {
$verb = 'Claimed';
$desc = 'claimed this task';
$classes[] = 'claimed';
} else if (!$new) {
$verb = 'Up For Grabs';
$desc = 'placed this task up for grabs';
$classes[] = 'upforgrab';
} else if (!$old) {
$verb = 'Assigned';
$desc = 'assigned this task to '.$this->renderHandles(array($new));
$classes[] = 'assigned';
} else {
$verb = 'Reassigned';
$desc = 'reassigned this task from '.
$this->renderHandles(array($old)).
' to '.
$this->renderHandles(array($new));
$classes[] = 'reassigned';
}
break;
case ManiphestTransactionType::TYPE_CCS:
if ($this->preview) {
$verb = 'Changed CC';
$desc = 'changed CCs..';
break;
}
$added = array_diff($new, $old);
$removed = array_diff($old, $new);
if ($added && !$removed) {
$verb = 'Added CC';
if (count($added) == 1) {
$desc = 'added '.$this->renderHandles($added).' to CC';
} else {
$desc = 'added CCs: '.$this->renderHandles($added);
}
} else if ($removed && !$added) {
$verb = 'Removed CC';
if (count($removed) == 1) {
$desc = 'removed '.$this->renderHandles($removed).' from CC';
} else {
$desc = 'removed CCs: '.$this->renderHandles($removed);
}
} else {
$verb = 'Changed CC';
$desc = 'changed CCs, added: '.$this->renderHandles($added).'; '.
'removed: '.$this->renderHandles($removed);
}
break;
case ManiphestTransactionType::TYPE_PROJECTS:
if ($this->preview) {
$verb = 'Changed Projects';
$desc = 'changed projects..';
break;
}
$added = array_diff($new, $old);
$removed = array_diff($old, $new);
if ($added && !$removed) {
$verb = 'Added Project';
if (count($added) == 1) {
$desc = 'added project '.$this->renderHandles($added);
} else {
$desc = 'added projects: '.$this->renderHandles($added);
}
} else if ($removed && !$added) {
$verb = 'Removed Project';
if (count($removed) == 1) {
$desc = 'removed project '.$this->renderHandles($removed);
} else {
$desc = 'removed projectss: '.$this->renderHandles($removed);
}
} else {
$verb = 'Changed Projects';
$desc = 'changed projects, added: '.$this->renderHandles($added).'; '.
'removed: '.$this->renderHandles($removed);
}
break;
case ManiphestTransactionType::TYPE_STATUS:
if ($new == ManiphestTaskStatus::STATUS_OPEN) {
if ($old) {
$verb = 'Reopened';
$desc = 'reopened this task';
$classes[] = 'reopened';
} else {
$verb = 'Created';
$desc = 'created this task';
$classes[] = 'created';
}
} else if ($new == ManiphestTaskStatus::STATUS_CLOSED_SPITE) {
$verb = 'Spited';
$desc = 'closed this task out of spite';
$classes[] = 'spited';
} else if ($new == ManiphestTaskStatus::STATUS_CLOSED_DUPLICATE) {
$verb = 'Merged';
$desc = 'closed this task as a duplicate';
$classes[] = 'duplicate';
} else {
$verb = 'Closed';
$full = idx(ManiphestTaskStatus::getTaskStatusMap(), $new, '???');
$desc = 'closed this task as "'.$full.'"';
$classes[] = 'closed';
}
break;
case ManiphestTransactionType::TYPE_PRIORITY:
$old_name = ManiphestTaskPriority::getTaskPriorityName($old);
$new_name = ManiphestTaskPriority::getTaskPriorityName($new);
if ($old == ManiphestTaskPriority::PRIORITY_TRIAGE) {
$verb = 'Triaged';
$desc = 'triaged this task as "'.$new_name.'" priority';
} else if ($old > $new) {
$verb = 'Lowered Priority';
$desc = 'lowered the priority of this task from "'.$old_name.'" to '.
'"'.$new_name.'"';
} else {
$verb = 'Raised Priority';
$desc = 'raised the priority of this task from "'.$old_name.'" to '.
'"'.$new_name.'"';
}
if ($new == ManiphestTaskPriority::PRIORITY_UNBREAK_NOW) {
$classes[] = 'unbreaknow';
}
break;
case ManiphestTransactionType::TYPE_ATTACH:
if ($this->preview) {
$verb = 'Changed Attached';
$desc = 'changed attachments..';
break;
}
$old_raw = nonempty($old, array());
$new_raw = nonempty($new, array());
foreach (array(PhabricatorPHIDConstants::PHID_TYPE_DREV,
PhabricatorPHIDConstants::PHID_TYPE_FILE) as $type) {
$old = array_keys(idx($old_raw, $type, array()));
$new = array_keys(idx($new_raw, $type, array()));
if ($old != $new) {
break;
}
}
$added = array_diff($new, $old);
$removed = array_diff($old, $new);
$add_desc = $this->renderHandles($added);
$rem_desc = $this->renderHandles($removed);
switch ($type) {
case PhabricatorPHIDConstants::PHID_TYPE_DREV:
$singular = 'Differential Revision';
$plural = 'Differential Revisions';
break;
case PhabricatorPHIDConstants::PHID_TYPE_FILE:
$singular = 'file';
$plural = 'files';
break;
}
if ($added && !$removed) {
$verb = 'Attached';
if (count($added) == 1) {
$desc = 'attached '.$singular.': '.$add_desc;
} else {
$desc = 'attached '.$plural.': '.$add_desc;
}
} else if ($removed && !$added) {
$verb = 'Detached';
if (count($removed) == 1) {
$desc = 'detached '.$singular.': '.$rem_desc;
} else {
$desc = 'detached '.$plural.': '.$rem_desc;
}
} else {
$verb = 'Changed Attached';
$desc = 'changed attached '.$plural.', added: '.$add_desc.
'removed: '.$rem_desc;
}
break;
default:
return array($type, ' brazenly '.$type."'d", $classes);
}
return array($verb, $desc, $classes);
}
private function renderFullSummary($transaction) {
switch ($transaction->getTransactionType()) {
case ManiphestTransactionType::TYPE_DESCRIPTION:
$engine = $this->markupEngine;
$old = $transaction->getOldValue();
$new = $transaction->getNewValue();
$table =
'<table class="maniphest-change-table">
<tr>
<th>Previous Description</th>
<th>New Description</th>
</tr>
<tr>
<td>
<div class="phabricator-remarkup">'.
$engine->markupText($old).
'</div>
</td>
<td>
<div class="phabricator-remarkup">'.
$engine->markupText($new).
'</div>
</td>
</tr>
</table>';
return $table;
}
return null;
}
private function renderExpandLink($transaction) {
$id = $transaction->getID();
Javelin::initBehavior('maniphest-transaction-expand');
return javelin_render_tag(
'a',
array(
'href' => '/maniphest/task/descriptionchange/'.$id.'/',
'sigil' => 'maniphest-expand-transaction',
'mustcapture' => true,
),
'show details');
}
private function renderHandles($phids) {
$links = array();
foreach ($phids as $phid) {
if ($this->forEmail) {
$links[] = $this->handles[$phid]->getName();
} else {
$links[] = $this->handles[$phid]->renderLink();
}
}
return implode(', ', $links);
}
private function renderString($string) {
if ($this->forEmail) {
return '"'.$string.'"';
} else {
return '"'.phutil_escape_html($string).'"';
}
}
}
diff --git a/src/applications/maniphest/view/transactionlist/ManiphestTransactionListView.php b/src/applications/maniphest/view/transactionlist/ManiphestTransactionListView.php
index ef95eecb0b..f2a33a1235 100644
--- a/src/applications/maniphest/view/transactionlist/ManiphestTransactionListView.php
+++ b/src/applications/maniphest/view/transactionlist/ManiphestTransactionListView.php
@@ -1,97 +1,98 @@
<?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 ManiphestTransactionListView extends AphrontView {
private $transactions;
private $handles;
private $user;
private $markupEngine;
private $preview;
public function setTransactions(array $transactions) {
$this->transactions = $transactions;
return $this;
}
public function setHandles(array $handles) {
$this->handles = $handles;
return $this;
}
public function setUser(PhabricatorUser $user) {
$this->user = $user;
return $this;
}
public function setMarkupEngine(PhutilMarkupEngine $engine) {
$this->markupEngine = $engine;
return $this;
}
public function setPreview($preview) {
$this->preview = $preview;
return $this;
}
public function render() {
$views = array();
$last = null;
$group = array();
$groups = array();
foreach ($this->transactions as $transaction) {
if ($last === null) {
$last = $transaction;
$group[] = $transaction;
continue;
} else if ($last->canGroupWith($transaction)) {
$group[] = $transaction;
if ($transaction->hasComments()) {
$last = $transaction;
}
} else {
$groups[] = $group;
$last = $transaction;
$group = array($transaction);
}
}
if ($group) {
$groups[] = $group;
}
$sequence = 1;
foreach ($groups as $group) {
$view = new ManiphestTransactionDetailView();
+ $view->setUser($this->user);
$view->setTransactionGroup($group);
$view->setHandles($this->handles);
$view->setMarkupEngine($this->markupEngine);
$view->setPreview($this->preview);
$view->setCommentNumber($sequence++);
$views[] = $view->render();
}
return
'<div class="maniphest-transaction-list-view">'.
implode("\n", $views).
'</div>';
}
}
diff --git a/src/applications/metamta/controller/list/PhabricatorMetaMTAListController.php b/src/applications/metamta/controller/list/PhabricatorMetaMTAListController.php
index be4e328587..14904c65b1 100644
--- a/src/applications/metamta/controller/list/PhabricatorMetaMTAListController.php
+++ b/src/applications/metamta/controller/list/PhabricatorMetaMTAListController.php
@@ -1,112 +1,113 @@
<?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 PhabricatorMetaMTAListController extends PhabricatorMetaMTAController {
public function processRequest() {
// Get a page of mails together with pager.
$request = $this->getRequest();
+ $user = $request->getUser();
$offset = $request->getInt('offset', 0);
$related_phid = $request->getStr('phid');
$pager = new AphrontPagerView();
$pager->setOffset($offset);
$pager->setURI($request->getRequestURI(), 'offset');
$mail = new PhabricatorMetaMTAMail();
$conn_r = $mail->establishConnection('r');
if ($related_phid) {
$where_clause = qsprintf(
$conn_r,
'WHERE relatedPHID = %s',
$related_phid);
} else {
$where_clause = 'WHERE 1 = 1';
}
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T
%Q
ORDER BY id DESC
LIMIT %d, %d',
$mail->getTableName(),
$where_clause,
$pager->getOffset(), $pager->getPageSize() + 1);
$data = $pager->sliceResults($data);
$mails = $mail->loadAllFromArray($data);
// Render the details table.
$rows = array();
foreach ($mails as $mail) {
$rows[] = array(
PhabricatorMetaMTAMail::getReadableStatus($mail->getStatus()),
$mail->getRetryCount(),
($mail->getNextRetry() - time()).' s',
- date('Y-m-d g:i:s A', $mail->getDateCreated()),
+ phabricator_datetime($mail->getDateCreated(), $user),
(time() - $mail->getDateModified()).' s',
phutil_escape_html($mail->getSubject()),
phutil_render_tag(
'a',
array(
'class' => 'button small grey',
'href' => '/mail/view/'.$mail->getID().'/',
),
'View'),
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
'Status',
'Retry',
'Next',
'Created',
'Updated',
'Subject',
'',
));
$table->setColumnClasses(
array(
null,
null,
null,
null,
null,
'wide',
'action',
));
// Render the whole page.
$panel = new AphrontPanelView();
$panel->appendChild($table);
$panel->setHeader('MetaMTA Messages');
$panel->setCreateButton('Send New Message', '/mail/send/');
$panel->appendChild($pager);
return $this->buildStandardPageResponse(
$panel,
array(
'title' => 'MetaMTA',
'tab' => 'queue',
));
}
}
diff --git a/src/applications/metamta/controller/list/__init__.php b/src/applications/metamta/controller/list/__init__.php
index 49a41c7b7f..c83288dc45 100644
--- a/src/applications/metamta/controller/list/__init__.php
+++ b/src/applications/metamta/controller/list/__init__.php
@@ -1,20 +1,21 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/metamta/controller/base');
phutil_require_module('phabricator', 'applications/metamta/storage/mail');
phutil_require_module('phabricator', 'storage/qsprintf');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phabricator', 'view/control/pager');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phabricator', 'view/layout/panel');
+phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_source('PhabricatorMetaMTAListController.php');
diff --git a/src/view/utils/viewutils.php b/src/view/utils/viewutils.php
index 3c18d95154..97fc5c3cb3 100644
--- a/src/view/utils/viewutils.php
+++ b/src/view/utils/viewutils.php
@@ -1,110 +1,113 @@
<?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.
*/
function phabricator_date($epoch, $user) {
$zone = new DateTimeZone($user->getTimezoneIdentifier());
- $date = new DateTime('@'.$epoch, $zone);
+ $date = new DateTime('@'.$epoch);
+ $date->setTimeZone($zone);
return $date->format('M j Y');
}
function phabricator_time($epoch, $user) {
$zone = new DateTimeZone($user->getTimezoneIdentifier());
- $date = new DateTime('@'.$epoch, $zone);
+ $date = new DateTime('@'.$epoch);
+ $date->setTimeZone($zone);
return $date->format('g:i A');
}
function phabricator_datetime($epoch, $user) {
$zone = new DateTimeZone($user->getTimezoneIdentifier());
- $date = new DateTime('@'.$epoch, $zone);
+ $date = new DateTime('@'.$epoch);
+ $date->setTimeZone($zone);
return $date->format('M j Y, g:i A');
}
function phabricator_format_relative_time($duration) {
return phabricator_format_units_generic(
$duration,
array(60, 60, 24, 7),
array('s', 'm', 'h', 'd', 'w'),
$precision = 0);
}
function phabricator_format_timestamp($epoch) {
$difference = (time() - $epoch);
if ($difference < 0) {
$difference = -$difference;
$relative = 'from now';
} else {
$relative = 'ago';
}
if ($difference < 60 * 60 * 24) {
return phabricator_format_relative_time($difference).' '.$relative;
} else if (date('Y') == date('Y', $epoch)) {
return date('M j, g:i A', $epoch);
} else {
return date('F jS, Y', $epoch);
}
}
function phabricator_format_units_generic(
$n,
array $scales,
array $labels,
$precision = 0,
&$remainder = null) {
$is_negative = false;
if ($n < 0) {
$is_negative = true;
$n = abs($n);
}
$remainder = 0;
$accum = 1;
$scale = array_shift($scales);
$label = array_shift($labels);
while ($n > $scale && count($labels)) {
$remainder += ($n % $scale) * $accum;
$n /= $scale;
$accum *= $scale;
$label = array_shift($labels);
if (!count($scales)) {
break;
}
$scale = array_shift($scales);
}
if ($is_negative) {
$n = -$n;
$remainder = -$remainder;
}
if ($precision) {
$num_string = number_format($n, $precision);
} else {
$num_string = (int)floor($n);
}
if ($label) {
$num_string .= ' '.$label;
}
return $num_string;
}
diff --git a/webroot/rsrc/css/application/maniphest/task-summary.css b/webroot/rsrc/css/application/maniphest/task-summary.css
index a2bd5dcd1a..f9072a7788 100644
--- a/webroot/rsrc/css/application/maniphest/task-summary.css
+++ b/webroot/rsrc/css/application/maniphest/task-summary.css
@@ -1,87 +1,87 @@
/**
* @provides maniphest-task-summary-css
*/
.maniphest-task-summary {
border: solid #aaaaaa;
border-width: 1px 0;
width: 100%;
margin: 2px 0;
border-collapse: separate;
border-spacing: 0 0px;
}
.maniphest-task-summary td {
padding: 4px 0.5%;
background: #f0f0f0;
white-space: nowrap;
}
.maniphest-task-summary td.maniphest-task-number {
font-weight: bold;
color: #444444;
width: 1%;
min-width: 80px;
border-left-width: 3px;
border-left-style: solid;
}
.maniphest-task-summary td.maniphest-task-status {
width: 6%;
text-align: center;
min-width: 75px;
}
.maniphest-task-summary td.maniphest-task-owner {
width: 11%;
}
.maniphest-task-summary td.maniphest-task-name {
overflow: hidden;
font-weight: bold;
white-space: normal;
}
.maniphest-task-summary td.maniphest-task-priority {
width: 11%;
min-width: 120px;
}
.maniphest-task-summary td.maniphest-task-updated {
text-align: left;
- width: 11%;
- min-width: 120px;
+ width: 13%;
+ min-width: 160px;
}
.maniphest-task-summary .pri-bullet {
}
.maniphest-task-summary .pri-unbreak {
border-color: #ff0000;
}
.maniphest-task-summary .pri-triage {
border-color: #ee00ee;
}
.maniphest-task-summary .pri-high {
border-color: #ff6666;
}
.maniphest-task-summary .pri-normal {
border-color: #ffaa66;
}
.maniphest-task-summary .pri-low {
border-color: #eecc66;
}
.maniphest-task-summary .pri-wish {
border-color: #0099ff;
}
.maniphest-task-group-header {
font-size: 18px;
margin: 1.5em 14px 0;
border-bottom: 1px solid #dddddd;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Feb 20, 23:36 (3 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1164512
Default Alt Text
(132 KB)

Event Timeline