diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index fc506ddcb2..7cdef0e7aa 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -1,1282 +1,1282 @@ 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/71783633/rsrc/css/aphront/headsup-action-list-view.css', + 'uri' => '/res/b7c6bbc2/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/2a59525c/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/dd6b4ca9/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/dfa0f979/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/12d4d90d/rsrc/js/application/core/behavior-object-selector.js', + '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', 'type' => 'css', 'requires' => array( ), 'disk' => '/rsrc/css/application/maniphest/task-summary.css', ), 'maniphest-transaction-detail-css' => array( - 'uri' => '/res/7ee02b5e/rsrc/css/application/maniphest/transaction-detail.css', + '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/14f11fd3/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/ced4098a/rsrc/css/application/objectselector/object-selector.css', + 'uri' => '/res/62a8fd92/rsrc/css/application/objectselector/object-selector.css', 'type' => 'css', 'requires' => array( 0 => 'aphront-dialog-view-css', ), 'disk' => '/rsrc/css/application/objectselector/object-selector.css', ), 'phabricator-profile-css' => array( 'uri' => '/res/adcdb5f3/rsrc/css/application/people/profile.css', 'type' => 'css', 'requires' => array( ), 'disk' => '/rsrc/css/application/people/profile.css', ), 'phabricator-remarkup-css' => array( 'uri' => '/res/774d4078/rsrc/css/core/remarkup.css', 'type' => 'css', 'requires' => array( ), 'disk' => '/rsrc/css/core/remarkup.css', ), 'phabricator-shaped-request' => array( 'uri' => '/res/d7ba774e/rsrc/js/application/core/ShapedRequest.js', 'type' => 'js', 'requires' => array( 0 => 'javelin-install', 1 => 'javelin-util', 2 => 'javelin-request', ), 'disk' => '/rsrc/js/application/core/ShapedRequest.js', ), 'phabricator-standard-page-view' => array( 'uri' => '/res/453bd261/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', ), '861d7db0' => 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/861d7db0/workflow.pkg.js', 'type' => 'js', ), '8f3a55d1' => 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/8f3a55d1/differential.pkg.css', 'type' => 'css', ), 'acfddc38' => 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/acfddc38/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', ), ), 'reverse' => array ( 'aphront-crumbs-view-css' => 'acfddc38', 'aphront-dialog-view-css' => 'acfddc38', 'aphront-form-view-css' => 'acfddc38', 'aphront-list-filter-view-css' => 'acfddc38', 'aphront-panel-view-css' => 'acfddc38', 'aphront-side-nav-view-css' => 'acfddc38', 'aphront-table-view-css' => 'acfddc38', 'aphront-tokenizer-control-css' => 'acfddc38', 'aphront-typeahead-control-css' => 'acfddc38', 'differential-changeset-view-css' => '8f3a55d1', 'differential-core-view-css' => '8f3a55d1', 'differential-revision-add-comment-css' => '8f3a55d1', 'differential-revision-comment-css' => '8f3a55d1', 'differential-revision-comment-list-css' => '8f3a55d1', 'differential-revision-detail-css' => '8f3a55d1', 'differential-revision-history-css' => '8f3a55d1', 'differential-table-of-contents-css' => '8f3a55d1', 'diffusion-commit-view-css' => '03ef179e', 'javelin-behavior' => 'db95a6d0', 'javelin-behavior-aphront-basic-tokenizer' => '2892314d', 'javelin-behavior-aphront-form-disable-on-submit' => '861d7db0', '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' => '861d7db0', 'javelin-behavior-workflow' => '861d7db0', 'javelin-dom' => 'db95a6d0', 'javelin-event' => 'db95a6d0', 'javelin-install' => 'db95a6d0', 'javelin-json' => 'db95a6d0', 'javelin-mask' => '861d7db0', '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' => '861d7db0', 'phabricator-core-buttons-css' => 'acfddc38', 'phabricator-core-css' => 'acfddc38', 'phabricator-directory-css' => 'acfddc38', 'phabricator-keyboard-shortcut' => '861d7db0', 'phabricator-keyboard-shortcut-manager' => '861d7db0', 'phabricator-remarkup-css' => 'acfddc38', 'phabricator-standard-page-view' => 'acfddc38', 'syntax-highlighting-css' => 'acfddc38', ), )); diff --git a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php index 0c760ba249..1a6611d623 100644 --- a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php +++ b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php @@ -1,444 +1,444 @@ getResourceURIMapRules() + array( '/' => array( '$' => 'PhabricatorDirectoryMainController', ), '/directory/' => array( 'item/$' => 'PhabricatorDirectoryItemListController', 'item/edit/(?:(?P\d+)/)?$' => 'PhabricatorDirectoryItemEditController', 'item/delete/(?P\d+)/' => 'PhabricatorDirectoryItemDeleteController', 'category/$' => 'PhabricatorDirectoryCategoryListController', 'category/edit/(?:(?P\d+)/)?$' => 'PhabricatorDirectoryCategoryEditController', 'category/delete/(?P\d+)/' => 'PhabricatorDirectoryCategoryDeleteController', ), '/file/' => array( '$' => 'PhabricatorFileListController', 'upload/$' => 'PhabricatorFileUploadController', 'dropupload/$' => 'PhabricatorFileDropUploadController', '(?Pinfo)/(?P[^/]+)/' => 'PhabricatorFileViewController', '(?Pview)/(?P[^/]+)/' => 'PhabricatorFileViewController', '(?Pdownload)/(?P[^/]+)/' => 'PhabricatorFileViewController', 'macro/' => array( '$' => 'PhabricatorFileMacroListController', 'edit/(?:(?P\d+)/)?$' => 'PhabricatorFileMacroEditController', 'delete/(?P\d+)/$' => 'PhabricatorFileMacroDeleteController', ), 'proxy/$' => 'PhabricatorFileProxyController', 'xform/(?P[^/]+)/(?P[^/]+)/' => 'PhabricatorFileTransformController', ), '/phid/' => array( '$' => 'PhabricatorPHIDLookupController', 'list/$' => 'PhabricatorPHIDListController', 'new/$' => 'PhabricatorPHIDAllocateController', ), '/people/' => array( '$' => 'PhabricatorPeopleListController', 'logs/$' => 'PhabricatorPeopleLogsController', 'edit/(?:(?P\d+)/(?:(?P\w+)/)?)?$' => 'PhabricatorPeopleEditController', ), '/p/(?P\w+)/$' => 'PhabricatorPeopleProfileController', '/profile/' => array( 'edit/$' => 'PhabricatorPeopleProfileEditController', ), '/conduit/' => array( '$' => 'PhabricatorConduitConsoleController', 'method/(?P[^/]+)$' => 'PhabricatorConduitConsoleController', 'log/$' => 'PhabricatorConduitLogController', ), '/api/(?P[^/]+)$' => 'PhabricatorConduitAPIController', '/D(?P\d+)' => 'DifferentialRevisionViewController', '/differential/' => array( '$' => 'DifferentialRevisionListController', 'filter/(?P\w+)/$' => 'DifferentialRevisionListController', 'diff/' => array( '(?P\d+)/$' => 'DifferentialDiffViewController', 'create/$' => 'DifferentialDiffCreateController', ), 'changeset/$' => 'DifferentialChangesetViewController', 'revision/edit/(?:(?P\d+)/)?$' => 'DifferentialRevisionEditController', 'comment/' => array( 'preview/(?P\d+)/$' => 'DifferentialCommentPreviewController', 'save/$' => 'DifferentialCommentSaveController', 'inline/' => array( 'preview/(?P\d+)/$' => 'DifferentialInlineCommentPreviewController', 'edit/(?P\d+)/$' => 'DifferentialInlineCommentEditController', ), ), 'subscribe/(?Padd|rem)/(?P\d+)/$' => 'DifferentialSubscribeController', ), '/typeahead/' => array( 'common/(?P\w+)/$' => 'PhabricatorTypeaheadCommonDatasourceController', ), '/mail/' => array( '$' => 'PhabricatorMetaMTAListController', 'send/$' => 'PhabricatorMetaMTASendController', 'view/(?P\d+)/$' => 'PhabricatorMetaMTAViewController', 'lists/$' => 'PhabricatorMetaMTAMailingListsController', 'lists/edit/(?:(?P\d+)/)?$' => 'PhabricatorMetaMTAMailingListEditController', 'receive/$' => 'PhabricatorMetaMTAReceiveController', 'received/$' => 'PhabricatorMetaMTAReceivedListController', 'sendgrid/$' => 'PhabricatorMetaMTASendGridReceiveController', ), '/login/' => array( '$' => 'PhabricatorLoginController', 'email/$' => 'PhabricatorEmailLoginController', 'etoken/(?P\w+)/$' => 'PhabricatorEmailTokenController', ), '/logout/$' => 'PhabricatorLogoutController', '/oauth/' => array( '(?Pgithub|facebook)/' => array( 'login/$' => 'PhabricatorOAuthLoginController', 'diagnose/$' => 'PhabricatorOAuthDiagnosticsController', 'unlink/$' => 'PhabricatorOAuthUnlinkController', ), ), '/xhprof/' => array( 'profile/(?P[^/]+)/$' => 'PhabricatorXHProfProfileController', ), '/~/' => 'DarkConsoleController', '/settings/' => array( '(?:page/(?P[^/]+)/)?$' => 'PhabricatorUserSettingsController', ), '/maniphest/' => array( '$' => 'ManiphestTaskListController', 'view/(?P\w+)/$' => 'ManiphestTaskListController', 'task/' => array( 'create/$' => 'ManiphestTaskEditController', 'edit/(?P\d+)/$' => 'ManiphestTaskEditController', 'descriptionchange/(?P\d+)/$' => 'ManiphestTaskDescriptionChangeController', ), 'transaction/' => array( 'save/' => 'ManiphestTransactionSaveController', 'preview/(?P\d+)/$' => 'ManiphestTransactionPreviewController', ), ), '/T(?P\d+)$' => 'ManiphestTaskDetailController', '/github-post-receive/(?P\d+)/(?P[^/]+)/$' => 'PhabricatorRepositoryGitHubPostReceiveController', '/repository/' => array( '$' => 'PhabricatorRepositoryListController', 'create/$' => 'PhabricatorRepositoryCreateController', 'edit/(?P\d+)/(?:(?P\w+)?/)?$' => 'PhabricatorRepositoryEditController', 'delete/(?P\d+)/$' => 'PhabricatorRepositoryDeleteController', 'project/(?P\d+)/' => 'PhabricatorRepositoryArcanistProjectEditController', ), '/search/' => array( '$' => 'PhabricatorSearchController', '(?P\d+)/$' => 'PhabricatorSearchController', - 'attach/(?P[^/]+)/(?P\w+)/$' + 'attach/(?P[^/]+)/(?P\w+)/(?:(?P\w+)/)?$' => 'PhabricatorSearchAttachController', 'select/(?P\w+)/$' => 'PhabricatorSearchSelectController', ), '/project/' => array( '$' => 'PhabricatorProjectListController', 'edit/(?:(?P\d+)/)?$' => 'PhabricatorProjectEditController', 'view/(?P\d+)/$' => 'PhabricatorProjectProfileController', 'affiliation/(?P\d+)/$' => 'PhabricatorProjectAffiliationEditController', 'quickcreate/$' => 'PhabricatorProjectQuickCreateController', ), '/r(?P[A-Z]+)(?P[a-z0-9]+)$' => 'DiffusionCommitController', '/diffusion/' => array( '$' => 'DiffusionHomeController', '(?P[A-Z]+)/' => array( '$' => 'DiffusionRepositoryController', 'repository/'. '(?P[^/]+)/'. '$' => 'DiffusionRepositoryController', 'change/'. '(?P.*?)'. '(?:[;](?P[a-z0-9]+))?'. '$' => 'DiffusionChangeController', 'history/'. '(?P.*?)'. '(?:[;](?P[a-z0-9]+))?'. '$' => 'DiffusionHistoryController', 'browse/'. '(?P.*?)'. '(?:[;](?P[a-z0-9]+))?'. '(?:[$](?P\d+))?'. '$' => 'DiffusionBrowseController', 'diff/'. '(?P.*?)'. '(?:[;](?P[a-z0-9]+))?'. '$' => 'DiffusionDiffController', 'lastmodified/'. '(?P.*?)'. '(?:[;](?P[a-z0-9]+))?'. '$' => 'DiffusionLastModifiedController', ), 'services/' => array( 'path/' => array( 'complete/$' => 'DiffusionPathCompleteController', 'validate/$' => 'DiffusionPathValidateController', ), ), ), '/daemon/' => array( 'task/(?P\d+)/$' => 'PhabricatorWorkerTaskDetailController', 'log/' => array( '$' => 'PhabricatorDaemonLogListController', 'combined/$' => 'PhabricatorDaemonCombinedLogController', '(?P\d+)/$' => 'PhabricatorDaemonLogViewController', ), 'timeline/$' => 'PhabricatorDaemonTimelineConsoleController', 'timeline/(?P\d+)/$' => 'PhabricatorDaemonTimelineEventController', '$' => 'PhabricatorDaemonConsoleController', ), '/herald/' => array( '$' => 'HeraldHomeController', 'view/(?P[^/]+)/$' => 'HeraldHomeController', 'new/(?:(?P[^/]+)/)?$' => 'HeraldNewController', 'rule/(?:(?P\d+)/)?$' => 'HeraldRuleController', 'delete/(?P\d+)/$' => 'HeraldDeleteController', 'test/$' => 'HeraldTestConsoleController', 'transcript/$' => 'HeraldTranscriptListController', 'transcript/(?P\d+)/(?:(?P\w+)/)?$' => 'HeraldTranscriptController', ), '/preferences/' => array( '$' => 'PhabricatorEditPreferencesController' ), '/uiexample/' => array( '$' => 'PhabricatorUIExampleRenderController', 'view/(?P[^/]+)/$' => 'PhabricatorUIExampleRenderController', ), '/owners/' => array( '$' => 'PhabricatorOwnersListController', 'view/(?P[^/]+)/$' => 'PhabricatorOwnersListController', 'edit/(?P\d+)/$' => 'PhabricatorOwnersEditController', 'new/$' => 'PhabricatorOwnersEditController', 'package/(?P\d+)/$' => 'PhabricatorOwnersDetailController', 'delete/(?P\d+)/$' => 'PhabricatorOwnersDeleteController', ), '/xhpast/' => array( '$' => 'PhabricatorXHPASTViewRunController', 'view/(?P\d+)/$' => 'PhabricatorXHPASTViewFrameController', 'frameset/(?P\d+)/$' => 'PhabricatorXHPASTViewFramesetController', 'input/(?P\d+)/$' => 'PhabricatorXHPASTViewInputController', 'tree/(?P\d+)/$' => 'PhabricatorXHPASTViewTreeController', 'stream/(?P\d+)/$' => 'PhabricatorXHPASTViewStreamController', ), '/status/$' => 'PhabricatorStatusController', '/paste/' => array( '$' => 'PhabricatorPasteCreateController', 'list/' => 'PhabricatorPasteListController', ), '/P(?P\d+)$' => 'PhabricatorPasteViewController', '/help/' => array( 'keyboardshortcut/$' => 'PhabricatorHelpKeyboardShortcutController', ), '/countdown/' => array( '$' => 'PhabricatorCountdownListController', '(?P\d+)/$' => 'PhabricatorCountdownViewController', 'edit/(?:(?P\d+)/)?$' => 'PhabricatorCountdownEditController', 'delete/(?P\d+)/$' => 'PhabricatorCountdownDeleteController' ), ); } protected function getResourceURIMapRules() { return array( '/res/' => array( '(?Ppkg/)?(?P[a-f0-9]{8})/(?P.+\.(?:css|js))$' => 'CelerityResourceController', ), ); } public function buildRequest() { $request = new AphrontRequest($this->getHost(), $this->getPath()); $request->setRequestData($_GET + $_POST); $request->setApplicationConfiguration($this); return $request; } public function handleException(Exception $ex) { // Always log the unhandled exception. phlog($ex); $class = phutil_escape_html(get_class($ex)); $message = phutil_escape_html($ex->getMessage()); $content = '
'. '

Unhandled Exception "'.$class.'": '.$message.'

'. ''.phutil_escape_html((string)$ex).''. '
'; $user = $this->getRequest()->getUser(); if (!$user) { // If we hit an exception very early, we won't have a user. $user = new PhabricatorUser(); } $dialog = new AphrontDialogView(); $dialog ->setTitle('Exception!') ->setClass('aphront-exception-dialog') ->setUser($user) ->appendChild($content) ->addCancelButton('/'); $response = new AphrontDialogResponse(); $response->setDialog($dialog); return $response; } public function willSendResponse(AphrontResponse $response) { $request = $this->getRequest(); $response->setRequest($request); if ($response instanceof AphrontDialogResponse) { if (!$request->isAjax()) { $view = new PhabricatorStandardPageView(); $view->setRequest($request); $view->appendChild( '
'. $response->buildResponseString(). '
'); $response = new AphrontWebpageResponse(); $response->setContent($view->render()); return $response; } else { return id(new AphrontAjaxResponse()) ->setContent(array( 'dialog' => $response->buildResponseString(), )); } } else if ($response instanceof AphrontRedirectResponse) { if ($request->isAjax()) { return id(new AphrontAjaxResponse()) ->setContent( array( 'redirect' => $response->getURI(), )); } } else if ($response instanceof Aphront404Response) { $failure = new AphrontRequestFailureView(); $failure->setHeader('404 Not Found'); $failure->appendChild( '

The page you requested was not found.

'); $view = new PhabricatorStandardPageView(); $view->setTitle('404 Not Found'); $view->setRequest($this->getRequest()); $view->appendChild($failure); $response = new AphrontWebpageResponse(); $response->setContent($view->render()); $response->setHTTPResponseCode(404); return $response; } return $response; } public function build404Controller() { return array(new Phabricator404Controller($this->getRequest()), array()); } public function buildRedirectController($uri) { return array( new PhabricatorRedirectController($this->getRequest()), array( 'uri' => $uri, )); } } diff --git a/src/applications/maniphest/controller/taskdetail/ManiphestTaskDetailController.php b/src/applications/maniphest/controller/taskdetail/ManiphestTaskDetailController.php index 9de54238a5..f90bd36843 100644 --- a/src/applications/maniphest/controller/taskdetail/ManiphestTaskDetailController.php +++ b/src/applications/maniphest/controller/taskdetail/ManiphestTaskDetailController.php @@ -1,381 +1,388 @@ id = $data['id']; } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $e_title = null; $priority_map = ManiphestTaskPriority::getTaskPriorityMap(); $task = id(new ManiphestTask())->load($this->id); if (!$task) { return new Aphront404Response(); } $transactions = id(new ManiphestTransaction())->loadAllWhere( 'taskID = %d ORDER BY id ASC', $task->getID()); $phids = array(); foreach ($transactions as $transaction) { foreach ($transaction->extractPHIDs() as $phid) { $phids[$phid] = true; } } foreach ($task->getCCPHIDs() as $phid) { $phids[$phid] = true; } foreach ($task->getProjectPHIDs() as $phid) { $phids[$phid] = true; } if ($task->getOwnerPHID()) { $phids[$task->getOwnerPHID()] = true; } $phids[$task->getAuthorPHID()] = true; $phids = array_keys($phids); $attached = $task->getAttached(); foreach ($attached as $type => $list) { foreach ($list as $phid => $info) { $phids[$phid] = true; } } $handles = id(new PhabricatorObjectHandleData($phids)) ->loadHandles(); $factory = new DifferentialMarkupEngineFactory(); $engine = $factory->newDifferentialCommentMarkupEngine(); $dict = array(); $dict['Status'] = ''. ManiphestTaskStatus::getTaskStatusFullName($task->getStatus()). ''; $dict['Assigned To'] = $task->getOwnerPHID() ? $handles[$task->getOwnerPHID()]->renderLink() : 'None'; $dict['Priority'] = ManiphestTaskPriority::getTaskPriorityName( $task->getPriority()); $cc = $task->getCCPHIDs(); if ($cc) { $cc_links = array(); foreach ($cc as $phid) { $cc_links[] = $handles[$phid]->renderLink(); } $dict['CC'] = implode(', ', $cc_links); } else { $dict['CC'] = 'None'; } $dict['Author'] = $handles[$task->getAuthorPHID()]->renderLink(); $projects = $task->getProjectPHIDs(); if ($projects) { $project_links = array(); foreach ($projects as $phid) { $project_links[] = $handles[$phid]->renderLink(); } $dict['Projects'] = implode(', ', $project_links); } else { $dict['Projects'] = 'None'; } if (idx($attached, PhabricatorPHIDConstants::PHID_TYPE_DREV)) { $revs = idx($attached, PhabricatorPHIDConstants::PHID_TYPE_DREV); $rev_links = array(); foreach ($revs as $rev => $info) { $rev_links[] = $handles[$rev]->renderLink(); } $rev_links = implode(', ', $rev_links); $dict['Revisions'] = $rev_links; } if (idx($attached, PhabricatorPHIDConstants::PHID_TYPE_FILE)) { $file_infos = idx($attached, PhabricatorPHIDConstants::PHID_TYPE_FILE); $file_phids = array_keys($file_infos); if ($file_phids) { $files = id(new PhabricatorFile())->loadAllWhere( 'phid IN (%Ls)', $file_phids); $views = array(); foreach ($files as $file) { $view = new AphrontFilePreviewView(); $view->setFile($file); $views[] = $view->render(); } $dict['Files'] = implode('', $views); } } $dict['Description'] = '
'. '
'. $engine->markupText($task->getDescription()). '
'. '
'; require_celerity_resource('mainphest-task-detail-css'); $table = array(); foreach ($dict as $key => $value) { $table[] = ''. ''.phutil_escape_html($key).':'. ''.$value.''. ''; } $table = ''. implode("\n", $table). '
'; $actions = array(); $action = new AphrontHeadsupActionView(); $action->setName('Edit Task'); $action->setURI('/maniphest/task/edit/'.$task->getID().'/'); $action->setClass('action-edit'); $actions[] = $action; require_celerity_resource('phabricator-object-selector-css'); require_celerity_resource('javelin-behavior-phabricator-object-selector'); + $action = new AphrontHeadsupActionView(); + $action->setName('Merge Duplicates'); + $action->setURI('/search/attach/'.$task->getPHID().'/TASK/merge/'); + $action->setWorkflow(true); + $action->setClass('action-merge'); + $actions[] = $action; + $action = new AphrontHeadsupActionView(); $action->setName('Edit Differential Revisions'); $action->setURI('/search/attach/'.$task->getPHID().'/DREV/'); $action->setWorkflow(true); $action->setClass('action-attach'); $actions[] = $action; $action_list = new AphrontHeadsupActionListView(); $action_list->setActions($actions); $panel = '
'. $action_list->render(). '
'. '

'. phutil_escape_html('T'.$task->getID().' '.$task->getTitle()). '

'. $table. '
'. '
'; $transaction_types = ManiphestTransactionType::getTransactionTypeMap(); $resolution_types = ManiphestTaskStatus::getTaskStatusMap(); if ($task->getStatus() == ManiphestTaskStatus::STATUS_OPEN) { $resolution_types = array_select_keys( $resolution_types, array( ManiphestTaskStatus::STATUS_CLOSED_RESOLVED, ManiphestTaskStatus::STATUS_CLOSED_WONTFIX, ManiphestTaskStatus::STATUS_CLOSED_INVALID, ManiphestTaskStatus::STATUS_CLOSED_SPITE, )); } else { $resolution_types = array( ManiphestTaskStatus::STATUS_OPEN => 'Reopened', ); $transaction_types[ManiphestTransactionType::TYPE_STATUS] = 'Reopen Task'; unset($transaction_types[ManiphestTransactionType::TYPE_PRIORITY]); unset($transaction_types[ManiphestTransactionType::TYPE_OWNER]); } $default_claim = array( $user->getPHID() => $user->getUsername().' ('.$user->getRealName().')', ); $draft = id(new PhabricatorDraft())->loadOneWhere( 'authorPHID = %s AND draftKey = %s', $user->getPHID(), $task->getPHID()); if ($draft) { $draft_text = $draft->getDraft(); } else { $draft_text = null; } $panel_id = celerity_generate_unique_node_id(); $comment_form = new AphrontFormView(); $comment_form ->setUser($user) ->setAction('/maniphest/transaction/save/') ->setEncType('multipart/form-data') ->addHiddenInput('taskID', $task->getID()) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel('Action') ->setName('action') ->setOptions($transaction_types) ->setID('transaction-action')) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel('Resolution') ->setName('resolution') ->setControlID('resolution') ->setControlStyle('display: none') ->setOptions($resolution_types)) ->appendChild( id(new AphrontFormTokenizerControl()) ->setLabel('Assign To') ->setName('assign_to') ->setControlID('assign_to') ->setControlStyle('display: none') ->setID('assign-tokenizer') ->setDisableBehavior(true)) ->appendChild( id(new AphrontFormTokenizerControl()) ->setLabel('CCs') ->setName('ccs') ->setControlID('ccs') ->setControlStyle('display: none') ->setID('cc-tokenizer') ->setDisableBehavior(true)) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel('Priority') ->setName('priority') ->setOptions($priority_map) ->setControlID('priority') ->setControlStyle('display: none') ->setValue($task->getPriority())) ->appendChild( id(new AphrontFormTokenizerControl()) ->setLabel('Projects') ->setName('projects') ->setControlID('projects') ->setControlStyle('display: none') ->setID('projects-tokenizer') ->setDisableBehavior(true)) ->appendChild( id(new AphrontFormFileControl()) ->setLabel('File') ->setName('file') ->setControlID('file') ->setControlStyle('display: none')) ->appendChild( id(new AphrontFormTextAreaControl()) ->setLabel('Comments') ->setName('comments') ->setValue($draft_text) ->setID('transaction-comments')) ->appendChild( id(new AphrontFormDragAndDropUploadControl()) ->setLabel('Attached Files') ->setName('files') ->setDragAndDropTarget($panel_id) ->setActivatedClass('aphront-panel-view-drag-and-drop')) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue('Avast!')); $control_map = array( ManiphestTransactionType::TYPE_STATUS => 'resolution', ManiphestTransactionType::TYPE_OWNER => 'assign_to', ManiphestTransactionType::TYPE_CCS => 'ccs', ManiphestTransactionType::TYPE_PRIORITY => 'priority', ManiphestTransactionType::TYPE_PROJECTS => 'projects', ManiphestTransactionType::TYPE_ATTACH => 'file', ); Javelin::initBehavior('maniphest-transaction-controls', array( 'select' => 'transaction-action', 'controlMap' => $control_map, 'tokenizers' => array( ManiphestTransactionType::TYPE_PROJECTS => array( 'id' => 'projects-tokenizer', 'src' => '/typeahead/common/projects/', ), ManiphestTransactionType::TYPE_OWNER => array( 'id' => 'assign-tokenizer', 'src' => '/typeahead/common/users/', 'value' => $default_claim, 'limit' => 1, ), ManiphestTransactionType::TYPE_CCS => array( 'id' => 'cc-tokenizer', 'src' => '/typeahead/common/mailable/', ), ), )); Javelin::initBehavior('maniphest-transaction-preview', array( 'uri' => '/maniphest/transaction/preview/'.$task->getID().'/', 'preview' => 'transaction-preview', 'comments' => 'transaction-comments', 'action' => 'transaction-action', 'map' => $control_map, )); $comment_panel = new AphrontPanelView(); $comment_panel->appendChild($comment_form); $comment_panel->setID($panel_id); $comment_panel->addClass('aphront-panel-accent'); $comment_panel->setHeader('Weigh In'); $preview_panel = '
Loading preview...
'; $transaction_view = new ManiphestTransactionListView(); $transaction_view->setTransactions($transactions); $transaction_view->setHandles($handles); $transaction_view->setUser($user); $transaction_view->setMarkupEngine($engine); return $this->buildStandardPageResponse( array( $panel, $transaction_view, $comment_panel, $preview_panel, ), array( 'title' => 'T'.$task->getID().' '.$task->getTitle(), )); } } diff --git a/src/applications/maniphest/view/transactiondetail/ManiphestTransactionDetailView.php b/src/applications/maniphest/view/transactiondetail/ManiphestTransactionDetailView.php index a2fff50384..f702a04125 100644 --- a/src/applications/maniphest/view/transactiondetail/ManiphestTransactionDetailView.php +++ b/src/applications/maniphest/view/transactiondetail/ManiphestTransactionDetailView.php @@ -1,557 +1,561 @@ 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 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; } $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() { $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 = '
'. $comments. '
'; } else { $comment_block = null; } if ($this->preview) { $timestamp = 'COMMENT PREVIEW'; } else { $timestamp = phabricator_format_timestamp($transaction->getDateCreated()); } $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(' · ', $info); return phutil_render_tag( 'div', array( 'class' => "maniphest-transaction-detail-container", 'style' => "background-image: url('".$author->getImageURI()."')", 'id' => $comment_anchor, ), '
'. '
'. '
'. $info. '
'. $descs. '
'. $comment_block. '
'); } 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 = '
Previous Description New Description
'. $engine->markupText($old). '
'. $engine->markupText($new). '
'; return $table; } return null; } private function renderExpandLink($transaction) { $id = $transaction->getID(); Javelin::initBehavior('maniphest-transaction-expand'); return javelin_render_tag( 'a', array( 'href' => '/maniphest/task/descriptionchange/'.$id.'/', 'sigil' => 'maniphest-expand-transaction', 'mustcapture' => true, ), 'show details'); } private function renderHandles($phids) { $links = array(); foreach ($phids as $phid) { 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/search/controller/attach/PhabricatorSearchAttachController.php b/src/applications/search/controller/attach/PhabricatorSearchAttachController.php index 17fc363c5a..0ec5c95457 100644 --- a/src/applications/search/controller/attach/PhabricatorSearchAttachController.php +++ b/src/applications/search/controller/attach/PhabricatorSearchAttachController.php @@ -1,199 +1,305 @@ phid = $data['phid']; $this->type = $data['type']; + $this->action = idx($data, 'action', self::ACTION_ATTACH); } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $handles = id(new PhabricatorObjectHandleData(array($this->phid))) ->loadHandles(); $handle = $handles[$this->phid]; $object_phid = $this->phid; $object_type = $handle->getType(); $attach_type = $this->type; - // Load the object we're going to attach/detach stuff from. This is the // object that triggered the action, e.g. the revision you clicked // "Edit Maniphest Tasks" on. $object = null; switch ($object_type) { case PhabricatorPHIDConstants::PHID_TYPE_DREV: $object = id(new DifferentialRevision())->loadOneWhere( 'phid = %s', $this->phid); break; case PhabricatorPHIDConstants::PHID_TYPE_TASK: $object = id(new ManiphestTask())->loadOneWhere( 'phid = %s', $this->phid); break; } if (!$object) { return new Aphront404Response(); } if ($request->isFormPost()) { $phids = explode(';', $request->getStr('phids')); $phids = array_filter($phids); $phids = array_values($phids); + + switch ($this->action) { + case self::ACTION_MERGE: + return $this->performMerge($object, $handle, $phids); + case self::ACTION_ATTACH: + // Fall through to the workflow below. + break; + default: + throw new Exception("Unsupported attach action."); + } + // sort() so that removing [X, Y] and then adding [Y, X] is correctly // detected as a no-op. sort($phids); $old_phids = $object->getAttachedPHIDs($attach_type); sort($old_phids); if (($phids || $old_phids) && ($phids !== $old_phids)) { // Load all the objects we're attaching or detaching from the main // object. switch ($attach_type) { case PhabricatorPHIDConstants::PHID_TYPE_DREV: $attach_objs = id(new DifferentialRevision())->loadAllWhere( 'phid IN (%Ls)', array_merge($phids, $old_phids)); break; case PhabricatorPHIDConstants::PHID_TYPE_TASK: $attach_objs = id(new ManiphestTask())->loadAllWhere( 'phid IN (%Ls)', array_merge($phids, $old_phids)); break; } $attach_objs = mpull($attach_objs, null, 'getPHID'); // Remove PHIDs which don't actually exist, to prevent silliness. $phids = array_keys(array_select_keys($attach_objs, $phids)); if ($phids) { $phids = array_combine($phids, $phids); } // Update the primary object. switch ($object_type) { case PhabricatorPHIDConstants::PHID_TYPE_DREV: $object->setAttachedPHIDs($attach_type, $phids); $object->save(); break; case PhabricatorPHIDConstants::PHID_TYPE_TASK: $this->applyTaskTransaction( $object, $attach_type, $phids); break; } // Loop through all of the attached/detached objects and update them. foreach ($attach_objs as $phid => $attach_obj) { $attached_phids = $attach_obj->getAttachedPHIDs($object_type); // Figure out if we're attaching or detaching this object. if (isset($phids[$phid])) { $attached_phids[] = $object_phid; } else { $attached_phids = array_fill_keys($attached_phids, true); unset($attached_phids[$object_phid]); $attached_phids = array_keys($attached_phids); } switch ($attach_type) { case PhabricatorPHIDConstants::PHID_TYPE_DREV: $attach_obj->setAttachedPHIDs($object_type, $attached_phids); $attach_obj->save(); break; case PhabricatorPHIDConstants::PHID_TYPE_TASK: $this->applyTaskTransaction( $attach_obj, $object_type, $attached_phids); break; } } } return id(new AphrontReloadResponse())->setURI($handle->getURI()); } else { - $phids = $object->getAttachedPHIDs($attach_type); + switch ($this->action) { + case self::ACTION_ATTACH: + $phids = $object->getAttachedPHIDs($attach_type); + break; + default: + $phids = array(); + break; + } } - switch ($attach_type) { + switch ($this->type) { case PhabricatorPHIDConstants::PHID_TYPE_DREV: $noun = 'Revisions'; $selected = 'created'; break; case PhabricatorPHIDConstants::PHID_TYPE_TASK: $noun = 'Tasks'; $selected = 'assigned'; break; } + switch ($this->action) { + case self::ACTION_ATTACH: + $dialog_title = "Manage Attached {$noun}"; + $header_text = "Currently Attached {$noun}"; + $button_text = "Save {$noun}"; + $instructions = null; + break; + case self::ACTION_MERGE: + $dialog_title = "Merge Duplicate Tasks"; + $header_text = "Tasks To Merge"; + $button_text = "Merge {$noun}"; + $instructions = + "These tasks will be merged into the current task and then closed. ". + "The current task (\"".phutil_escape_html($handle->getName())."\") ". + "will grow stronger."; + break; + } + $handles = id(new PhabricatorObjectHandleData($phids)) ->loadHandles(); $obj_dialog = new PhabricatorObjectSelectorDialog(); $obj_dialog ->setUser($user) ->setHandles($handles) ->setFilters(array( 'assigned' => 'Assigned to Me', 'created' => 'Created By Me', 'open' => 'All Open '.$noun, 'all' => 'All '.$noun, )) ->setSelectedFilter($selected) ->setCancelURI($handle->getURI()) ->setSearchURI('/search/select/'.$attach_type.'/') - ->setNoun($noun); + ->setTitle($dialog_title) + ->setHeader($header_text) + ->setButtonText($button_text) + ->setInstructions($instructions); $dialog = $obj_dialog->buildDialog(); return id(new AphrontDialogResponse())->setDialog($dialog); } private function applyTaskTransaction( ManiphestTask $task, $attach_type, array $new_phids) { $user = $this->getRequest()->getUser(); $editor = new ManiphestTransactionEditor(); $type = ManiphestTransactionType::TYPE_ATTACH; $transaction = new ManiphestTransaction(); $transaction->setAuthorPHID($user->getPHID()); $transaction->setTransactionType($type); $new = $task->getAttached(); $new[$attach_type] = array_fill_keys($new_phids, array()); $transaction->setNewValue($new); $editor->applyTransactions($task, array($transaction)); } + + private function performMerge( + ManiphestTask $task, + PhabricatorObjectHandle $handle, + array $phids) { + + $user = $this->getRequest()->getUser(); + $response = id(new AphrontReloadResponse())->setURI($handle->getURI()); + + $phids = array_fill_keys($phids, true); + unset($phids[$task->getPHID()]); // Prevent merging a task into itself. + + if (!$phids) { + return $response; + } + + $targets = id(new ManiphestTask())->loadAllWhere( + 'phid in (%Ls) ORDER BY id ASC', + array_keys($phids)); + + if (empty($targets)) { + return $response; + } + + $editor = new ManiphestTransactionEditor(); + + $task_names = array(); + + $merge_into_name = 'T'.$task->getID(); + + $cc_vector = array(); + $cc_vector[] = $task->getCCPHIDs(); + foreach ($targets as $target) { + $cc_vector[] = $target->getCCPHIDs(); + $cc_vector[] = array( + $target->getAuthorPHID(), + $target->getOwnerPHID()); + + $close_task = id(new ManiphestTransaction()) + ->setAuthorPHID($user->getPHID()) + ->setTransactionType(ManiphestTransactionType::TYPE_STATUS) + ->setNewValue(ManiphestTaskStatus::STATUS_CLOSED_DUPLICATE) + ->setComments("\xE2\x9C\x98 Merged into {$merge_into_name}."); + + $editor->applyTransactions($target, array($close_task)); + + $task_names[] = 'T'.$target->getID(); + } + $all_ccs = array_mergev($cc_vector); + $all_ccs = array_filter($all_ccs); + $all_ccs = array_unique($all_ccs); + + $task_names = implode(', ', $task_names); + + $add_ccs = id(new ManiphestTransaction()) + ->setAuthorPHID($user->getPHID()) + ->setTransactionType(ManiphestTransactionType::TYPE_CCS) + ->setNewValue($all_ccs) + ->setComments("\xE2\x97\x80 Merged tasks: {$task_names}."); + $editor->applyTransactions($task, array($add_ccs)); + + return $response; + } } diff --git a/src/applications/search/controller/attach/__init__.php b/src/applications/search/controller/attach/__init__.php index db0bb2a3fa..15b3b8450e 100644 --- a/src/applications/search/controller/attach/__init__.php +++ b/src/applications/search/controller/attach/__init__.php @@ -1,25 +1,27 @@ user = $user; return $this; } public function setFilters(array $filters) { $this->filters = $filters; return $this; } public function setSelectedFilter($selected_filter) { $this->selectedFilter = $selected_filter; return $this; } public function setHandles(array $handles) { $this->handles = $handles; return $this; } public function setCancelURI($cancel_uri) { $this->cancelURI = $cancel_uri; return $this; } public function setSubmitURI($submit_uri) { $this->submitURI = $submit_uri; return $this; } public function setSearchURI($search_uri) { $this->searchURI = $search_uri; return $this; } - public function setNoun($noun) { - $this->noun = $noun; + public function setTitle($title) { + $this->title = $title; + return $this; + } + + public function setHeader($header) { + $this->header = $header; + return $this; + } + + public function setButtonText($button_text) { + $this->buttonText = $button_text; + return $this; + } + + public function setInstructions($instructions) { + $this->instructions = $instructions; return $this; } public function buildDialog() { $user = $this->user; $filter_id = celerity_generate_unique_node_id(); $query_id = celerity_generate_unique_node_id(); $results_id = celerity_generate_unique_node_id(); $current_id = celerity_generate_unique_node_id(); $search_id = celerity_generate_unique_node_id(); $form_id = celerity_generate_unique_node_id(); require_celerity_resource('phabricator-object-selector-css'); $options = array(); foreach ($this->filters as $key => $label) { $options[] = phutil_render_tag( 'option', array( 'value' => $key, 'selected' => ($key == $this->selectedFilter) ? 'selected' : null, ), $label); } $options = implode("\n", $options); + $instructions = null; + if ($this->instructions) { + $instructions = + '

'. + $this->instructions. + '

'; + } + $search_box = phabricator_render_form( $user, array( 'method' => 'POST', 'action' => $this->submitURI, 'id' => $search_id, ), ''); $result_box = '
'. '
'; $attached_box = '
'. '
'. '
'. - 'Currently Attached '.$this->noun. + phutil_escape_html($this->header). '
'. '
'. '
'. + $instructions. '
'. '
'; $dialog = new AphrontDialogView(); $dialog ->setUser($this->user) - ->setTitle('Manage Attached '.$this->noun) + ->setTitle($this->title) ->setClass('phabricator-object-selector-dialog') ->appendChild($search_box) ->appendChild($result_box) ->appendChild($attached_box) ->setRenderDialogAsDiv() ->setFormID($form_id) - ->addSubmitButton('Save '.$this->noun); + ->addSubmitButton($this->buttonText); if ($this->cancelURI) { $dialog->addCancelButton($this->cancelURI); } $handle_views = array(); foreach ($this->handles as $handle) { $phid = $handle->getPHID(); $view = new PhabricatorHandleObjectSelectorDataView($handle); $handle_views[$phid] = $view->renderData(); } $dialog->addHiddenInput('phids', implode(';', array_keys($this->handles))); Javelin::initBehavior( 'phabricator-object-selector', array( 'filter' => $filter_id, 'query' => $query_id, 'search' => $search_id, 'results' => $results_id, 'current' => $current_id, 'form' => $form_id, 'uri' => $this->searchURI, 'handles' => $handle_views, )); return $dialog; } } diff --git a/webroot/rsrc/css/aphront/headsup-action-list-view.css b/webroot/rsrc/css/aphront/headsup-action-list-view.css index ac402400f7..23a4d88b29 100644 --- a/webroot/rsrc/css/aphront/headsup-action-list-view.css +++ b/webroot/rsrc/css/aphront/headsup-action-list-view.css @@ -1,60 +1,63 @@ /** * @provides aphront-headsup-action-list-view-css */ .aphront-headsup-action-list { float: right; width: 250px; background: #cfcfbf; border: 1px solid #666622; border-width: 0px 0px 1px 1px; margin: -15px -20px 1em 0; font-size: 11px; } .aphront-headsup-action-list a, .aphront-headsup-action-list span, .aphront-headsup-action-list button { background-position: 8px center; background-repeat: no-repeat; display: block; padding: 4px 4px 4px 32px; line-height: normal; } .aphront-headsup-action-list span.unavailable { color: #666666; font-style: italic; } .aphront-headsup-action-list .subscribe-rem { background-image: url(/rsrc/image/icon/unsubscribe.png); } .aphront-headsup-action-list .subscribe-add { background-image: url(/rsrc/image/icon/subscribe.png); } .aphront-headsup-action-list .action-edit, .aphront-headsup-action-list .revision-edit { background-image: url(/rsrc/image/icon/tango/edit.png); } .aphront-headsup-action-list .action-attach, .aphront-headsup-action-list .attach-maniphest { background-image: url(/rsrc/image/icon/tango/attachment.png); } .aphront-headsup-action-list .action-upload { background-image: url(/rsrc/image/icon/tango/upload.png); } .aphront-headsup-action-list .transcripts-metamta { background-image: url(/rsrc/image/icon/tango/log.png); } .aphront-headsup-action-list .transcripts-herald { background-image: url(/rsrc/image/icon/tango/log.png); } +.aphront-headsup-action-list .action-merge { + background-image: url(/rsrc/image/icon/fatcow/arrow_merge.png); +} diff --git a/webroot/rsrc/css/application/maniphest/transaction-detail.css b/webroot/rsrc/css/application/maniphest/transaction-detail.css index 31449f8ee4..2e60d0a069 100644 --- a/webroot/rsrc/css/application/maniphest/transaction-detail.css +++ b/webroot/rsrc/css/application/maniphest/transaction-detail.css @@ -1,103 +1,107 @@ /** * @provides maniphest-transaction-detail-css */ .maniphest-trnasaction-list-view { padding: .5em 1.5em; } .maniphest-transaction-detail-container { margin: 1em 1em 1.25em; background: 2px 2px no-repeat; min-height: 50px; padding: 2px 2px; border: 1px solid transparent; } .maniphest-transaction-list-view .anchor-target { background-color: #ffffdd; border-color: #ffff00; } .maniphest-transaction-detail-container .upforgrab { border-color: #cc9966; } .maniphest-transaction-detail-container .reassigned { border-color: #0099aa; } .maniphest-transaction-detail-container .assigned { border-color: #0099aa; } .maniphest-transaction-detail-container .claimed { border-color: #0099aa; } .maniphest-transaction-detail-container .created { border-color: #660099; } .maniphest-transaction-detail-container .closed { border-color: #006699; } .maniphest-transaction-detail-container .spited { border-color: #006699; } .maniphest-transaction-detail-container .reopened { border-color: #660099; } .maniphest-transaction-detail-container .unbreaknow { border-color: #aa0000; } +.maniphest-transaction-detail-container .duplicate { + border-color: #333333; +} + .maniphest-transaction-header { background: #f3f3f3; padding: 4px 1em; } .maniphest-transaction-header a { font-weight: bold; } .maniphest-transaction-detail-view { margin-left: 54px; border-color: #dddddd; border-width: 1px 10px; border-style: solid; } .maniphest-transaction-timestamp { float: right; font-size: 11px; color: #666666; } .maniphest-transaction-comments { border-top: 1px solid #e6e6e6; padding: 4px 1em; background: #fcfcfc; } .maniphest-change-table { width: 100%; margin: .5em 0em; border-collapse: separate; border-spacing: 4px 0px; } .maniphest-change-table td { width: 50%; padding: 0.25em 1em; background: #f9f9f9; } .maniphest-change-table th { font-weight: bold; padding: 0.25em; border-bottom: 1px solid #cccccc; } diff --git a/webroot/rsrc/css/application/objectselector/object-selector.css b/webroot/rsrc/css/application/objectselector/object-selector.css index 0b2e23eff2..3b7d64e9b7 100644 --- a/webroot/rsrc/css/application/objectselector/object-selector.css +++ b/webroot/rsrc/css/application/objectselector/object-selector.css @@ -1,88 +1,94 @@ /** * @provides phabricator-object-selector-css * @requires aphront-dialog-view-css */ .phabricator-object-selector-dialog { width: 960px; } .phabricator-object-selector-dialog .aphront-dialog-body { padding: 0; } .phabricator-object-selector-search { width: 100%; background: #ededed; } .phabricator-object-selector-search td { padding: 4px 8px; } td.phabricator-object-selector-search-text { width: 100%; } .phabricator-object-selector-search-text input { width: 100%; } .phabricator-object-selector-results { position: relative; height: 24em; border: solid #bbbbbb; border-width: 1px 0px; overflow-y: scroll; overflow-x: hidden; } .phabricator-object-selector-handle { width: 100%; background: #e9e9e9; margin-bottom: 1px; } .phabricator-object-selector-handle td { padding: 4px 1em; } .phabricator-object-selector-handle th { padding: 4px 1em; font-weight: bold; vertical-align: middle; width: 100%; overflow: hidden; } .phabricator-object-selector-header { padding: 2px; border-bottom: 1px solid #d0d0d0; margin-bottom: 16px; color: #444444; } .phabricator-object-selector-attach-explicit { padding: 4px; background: #f3f3f3; border: solid #bbbbbb; border-width: 1px 0px; } .phabricator-object-selector-currently-attached { background: #fff; padding: 16px; border: 1px solid #dddddd; } .phabricator-object-selector-current { background: #ededed; padding: 8px 8px; } .object-selector-nothing { padding: 1em; color: #888888; text-align: center; } + +.phabricator-object-selector-instructions { + font-size: 11px; + color: #666666; + margin-top: 1.25em; +} diff --git a/webroot/rsrc/image/icon/fatcow/README b/webroot/rsrc/image/icon/fatcow/README index 67fe8639e1..eb6a114001 100644 --- a/webroot/rsrc/image/icon/fatcow/README +++ b/webroot/rsrc/image/icon/fatcow/README @@ -1,11 +1,12 @@ These icons come from the FatCow icon set: http://www.fatcow.com/free-icons They are available under the Creative Commons Attribution 3.0 License: http://creativecommons.org/licenses/by/3.0/us/ Some icons have been adapted from the FatCow set for use in Phabricator: - key_question.png \ No newline at end of file + key_question.png + diff --git a/webroot/rsrc/image/icon/fatcow/arrow_merge.png b/webroot/rsrc/image/icon/fatcow/arrow_merge.png new file mode 100644 index 0000000000..5a066e5910 Binary files /dev/null and b/webroot/rsrc/image/icon/fatcow/arrow_merge.png differ diff --git a/webroot/rsrc/js/application/core/behavior-object-selector.js b/webroot/rsrc/js/application/core/behavior-object-selector.js index c0a6a0c407..034fa579b1 100644 --- a/webroot/rsrc/js/application/core/behavior-object-selector.js +++ b/webroot/rsrc/js/application/core/behavior-object-selector.js @@ -1,185 +1,185 @@ /** * @provides javelin-behavior-phabricator-object-selector * @requires javelin-behavior * javelin-dom * javelin-request * javelin-util * javelin-stratcom */ JX.behavior('phabricator-object-selector', function(config) { var n = 0; var phids = {}; var handles = config.handles; for (var k in handles) { phids[k] = true; } var attach_list = {}; var query_timer = null; var query_delay = 50; var phid_input = JX.DOM.find( JX.$(config.form), 'input', 'aphront-dialog-application-input'); var last_value = JX.$(config.query).value; function onreceive(seq, r) { if (seq != n) { return; } var display = []; attach_list = {}; for (var k in r) { handles[r[k].phid] = r[k]; display.push(renderHandle(r[k], true)); } if (!display.length) { display = renderNote('No results.'); } JX.DOM.setContent(JX.$(config.results), display); } function redrawAttached() { var display = []; for (var k in phids) { display.push(renderHandle(handles[k], false)); } if (!display.length) { display = renderNote('Nothing attached.'); } JX.DOM.setContent(JX.$(config.current), display); phid_input.value = JX.keys(phids).join(';'); } function renderHandle(h, attach) { var link = JX.$N( 'a', {href : h.uri, target : '_blank'}, h.name); var td = JX.$N('td'); var table = JX.$N( 'table', {className: 'phabricator-object-selector-handle'}, JX.$N( 'tbody', {}, [JX.$N('th', {}, link), td])); var btn = JX.$N( 'a', {className: 'button small grey'}, - attach ? 'Attach' : 'Remove'); + attach ? 'Select' : 'Remove'); JX.Stratcom.addSigil(btn, 'object-attach-button'); JX.Stratcom.addData(btn, {handle : h, table : table}); if (attach) { attach_list[h.phid] = btn; if (h.phid in phids) { JX.DOM.alterClass(btn, 'disabled', true); btn.disabled = true; } } JX.DOM.setContent(td, btn); return table; } function renderNote(note) { return JX.$N('div', {className : 'object-selector-nothing'}, note); } function sendQuery() { query_timer = null; JX.DOM.setContent(JX.$(config.results), renderNote('Loading...')) new JX.Request(config.uri, JX.bind(null, onreceive, ++n)) .setData({ filter: JX.$(config.filter).value, query: JX.$(config.query).value }) .send(); } JX.DOM.listen( JX.$(config.results), 'click', 'object-attach-button', function(e) { e.kill(); var button = e.getNode('object-attach-button'); if (button.disabled) { return; } var data = e.getNodeData('object-attach-button'); phids[data.handle.phid] = true; JX.DOM.alterClass(button, 'disabled', true); button.disabled = true; redrawAttached(); }); JX.DOM.listen( JX.$(config.current), 'click', 'object-attach-button', function(e) { e.kill(); var button = e.getNode('object-attach-button'); if (button.disabled) { return; } var data = e.getNodeData('object-attach-button'); delete phids[data.handle.phid]; if (attach_list[data.handle.phid]) { JX.DOM.alterClass(attach_list[data.handle.phid], 'disabled', false); attach_list[data.handle.phid].disabled = false; } redrawAttached(); }); JX.DOM.listen( JX.$(config.filter), 'change', null, function(e) { e.kill(); sendQuery(); }); JX.DOM.listen( JX.$(config.query), ['change', 'keydown', 'keyup', 'keypress'], null, function(e) { var cur_value = JX.$(config.query).value; if (last_value == cur_value) { return; } last_value = cur_value; if (query_timer) { query_timer.stop(); } query_timer = JX.defer(sendQuery, query_delay); }); sendQuery(); redrawAttached(); });