Page MenuHomestyx hydra

No OneTemporary

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
index 43c3f83408..07c9873003 100644
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -1,2408 +1,2415 @@
<?php
/**
* This file is automatically generated. Use 'bin/celerity map' to rebuild it.
*
* @generated
*/
return array(
'names' => array(
- 'core.pkg.css' => 'b9e2e1e5',
- 'core.pkg.js' => '80f86a0a',
+ 'core.pkg.css' => 'f577cd20',
+ 'core.pkg.js' => 'f2139810',
'darkconsole.pkg.js' => 'e7393ebb',
'differential.pkg.css' => 'b3eea3f5',
'differential.pkg.js' => '4b7d8f19',
'diffusion.pkg.css' => '91c5d3a6',
'diffusion.pkg.js' => '3a9a8bfa',
'maniphest.pkg.css' => '4845691a',
'maniphest.pkg.js' => '949a7498',
'rsrc/css/aphront/aphront-bars.css' => '231ac33c',
'rsrc/css/aphront/dark-console.css' => 'f54bf286',
'rsrc/css/aphront/dialog-view.css' => '913c172e',
'rsrc/css/aphront/lightbox-attachment.css' => '7acac05d',
'rsrc/css/aphront/list-filter-view.css' => '5d6f0526',
'rsrc/css/aphront/multi-column.css' => 'fd18389d',
'rsrc/css/aphront/notification.css' => '3f6c89c9',
'rsrc/css/aphront/panel-view.css' => '8427b78d',
'rsrc/css/aphront/phabricator-nav-view.css' => 'ac79a758',
'rsrc/css/aphront/table-view.css' => '9258e19f',
'rsrc/css/aphront/tokenizer.css' => '056da01b',
'rsrc/css/aphront/tooltip.css' => '1a07aea8',
'rsrc/css/aphront/typeahead-browse.css' => '8904346a',
'rsrc/css/aphront/typeahead.css' => 'd4f16145',
'rsrc/css/application/almanac/almanac.css' => 'dbb9b3af',
'rsrc/css/application/auth/auth.css' => '0877ed6e',
'rsrc/css/application/base/main-menu-view.css' => 'b623169f',
'rsrc/css/application/base/notification-menu.css' => 'f31c0bde',
'rsrc/css/application/base/phabricator-application-launch-view.css' => '95351601',
'rsrc/css/application/base/phui-theme.css' => '027ba77e',
'rsrc/css/application/base/standard-page-view.css' => 'e709f6d0',
'rsrc/css/application/chatlog/chatlog.css' => 'd295b020',
'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4',
'rsrc/css/application/config/config-options.css' => '0ede4c9b',
'rsrc/css/application/config/config-template.css' => '8e6c6fcd',
'rsrc/css/application/config/config-welcome.css' => '6abd79be',
'rsrc/css/application/config/setup-issue.css' => 'db7e9c40',
'rsrc/css/application/config/unhandled-exception.css' => '4c96257a',
'rsrc/css/application/conpherence/durable-column.css' => '86396117',
'rsrc/css/application/conpherence/menu.css' => 'f99fee4c',
'rsrc/css/application/conpherence/message-pane.css' => '5897d3ac',
'rsrc/css/application/conpherence/notification.css' => '6cdcc253',
'rsrc/css/application/conpherence/transaction.css' => '85d0974c',
'rsrc/css/application/conpherence/update.css' => 'faf6be09',
'rsrc/css/application/conpherence/widget-pane.css' => '775eaaba',
'rsrc/css/application/contentsource/content-source-view.css' => '4b8b05d4',
'rsrc/css/application/countdown/timer.css' => '16c52f5c',
'rsrc/css/application/daemon/bulk-job.css' => 'df9c1d4a',
'rsrc/css/application/dashboard/dashboard.css' => 'bc6f2127',
'rsrc/css/application/diff/inline-comment-summary.css' => '51efda3a',
'rsrc/css/application/differential/add-comment.css' => 'c47f8c40',
'rsrc/css/application/differential/changeset-view.css' => 'ccfbc869',
'rsrc/css/application/differential/core.css' => '5b7b8ff4',
'rsrc/css/application/differential/phui-inline-comment.css' => '5953c28e',
'rsrc/css/application/differential/revision-comment.css' => '14b8565a',
'rsrc/css/application/differential/revision-history.css' => '0e8eb855',
'rsrc/css/application/differential/revision-list.css' => 'f3c47d33',
'rsrc/css/application/differential/table-of-contents.css' => 'ae4b7a55',
'rsrc/css/application/diffusion/diffusion-icons.css' => 'd678600a',
'rsrc/css/application/diffusion/diffusion-readme.css' => '297373eb',
'rsrc/css/application/diffusion/diffusion-source.css' => '68b30fd3',
'rsrc/css/application/feed/feed.css' => 'ecd4ec57',
'rsrc/css/application/files/global-drag-and-drop.css' => '5c1b47c2',
'rsrc/css/application/flag/flag.css' => '5337623f',
'rsrc/css/application/harbormaster/harbormaster.css' => 'f491c9f4',
'rsrc/css/application/herald/herald-test.css' => 'a52e323e',
'rsrc/css/application/herald/herald.css' => 'dc31f6e9',
'rsrc/css/application/maniphest/batch-editor.css' => 'b0f0b6d5',
'rsrc/css/application/maniphest/report.css' => '9b9580b7',
'rsrc/css/application/maniphest/task-edit.css' => 'fda62a9b',
'rsrc/css/application/maniphest/task-summary.css' => '11cc5344',
'rsrc/css/application/objectselector/object-selector.css' => '85ee8ce6',
'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b',
'rsrc/css/application/paste/paste.css' => '1898e534',
'rsrc/css/application/people/people-profile.css' => '2473d929',
'rsrc/css/application/phame/phame.css' => 'bf6a743f',
'rsrc/css/application/pholio/pholio-edit.css' => '07676f51',
'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49',
'rsrc/css/application/pholio/pholio.css' => 'ca89d380',
'rsrc/css/application/phortune/phortune-credit-card-form.css' => '8391eb02',
'rsrc/css/application/phortune/phortune.css' => '5b99dae0',
'rsrc/css/application/phrequent/phrequent.css' => 'ffc185ad',
'rsrc/css/application/phriction/phriction-document-css.css' => '4282e4ad',
'rsrc/css/application/policy/policy-edit.css' => '815c66f7',
'rsrc/css/application/policy/policy-transaction-detail.css' => '82100a43',
'rsrc/css/application/policy/policy.css' => '957ea14c',
'rsrc/css/application/ponder/ponder-view.css' => 'fbd45f96',
'rsrc/css/application/project/project-card-view.css' => '9418c97d',
'rsrc/css/application/project/project-view.css' => 'cbaa10a1',
'rsrc/css/application/releeph/releeph-core.css' => '9b3c5733',
'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5',
'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd',
'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae',
'rsrc/css/application/search/search-results.css' => '7dea472c',
'rsrc/css/application/slowvote/slowvote.css' => 'a94b7230',
'rsrc/css/application/tokens/tokens.css' => '3d0f239e',
'rsrc/css/application/uiexample/example.css' => '528b19de',
'rsrc/css/core/core.css' => 'd0801452',
'rsrc/css/core/remarkup.css' => '523d34bb',
'rsrc/css/core/syntax.css' => '9fc496d5',
'rsrc/css/core/z-index.css' => '5b6fcf3f',
'rsrc/css/diviner/diviner-shared.css' => 'aa3656aa',
'rsrc/css/font/font-aleo.css' => '8bdb2835',
'rsrc/css/font/font-awesome.css' => '2b7ebbcc',
'rsrc/css/font/font-lato.css' => 'c7ccd872',
'rsrc/css/font/phui-font-icon-base.css' => '6449bce8',
'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82',
'rsrc/css/layout/phabricator-side-menu-view.css' => 'dd849797',
'rsrc/css/layout/phabricator-source-code-view.css' => 'cbeef983',
'rsrc/css/phui/calendar/phui-calendar-day.css' => 'd1cf6f93',
'rsrc/css/phui/calendar/phui-calendar-list.css' => '56e6381a',
'rsrc/css/phui/calendar/phui-calendar-month.css' => '476be7e0',
'rsrc/css/phui/calendar/phui-calendar.css' => 'ccabe893',
'rsrc/css/phui/phui-action-list.css' => 'c5eba19d',
'rsrc/css/phui/phui-action-panel.css' => '91c7b835',
'rsrc/css/phui/phui-badge.css' => '3baef8db',
'rsrc/css/phui/phui-big-info-view.css' => 'bd903741',
'rsrc/css/phui/phui-box.css' => '5c8387cf',
- 'rsrc/css/phui/phui-button.css' => 'a64a8de6',
+ 'rsrc/css/phui/phui-button.css' => 'e266e0bc',
'rsrc/css/phui/phui-chart.css' => '6bf6f78e',
'rsrc/css/phui/phui-crumbs-view.css' => '6b813619',
'rsrc/css/phui/phui-curtain-view.css' => '7148ae25',
'rsrc/css/phui/phui-document-pro.css' => 'a3730b94',
'rsrc/css/phui/phui-document-summary.css' => '9ca48bdf',
'rsrc/css/phui/phui-document.css' => '715aedfb',
'rsrc/css/phui/phui-feed-story.css' => 'aa49845d',
'rsrc/css/phui/phui-fontkit.css' => '9cda225e',
'rsrc/css/phui/phui-form-view.css' => '6a51768e',
'rsrc/css/phui/phui-form.css' => 'aac1d51d',
'rsrc/css/phui/phui-head-thing.css' => 'fd311e5f',
'rsrc/css/phui/phui-header-view.css' => '4c7dd8f5',
'rsrc/css/phui/phui-hovercard.css' => 'de1a2119',
'rsrc/css/phui/phui-icon-set-selector.css' => '1ab67aad',
'rsrc/css/phui/phui-icon.css' => '3f33ab57',
'rsrc/css/phui/phui-image-mask.css' => 'a8498f9c',
'rsrc/css/phui/phui-info-panel.css' => '27ea50a1',
'rsrc/css/phui/phui-info-view.css' => '28efab79',
'rsrc/css/phui/phui-list.css' => '9da2aa00',
'rsrc/css/phui/phui-object-box.css' => '6b487c57',
'rsrc/css/phui/phui-object-item-list-view.css' => '8d99e42b',
'rsrc/css/phui/phui-pager.css' => 'bea33d23',
'rsrc/css/phui/phui-pinboard-view.css' => '2495140e',
'rsrc/css/phui/phui-profile-menu.css' => 'c8557f33',
'rsrc/css/phui/phui-property-list-view.css' => 'd4bbd0cb',
'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591',
'rsrc/css/phui/phui-segment-bar-view.css' => '46342871',
'rsrc/css/phui/phui-spacing.css' => '042804d6',
'rsrc/css/phui/phui-status.css' => 'd5263e49',
'rsrc/css/phui/phui-tag-view.css' => '6bbd83e2',
'rsrc/css/phui/phui-timeline-view.css' => '8ea41b25',
'rsrc/css/phui/phui-two-column-view.css' => '9fb86c85',
'rsrc/css/phui/workboards/phui-workboard-color.css' => 'ac6fe6a7',
'rsrc/css/phui/workboards/phui-workboard.css' => 'e6d89647',
'rsrc/css/phui/workboards/phui-workcard.css' => '0c62d7c5',
'rsrc/css/phui/workboards/phui-workpanel.css' => '92197373',
'rsrc/css/sprite-login.css' => '60e8560e',
'rsrc/css/sprite-menu.css' => '9dd65b92',
'rsrc/css/sprite-tokens.css' => '4f399012',
'rsrc/css/syntax/syntax-default.css' => '9923583c',
'rsrc/externals/d3/d3.min.js' => 'a11a5ff2',
'rsrc/externals/font/aleo/aleo-bold.eot' => 'd3d3bed7',
'rsrc/externals/font/aleo/aleo-bold.svg' => '45899c8e',
'rsrc/externals/font/aleo/aleo-bold.ttf' => '4b08bef0',
'rsrc/externals/font/aleo/aleo-bold.woff' => '93b513a1',
'rsrc/externals/font/aleo/aleo-bold.woff2' => '75fbf322',
'rsrc/externals/font/aleo/aleo-regular.eot' => 'a4e29e2f',
'rsrc/externals/font/aleo/aleo-regular.svg' => '42a86f7a',
'rsrc/externals/font/aleo/aleo-regular.ttf' => '751e7479',
'rsrc/externals/font/aleo/aleo-regular.woff' => 'c3744be9',
'rsrc/externals/font/aleo/aleo-regular.woff2' => '851aa0ee',
'rsrc/externals/font/fontawesome/fontawesome-webfont.eot' => '59b3076c',
'rsrc/externals/font/fontawesome/fontawesome-webfont.ttf' => '45ad7e57',
'rsrc/externals/font/fontawesome/fontawesome-webfont.woff' => 'f861e2a8',
'rsrc/externals/font/fontawesome/fontawesome-webfont.woff2' => '0ee0f078',
'rsrc/externals/font/lato/lato-bold.eot' => '99fbcf8c',
'rsrc/externals/font/lato/lato-bold.svg' => '2aa83045',
'rsrc/externals/font/lato/lato-bold.ttf' => '0a7141f7',
'rsrc/externals/font/lato/lato-bold.woff' => 'f5db2061',
'rsrc/externals/font/lato/lato-bold.woff2' => '37a94ecd',
'rsrc/externals/font/lato/lato-bolditalic.eot' => 'b93389d0',
'rsrc/externals/font/lato/lato-bolditalic.svg' => '5442e1ef',
'rsrc/externals/font/lato/lato-bolditalic.ttf' => 'dad31252',
'rsrc/externals/font/lato/lato-bolditalic.woff' => 'e53bcf47',
'rsrc/externals/font/lato/lato-bolditalic.woff2' => 'd035007f',
'rsrc/externals/font/lato/lato-italic.eot' => '6a903f5d',
'rsrc/externals/font/lato/lato-italic.svg' => '0dc7cf2f',
'rsrc/externals/font/lato/lato-italic.ttf' => '629f64f0',
'rsrc/externals/font/lato/lato-italic.woff' => '678dc4bb',
'rsrc/externals/font/lato/lato-italic.woff2' => '7c8dd650',
'rsrc/externals/font/lato/lato-regular.eot' => '848dfb1e',
'rsrc/externals/font/lato/lato-regular.svg' => 'cbd5fd6b',
'rsrc/externals/font/lato/lato-regular.ttf' => 'e270165b',
'rsrc/externals/font/lato/lato-regular.woff' => '13d39fe2',
'rsrc/externals/font/lato/lato-regular.woff2' => '57a9f742',
'rsrc/externals/javelin/core/Event.js' => '2ee659ce',
'rsrc/externals/javelin/core/Stratcom.js' => '6ad39b6f',
'rsrc/externals/javelin/core/__tests__/event-stop-and-kill.js' => '717554e4',
'rsrc/externals/javelin/core/__tests__/install.js' => 'c432ee85',
'rsrc/externals/javelin/core/__tests__/stratcom.js' => '88bf7313',
'rsrc/externals/javelin/core/__tests__/util.js' => 'e251703d',
'rsrc/externals/javelin/core/init.js' => '3010e992',
'rsrc/externals/javelin/core/init_node.js' => 'c234aded',
'rsrc/externals/javelin/core/install.js' => '05270951',
'rsrc/externals/javelin/core/util.js' => '93cc50d6',
'rsrc/externals/javelin/docs/Base.js' => '74676256',
'rsrc/externals/javelin/docs/onload.js' => 'e819c479',
'rsrc/externals/javelin/ext/fx/Color.js' => '7e41274a',
'rsrc/externals/javelin/ext/fx/FX.js' => '54b612ba',
'rsrc/externals/javelin/ext/reactor/core/DynVal.js' => 'f6555212',
'rsrc/externals/javelin/ext/reactor/core/Reactor.js' => '2b8de964',
'rsrc/externals/javelin/ext/reactor/core/ReactorNode.js' => '1ad0a787',
'rsrc/externals/javelin/ext/reactor/core/ReactorNodeCalmer.js' => '76f4ebed',
'rsrc/externals/javelin/ext/reactor/dom/RDOM.js' => 'c90a04fc',
'rsrc/externals/javelin/ext/view/HTMLView.js' => 'fe287620',
'rsrc/externals/javelin/ext/view/View.js' => '0f764c35',
'rsrc/externals/javelin/ext/view/ViewInterpreter.js' => 'f829edb3',
'rsrc/externals/javelin/ext/view/ViewPlaceholder.js' => '47830651',
'rsrc/externals/javelin/ext/view/ViewRenderer.js' => '6c2b09a2',
'rsrc/externals/javelin/ext/view/ViewVisitor.js' => 'efe49472',
'rsrc/externals/javelin/ext/view/__tests__/HTMLView.js' => 'f92d7bcb',
'rsrc/externals/javelin/ext/view/__tests__/View.js' => '6450b38b',
'rsrc/externals/javelin/ext/view/__tests__/ViewInterpreter.js' => '7a94d6a5',
'rsrc/externals/javelin/ext/view/__tests__/ViewRenderer.js' => '6ea96ac9',
'rsrc/externals/javelin/lib/Cookie.js' => '62dfea03',
'rsrc/externals/javelin/lib/DOM.js' => '805b806a',
'rsrc/externals/javelin/lib/History.js' => 'd4505101',
'rsrc/externals/javelin/lib/JSON.js' => '69adf288',
'rsrc/externals/javelin/lib/Leader.js' => 'fea0eb47',
'rsrc/externals/javelin/lib/Mask.js' => '8a41885b',
'rsrc/externals/javelin/lib/Quicksand.js' => '6b8ef10b',
'rsrc/externals/javelin/lib/Request.js' => '94b750d2',
'rsrc/externals/javelin/lib/Resource.js' => '44959b73',
'rsrc/externals/javelin/lib/Routable.js' => 'b3e7d692',
'rsrc/externals/javelin/lib/Router.js' => '29274e2b',
'rsrc/externals/javelin/lib/Scrollbar.js' => '087e919c',
'rsrc/externals/javelin/lib/Sound.js' => '949c0fe5',
'rsrc/externals/javelin/lib/URI.js' => 'c989ade3',
'rsrc/externals/javelin/lib/Vector.js' => '2caa8fb8',
'rsrc/externals/javelin/lib/WebSocket.js' => 'e292eaf4',
'rsrc/externals/javelin/lib/Workflow.js' => '1e911d0f',
'rsrc/externals/javelin/lib/__tests__/Cookie.js' => '5ed109e8',
'rsrc/externals/javelin/lib/__tests__/DOM.js' => 'c984504b',
'rsrc/externals/javelin/lib/__tests__/JSON.js' => '837a7d68',
'rsrc/externals/javelin/lib/__tests__/URI.js' => '1e45fda9',
'rsrc/externals/javelin/lib/__tests__/behavior.js' => '1ea62783',
'rsrc/externals/javelin/lib/behavior.js' => '61cbc29a',
'rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js' => '8d3bc1b2',
'rsrc/externals/javelin/lib/control/typeahead/Typeahead.js' => '70baed2f',
'rsrc/externals/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js' => 'e6e25838',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js' => '503e17fd',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js' => '013ffff9',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js' => '54f314a0',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => 'b25d5444',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js' => '6c0e62fa',
'rsrc/favicons/apple-touch-icon-120x120.png' => '43742962',
'rsrc/favicons/apple-touch-icon-152x152.png' => '669eaec3',
'rsrc/favicons/apple-touch-icon-76x76.png' => 'ecdef672',
'rsrc/favicons/favicon-128.png' => '47cdff03',
'rsrc/favicons/favicon-16x16.png' => 'ee2523ac',
'rsrc/favicons/favicon-32x32.png' => 'b6a8150e',
'rsrc/favicons/favicon-96x96.png' => '8f7ea177',
'rsrc/favicons/mask-icon.svg' => '0460cb1f',
'rsrc/image/BFCFDA.png' => 'd5ec91f4',
'rsrc/image/actions/edit.png' => '2fc41442',
'rsrc/image/avatar.png' => 'e132bb6a',
'rsrc/image/checker_dark.png' => 'd8e65881',
'rsrc/image/checker_light.png' => 'a0155918',
'rsrc/image/checker_lighter.png' => 'd5da91b6',
'rsrc/image/d5d8e1.png' => '0c2a1497',
'rsrc/image/darkload.gif' => '1ffd3ec6',
'rsrc/image/divot.png' => '94dded62',
'rsrc/image/examples/hero.png' => '979a86ae',
'rsrc/image/grippy_texture.png' => 'aca81e2f',
'rsrc/image/icon/fatcow/arrow_branch.png' => '2537c01c',
'rsrc/image/icon/fatcow/arrow_merge.png' => '21b660e0',
'rsrc/image/icon/fatcow/bullet_black.png' => 'ff190031',
'rsrc/image/icon/fatcow/bullet_orange.png' => 'e273e5bb',
'rsrc/image/icon/fatcow/bullet_red.png' => 'c0b75434',
'rsrc/image/icon/fatcow/calendar_edit.png' => '24632275',
'rsrc/image/icon/fatcow/document_black.png' => '45fe1c60',
'rsrc/image/icon/fatcow/flag_blue.png' => 'a01abb1d',
'rsrc/image/icon/fatcow/flag_finish.png' => '67825cee',
'rsrc/image/icon/fatcow/flag_ghost.png' => '20ca8783',
'rsrc/image/icon/fatcow/flag_green.png' => '7e0eaa7a',
'rsrc/image/icon/fatcow/flag_orange.png' => '9e73df66',
'rsrc/image/icon/fatcow/flag_pink.png' => '7e92f3b2',
'rsrc/image/icon/fatcow/flag_purple.png' => 'cc517522',
'rsrc/image/icon/fatcow/flag_red.png' => '04ec726f',
'rsrc/image/icon/fatcow/flag_yellow.png' => '73946fd4',
'rsrc/image/icon/fatcow/key_question.png' => '52a0c26a',
'rsrc/image/icon/fatcow/link.png' => '7afd4d5e',
'rsrc/image/icon/fatcow/page_white_edit.png' => '39a2eed8',
'rsrc/image/icon/fatcow/page_white_put.png' => '08c95a0c',
'rsrc/image/icon/fatcow/source/conduit.png' => '4ea01d2f',
'rsrc/image/icon/fatcow/source/email.png' => '9bab3239',
'rsrc/image/icon/fatcow/source/fax.png' => '04195e68',
'rsrc/image/icon/fatcow/source/mobile.png' => 'f1321264',
'rsrc/image/icon/fatcow/source/tablet.png' => '49396799',
'rsrc/image/icon/fatcow/source/web.png' => '136ccb5d',
'rsrc/image/icon/lightbox/close-2.png' => 'cc40e7c8',
'rsrc/image/icon/lightbox/close-hover-2.png' => 'fb5d6d9e',
'rsrc/image/icon/lightbox/left-arrow-2.png' => '8426133b',
'rsrc/image/icon/lightbox/left-arrow-hover-2.png' => '701e5ee3',
'rsrc/image/icon/lightbox/right-arrow-2.png' => '6d5519a0',
'rsrc/image/icon/lightbox/right-arrow-hover-2.png' => '3a04aa21',
'rsrc/image/icon/subscribe.png' => 'd03ed5a5',
'rsrc/image/icon/tango/attachment.png' => 'ecc8022e',
'rsrc/image/icon/tango/edit.png' => '929a1363',
'rsrc/image/icon/tango/go-down.png' => '96d95e43',
'rsrc/image/icon/tango/log.png' => 'b08cc63a',
'rsrc/image/icon/tango/upload.png' => '7bbb7984',
'rsrc/image/icon/unsubscribe.png' => '25725013',
'rsrc/image/lightblue-header.png' => '5c168b6d',
'rsrc/image/main_texture.png' => '29a2c5ad',
'rsrc/image/menu_texture.png' => '5a17580d',
'rsrc/image/people/harding.png' => '45aa614e',
'rsrc/image/people/jefferson.png' => 'afca0e53',
'rsrc/image/people/lincoln.png' => '9369126d',
'rsrc/image/people/mckinley.png' => 'fb8f16ce',
'rsrc/image/people/taft.png' => 'd7bc402c',
'rsrc/image/people/user0.png' => '03dacaea',
'rsrc/image/people/user1.png' => '4a4e7702',
'rsrc/image/people/user2.png' => '47a0ee40',
'rsrc/image/people/user3.png' => '835ff627',
'rsrc/image/people/user4.png' => 'b0e830f1',
'rsrc/image/people/user5.png' => '9c95b369',
'rsrc/image/people/user6.png' => 'ba3fbfb0',
'rsrc/image/people/user7.png' => 'da613924',
'rsrc/image/people/user8.png' => 'f1035edf',
'rsrc/image/people/user9.png' => '66730be3',
'rsrc/image/people/washington.png' => '40dd301c',
'rsrc/image/phrequent_active.png' => 'a466a8ed',
'rsrc/image/phrequent_inactive.png' => 'bfc15a69',
'rsrc/image/resize.png' => 'fd476de4',
'rsrc/image/sprite-login-X2.png' => 'e3991e37',
'rsrc/image/sprite-login.png' => '03d5af29',
'rsrc/image/sprite-menu-X2.png' => 'cfd8fca5',
'rsrc/image/sprite-menu.png' => 'd7a99faa',
'rsrc/image/sprite-tokens-X2.png' => '348f1745',
'rsrc/image/sprite-tokens.png' => 'ce0b62be',
'rsrc/image/texture/card-gradient.png' => '815f26e8',
'rsrc/image/texture/dark-menu-hover.png' => '5fa7ece8',
'rsrc/image/texture/dark-menu.png' => '7e22296e',
'rsrc/image/texture/grip.png' => '719404f3',
'rsrc/image/texture/panel-header-gradient.png' => 'e3b8dcfe',
'rsrc/image/texture/phlnx-bg.png' => '8d819209',
'rsrc/image/texture/pholio-background.gif' => 'ba29239c',
'rsrc/image/texture/table_header.png' => '5c433037',
'rsrc/image/texture/table_header_hover.png' => '038ec3b9',
'rsrc/image/texture/table_header_tall.png' => 'd56b434f',
'rsrc/js/application/aphlict/Aphlict.js' => '5359e785',
'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => '031cee25',
'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'fb20ac8d',
'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'ea681761',
'rsrc/js/application/aphlict/behavior-desktop-notifications-control.js' => 'edd1ba66',
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
'rsrc/js/application/calendar/behavior-day-view.js' => '5c46cff2',
'rsrc/js/application/calendar/behavior-event-all-day.js' => '38dcf3c8',
'rsrc/js/application/calendar/behavior-recurring-edit.js' => '5f1c4d5f',
'rsrc/js/application/config/behavior-reorder-fields.js' => 'b6993408',
'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => '01774ab2',
'rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js' => 'cf86d16a',
'rsrc/js/application/conpherence/behavior-durable-column.js' => 'd3506890',
'rsrc/js/application/conpherence/behavior-menu.js' => '1d45c74d',
'rsrc/js/application/conpherence/behavior-pontificate.js' => '21ba5861',
'rsrc/js/application/conpherence/behavior-quicksand-blacklist.js' => '7927a7d3',
'rsrc/js/application/conpherence/behavior-widget-pane.js' => 'a8458711',
'rsrc/js/application/countdown/timer.js' => 'e4cc26b3',
'rsrc/js/application/daemon/behavior-bulk-job-reload.js' => 'edf8a145',
'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => '469c0d9e',
'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => '019f36c4',
'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '453c5375',
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => 'd4eecc63',
'rsrc/js/application/differential/ChangesetViewManager.js' => 'a2828756',
'rsrc/js/application/differential/DifferentialInlineCommentEditor.js' => '64a5550f',
'rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js' => 'e10f8e18',
'rsrc/js/application/differential/behavior-comment-jump.js' => '4fdb476d',
'rsrc/js/application/differential/behavior-comment-preview.js' => 'b064af76',
'rsrc/js/application/differential/behavior-diff-radios.js' => 'e1ff79b1',
'rsrc/js/application/differential/behavior-dropdown-menus.js' => '9a6b9324',
'rsrc/js/application/differential/behavior-edit-inline-comments.js' => '4fbbc3e9',
'rsrc/js/application/differential/behavior-keyboard-nav.js' => '2c426492',
'rsrc/js/application/differential/behavior-populate.js' => '8694b1df',
'rsrc/js/application/differential/behavior-toggle-files.js' => 'ca3f91eb',
'rsrc/js/application/differential/behavior-user-select.js' => 'a8d8459d',
'rsrc/js/application/diffusion/DiffusionLocateFileSource.js' => 'b42eddc7',
'rsrc/js/application/diffusion/behavior-audit-preview.js' => 'd835b03a',
'rsrc/js/application/diffusion/behavior-commit-branches.js' => 'bdaf4d04',
'rsrc/js/application/diffusion/behavior-commit-graph.js' => '5a0b1a64',
'rsrc/js/application/diffusion/behavior-diffusion-browse-file.js' => '054a0f0b',
'rsrc/js/application/diffusion/behavior-jump-to.js' => '73d09eef',
'rsrc/js/application/diffusion/behavior-load-blame.js' => '42126667',
'rsrc/js/application/diffusion/behavior-locate-file.js' => '6d3e1947',
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc',
'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => 'e5822781',
'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef',
'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab',
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888',
'rsrc/js/application/herald/HeraldRuleEditor.js' => 'd6a7e717',
'rsrc/js/application/herald/PathTypeahead.js' => 'f7fc67ec',
'rsrc/js/application/herald/herald-rule-editor.js' => '7ebaeed3',
'rsrc/js/application/maniphest/behavior-batch-editor.js' => '782ab6e7',
'rsrc/js/application/maniphest/behavior-batch-selector.js' => '7b98d7c5',
'rsrc/js/application/maniphest/behavior-line-chart.js' => 'e4232876',
'rsrc/js/application/maniphest/behavior-list-edit.js' => 'a9f88de2',
'rsrc/js/application/maniphest/behavior-subpriorityeditor.js' => '71237763',
'rsrc/js/application/owners/OwnersPathEditor.js' => 'aa1733d0',
'rsrc/js/application/owners/owners-path-editor.js' => '7a68dda3',
'rsrc/js/application/passphrase/passphrase-credential-control.js' => '3cb0b2fc',
'rsrc/js/application/pholio/behavior-pholio-mock-edit.js' => 'bee502c8',
'rsrc/js/application/pholio/behavior-pholio-mock-view.js' => 'fbe497e7',
'rsrc/js/application/phortune/behavior-stripe-payment-form.js' => '3f5d6dbf',
'rsrc/js/application/phortune/behavior-test-payment-form.js' => 'fc91ab6c',
'rsrc/js/application/phortune/phortune-credit-card-form.js' => '2290aeef',
'rsrc/js/application/policy/behavior-policy-control.js' => 'd0c516d5',
'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '5e9f347c',
'rsrc/js/application/projects/WorkboardBoard.js' => '52291776',
'rsrc/js/application/projects/WorkboardCard.js' => 'c587b80f',
'rsrc/js/application/projects/WorkboardColumn.js' => 'bae58312',
'rsrc/js/application/projects/WorkboardController.js' => '55baf5ed',
'rsrc/js/application/projects/behavior-project-boards.js' => '14a1faae',
'rsrc/js/application/projects/behavior-project-create.js' => '065227cc',
'rsrc/js/application/projects/behavior-reorder-columns.js' => 'e1d25dfb',
'rsrc/js/application/releeph/releeph-preview-branch.js' => 'b2b4fbaf',
'rsrc/js/application/releeph/releeph-request-state-change.js' => 'a0b57eb8',
'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'de2e896f',
'rsrc/js/application/repository/repository-crossreference.js' => 'e5339c43',
'rsrc/js/application/search/behavior-reorder-profile-menu-items.js' => 'e2e0a072',
'rsrc/js/application/search/behavior-reorder-queries.js' => 'e9581f08',
'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => '887ad43f',
'rsrc/js/application/transactions/behavior-comment-actions.js' => '06460e71',
'rsrc/js/application/transactions/behavior-reorder-configs.js' => 'd7a74243',
'rsrc/js/application/transactions/behavior-reorder-fields.js' => 'b59e1e96',
'rsrc/js/application/transactions/behavior-show-older-transactions.js' => 'dbbf48b6',
'rsrc/js/application/transactions/behavior-transaction-comment-form.js' => 'b23b49e6',
'rsrc/js/application/transactions/behavior-transaction-list.js' => '13c739ea',
'rsrc/js/application/typeahead/behavior-typeahead-browse.js' => '635de1ec',
'rsrc/js/application/typeahead/behavior-typeahead-search.js' => '93d0c9e3',
'rsrc/js/application/uiexample/JavelinViewExample.js' => 'd4a14807',
'rsrc/js/application/uiexample/ReactorButtonExample.js' => 'd19198c8',
'rsrc/js/application/uiexample/ReactorCheckboxExample.js' => '519705ea',
'rsrc/js/application/uiexample/ReactorFocusExample.js' => '40a6a403',
'rsrc/js/application/uiexample/ReactorInputExample.js' => '886fd850',
'rsrc/js/application/uiexample/ReactorMouseoverExample.js' => '47c794d8',
'rsrc/js/application/uiexample/ReactorRadioExample.js' => '988040b4',
'rsrc/js/application/uiexample/ReactorSelectExample.js' => 'a155550f',
'rsrc/js/application/uiexample/ReactorSendClassExample.js' => '1def2711',
'rsrc/js/application/uiexample/ReactorSendPropertiesExample.js' => 'b1f0ccee',
'rsrc/js/application/uiexample/busy-example.js' => '60479091',
'rsrc/js/application/uiexample/gesture-example.js' => '558829c2',
'rsrc/js/application/uiexample/notification-example.js' => '8ce821c5',
'rsrc/js/core/Busy.js' => '59a7976a',
'rsrc/js/core/DragAndDropFileUpload.js' => '58dea2fa',
'rsrc/js/core/DraggableList.js' => '5a13c79f',
'rsrc/js/core/FileUpload.js' => '680ea2c8',
'rsrc/js/core/Hovercard.js' => '1bd28176',
'rsrc/js/core/KeyboardShortcut.js' => '1ae869f2',
'rsrc/js/core/KeyboardShortcutManager.js' => 'c1700f6f',
'rsrc/js/core/MultirowRowManager.js' => 'b5d57730',
'rsrc/js/core/Notification.js' => 'ccf1cbf8',
'rsrc/js/core/Prefab.js' => 'cfd23f37',
'rsrc/js/core/ShapedRequest.js' => '7cbe244b',
'rsrc/js/core/TextAreaUtils.js' => '320810c8',
'rsrc/js/core/Title.js' => 'df5e11d2',
'rsrc/js/core/ToolTip.js' => '6323f942',
'rsrc/js/core/behavior-active-nav.js' => 'e379b58e',
'rsrc/js/core/behavior-audio-source.js' => '59b251eb',
'rsrc/js/core/behavior-autofocus.js' => '7319e029',
'rsrc/js/core/behavior-badge-view.js' => '8ff5e24c',
'rsrc/js/core/behavior-choose-control.js' => '327a00d1',
'rsrc/js/core/behavior-crop.js' => 'fa0f4fc2',
'rsrc/js/core/behavior-dark-console.js' => 'f411b6ae',
'rsrc/js/core/behavior-detect-timezone.js' => '4c193c96',
'rsrc/js/core/behavior-device.js' => 'bb1dd507',
'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '484a6e22',
'rsrc/js/core/behavior-error-log.js' => '6882e80a',
'rsrc/js/core/behavior-fancy-datepicker.js' => '568931f3',
'rsrc/js/core/behavior-file-tree.js' => '88236f00',
'rsrc/js/core/behavior-form.js' => '5c54cbf3',
'rsrc/js/core/behavior-gesture.js' => '3ab51e2c',
'rsrc/js/core/behavior-global-drag-and-drop.js' => 'c8e57404',
'rsrc/js/core/behavior-high-security-warning.js' => 'a464fe03',
'rsrc/js/core/behavior-history-install.js' => '7ee2b591',
'rsrc/js/core/behavior-hovercard.js' => 'bcaccd64',
'rsrc/js/core/behavior-keyboard-pager.js' => 'a8da01f0',
'rsrc/js/core/behavior-keyboard-shortcuts.js' => '7835f8c9',
'rsrc/js/core/behavior-lightbox-attachments.js' => 'f8ba29d7',
'rsrc/js/core/behavior-line-linker.js' => '1499a8cb',
'rsrc/js/core/behavior-more.js' => 'a80d0378',
'rsrc/js/core/behavior-object-selector.js' => '49b73b36',
'rsrc/js/core/behavior-oncopy.js' => '2926fff2',
'rsrc/js/core/behavior-phabricator-nav.js' => '56a1ca03',
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '116cf19b',
'rsrc/js/core/behavior-read-only-warning.js' => 'ba158207',
'rsrc/js/core/behavior-refresh-csrf.js' => 'ab2f381b',
'rsrc/js/core/behavior-remarkup-preview.js' => '4b700e9e',
'rsrc/js/core/behavior-reorder-applications.js' => '76b9fc3e',
'rsrc/js/core/behavior-reveal-content.js' => '60821bc7',
'rsrc/js/core/behavior-scrollbar.js' => '834a1173',
'rsrc/js/core/behavior-search-typeahead.js' => '06c32383',
'rsrc/js/core/behavior-select-content.js' => 'bf5374ef',
'rsrc/js/core/behavior-select-on-click.js' => '4e3e79a6',
'rsrc/js/core/behavior-setup-check-https.js' => '491416b3',
'rsrc/js/core/behavior-time-typeahead.js' => '522431f7',
'rsrc/js/core/behavior-toggle-class.js' => '92b9ec77',
'rsrc/js/core/behavior-tokenizer.js' => 'b3a4b884',
'rsrc/js/core/behavior-tooltip.js' => '42fcb747',
'rsrc/js/core/behavior-watch-anchor.js' => '9f36c42d',
'rsrc/js/core/behavior-workflow.js' => '0a3f3021',
'rsrc/js/core/phtize.js' => 'd254d646',
- 'rsrc/js/phui/behavior-phui-dropdown-menu.js' => '54733475',
+ 'rsrc/js/phui/behavior-phui-dropdown-menu.js' => '1aa4c968',
'rsrc/js/phui/behavior-phui-file-upload.js' => 'b003d4fb',
'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836',
'rsrc/js/phui/behavior-phui-profile-menu.js' => '12884df9',
+ 'rsrc/js/phui/behavior-phui-submenu.js' => 'a6f7a73b',
'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8',
'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262',
'rsrc/js/phuix/PHUIXAutocomplete.js' => '9196fb06',
- 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca',
+ 'rsrc/js/phuix/PHUIXDropdownMenu.js' => '82e270da',
'rsrc/js/phuix/PHUIXFormControl.js' => 'e15869a8',
'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b',
),
'symbols' => array(
'almanac-css' => 'dbb9b3af',
'aphront-bars' => '231ac33c',
'aphront-dark-console-css' => 'f54bf286',
'aphront-dialog-view-css' => '913c172e',
'aphront-list-filter-view-css' => '5d6f0526',
'aphront-multi-column-view-css' => 'fd18389d',
'aphront-panel-view-css' => '8427b78d',
'aphront-table-view-css' => '9258e19f',
'aphront-tokenizer-control-css' => '056da01b',
'aphront-tooltip-css' => '1a07aea8',
'aphront-typeahead-control-css' => 'd4f16145',
'auth-css' => '0877ed6e',
'bulk-job-css' => 'df9c1d4a',
'changeset-view-manager' => 'a2828756',
'conduit-api-css' => '7bc725c4',
'config-options-css' => '0ede4c9b',
'config-welcome-css' => '6abd79be',
'conpherence-durable-column-view' => '86396117',
'conpherence-menu-css' => 'f99fee4c',
'conpherence-message-pane-css' => '5897d3ac',
'conpherence-notification-css' => '6cdcc253',
'conpherence-thread-manager' => '01774ab2',
'conpherence-transaction-css' => '85d0974c',
'conpherence-update-css' => 'faf6be09',
'conpherence-widget-pane-css' => '775eaaba',
'd3' => 'a11a5ff2',
'differential-changeset-view-css' => 'ccfbc869',
'differential-core-view-css' => '5b7b8ff4',
'differential-inline-comment-editor' => '64a5550f',
'differential-revision-add-comment-css' => 'c47f8c40',
'differential-revision-comment-css' => '14b8565a',
'differential-revision-history-css' => '0e8eb855',
'differential-revision-list-css' => 'f3c47d33',
'differential-table-of-contents-css' => 'ae4b7a55',
'diffusion-icons-css' => 'd678600a',
'diffusion-readme-css' => '297373eb',
'diffusion-source-css' => '68b30fd3',
'diviner-shared-css' => 'aa3656aa',
'font-aleo' => '8bdb2835',
'font-fontawesome' => '2b7ebbcc',
'font-lato' => 'c7ccd872',
'global-drag-and-drop-css' => '5c1b47c2',
'harbormaster-css' => 'f491c9f4',
'herald-css' => 'dc31f6e9',
'herald-rule-editor' => 'd6a7e717',
'herald-test-css' => 'a52e323e',
'inline-comment-summary-css' => '51efda3a',
'javelin-aphlict' => '5359e785',
'javelin-behavior' => '61cbc29a',
'javelin-behavior-aphlict-dropdown' => '031cee25',
'javelin-behavior-aphlict-listen' => 'fb20ac8d',
'javelin-behavior-aphlict-status' => 'ea681761',
'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884',
'javelin-behavior-aphront-crop' => 'fa0f4fc2',
'javelin-behavior-aphront-drag-and-drop-textarea' => '484a6e22',
'javelin-behavior-aphront-form-disable-on-submit' => '5c54cbf3',
'javelin-behavior-aphront-more' => 'a80d0378',
'javelin-behavior-audio-source' => '59b251eb',
'javelin-behavior-audit-preview' => 'd835b03a',
'javelin-behavior-badge-view' => '8ff5e24c',
'javelin-behavior-bulk-job-reload' => 'edf8a145',
'javelin-behavior-choose-control' => '327a00d1',
'javelin-behavior-comment-actions' => '06460e71',
'javelin-behavior-config-reorder-fields' => 'b6993408',
'javelin-behavior-conpherence-drag-and-drop-photo' => 'cf86d16a',
'javelin-behavior-conpherence-menu' => '1d45c74d',
'javelin-behavior-conpherence-pontificate' => '21ba5861',
'javelin-behavior-conpherence-widget-pane' => 'a8458711',
'javelin-behavior-countdown-timer' => 'e4cc26b3',
'javelin-behavior-dark-console' => 'f411b6ae',
'javelin-behavior-dashboard-async-panel' => '469c0d9e',
'javelin-behavior-dashboard-move-panels' => '019f36c4',
'javelin-behavior-dashboard-query-panel-select' => '453c5375',
'javelin-behavior-dashboard-tab-panel' => 'd4eecc63',
'javelin-behavior-day-view' => '5c46cff2',
'javelin-behavior-desktop-notifications-control' => 'edd1ba66',
'javelin-behavior-detect-timezone' => '4c193c96',
'javelin-behavior-device' => 'bb1dd507',
'javelin-behavior-differential-add-reviewers-and-ccs' => 'e10f8e18',
'javelin-behavior-differential-comment-jump' => '4fdb476d',
'javelin-behavior-differential-diff-radios' => 'e1ff79b1',
'javelin-behavior-differential-dropdown-menus' => '9a6b9324',
'javelin-behavior-differential-edit-inline-comments' => '4fbbc3e9',
'javelin-behavior-differential-feedback-preview' => 'b064af76',
'javelin-behavior-differential-keyboard-navigation' => '2c426492',
'javelin-behavior-differential-populate' => '8694b1df',
'javelin-behavior-differential-toggle-files' => 'ca3f91eb',
'javelin-behavior-differential-user-select' => 'a8d8459d',
'javelin-behavior-diffusion-browse-file' => '054a0f0b',
'javelin-behavior-diffusion-commit-branches' => 'bdaf4d04',
'javelin-behavior-diffusion-commit-graph' => '5a0b1a64',
'javelin-behavior-diffusion-jump-to' => '73d09eef',
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc',
'javelin-behavior-doorkeeper-tag' => 'e5822781',
'javelin-behavior-drydock-live-operation-status' => '901935ef',
'javelin-behavior-durable-column' => 'd3506890',
'javelin-behavior-editengine-reorder-configs' => 'd7a74243',
'javelin-behavior-editengine-reorder-fields' => 'b59e1e96',
'javelin-behavior-error-log' => '6882e80a',
'javelin-behavior-event-all-day' => '38dcf3c8',
'javelin-behavior-fancy-datepicker' => '568931f3',
'javelin-behavior-global-drag-and-drop' => 'c8e57404',
'javelin-behavior-herald-rule-editor' => '7ebaeed3',
'javelin-behavior-high-security-warning' => 'a464fe03',
'javelin-behavior-history-install' => '7ee2b591',
'javelin-behavior-icon-composer' => '8499b6ab',
'javelin-behavior-launch-icon-composer' => '48086888',
'javelin-behavior-lightbox-attachments' => 'f8ba29d7',
'javelin-behavior-line-chart' => 'e4232876',
'javelin-behavior-load-blame' => '42126667',
'javelin-behavior-maniphest-batch-editor' => '782ab6e7',
'javelin-behavior-maniphest-batch-selector' => '7b98d7c5',
'javelin-behavior-maniphest-list-editor' => 'a9f88de2',
'javelin-behavior-maniphest-subpriority-editor' => '71237763',
'javelin-behavior-owners-path-editor' => '7a68dda3',
'javelin-behavior-passphrase-credential-control' => '3cb0b2fc',
'javelin-behavior-persona-login' => '9414ff18',
'javelin-behavior-phabricator-active-nav' => 'e379b58e',
'javelin-behavior-phabricator-autofocus' => '7319e029',
'javelin-behavior-phabricator-busy-example' => '60479091',
'javelin-behavior-phabricator-file-tree' => '88236f00',
'javelin-behavior-phabricator-gesture' => '3ab51e2c',
'javelin-behavior-phabricator-gesture-example' => '558829c2',
'javelin-behavior-phabricator-keyboard-pager' => 'a8da01f0',
'javelin-behavior-phabricator-keyboard-shortcuts' => '7835f8c9',
'javelin-behavior-phabricator-line-linker' => '1499a8cb',
'javelin-behavior-phabricator-nav' => '56a1ca03',
'javelin-behavior-phabricator-notification-example' => '8ce821c5',
'javelin-behavior-phabricator-object-selector' => '49b73b36',
'javelin-behavior-phabricator-oncopy' => '2926fff2',
'javelin-behavior-phabricator-remarkup-assist' => '116cf19b',
'javelin-behavior-phabricator-reveal-content' => '60821bc7',
'javelin-behavior-phabricator-search-typeahead' => '06c32383',
'javelin-behavior-phabricator-show-older-transactions' => 'dbbf48b6',
'javelin-behavior-phabricator-tooltips' => '42fcb747',
'javelin-behavior-phabricator-transaction-comment-form' => 'b23b49e6',
'javelin-behavior-phabricator-transaction-list' => '13c739ea',
'javelin-behavior-phabricator-watch-anchor' => '9f36c42d',
'javelin-behavior-pholio-mock-edit' => 'bee502c8',
'javelin-behavior-pholio-mock-view' => 'fbe497e7',
- 'javelin-behavior-phui-dropdown-menu' => '54733475',
+ 'javelin-behavior-phui-dropdown-menu' => '1aa4c968',
'javelin-behavior-phui-file-upload' => 'b003d4fb',
'javelin-behavior-phui-hovercards' => 'bcaccd64',
'javelin-behavior-phui-object-box-tabs' => '2bfa2836',
'javelin-behavior-phui-profile-menu' => '12884df9',
+ 'javelin-behavior-phui-submenu' => 'a6f7a73b',
'javelin-behavior-policy-control' => 'd0c516d5',
'javelin-behavior-policy-rule-editor' => '5e9f347c',
'javelin-behavior-project-boards' => '14a1faae',
'javelin-behavior-project-create' => '065227cc',
'javelin-behavior-quicksand-blacklist' => '7927a7d3',
'javelin-behavior-read-only-warning' => 'ba158207',
'javelin-behavior-recurring-edit' => '5f1c4d5f',
'javelin-behavior-refresh-csrf' => 'ab2f381b',
'javelin-behavior-releeph-preview-branch' => 'b2b4fbaf',
'javelin-behavior-releeph-request-state-change' => 'a0b57eb8',
'javelin-behavior-releeph-request-typeahead' => 'de2e896f',
'javelin-behavior-remarkup-preview' => '4b700e9e',
'javelin-behavior-reorder-applications' => '76b9fc3e',
'javelin-behavior-reorder-columns' => 'e1d25dfb',
'javelin-behavior-reorder-profile-menu-items' => 'e2e0a072',
'javelin-behavior-repository-crossreference' => 'e5339c43',
'javelin-behavior-scrollbar' => '834a1173',
'javelin-behavior-search-reorder-queries' => 'e9581f08',
'javelin-behavior-select-content' => 'bf5374ef',
'javelin-behavior-select-on-click' => '4e3e79a6',
'javelin-behavior-setup-check-https' => '491416b3',
'javelin-behavior-slowvote-embed' => '887ad43f',
'javelin-behavior-stripe-payment-form' => '3f5d6dbf',
'javelin-behavior-test-payment-form' => 'fc91ab6c',
'javelin-behavior-time-typeahead' => '522431f7',
'javelin-behavior-toggle-class' => '92b9ec77',
'javelin-behavior-typeahead-browse' => '635de1ec',
'javelin-behavior-typeahead-search' => '93d0c9e3',
'javelin-behavior-view-placeholder' => '47830651',
'javelin-behavior-workflow' => '0a3f3021',
'javelin-color' => '7e41274a',
'javelin-cookie' => '62dfea03',
'javelin-diffusion-locate-file-source' => 'b42eddc7',
'javelin-dom' => '805b806a',
'javelin-dynval' => 'f6555212',
'javelin-event' => '2ee659ce',
'javelin-fx' => '54b612ba',
'javelin-history' => 'd4505101',
'javelin-install' => '05270951',
'javelin-json' => '69adf288',
'javelin-leader' => 'fea0eb47',
'javelin-magical-init' => '3010e992',
'javelin-mask' => '8a41885b',
'javelin-quicksand' => '6b8ef10b',
'javelin-reactor' => '2b8de964',
'javelin-reactor-dom' => 'c90a04fc',
'javelin-reactor-node-calmer' => '76f4ebed',
'javelin-reactornode' => '1ad0a787',
'javelin-request' => '94b750d2',
'javelin-resource' => '44959b73',
'javelin-routable' => 'b3e7d692',
'javelin-router' => '29274e2b',
'javelin-scrollbar' => '087e919c',
'javelin-sound' => '949c0fe5',
'javelin-stratcom' => '6ad39b6f',
'javelin-tokenizer' => '8d3bc1b2',
'javelin-typeahead' => '70baed2f',
'javelin-typeahead-composite-source' => '503e17fd',
'javelin-typeahead-normalizer' => 'e6e25838',
'javelin-typeahead-ondemand-source' => '013ffff9',
'javelin-typeahead-preloaded-source' => '54f314a0',
'javelin-typeahead-source' => 'b25d5444',
'javelin-typeahead-static-source' => '6c0e62fa',
'javelin-uri' => 'c989ade3',
'javelin-util' => '93cc50d6',
'javelin-vector' => '2caa8fb8',
'javelin-view' => '0f764c35',
'javelin-view-html' => 'fe287620',
'javelin-view-interpreter' => 'f829edb3',
'javelin-view-renderer' => '6c2b09a2',
'javelin-view-visitor' => 'efe49472',
'javelin-websocket' => 'e292eaf4',
'javelin-workboard-board' => '52291776',
'javelin-workboard-card' => 'c587b80f',
'javelin-workboard-column' => 'bae58312',
'javelin-workboard-controller' => '55baf5ed',
'javelin-workflow' => '1e911d0f',
'lightbox-attachment-css' => '7acac05d',
'maniphest-batch-editor' => 'b0f0b6d5',
'maniphest-report-css' => '9b9580b7',
'maniphest-task-edit-css' => 'fda62a9b',
'maniphest-task-summary-css' => '11cc5344',
'multirow-row-manager' => 'b5d57730',
'owners-path-editor' => 'aa1733d0',
'owners-path-editor-css' => '2f00933b',
'paste-css' => '1898e534',
'path-typeahead' => 'f7fc67ec',
'people-profile-css' => '2473d929',
'phabricator-action-list-view-css' => 'c5eba19d',
'phabricator-application-launch-view-css' => '95351601',
'phabricator-busy' => '59a7976a',
'phabricator-chatlog-css' => 'd295b020',
'phabricator-content-source-view-css' => '4b8b05d4',
'phabricator-core-css' => 'd0801452',
'phabricator-countdown-css' => '16c52f5c',
'phabricator-dashboard-css' => 'bc6f2127',
'phabricator-drag-and-drop-file-upload' => '58dea2fa',
'phabricator-draggable-list' => '5a13c79f',
'phabricator-fatal-config-template-css' => '8e6c6fcd',
'phabricator-feed-css' => 'ecd4ec57',
'phabricator-file-upload' => '680ea2c8',
'phabricator-filetree-view-css' => 'fccf9f82',
'phabricator-flag-css' => '5337623f',
'phabricator-keyboard-shortcut' => '1ae869f2',
'phabricator-keyboard-shortcut-manager' => 'c1700f6f',
'phabricator-main-menu-view' => 'b623169f',
'phabricator-nav-view-css' => 'ac79a758',
'phabricator-notification' => 'ccf1cbf8',
'phabricator-notification-css' => '3f6c89c9',
'phabricator-notification-menu-css' => 'f31c0bde',
'phabricator-object-selector-css' => '85ee8ce6',
'phabricator-phtize' => 'd254d646',
'phabricator-prefab' => 'cfd23f37',
'phabricator-remarkup-css' => '523d34bb',
'phabricator-search-results-css' => '7dea472c',
'phabricator-shaped-request' => '7cbe244b',
'phabricator-side-menu-view-css' => 'dd849797',
'phabricator-slowvote-css' => 'a94b7230',
'phabricator-source-code-view-css' => 'cbeef983',
'phabricator-standard-page-view' => 'e709f6d0',
'phabricator-textareautils' => '320810c8',
'phabricator-title' => 'df5e11d2',
'phabricator-tooltip' => '6323f942',
'phabricator-ui-example-css' => '528b19de',
'phabricator-uiexample-javelin-view' => 'd4a14807',
'phabricator-uiexample-reactor-button' => 'd19198c8',
'phabricator-uiexample-reactor-checkbox' => '519705ea',
'phabricator-uiexample-reactor-focus' => '40a6a403',
'phabricator-uiexample-reactor-input' => '886fd850',
'phabricator-uiexample-reactor-mouseover' => '47c794d8',
'phabricator-uiexample-reactor-radio' => '988040b4',
'phabricator-uiexample-reactor-select' => 'a155550f',
'phabricator-uiexample-reactor-sendclass' => '1def2711',
'phabricator-uiexample-reactor-sendproperties' => 'b1f0ccee',
'phabricator-zindex-css' => '5b6fcf3f',
'phame-css' => 'bf6a743f',
'pholio-css' => 'ca89d380',
'pholio-edit-css' => '07676f51',
'pholio-inline-comments-css' => '8e545e49',
'phortune-credit-card-form' => '2290aeef',
'phortune-credit-card-form-css' => '8391eb02',
'phortune-css' => '5b99dae0',
'phrequent-css' => 'ffc185ad',
'phriction-document-css' => '4282e4ad',
'phui-action-panel-css' => '91c7b835',
'phui-badge-view-css' => '3baef8db',
'phui-big-info-view-css' => 'bd903741',
'phui-box-css' => '5c8387cf',
- 'phui-button-css' => 'a64a8de6',
+ 'phui-button-css' => 'e266e0bc',
'phui-calendar-css' => 'ccabe893',
'phui-calendar-day-css' => 'd1cf6f93',
'phui-calendar-list-css' => '56e6381a',
'phui-calendar-month-css' => '476be7e0',
'phui-chart-css' => '6bf6f78e',
'phui-crumbs-view-css' => '6b813619',
'phui-curtain-view-css' => '7148ae25',
'phui-document-summary-view-css' => '9ca48bdf',
'phui-document-view-css' => '715aedfb',
'phui-document-view-pro-css' => 'a3730b94',
'phui-feed-story-css' => 'aa49845d',
'phui-font-icon-base-css' => '6449bce8',
'phui-fontkit-css' => '9cda225e',
'phui-form-css' => 'aac1d51d',
'phui-form-view-css' => '6a51768e',
'phui-head-thing-view-css' => 'fd311e5f',
'phui-header-view-css' => '4c7dd8f5',
'phui-hovercard' => '1bd28176',
'phui-hovercard-view-css' => 'de1a2119',
'phui-icon-set-selector-css' => '1ab67aad',
'phui-icon-view-css' => '3f33ab57',
'phui-image-mask-css' => 'a8498f9c',
'phui-info-panel-css' => '27ea50a1',
'phui-info-view-css' => '28efab79',
'phui-inline-comment-view-css' => '5953c28e',
'phui-list-view-css' => '9da2aa00',
'phui-object-box-css' => '6b487c57',
'phui-object-item-list-view-css' => '8d99e42b',
'phui-pager-css' => 'bea33d23',
'phui-pinboard-view-css' => '2495140e',
'phui-profile-menu-css' => 'c8557f33',
'phui-property-list-view-css' => 'd4bbd0cb',
'phui-remarkup-preview-css' => '1a8f2591',
'phui-segment-bar-view-css' => '46342871',
'phui-spacing-css' => '042804d6',
'phui-status-list-view-css' => 'd5263e49',
'phui-tag-view-css' => '6bbd83e2',
'phui-theme-css' => '027ba77e',
'phui-timeline-view-css' => '8ea41b25',
'phui-two-column-view-css' => '9fb86c85',
'phui-workboard-color-css' => 'ac6fe6a7',
'phui-workboard-view-css' => 'e6d89647',
'phui-workcard-view-css' => '0c62d7c5',
'phui-workpanel-view-css' => '92197373',
'phuix-action-list-view' => 'b5c256b8',
'phuix-action-view' => '8cf6d262',
'phuix-autocomplete' => '9196fb06',
- 'phuix-dropdown-menu' => 'bd4c8dca',
+ 'phuix-dropdown-menu' => '82e270da',
'phuix-form-control-view' => 'e15869a8',
'phuix-icon-view' => 'bff6884b',
'policy-css' => '957ea14c',
'policy-edit-css' => '815c66f7',
'policy-transaction-detail-css' => '82100a43',
'ponder-view-css' => 'fbd45f96',
'project-card-view-css' => '9418c97d',
'project-view-css' => 'cbaa10a1',
'releeph-core' => '9b3c5733',
'releeph-preview-branch' => 'b7a6f4a5',
'releeph-request-differential-create-dialog' => '8d8b92cd',
'releeph-request-typeahead-css' => '667a48ae',
'setup-issue-css' => 'db7e9c40',
'sprite-login-css' => '60e8560e',
'sprite-menu-css' => '9dd65b92',
'sprite-tokens-css' => '4f399012',
'syntax-default-css' => '9923583c',
'syntax-highlighting-css' => '9fc496d5',
'tokens-css' => '3d0f239e',
'typeahead-browse-css' => '8904346a',
'unhandled-exception-css' => '4c96257a',
),
'requires' => array(
'013ffff9' => array(
'javelin-install',
'javelin-util',
'javelin-request',
'javelin-typeahead-source',
),
'01774ab2' => array(
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-install',
'javelin-aphlict',
'javelin-workflow',
'javelin-router',
'javelin-behavior-device',
'javelin-vector',
),
'019f36c4' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-workflow',
'phabricator-draggable-list',
),
'031cee25' => array(
'javelin-behavior',
'javelin-request',
'javelin-stratcom',
'javelin-vector',
'javelin-dom',
'javelin-uri',
'javelin-behavior-device',
'phabricator-title',
),
'05270951' => array(
'javelin-util',
'javelin-magical-init',
),
'054a0f0b' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'phabricator-tooltip',
),
'056da01b' => array(
'aphront-typeahead-control-css',
'phui-tag-view-css',
),
'06460e71' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-workflow',
'javelin-dom',
'phuix-form-control-view',
'phuix-icon-view',
'javelin-behavior-phabricator-gesture',
),
'065227cc' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-workflow',
),
'06c32383' => array(
'javelin-behavior',
'javelin-typeahead-ondemand-source',
'javelin-typeahead',
'javelin-dom',
'javelin-uri',
'javelin-util',
'javelin-stratcom',
'phabricator-prefab',
'phuix-icon-view',
),
'087e919c' => array(
'javelin-install',
'javelin-dom',
'javelin-stratcom',
'javelin-vector',
),
'0a3f3021' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-workflow',
'javelin-dom',
'javelin-router',
),
'0f764c35' => array(
'javelin-install',
'javelin-util',
),
'116cf19b' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'phabricator-phtize',
'phabricator-textareautils',
'javelin-workflow',
'javelin-vector',
'phuix-autocomplete',
),
'12884df9' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
),
'13c739ea' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-workflow',
'javelin-dom',
'javelin-uri',
'phabricator-textareautils',
),
'1499a8cb' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'javelin-history',
),
'14a1faae' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-vector',
'javelin-stratcom',
'javelin-workflow',
'javelin-workboard-controller',
),
+ '1aa4c968' => array(
+ 'javelin-behavior',
+ 'javelin-stratcom',
+ 'javelin-dom',
+ 'phuix-dropdown-menu',
+ ),
'1ad0a787' => array(
'javelin-install',
'javelin-reactor',
'javelin-util',
'javelin-reactor-node-calmer',
),
'1ae869f2' => array(
'javelin-install',
'javelin-util',
'phabricator-keyboard-shortcut-manager',
),
'1bd28176' => array(
'javelin-install',
'javelin-dom',
'javelin-vector',
'javelin-request',
'javelin-uri',
),
'1d45c74d' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-workflow',
'javelin-behavior-device',
'javelin-history',
'javelin-vector',
'javelin-scrollbar',
'phabricator-title',
'phabricator-shaped-request',
'conpherence-thread-manager',
),
'1def2711' => array(
'javelin-install',
'javelin-dom',
'javelin-reactor-dom',
),
'1e911d0f' => array(
'javelin-stratcom',
'javelin-request',
'javelin-dom',
'javelin-vector',
'javelin-install',
'javelin-util',
'javelin-mask',
'javelin-uri',
'javelin-routable',
),
'21ba5861' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-workflow',
'javelin-stratcom',
'conpherence-thread-manager',
),
'2290aeef' => array(
'javelin-install',
'javelin-dom',
'javelin-json',
'javelin-workflow',
'javelin-util',
),
'2926fff2' => array(
'javelin-behavior',
'javelin-dom',
),
'29274e2b' => array(
'javelin-install',
'javelin-util',
),
'2b8de964' => array(
'javelin-install',
'javelin-util',
),
'2bfa2836' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
),
'2c426492' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'phabricator-keyboard-shortcut',
),
'2caa8fb8' => array(
'javelin-install',
'javelin-event',
),
'2ee659ce' => array(
'javelin-install',
),
'320810c8' => array(
'javelin-install',
'javelin-dom',
'javelin-vector',
),
'327a00d1' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'javelin-workflow',
),
'3ab51e2c' => array(
'javelin-behavior',
'javelin-behavior-device',
'javelin-stratcom',
'javelin-vector',
'javelin-dom',
'javelin-magical-init',
),
'3cb0b2fc' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-workflow',
'javelin-util',
'javelin-uri',
),
'3f5d6dbf' => array(
'javelin-behavior',
'javelin-dom',
'phortune-credit-card-form',
),
'40a6a403' => array(
'javelin-install',
'javelin-dom',
'javelin-reactor-dom',
),
42126667 => array(
'javelin-behavior',
'javelin-dom',
'javelin-request',
),
'42fcb747' => array(
'javelin-behavior',
'javelin-behavior-device',
'javelin-stratcom',
'phabricator-tooltip',
),
'44959b73' => array(
'javelin-util',
'javelin-uri',
'javelin-install',
),
'453c5375' => array(
'javelin-behavior',
'javelin-dom',
),
'469c0d9e' => array(
'javelin-behavior',
'javelin-dom',
'javelin-workflow',
),
47830651 => array(
'javelin-behavior',
'javelin-dom',
'javelin-view-renderer',
'javelin-install',
),
'47c794d8' => array(
'javelin-install',
'javelin-dom',
'javelin-reactor-dom',
),
48086888 => array(
'javelin-behavior',
'javelin-dom',
'javelin-workflow',
),
'484a6e22' => array(
'javelin-behavior',
'javelin-dom',
'phabricator-drag-and-drop-file-upload',
'phabricator-textareautils',
),
'491416b3' => array(
'javelin-behavior',
'javelin-uri',
'phabricator-notification',
),
'49b73b36' => array(
'javelin-behavior',
'javelin-dom',
'javelin-request',
'javelin-util',
),
'4b700e9e' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'phabricator-shaped-request',
),
'4c193c96' => array(
'javelin-behavior',
'javelin-uri',
'phabricator-notification',
),
'4e3e79a6' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
),
'4fbbc3e9' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'javelin-util',
'javelin-vector',
'differential-inline-comment-editor',
),
'4fdb476d' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
),
'503e17fd' => array(
'javelin-install',
'javelin-typeahead-source',
'javelin-util',
),
'519705ea' => array(
'javelin-install',
'javelin-dom',
'javelin-reactor-dom',
),
'522431f7' => array(
'javelin-behavior',
'javelin-util',
'javelin-dom',
'javelin-stratcom',
'javelin-vector',
'javelin-typeahead-static-source',
),
52291776 => array(
'javelin-install',
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-workflow',
'phabricator-draggable-list',
'javelin-workboard-column',
),
'5359e785' => array(
'javelin-install',
'javelin-util',
'javelin-websocket',
'javelin-leader',
'javelin-json',
),
- 54733475 => array(
- 'javelin-behavior',
- 'javelin-stratcom',
- 'javelin-dom',
- 'phuix-dropdown-menu',
- ),
'54b612ba' => array(
'javelin-color',
'javelin-install',
'javelin-util',
),
'54f314a0' => array(
'javelin-install',
'javelin-util',
'javelin-request',
'javelin-typeahead-source',
),
'558829c2' => array(
'javelin-stratcom',
'javelin-behavior',
'javelin-vector',
'javelin-dom',
),
'55baf5ed' => array(
'javelin-install',
'javelin-dom',
'javelin-util',
'javelin-vector',
'javelin-stratcom',
'javelin-workflow',
'phabricator-drag-and-drop-file-upload',
'javelin-workboard-board',
),
'568931f3' => array(
'javelin-behavior',
'javelin-util',
'javelin-dom',
'javelin-stratcom',
'javelin-vector',
),
'56a1ca03' => array(
'javelin-behavior',
'javelin-behavior-device',
'javelin-stratcom',
'javelin-dom',
'javelin-magical-init',
'javelin-vector',
'javelin-request',
'javelin-util',
),
'58dea2fa' => array(
'javelin-install',
'javelin-util',
'javelin-request',
'javelin-dom',
'javelin-uri',
'phabricator-file-upload',
),
'59a7976a' => array(
'javelin-install',
'javelin-dom',
'javelin-fx',
),
'59b251eb' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-vector',
'javelin-dom',
),
'5a0b1a64' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
),
'5a13c79f' => array(
'javelin-install',
'javelin-dom',
'javelin-stratcom',
'javelin-util',
'javelin-vector',
'javelin-magical-init',
),
'5c54cbf3' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
),
'5e9f347c' => array(
'javelin-behavior',
'multirow-row-manager',
'javelin-dom',
'javelin-util',
'phabricator-prefab',
'javelin-json',
),
60479091 => array(
'phabricator-busy',
'javelin-behavior',
),
'60821bc7' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
),
'61cbc29a' => array(
'javelin-magical-init',
'javelin-util',
),
'62dfea03' => array(
'javelin-install',
'javelin-util',
),
'6323f942' => array(
'javelin-install',
'javelin-util',
'javelin-dom',
'javelin-vector',
),
'635de1ec' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-workflow',
'javelin-dom',
),
'64a5550f' => array(
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-install',
'javelin-request',
'javelin-workflow',
),
'680ea2c8' => array(
'javelin-install',
'javelin-dom',
'phabricator-notification',
),
'6882e80a' => array(
'javelin-dom',
),
'69adf288' => array(
'javelin-install',
),
'6ad39b6f' => array(
'javelin-install',
'javelin-event',
'javelin-util',
'javelin-magical-init',
),
'6b8ef10b' => array(
'javelin-install',
),
'6c0e62fa' => array(
'javelin-install',
'javelin-typeahead-source',
),
'6c2b09a2' => array(
'javelin-install',
'javelin-util',
),
'6d3e1947' => array(
'javelin-behavior',
'javelin-diffusion-locate-file-source',
'javelin-dom',
'javelin-typeahead',
'javelin-uri',
),
'70baed2f' => array(
'javelin-install',
'javelin-dom',
'javelin-vector',
'javelin-util',
),
71237763 => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-workflow',
'phabricator-draggable-list',
),
'7319e029' => array(
'javelin-behavior',
'javelin-dom',
),
'73d09eef' => array(
'javelin-behavior',
'javelin-vector',
'javelin-dom',
),
'76b9fc3e' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-workflow',
'javelin-dom',
'phabricator-draggable-list',
),
'76f4ebed' => array(
'javelin-install',
'javelin-reactor',
'javelin-util',
),
'782ab6e7' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'phabricator-prefab',
'multirow-row-manager',
'javelin-json',
),
'7835f8c9' => array(
'javelin-behavior',
'javelin-workflow',
'javelin-json',
'javelin-dom',
'phabricator-keyboard-shortcut',
),
'7927a7d3' => array(
'javelin-behavior',
'javelin-quicksand',
),
'7a68dda3' => array(
'owners-path-editor',
'javelin-behavior',
),
'7b98d7c5' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-util',
),
'7cbe244b' => array(
'javelin-install',
'javelin-util',
'javelin-request',
'javelin-router',
),
'7e41274a' => array(
'javelin-install',
),
'7ebaeed3' => array(
'herald-rule-editor',
'javelin-behavior',
),
'7ee2b591' => array(
'javelin-behavior',
'javelin-history',
),
'805b806a' => array(
'javelin-magical-init',
'javelin-install',
'javelin-util',
'javelin-vector',
'javelin-stratcom',
),
+ '82e270da' => array(
+ 'javelin-install',
+ 'javelin-util',
+ 'javelin-dom',
+ 'javelin-vector',
+ 'javelin-stratcom',
+ ),
'834a1173' => array(
'javelin-behavior',
'javelin-scrollbar',
),
'8499b6ab' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
),
'85ee8ce6' => array(
'aphront-dialog-view-css',
),
'8694b1df' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'phabricator-tooltip',
'changeset-view-manager',
),
'88236f00' => array(
'javelin-behavior',
'phabricator-keyboard-shortcut',
'javelin-stratcom',
),
'886fd850' => array(
'javelin-install',
'javelin-reactor-dom',
'javelin-view-html',
'javelin-view-interpreter',
'javelin-view-renderer',
),
'887ad43f' => array(
'javelin-behavior',
'javelin-request',
'javelin-stratcom',
'javelin-dom',
),
'8a41885b' => array(
'javelin-install',
'javelin-dom',
),
'8bdb2835' => array(
'phui-fontkit-css',
),
'8ce821c5' => array(
'phabricator-notification',
'javelin-stratcom',
'javelin-behavior',
),
'8cf6d262' => array(
'javelin-install',
'javelin-dom',
'javelin-util',
),
'8d3bc1b2' => array(
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-install',
),
'8ff5e24c' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
),
'901935ef' => array(
'javelin-behavior',
'javelin-dom',
'javelin-request',
),
'9196fb06' => array(
'javelin-install',
'javelin-dom',
'phuix-icon-view',
'phabricator-prefab',
),
92197373 => array(
'phui-workcard-view-css',
),
'92b9ec77' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
),
'93d0c9e3' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-workflow',
'javelin-dom',
),
'9414ff18' => array(
'javelin-behavior',
'javelin-resource',
'javelin-stratcom',
'javelin-workflow',
'javelin-util',
),
'949c0fe5' => array(
'javelin-install',
),
'94b750d2' => array(
'javelin-install',
'javelin-stratcom',
'javelin-util',
'javelin-behavior',
'javelin-json',
'javelin-dom',
'javelin-resource',
'javelin-routable',
),
'988040b4' => array(
'javelin-install',
'javelin-dom',
'javelin-reactor-dom',
),
'9a6b9324' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-workflow',
'phuix-dropdown-menu',
'phuix-action-list-view',
'phuix-action-view',
'phabricator-phtize',
'changeset-view-manager',
),
'9f36c42d' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'javelin-vector',
),
'9fc496d5' => array(
'syntax-default-css',
),
'a0b57eb8' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-workflow',
'javelin-util',
'phabricator-keyboard-shortcut',
),
'a155550f' => array(
'javelin-install',
'javelin-dom',
'javelin-reactor-dom',
),
'a2828756' => array(
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-install',
'javelin-workflow',
'javelin-router',
'javelin-behavior-device',
'javelin-vector',
),
'a464fe03' => array(
'javelin-behavior',
'javelin-uri',
'phabricator-notification',
),
+ 'a6f7a73b' => array(
+ 'javelin-behavior',
+ 'javelin-stratcom',
+ 'javelin-dom',
+ ),
'a80d0378' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
),
'a8458711' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-workflow',
'javelin-util',
'phabricator-notification',
'javelin-behavior-device',
'phuix-dropdown-menu',
'phuix-action-list-view',
'phuix-action-view',
'conpherence-thread-manager',
),
'a8d8459d' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
),
'a8da01f0' => array(
'javelin-behavior',
'javelin-uri',
'phabricator-keyboard-shortcut',
),
'a9f88de2' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-workflow',
'javelin-fx',
'javelin-util',
),
'aa1733d0' => array(
'multirow-row-manager',
'javelin-install',
'path-typeahead',
'javelin-dom',
'javelin-util',
'phabricator-prefab',
),
'ab2f381b' => array(
'javelin-request',
'javelin-behavior',
'javelin-dom',
'javelin-router',
'javelin-util',
'phabricator-busy',
),
'b003d4fb' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'phuix-dropdown-menu',
),
'b064af76' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'javelin-request',
'javelin-util',
'phabricator-shaped-request',
),
'b1f0ccee' => array(
'javelin-install',
'javelin-dom',
'javelin-reactor-dom',
),
'b23b49e6' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-request',
'phabricator-shaped-request',
),
'b25d5444' => array(
'javelin-install',
'javelin-util',
'javelin-dom',
'javelin-typeahead-normalizer',
),
'b2b4fbaf' => array(
'javelin-behavior',
'javelin-dom',
'javelin-uri',
'javelin-request',
),
'b3a4b884' => array(
'javelin-behavior',
'phabricator-prefab',
),
'b3e7d692' => array(
'javelin-install',
),
'b42eddc7' => array(
'javelin-install',
'javelin-dom',
'javelin-typeahead-preloaded-source',
'javelin-util',
),
'b59e1e96' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-workflow',
'javelin-dom',
'phabricator-draggable-list',
),
'b5c256b8' => array(
'javelin-install',
'javelin-dom',
),
'b5d57730' => array(
'javelin-install',
'javelin-stratcom',
'javelin-dom',
'javelin-util',
),
'b623169f' => array(
'phui-theme-css',
),
'b6993408' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'javelin-json',
'phabricator-draggable-list',
),
'ba158207' => array(
'javelin-behavior',
'javelin-uri',
'phabricator-notification',
),
'bae58312' => array(
'javelin-install',
'javelin-workboard-card',
),
'bb1dd507' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'javelin-vector',
'javelin-install',
),
'bcaccd64' => array(
'javelin-behavior',
'javelin-behavior-device',
'javelin-stratcom',
'javelin-vector',
'phui-hovercard',
),
- 'bd4c8dca' => array(
- 'javelin-install',
- 'javelin-util',
- 'javelin-dom',
- 'javelin-vector',
- 'javelin-stratcom',
- ),
'bdaf4d04' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-request',
),
'bee502c8' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'javelin-workflow',
'javelin-quicksand',
'phabricator-phtize',
'phabricator-drag-and-drop-file-upload',
'phabricator-draggable-list',
),
'bf5374ef' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
),
'bff6884b' => array(
'javelin-install',
'javelin-dom',
),
'c1700f6f' => array(
'javelin-install',
'javelin-util',
'javelin-stratcom',
'javelin-dom',
'javelin-vector',
),
'c587b80f' => array(
'javelin-install',
),
'c7ccd872' => array(
'phui-fontkit-css',
),
'c8e57404' => array(
'javelin-behavior',
'javelin-dom',
'javelin-uri',
'javelin-mask',
'phabricator-drag-and-drop-file-upload',
),
'c90a04fc' => array(
'javelin-dom',
'javelin-dynval',
'javelin-reactor',
'javelin-reactornode',
'javelin-install',
'javelin-util',
),
'c989ade3' => array(
'javelin-install',
'javelin-util',
'javelin-stratcom',
),
'ca3f91eb' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'phabricator-phtize',
),
'ccf1cbf8' => array(
'javelin-install',
'javelin-dom',
'javelin-stratcom',
'javelin-util',
'phabricator-notification-css',
),
'ccfbc869' => array(
'phui-inline-comment-view-css',
),
'cf86d16a' => array(
'javelin-behavior',
'javelin-dom',
'javelin-workflow',
'phabricator-drag-and-drop-file-upload',
),
'cfd23f37' => array(
'javelin-install',
'javelin-util',
'javelin-dom',
'javelin-typeahead',
'javelin-tokenizer',
'javelin-typeahead-preloaded-source',
'javelin-typeahead-ondemand-source',
'javelin-dom',
'javelin-stratcom',
'javelin-util',
),
'd0c516d5' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'phuix-dropdown-menu',
'phuix-action-list-view',
'phuix-action-view',
'javelin-workflow',
'phuix-icon-view',
),
'd19198c8' => array(
'javelin-install',
'javelin-dom',
'javelin-util',
'javelin-dynval',
'javelin-reactor-dom',
),
'd254d646' => array(
'javelin-util',
),
'd3506890' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-behavior-device',
'javelin-scrollbar',
'javelin-quicksand',
'phabricator-keyboard-shortcut',
'conpherence-thread-manager',
),
'd4505101' => array(
'javelin-stratcom',
'javelin-install',
'javelin-uri',
'javelin-util',
),
'd4a14807' => array(
'javelin-install',
'javelin-dom',
'javelin-view',
),
'd4eecc63' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
),
'd6a7e717' => array(
'multirow-row-manager',
'javelin-install',
'javelin-util',
'javelin-dom',
'javelin-stratcom',
'javelin-json',
'phabricator-prefab',
),
'd7a74243' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-workflow',
'javelin-dom',
'phabricator-draggable-list',
),
'd835b03a' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'phabricator-shaped-request',
),
'dbbf48b6' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'phabricator-busy',
),
'de2e896f' => array(
'javelin-behavior',
'javelin-dom',
'javelin-typeahead',
'javelin-typeahead-ondemand-source',
'javelin-dom',
),
'df5e11d2' => array(
'javelin-install',
),
'e10f8e18' => array(
'javelin-behavior',
'javelin-dom',
'phabricator-prefab',
),
'e15869a8' => array(
'javelin-install',
'javelin-dom',
),
'e1d25dfb' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-workflow',
'javelin-dom',
'phabricator-draggable-list',
),
'e1ff79b1' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
),
'e292eaf4' => array(
'javelin-install',
),
'e2e0a072' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-workflow',
'javelin-dom',
'phabricator-draggable-list',
),
'e379b58e' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-vector',
'javelin-dom',
'javelin-uri',
),
'e4232876' => array(
'javelin-behavior',
'javelin-dom',
'javelin-vector',
'phui-chart-css',
),
'e4cc26b3' => array(
'javelin-behavior',
'javelin-dom',
),
'e5339c43' => array(
'javelin-behavior',
'javelin-dom',
'javelin-stratcom',
'javelin-uri',
),
'e5822781' => array(
'javelin-behavior',
'javelin-dom',
'javelin-json',
'javelin-workflow',
'javelin-magical-init',
),
'e6e25838' => array(
'javelin-install',
),
'e9581f08' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-workflow',
'javelin-dom',
'phabricator-draggable-list',
),
'ea681761' => array(
'javelin-behavior',
'javelin-aphlict',
'phabricator-phtize',
'javelin-dom',
),
'edd1ba66' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'javelin-uri',
'phabricator-notification',
),
'edf8a145' => array(
'javelin-behavior',
'javelin-uri',
),
'efe49472' => array(
'javelin-install',
'javelin-util',
),
'f01586dc' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-workflow',
'javelin-json',
),
'f411b6ae' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-util',
'javelin-dom',
'javelin-request',
'phabricator-keyboard-shortcut',
),
'f6555212' => array(
'javelin-install',
'javelin-reactornode',
'javelin-util',
'javelin-reactor',
),
'f7fc67ec' => array(
'javelin-install',
'javelin-typeahead',
'javelin-dom',
'javelin-request',
'javelin-typeahead-ondemand-source',
'javelin-util',
),
'f829edb3' => array(
'javelin-view',
'javelin-install',
'javelin-dom',
),
'f8ba29d7' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'javelin-mask',
'javelin-util',
'phabricator-busy',
),
'fa0f4fc2' => array(
'javelin-behavior',
'javelin-dom',
'javelin-vector',
'javelin-magical-init',
),
'fb20ac8d' => array(
'javelin-behavior',
'javelin-aphlict',
'javelin-stratcom',
'javelin-request',
'javelin-uri',
'javelin-dom',
'javelin-json',
'javelin-router',
'javelin-util',
'javelin-leader',
'javelin-sound',
'phabricator-notification',
),
'fbe497e7' => array(
'javelin-behavior',
'javelin-util',
'javelin-stratcom',
'javelin-dom',
'javelin-vector',
'javelin-magical-init',
'javelin-request',
'javelin-history',
'javelin-workflow',
'javelin-mask',
'javelin-behavior-device',
'phabricator-keyboard-shortcut',
),
'fc91ab6c' => array(
'javelin-behavior',
'javelin-dom',
'phortune-credit-card-form',
),
'fe287620' => array(
'javelin-install',
'javelin-dom',
'javelin-view-visitor',
'javelin-util',
),
'fea0eb47' => array(
'javelin-install',
),
),
'packages' => array(
'core.pkg.css' => array(
'phabricator-core-css',
'phabricator-zindex-css',
'phui-button-css',
'phabricator-standard-page-view',
'aphront-dialog-view-css',
'phui-form-view-css',
'aphront-panel-view-css',
'aphront-table-view-css',
'aphront-tokenizer-control-css',
'aphront-typeahead-control-css',
'aphront-list-filter-view-css',
'phabricator-remarkup-css',
'syntax-highlighting-css',
'syntax-default-css',
'phui-pager-css',
'aphront-tooltip-css',
'phabricator-flag-css',
'phui-info-view-css',
'sprite-menu-css',
'phabricator-main-menu-view',
'phabricator-notification-css',
'phabricator-notification-menu-css',
'lightbox-attachment-css',
'phui-header-view-css',
'phabricator-filetree-view-css',
'phabricator-nav-view-css',
'phabricator-side-menu-view-css',
'phui-crumbs-view-css',
'phui-object-item-list-view-css',
'global-drag-and-drop-css',
'phui-spacing-css',
'phui-form-css',
'phui-icon-view-css',
'phui-profile-menu-css',
'phabricator-application-launch-view-css',
'phabricator-action-list-view-css',
'phui-property-list-view-css',
'phui-tag-view-css',
'phui-list-view-css',
'font-fontawesome',
'phui-font-icon-base-css',
'phui-box-css',
'phui-object-box-css',
'phui-timeline-view-css',
'sprite-tokens-css',
'tokens-css',
'phui-status-list-view-css',
'phui-feed-story-css',
'phabricator-feed-css',
'phabricator-dashboard-css',
'aphront-multi-column-view-css',
'conpherence-durable-column-view',
),
'core.pkg.js' => array(
'javelin-util',
'javelin-install',
'javelin-event',
'javelin-stratcom',
'javelin-behavior',
'javelin-resource',
'javelin-request',
'javelin-vector',
'javelin-dom',
'javelin-json',
'javelin-uri',
'javelin-workflow',
'javelin-mask',
'javelin-typeahead',
'javelin-typeahead-normalizer',
'javelin-typeahead-source',
'javelin-typeahead-preloaded-source',
'javelin-typeahead-ondemand-source',
'javelin-tokenizer',
'javelin-history',
'javelin-router',
'javelin-routable',
'javelin-behavior-aphront-basic-tokenizer',
'javelin-behavior-workflow',
'javelin-behavior-aphront-form-disable-on-submit',
'phabricator-keyboard-shortcut-manager',
'phabricator-keyboard-shortcut',
'javelin-behavior-phabricator-keyboard-shortcuts',
'javelin-behavior-refresh-csrf',
'javelin-behavior-phabricator-watch-anchor',
'javelin-behavior-phabricator-autofocus',
'phuix-dropdown-menu',
'phuix-action-list-view',
'phuix-action-view',
'phabricator-phtize',
'javelin-behavior-phabricator-oncopy',
'phabricator-tooltip',
'javelin-behavior-phabricator-tooltips',
'phabricator-prefab',
'javelin-behavior-device',
'javelin-behavior-toggle-class',
'javelin-behavior-lightbox-attachments',
'phabricator-busy',
'javelin-aphlict',
'phabricator-notification',
'javelin-behavior-aphlict-listen',
'javelin-behavior-phabricator-search-typeahead',
'javelin-behavior-aphlict-dropdown',
'javelin-behavior-history-install',
'javelin-behavior-phabricator-gesture',
'javelin-behavior-phabricator-active-nav',
'javelin-behavior-phabricator-nav',
'javelin-behavior-phabricator-remarkup-assist',
'phabricator-textareautils',
'phabricator-file-upload',
'javelin-behavior-global-drag-and-drop',
'javelin-behavior-phabricator-reveal-content',
'phui-hovercard',
'javelin-behavior-phui-hovercards',
'javelin-color',
'javelin-fx',
'phabricator-draggable-list',
'javelin-behavior-phabricator-transaction-list',
'javelin-behavior-phabricator-show-older-transactions',
'javelin-behavior-phui-dropdown-menu',
'javelin-behavior-doorkeeper-tag',
'phabricator-title',
'javelin-leader',
'javelin-websocket',
'javelin-behavior-dashboard-async-panel',
'javelin-behavior-dashboard-tab-panel',
'javelin-quicksand',
'javelin-behavior-quicksand-blacklist',
'javelin-behavior-high-security-warning',
'javelin-behavior-read-only-warning',
'javelin-scrollbar',
'javelin-behavior-scrollbar',
'javelin-behavior-durable-column',
'conpherence-thread-manager',
'javelin-behavior-detect-timezone',
'javelin-behavior-setup-check-https',
),
'darkconsole.pkg.js' => array(
'javelin-behavior-dark-console',
'javelin-behavior-error-log',
),
'differential.pkg.css' => array(
'differential-core-view-css',
'differential-changeset-view-css',
'differential-revision-history-css',
'differential-revision-list-css',
'differential-table-of-contents-css',
'differential-revision-comment-css',
'differential-revision-add-comment-css',
'phabricator-object-selector-css',
'phabricator-content-source-view-css',
'inline-comment-summary-css',
'phui-inline-comment-view-css',
),
'differential.pkg.js' => array(
'phabricator-drag-and-drop-file-upload',
'phabricator-shaped-request',
'javelin-behavior-differential-feedback-preview',
'javelin-behavior-differential-edit-inline-comments',
'javelin-behavior-differential-populate',
'javelin-behavior-differential-diff-radios',
'javelin-behavior-differential-comment-jump',
'javelin-behavior-differential-add-reviewers-and-ccs',
'javelin-behavior-differential-keyboard-navigation',
'javelin-behavior-aphront-drag-and-drop-textarea',
'javelin-behavior-phabricator-object-selector',
'javelin-behavior-repository-crossreference',
'javelin-behavior-load-blame',
'differential-inline-comment-editor',
'javelin-behavior-differential-dropdown-menus',
'javelin-behavior-differential-toggle-files',
'javelin-behavior-differential-user-select',
'javelin-behavior-aphront-more',
'changeset-view-manager',
),
'diffusion.pkg.css' => array(
'diffusion-icons-css',
),
'diffusion.pkg.js' => array(
'javelin-behavior-diffusion-pull-lastmodified',
'javelin-behavior-diffusion-commit-graph',
'javelin-behavior-audit-preview',
),
'maniphest.pkg.css' => array(
'maniphest-task-summary-css',
),
'maniphest.pkg.js' => array(
'javelin-behavior-maniphest-batch-selector',
'javelin-behavior-maniphest-subpriority-editor',
'javelin-behavior-maniphest-list-editor',
),
),
);
diff --git a/src/applications/base/controller/PhabricatorController.php b/src/applications/base/controller/PhabricatorController.php
index 08966f29a5..0cb8182776 100644
--- a/src/applications/base/controller/PhabricatorController.php
+++ b/src/applications/base/controller/PhabricatorController.php
@@ -1,615 +1,618 @@
<?php
abstract class PhabricatorController extends AphrontController {
private $handles;
public function shouldRequireLogin() {
return true;
}
public function shouldRequireAdmin() {
return false;
}
public function shouldRequireEnabledUser() {
return true;
}
public function shouldAllowPublic() {
return false;
}
public function shouldAllowPartialSessions() {
return false;
}
public function shouldRequireEmailVerification() {
return PhabricatorUserEmail::isEmailVerificationRequired();
}
public function shouldAllowRestrictedParameter($parameter_name) {
return false;
}
public function shouldRequireMultiFactorEnrollment() {
if (!$this->shouldRequireLogin()) {
return false;
}
if (!$this->shouldRequireEnabledUser()) {
return false;
}
if ($this->shouldAllowPartialSessions()) {
return false;
}
$user = $this->getRequest()->getUser();
if (!$user->getIsStandardUser()) {
return false;
}
return PhabricatorEnv::getEnvConfig('security.require-multi-factor-auth');
}
public function shouldAllowLegallyNonCompliantUsers() {
return false;
}
public function isGlobalDragAndDropUploadEnabled() {
return false;
}
public function willBeginExecution() {
$request = $this->getRequest();
if ($request->getUser()) {
// NOTE: Unit tests can set a user explicitly. Normal requests are not
// permitted to do this.
PhabricatorTestCase::assertExecutingUnitTests();
$user = $request->getUser();
} else {
$user = new PhabricatorUser();
$session_engine = new PhabricatorAuthSessionEngine();
$phsid = $request->getCookie(PhabricatorCookies::COOKIE_SESSION);
if (strlen($phsid)) {
$session_user = $session_engine->loadUserForSession(
PhabricatorAuthSession::TYPE_WEB,
$phsid);
if ($session_user) {
$user = $session_user;
}
} else {
// If the client doesn't have a session token, generate an anonymous
// session. This is used to provide CSRF protection to logged-out users.
$phsid = $session_engine->establishSession(
PhabricatorAuthSession::TYPE_WEB,
null,
$partial = false);
// This may be a resource request, in which case we just don't set
// the cookie.
if ($request->canSetCookies()) {
$request->setCookie(PhabricatorCookies::COOKIE_SESSION, $phsid);
}
}
if (!$user->isLoggedIn()) {
$user->attachAlternateCSRFString(PhabricatorHash::digest($phsid));
}
$request->setUser($user);
}
id(new PhabricatorAuthSessionEngine())
->willServeRequestForUser($user);
if (PhabricatorEnv::getEnvConfig('darkconsole.enabled')) {
$dark_console = PhabricatorDarkConsoleSetting::SETTINGKEY;
if ($user->getUserSetting($dark_console) ||
PhabricatorEnv::getEnvConfig('darkconsole.always-on')) {
$console = new DarkConsoleCore();
$request->getApplicationConfiguration()->setConsole($console);
}
}
// NOTE: We want to set up the user first so we can render a real page
// here, but fire this before any real logic.
$restricted = array(
'code',
);
foreach ($restricted as $parameter) {
if ($request->getExists($parameter)) {
if (!$this->shouldAllowRestrictedParameter($parameter)) {
throw new Exception(
pht(
'Request includes restricted parameter "%s", but this '.
'controller ("%s") does not whitelist it. Refusing to '.
'serve this request because it might be part of a redirection '.
'attack.',
$parameter,
get_class($this)));
}
}
}
if ($this->shouldRequireEnabledUser()) {
if ($user->isLoggedIn() && !$user->getIsApproved()) {
$controller = new PhabricatorAuthNeedsApprovalController();
return $this->delegateToController($controller);
}
if ($user->getIsDisabled()) {
$controller = new PhabricatorDisabledUserController();
return $this->delegateToController($controller);
}
}
$auth_class = 'PhabricatorAuthApplication';
$auth_application = PhabricatorApplication::getByClass($auth_class);
// Require partial sessions to finish login before doing anything.
if (!$this->shouldAllowPartialSessions()) {
if ($user->hasSession() &&
$user->getSession()->getIsPartial()) {
$login_controller = new PhabricatorAuthFinishController();
$this->setCurrentApplication($auth_application);
return $this->delegateToController($login_controller);
}
}
// Check if the user needs to configure MFA.
$need_mfa = $this->shouldRequireMultiFactorEnrollment();
$have_mfa = $user->getIsEnrolledInMultiFactor();
if ($need_mfa && !$have_mfa) {
// Check if the cache is just out of date. Otherwise, roadblock the user
// and require MFA enrollment.
$user->updateMultiFactorEnrollment();
if (!$user->getIsEnrolledInMultiFactor()) {
$mfa_controller = new PhabricatorAuthNeedsMultiFactorController();
$this->setCurrentApplication($auth_application);
return $this->delegateToController($mfa_controller);
}
}
if ($this->shouldRequireLogin()) {
// This actually means we need either:
// - a valid user, or a public controller; and
// - permission to see the application; and
// - permission to see at least one Space if spaces are configured.
$allow_public = $this->shouldAllowPublic() &&
PhabricatorEnv::getEnvConfig('policy.allow-public');
// If this controller isn't public, and the user isn't logged in, require
// login.
if (!$allow_public && !$user->isLoggedIn()) {
$login_controller = new PhabricatorAuthStartController();
$this->setCurrentApplication($auth_application);
return $this->delegateToController($login_controller);
}
if ($user->isLoggedIn()) {
if ($this->shouldRequireEmailVerification()) {
if (!$user->getIsEmailVerified()) {
$controller = new PhabricatorMustVerifyEmailController();
$this->setCurrentApplication($auth_application);
return $this->delegateToController($controller);
}
}
}
// If Spaces are configured, require that the user have access to at
// least one. If we don't do this, they'll get confusing error messages
// later on.
$spaces = PhabricatorSpacesNamespaceQuery::getSpacesExist();
if ($spaces) {
$viewer_spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces(
$user);
if (!$viewer_spaces) {
$controller = new PhabricatorSpacesNoAccessController();
return $this->delegateToController($controller);
}
}
// If the user doesn't have access to the application, don't let them use
// any of its controllers. We query the application in order to generate
// a policy exception if the viewer doesn't have permission.
$application = $this->getCurrentApplication();
if ($application) {
id(new PhabricatorApplicationQuery())
->setViewer($user)
->withPHIDs(array($application->getPHID()))
->executeOne();
}
}
if (!$this->shouldAllowLegallyNonCompliantUsers()) {
$legalpad_class = 'PhabricatorLegalpadApplication';
$legalpad = id(new PhabricatorApplicationQuery())
->setViewer($user)
->withClasses(array($legalpad_class))
->withInstalled(true)
->execute();
$legalpad = head($legalpad);
$doc_query = id(new LegalpadDocumentQuery())
->setViewer($user)
->withSignatureRequired(1)
->needViewerSignatures(true);
if ($user->hasSession() &&
!$user->getSession()->getIsPartial() &&
!$user->getSession()->getSignedLegalpadDocuments() &&
$user->isLoggedIn() &&
$legalpad) {
$sign_docs = $doc_query->execute();
$must_sign_docs = array();
foreach ($sign_docs as $sign_doc) {
if (!$sign_doc->getUserSignature($user->getPHID())) {
$must_sign_docs[] = $sign_doc;
}
}
if ($must_sign_docs) {
$controller = new LegalpadDocumentSignController();
$this->getRequest()->setURIMap(array(
'id' => head($must_sign_docs)->getID(),
));
$this->setCurrentApplication($legalpad);
return $this->delegateToController($controller);
} else {
$engine = id(new PhabricatorAuthSessionEngine())
->signLegalpadDocuments($user, $sign_docs);
}
}
}
// NOTE: We do this last so that users get a login page instead of a 403
// if they need to login.
if ($this->shouldRequireAdmin() && !$user->getIsAdmin()) {
return new Aphront403Response();
}
}
public function getApplicationURI($path = '') {
if (!$this->getCurrentApplication()) {
throw new Exception(pht('No application!'));
}
return $this->getCurrentApplication()->getApplicationURI($path);
}
public function willSendResponse(AphrontResponse $response) {
$request = $this->getRequest();
if ($response instanceof AphrontDialogResponse) {
if (!$request->isAjax() && !$request->isQuicksand()) {
$dialog = $response->getDialog();
$title = $dialog->getTitle();
$short = $dialog->getShortTitle();
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(coalesce($short, $title));
$page_content = array(
$crumbs,
$response->buildResponseString(),
);
$view = id(new PhabricatorStandardPageView())
->setRequest($request)
->setController($this)
->setDeviceReady(true)
->setTitle($title)
->appendChild($page_content);
$response = id(new AphrontWebpageResponse())
->setContent($view->render())
->setHTTPResponseCode($response->getHTTPResponseCode());
} else {
$response->getDialog()->setIsStandalone(true);
return id(new AphrontAjaxResponse())
->setContent(array(
'dialog' => $response->buildResponseString(),
));
}
} else if ($response instanceof AphrontRedirectResponse) {
if ($request->isAjax() || $request->isQuicksand()) {
return id(new AphrontAjaxResponse())
->setContent(
array(
'redirect' => $response->getURI(),
));
}
}
return $response;
}
/**
* WARNING: Do not call this in new code.
*
* @deprecated See "Handles Technical Documentation".
*/
protected function loadViewerHandles(array $phids) {
return id(new PhabricatorHandleQuery())
->setViewer($this->getRequest()->getUser())
->withPHIDs($phids)
->execute();
}
public function buildApplicationMenu() {
return null;
}
protected function buildApplicationCrumbs() {
$crumbs = array();
$application = $this->getCurrentApplication();
if ($application) {
$icon = $application->getIcon();
if (!$icon) {
$icon = 'fa-puzzle';
}
$crumbs[] = id(new PHUICrumbView())
->setHref($this->getApplicationURI())
->setName($application->getName())
->setIcon($icon);
}
$view = new PHUICrumbsView();
foreach ($crumbs as $crumb) {
$view->addCrumb($crumb);
}
return $view;
}
protected function hasApplicationCapability($capability) {
return PhabricatorPolicyFilter::hasCapability(
$this->getRequest()->getUser(),
$this->getCurrentApplication(),
$capability);
}
protected function requireApplicationCapability($capability) {
PhabricatorPolicyFilter::requireCapability(
$this->getRequest()->getUser(),
$this->getCurrentApplication(),
$capability);
}
protected function explainApplicationCapability(
$capability,
$positive_message,
$negative_message) {
$can_act = $this->hasApplicationCapability($capability);
if ($can_act) {
$message = $positive_message;
$icon_name = 'fa-play-circle-o lightgreytext';
} else {
$message = $negative_message;
$icon_name = 'fa-lock';
}
$icon = id(new PHUIIconView())
->setIcon($icon_name);
require_celerity_resource('policy-css');
$phid = $this->getCurrentApplication()->getPHID();
$explain_uri = "/policy/explain/{$phid}/{$capability}/";
$message = phutil_tag(
'div',
array(
'class' => 'policy-capability-explanation',
),
array(
$icon,
javelin_tag(
'a',
array(
'href' => $explain_uri,
'sigil' => 'workflow',
),
$message),
));
return array($can_act, $message);
}
public function getDefaultResourceSource() {
return 'phabricator';
}
/**
* Create a new @{class:AphrontDialogView} with defaults filled in.
*
* @return AphrontDialogView New dialog.
*/
public function newDialog() {
$submit_uri = new PhutilURI($this->getRequest()->getRequestURI());
$submit_uri = $submit_uri->getPath();
return id(new AphrontDialogView())
->setUser($this->getRequest()->getUser())
->setSubmitURI($submit_uri);
}
public function newPage() {
$page = id(new PhabricatorStandardPageView())
->setRequest($this->getRequest())
->setController($this)
->setDeviceReady(true);
$application = $this->getCurrentApplication();
if ($application) {
$page->setApplicationName($application->getName());
if ($application->getTitleGlyph()) {
$page->setGlyph($application->getTitleGlyph());
}
}
$viewer = $this->getRequest()->getUser();
if ($viewer) {
$page->setUser($viewer);
}
return $page;
}
public function newApplicationMenu() {
return id(new PHUIApplicationMenuView())
->setViewer($this->getViewer());
}
public function newCurtainView($object) {
$viewer = $this->getViewer();
+ $action_id = celerity_generate_unique_node_id();
+
$action_list = id(new PhabricatorActionListView())
- ->setViewer($viewer);
+ ->setViewer($viewer)
+ ->setID($action_id);
// NOTE: Applications (objects of class PhabricatorApplication) can't
// currently be set here, although they don't need any of the extensions
// anyway. This should probably work differently than it does, though.
if ($object instanceof PhabricatorLiskDAO) {
$action_list->setObject($object);
}
$curtain = id(new PHUICurtainView())
->setViewer($viewer)
->setActionList($action_list);
$panels = PHUICurtainExtension::buildExtensionPanels($viewer, $object);
foreach ($panels as $panel) {
$curtain->addPanel($panel);
}
return $curtain;
}
protected function buildTransactionTimeline(
PhabricatorApplicationTransactionInterface $object,
PhabricatorApplicationTransactionQuery $query,
PhabricatorMarkupEngine $engine = null,
$render_data = array()) {
$viewer = $this->getRequest()->getUser();
$xaction = $object->getApplicationTransactionTemplate();
$view = $xaction->getApplicationTransactionViewObject();
$pager = id(new AphrontCursorPagerView())
->readFromRequest($this->getRequest())
->setURI(new PhutilURI(
'/transactions/showolder/'.$object->getPHID().'/'));
$xactions = $query
->setViewer($viewer)
->withObjectPHIDs(array($object->getPHID()))
->needComments(true)
->executeWithCursorPager($pager);
$xactions = array_reverse($xactions);
if ($engine) {
foreach ($xactions as $xaction) {
if ($xaction->getComment()) {
$engine->addObject(
$xaction->getComment(),
PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
}
}
$engine->process();
$view->setMarkupEngine($engine);
}
$timeline = $view
->setUser($viewer)
->setObjectPHID($object->getPHID())
->setTransactions($xactions)
->setPager($pager)
->setRenderData($render_data)
->setQuoteTargetID($this->getRequest()->getStr('quoteTargetID'))
->setQuoteRef($this->getRequest()->getStr('quoteRef'));
$object->willRenderTimeline($timeline, $this->getRequest());
return $timeline;
}
public function buildApplicationCrumbsForEditEngine() {
// TODO: This is kind of gross, I'm bascially just making this public so
// I can use it in EditEngine. We could do this without making it public
// by using controller delegation, or make it properly public.
return $this->buildApplicationCrumbs();
}
/* -( Deprecated )--------------------------------------------------------- */
/**
* DEPRECATED. Use @{method:newPage}.
*/
public function buildStandardPageView() {
return $this->newPage();
}
/**
* DEPRECATED. Use @{method:newPage}.
*/
public function buildStandardPageResponse($view, array $data) {
$page = $this->buildStandardPageView();
$page->appendChild($view);
return $page->produceAphrontResponse();
}
/**
* DEPRECATED. Use @{method:newPage}.
*/
public function buildApplicationPage($view, array $options) {
$page = $this->newPage();
$title = PhabricatorEnv::getEnvConfig('phabricator.serious-business') ?
'Phabricator' :
pht('Bacon Ice Cream for Breakfast');
$page->setTitle(idx($options, 'title', $title));
if (idx($options, 'class')) {
$page->addClass($options['class']);
}
if (!($view instanceof AphrontSideNavFilterView)) {
$nav = new AphrontSideNavFilterView();
$nav->appendChild($view);
$view = $nav;
}
$page->appendChild($view);
$object_phids = idx($options, 'pageObjects', array());
if ($object_phids) {
$page->setPageObjectPHIDs($object_phids);
}
if (!idx($options, 'device', true)) {
$page->setDeviceReady(false);
}
$page->setShowFooter(idx($options, 'showFooter', true));
$page->setShowChrome(idx($options, 'chrome', true));
return $page->produceAphrontResponse();
}
}
diff --git a/src/applications/maniphest/controller/ManiphestTaskDetailController.php b/src/applications/maniphest/controller/ManiphestTaskDetailController.php
index 1007672e23..2195089d24 100644
--- a/src/applications/maniphest/controller/ManiphestTaskDetailController.php
+++ b/src/applications/maniphest/controller/ManiphestTaskDetailController.php
@@ -1,364 +1,368 @@
<?php
final class ManiphestTaskDetailController extends ManiphestController {
public function shouldAllowPublic() {
return true;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$id = $request->getURIData('id');
$task = id(new ManiphestTaskQuery())
->setViewer($viewer)
->withIDs(array($id))
->needSubscriberPHIDs(true)
->executeOne();
if (!$task) {
return new Aphront404Response();
}
$field_list = PhabricatorCustomField::getObjectFields(
$task,
PhabricatorCustomField::ROLE_VIEW);
$field_list
->setViewer($viewer)
->readFieldsFromStorage($task);
$edit_engine = id(new ManiphestEditEngine())
->setViewer($viewer)
->setTargetObject($task);
$e_commit = ManiphestTaskHasCommitEdgeType::EDGECONST;
$e_dep_on = ManiphestTaskDependsOnTaskEdgeType::EDGECONST;
$e_dep_by = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST;
$e_rev = ManiphestTaskHasRevisionEdgeType::EDGECONST;
$e_mock = ManiphestTaskHasMockEdgeType::EDGECONST;
$phid = $task->getPHID();
$query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array($phid))
->withEdgeTypes(
array(
$e_commit,
$e_dep_on,
$e_dep_by,
$e_rev,
$e_mock,
));
$edges = idx($query->execute(), $phid);
$phids = array_fill_keys($query->getDestinationPHIDs(), true);
if ($task->getOwnerPHID()) {
$phids[$task->getOwnerPHID()] = true;
}
$phids[$task->getAuthorPHID()] = true;
$phids = array_keys($phids);
$handles = $viewer->loadHandles($phids);
$timeline = $this->buildTransactionTimeline(
$task,
new ManiphestTransactionQuery());
$monogram = $task->getMonogram();
$crumbs = $this->buildApplicationCrumbs()
->addTextCrumb($monogram)
->setBorder(true);
$header = $this->buildHeaderView($task);
$details = $this->buildPropertyView($task, $field_list, $edges, $handles);
$description = $this->buildDescriptionView($task);
$curtain = $this->buildCurtain($task, $edit_engine);
$title = pht('%s %s', $monogram, $task->getTitle());
$comment_view = $edit_engine
->buildEditEngineCommentView($task);
$timeline->setQuoteRef($monogram);
$comment_view->setTransactionTimeline($timeline);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
->setMainColumn(array(
$timeline,
$comment_view,
))
->addPropertySection(pht('Description'), $description)
->addPropertySection(pht('Details'), $details);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->setPageObjectPHIDs(
array(
$task->getPHID(),
))
->appendChild(
array(
$view,
));
}
private function buildHeaderView(ManiphestTask $task) {
$view = id(new PHUIHeaderView())
->setHeader($task->getTitle())
->setUser($this->getRequest()->getUser())
->setPolicyObject($task);
$priority_name = ManiphestTaskPriority::getTaskPriorityName(
$task->getPriority());
$priority_color = ManiphestTaskPriority::getTaskPriorityColor(
$task->getPriority());
$status = $task->getStatus();
$status_name = ManiphestTaskStatus::renderFullDescription(
$status, $priority_name, $priority_color);
$view->addProperty(PHUIHeaderView::PROPERTY_STATUS, $status_name);
$view->setHeaderIcon(ManiphestTaskStatus::getStatusIcon(
$task->getStatus()).' '.$priority_color);
if (ManiphestTaskPoints::getIsEnabled()) {
$points = $task->getPoints();
if ($points !== null) {
$points_name = pht('%s %s',
$task->getPoints(),
ManiphestTaskPoints::getPointsLabel());
$tag = id(new PHUITagView())
->setName($points_name)
->setShade('blue')
->setType(PHUITagView::TYPE_SHADE);
$view->addTag($tag);
}
}
return $view;
}
private function buildCurtain(
ManiphestTask $task,
PhabricatorEditEngine $edit_engine) {
$viewer = $this->getViewer();
$id = $task->getID();
$phid = $task->getPHID();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$task,
PhabricatorPolicyCapability::CAN_EDIT);
$curtain = $this->newCurtainView($task);
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Task'))
->setIcon('fa-pencil')
->setHref($this->getApplicationURI("/task/edit/{$id}/"))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
- $curtain->addAction(
- id(new PhabricatorActionView())
- ->setName(pht('Merge Duplicates In'))
- ->setHref("/search/attach/{$phid}/TASK/merge/")
- ->setWorkflow(true)
- ->setIcon('fa-compress')
- ->setDisabled(!$can_edit)
- ->setWorkflow(true));
-
$edit_config = $edit_engine->loadDefaultEditConfiguration();
$can_create = (bool)$edit_config;
$can_reassign = $edit_engine->hasEditAccessToTransaction(
ManiphestTransaction::TYPE_OWNER);
if ($can_create) {
$form_key = $edit_config->getIdentifier();
$edit_uri = id(new PhutilURI("/task/edit/form/{$form_key}/"))
->setQueryParam('parent', $id)
->setQueryParam('template', $id)
->setQueryParam('status', ManiphestTaskStatus::getDefaultStatus());
$edit_uri = $this->getApplicationURI($edit_uri);
} else {
// TODO: This will usually give us a somewhat-reasonable error page, but
// could be a bit cleaner.
$edit_uri = "/task/edit/{$id}/";
$edit_uri = $this->getApplicationURI($edit_uri);
}
- $curtain->addAction(
- id(new PhabricatorActionView())
- ->setName(pht('Create Subtask'))
- ->setHref($edit_uri)
- ->setIcon('fa-level-down')
- ->setDisabled(!$can_create)
- ->setWorkflow(!$can_create));
+ $task_submenu = array();
+
+ $task_submenu[] = id(new PhabricatorActionView())
+ ->setName(pht('Create Subtask'))
+ ->setHref($edit_uri)
+ ->setIcon('fa-level-down')
+ ->setDisabled(!$can_create)
+ ->setWorkflow(!$can_create);
+
+ $task_submenu[] = id(new PhabricatorActionView())
+ ->setName(pht('Edit Blocking Tasks'))
+ ->setHref("/search/attach/{$phid}/TASK/blocks/")
+ ->setWorkflow(true)
+ ->setIcon('fa-link')
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(true);
+
+ $task_submenu[] = id(new PhabricatorActionView())
+ ->setName(pht('Merge Duplicates In'))
+ ->setHref("/search/attach/{$phid}/TASK/merge/")
+ ->setWorkflow(true)
+ ->setIcon('fa-compress')
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(true);
$curtain->addAction(
id(new PhabricatorActionView())
- ->setName(pht('Edit Blocking Tasks'))
- ->setHref("/search/attach/{$phid}/TASK/blocks/")
- ->setWorkflow(true)
- ->setIcon('fa-link')
- ->setDisabled(!$can_edit)
- ->setWorkflow(true));
-
+ ->setName(pht('Edit Related Tasks...'))
+ ->setIcon('fa-anchor')
+ ->setSubmenu($task_submenu));
$owner_phid = $task->getOwnerPHID();
$author_phid = $task->getAuthorPHID();
$handles = $viewer->loadHandles(array($owner_phid, $author_phid));
if ($owner_phid) {
$image_uri = $handles[$owner_phid]->getImageURI();
$image_href = $handles[$owner_phid]->getURI();
$owner = $viewer->renderHandle($owner_phid)->render();
$content = phutil_tag('strong', array(), $owner);
$assigned_to = id(new PHUIHeadThingView())
->setImage($image_uri)
->setImageHref($image_href)
->setContent($content);
} else {
$assigned_to = phutil_tag('em', array(), pht('None'));
}
$curtain->newPanel()
->setHeaderText(pht('Assigned To'))
->appendChild($assigned_to);
$author_uri = $handles[$author_phid]->getImageURI();
$author_href = $handles[$author_phid]->getURI();
$author = $viewer->renderHandle($author_phid)->render();
$content = phutil_tag('strong', array(), $author);
$date = phabricator_date($task->getDateCreated(), $viewer);
$content = pht('%s, %s', $content, $date);
$authored_by = id(new PHUIHeadThingView())
->setImage($author_uri)
->setImageHref($author_href)
->setContent($content);
$curtain->newPanel()
->setHeaderText(pht('Authored By'))
->appendChild($authored_by);
return $curtain;
}
private function buildPropertyView(
ManiphestTask $task,
PhabricatorCustomFieldList $field_list,
array $edges,
$handles) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer);
$source = $task->getOriginalEmailSource();
if ($source) {
$subject = '[T'.$task->getID().'] '.$task->getTitle();
$view->addProperty(
pht('From Email'),
phutil_tag(
'a',
array(
'href' => 'mailto:'.$source.'?subject='.$subject,
),
$source));
}
$edge_types = array(
ManiphestTaskDependedOnByTaskEdgeType::EDGECONST
=> pht('Blocks'),
ManiphestTaskDependsOnTaskEdgeType::EDGECONST
=> pht('Blocked By'),
ManiphestTaskHasRevisionEdgeType::EDGECONST
=> pht('Differential Revisions'),
ManiphestTaskHasMockEdgeType::EDGECONST
=> pht('Pholio Mocks'),
);
$revisions_commits = array();
$commit_phids = array_keys(
$edges[ManiphestTaskHasCommitEdgeType::EDGECONST]);
if ($commit_phids) {
$commit_drev = DiffusionCommitHasRevisionEdgeType::EDGECONST;
$drev_edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs($commit_phids)
->withEdgeTypes(array($commit_drev))
->execute();
foreach ($commit_phids as $phid) {
$revisions_commits[$phid] = $handles->renderHandle($phid)
->setShowHovercard(true);
$revision_phid = key($drev_edges[$phid][$commit_drev]);
$revision_handle = $handles->getHandleIfExists($revision_phid);
if ($revision_handle) {
$task_drev = ManiphestTaskHasRevisionEdgeType::EDGECONST;
unset($edges[$task_drev][$revision_phid]);
$revisions_commits[$phid] = hsprintf(
'%s / %s',
$revision_handle->renderHovercardLink($revision_handle->getName()),
$revisions_commits[$phid]);
}
}
}
foreach ($edge_types as $edge_type => $edge_name) {
if ($edges[$edge_type]) {
$edge_handles = $viewer->loadHandles(array_keys($edges[$edge_type]));
$view->addProperty(
$edge_name,
$edge_handles->renderList());
}
}
if ($revisions_commits) {
$view->addProperty(
pht('Commits'),
phutil_implode_html(phutil_tag('br'), $revisions_commits));
}
$field_list->appendFieldsToPropertyList(
$task,
$viewer,
$view);
if ($view->hasAnyProperties()) {
return $view;
}
return null;
}
private function buildDescriptionView(ManiphestTask $task) {
$viewer = $this->getViewer();
$section = null;
$description = $task->getDescription();
if (strlen($description)) {
$section = new PHUIPropertyListView();
$section->addTextContent(
phutil_tag(
'div',
array(
'class' => 'phabricator-remarkup',
),
id(new PHUIRemarkupView($viewer, $description))
->setContextObject($task)));
}
return $section;
}
}
diff --git a/src/view/layout/PhabricatorActionListView.php b/src/view/layout/PhabricatorActionListView.php
index 5c3facbf42..fd18e7f429 100644
--- a/src/view/layout/PhabricatorActionListView.php
+++ b/src/view/layout/PhabricatorActionListView.php
@@ -1,63 +1,74 @@
<?php
final class PhabricatorActionListView extends AphrontView {
private $actions = array();
private $object;
private $id = null;
public function setObject(PhabricatorLiskDAO $object) {
$this->object = $object;
return $this;
}
public function addAction(PhabricatorActionView $view) {
$this->actions[] = $view;
return $this;
}
public function setID($id) {
$this->id = $id;
return $this;
}
+ public function getID() {
+ return $this->id;
+ }
+
public function render() {
$viewer = $this->getViewer();
$event = new PhabricatorEvent(
PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS,
array(
'object' => $this->object,
'actions' => $this->actions,
));
$event->setUser($viewer);
PhutilEventEngine::dispatchEvent($event);
$actions = $event->getValue('actions');
if (!$actions) {
return null;
}
foreach ($actions as $action) {
$action->setViewer($viewer);
}
require_celerity_resource('phabricator-action-list-view-css');
+ $items = array();
+ foreach ($actions as $action) {
+ foreach ($action->getItems() as $item) {
+ $items[] = $item;
+ }
+ }
+
return phutil_tag(
'ul',
array(
'class' => 'phabricator-action-list-view',
'id' => $this->id,
),
- $actions);
+ $items);
}
public function getDropdownMenuMetadata() {
return array(
'items' => (string)hsprintf('%s', $this),
);
}
}
diff --git a/src/view/layout/PhabricatorActionView.php b/src/view/layout/PhabricatorActionView.php
index 3efa32071d..a936b36e47 100644
--- a/src/view/layout/PhabricatorActionView.php
+++ b/src/view/layout/PhabricatorActionView.php
@@ -1,201 +1,307 @@
<?php
final class PhabricatorActionView extends AphrontView {
private $name;
private $icon;
private $href;
private $disabled;
private $label;
private $workflow;
private $renderAsForm;
private $download;
private $sigils = array();
private $metadata;
private $selected;
private $openInNewWindow;
+ private $submenu = array();
+ private $hidden;
+ private $depth;
+ private $id;
public function setSelected($selected) {
$this->selected = $selected;
return $this;
}
public function getSelected() {
return $this->selected;
}
public function setMetadata($metadata) {
$this->metadata = $metadata;
return $this;
}
public function getMetadata() {
return $this->metadata;
}
public function setDownload($download) {
$this->download = $download;
return $this;
}
public function getDownload() {
return $this->download;
}
public function setHref($href) {
$this->href = $href;
return $this;
}
public function addSigil($sigil) {
$this->sigils[] = $sigil;
return $this;
}
public function getHref() {
return $this->href;
}
public function setIcon($icon) {
$this->icon = $icon;
return $this;
}
public function setName($name) {
$this->name = $name;
return $this;
}
public function setLabel($label) {
$this->label = $label;
return $this;
}
public function setDisabled($disabled) {
$this->disabled = $disabled;
return $this;
}
public function setWorkflow($workflow) {
$this->workflow = $workflow;
return $this;
}
public function setRenderAsForm($form) {
$this->renderAsForm = $form;
return $this;
}
public function setOpenInNewWindow($open_in_new_window) {
$this->openInNewWindow = $open_in_new_window;
return $this;
}
public function getOpenInNewWindow() {
return $this->openInNewWindow;
}
+ public function getID() {
+ if (!$this->id) {
+ $this->id = celerity_generate_unique_node_id();
+ }
+ return $this->id;
+ }
+
+ public function setSubmenu(array $submenu) {
+ $this->submenu = $submenu;
+
+ if (!$this->getHref()) {
+ $this->setHref('#');
+ }
+
+ return $this;
+ }
+
+ public function getItems($depth = 0) {
+ $items = array();
+
+ $items[] = $this;
+ foreach ($this->submenu as $action) {
+ foreach ($action->getItems($depth + 1) as $item) {
+ $item
+ ->setHidden(true)
+ ->setDepth($depth + 1);
+
+ $items[] = $item;
+ }
+ }
+
+ return $items;
+ }
+
+ public function setHidden($hidden) {
+ $this->hidden = $hidden;
+ return $this;
+ }
+
+ public function getHidden() {
+ return $this->hidden;
+ }
+
+ public function setDepth($depth) {
+ $this->depth = $depth;
+ return $this;
+ }
+
+ public function getDepth() {
+ return $this->depth;
+ }
+
public function render() {
+ $caret_id = celerity_generate_unique_node_id();
$icon = null;
if ($this->icon) {
$color = '';
if ($this->disabled) {
$color = ' grey';
}
$icon = id(new PHUIIconView())
->addClass('phabricator-action-view-icon')
->setIcon($this->icon.$color);
}
if ($this->href) {
$sigils = array();
if ($this->workflow) {
$sigils[] = 'workflow';
}
if ($this->download) {
$sigils[] = 'download';
}
if ($this->sigils) {
$sigils = array_merge($sigils, $this->sigils);
}
$sigils = $sigils ? implode(' ', $sigils) : null;
if ($this->renderAsForm) {
if (!$this->hasViewer()) {
throw new Exception(
pht(
'Call %s when rendering an action as a form.',
'setViewer()'));
}
$item = javelin_tag(
'button',
array(
'class' => 'phabricator-action-view-item',
),
array($icon, $this->name));
$item = phabricator_form(
$this->getViewer(),
array(
'action' => $this->getHref(),
'method' => 'POST',
'sigil' => $sigils,
'meta' => $this->metadata,
),
$item);
} else {
if ($this->getOpenInNewWindow()) {
$target = '_blank';
} else {
$target = null;
}
+ if ($this->submenu) {
+ $caret = javelin_tag(
+ 'span',
+ array(
+ 'class' => 'caret-right',
+ 'id' => $caret_id,
+ ),
+ '');
+ } else {
+ $caret = null;
+ }
+
$item = javelin_tag(
'a',
array(
'href' => $this->getHref(),
'class' => 'phabricator-action-view-item',
'target' => $target,
'sigil' => $sigils,
'meta' => $this->metadata,
),
- array($icon, $this->name));
+ array($icon, $this->name, $caret));
}
} else {
$item = phutil_tag(
'span',
array(
'class' => 'phabricator-action-view-item',
),
array($icon, $this->name));
}
$classes = array();
$classes[] = 'phabricator-action-view';
if ($this->disabled) {
$classes[] = 'phabricator-action-view-disabled';
}
if ($this->label) {
$classes[] = 'phabricator-action-view-label';
}
if ($this->selected) {
$classes[] = 'phabricator-action-view-selected';
}
- return phutil_tag(
+ if ($this->submenu) {
+ $classes[] = 'phabricator-action-view-submenu';
+ }
+
+ $style = array();
+
+ if ($this->hidden) {
+ $style[] = 'display: none;';
+ }
+
+ if ($this->depth) {
+ $indent = ($this->depth * 16);
+ $style[] = "margin-left: {$indent}px;";
+ }
+
+ $sigil = null;
+ $meta = null;
+
+ if ($this->submenu) {
+ Javelin::initBehavior('phui-submenu');
+ $sigil = 'phui-submenu';
+
+ $item_ids = array();
+ foreach ($this->submenu as $subitem) {
+ $item_ids[] = $subitem->getID();
+ }
+
+ $meta = array(
+ 'itemIDs' => $item_ids,
+ 'caretID' => $caret_id,
+ );
+ }
+
+ return javelin_tag(
'li',
array(
+ 'id' => $this->getID(),
'class' => implode(' ', $classes),
+ 'style' => implode(' ', $style),
+ 'sigil' => $sigil,
+ 'meta' => $meta,
),
$item);
}
}
diff --git a/src/view/phui/PHUIButtonView.php b/src/view/phui/PHUIButtonView.php
index f9266a170a..bda7723ef1 100644
--- a/src/view/phui/PHUIButtonView.php
+++ b/src/view/phui/PHUIButtonView.php
@@ -1,192 +1,204 @@
<?php
final class PHUIButtonView extends AphrontTagView {
const GREEN = 'green';
const GREY = 'grey';
const DISABLED = 'disabled';
const SIMPLE = 'simple';
const SIMPLE_YELLOW = 'simple simple-yellow';
const SIMPLE_GREY = 'simple simple-grey';
const SIMPLE_BLUE = 'simple simple-blue';
const SMALL = 'small';
const BIG = 'big';
private $size;
private $text;
private $subtext;
private $color;
private $tag = 'button';
private $dropdown;
private $icon;
private $iconFirst;
private $href = null;
private $title = null;
private $disabled;
private $name;
private $tooltip;
public function setName($name) {
$this->name = $name;
return $this;
}
public function getName() {
return $this->name;
}
public function setText($text) {
$this->text = $text;
return $this;
}
public function setHref($href) {
$this->href = $href;
return $this;
}
public function setTitle($title) {
$this->title = $title;
return $this;
}
public function setSubtext($subtext) {
$this->subtext = $subtext;
return $this;
}
public function setColor($color) {
$this->color = $color;
return $this;
}
public function setDisabled($disabled) {
$this->disabled = $disabled;
return $this;
}
public function setTag($tag) {
$this->tag = $tag;
return $this;
}
public function setSize($size) {
$this->size = $size;
return $this;
}
public function setDropdown($dd) {
$this->dropdown = $dd;
return $this;
}
public function setTooltip($text) {
$this->tooltip = $text;
return $this;
}
public function setIcon($icon, $first = true) {
if (!($icon instanceof PHUIIconView)) {
$icon = id(new PHUIIconView())
->setIcon($icon);
}
$this->icon = $icon;
$this->iconFirst = $first;
return $this;
}
protected function getTagName() {
return $this->tag;
}
public function setDropdownMenu(PhabricatorActionListView $actions) {
Javelin::initBehavior('phui-dropdown-menu');
$this->addSigil('phui-dropdown-menu');
$this->setMetadata($actions->getDropdownMenuMetadata());
return $this;
}
+ public function setDropdownMenuID($id) {
+ Javelin::initBehavior('phui-dropdown-menu');
+
+ $this->addSigil('phui-dropdown-menu');
+ $this->setMetadata(
+ array(
+ 'menuID' => $id,
+ ));
+
+ return $this;
+ }
+
protected function getTagAttributes() {
require_celerity_resource('phui-button-css');
$classes = array();
$classes[] = 'button';
if ($this->color) {
$classes[] = $this->color;
}
if ($this->size) {
$classes[] = $this->size;
}
if ($this->dropdown) {
$classes[] = 'dropdown';
}
if ($this->icon) {
$classes[] = 'has-icon';
}
if ($this->iconFirst == false) {
$classes[] = 'icon-last';
}
if ($this->disabled) {
$classes[] = 'disabled';
}
$sigil = null;
$meta = null;
if ($this->tooltip) {
Javelin::initBehavior('phabricator-tooltips');
require_celerity_resource('aphront-tooltip-css');
$sigil = 'has-tooltip';
$meta = array(
'tip' => $this->tooltip,
);
}
return array(
'class' => $classes,
'href' => $this->href,
'name' => $this->name,
'title' => $this->title,
'sigil' => $sigil,
'meta' => $meta,
);
}
protected function getTagContent() {
$icon = null;
$text = $this->text;
if ($this->icon) {
$icon = $this->icon;
$subtext = null;
if ($this->subtext) {
$subtext = phutil_tag(
'div', array('class' => 'phui-button-subtext'), $this->subtext);
}
$text = phutil_tag(
'div', array('class' => 'phui-button-text'), array($text, $subtext));
}
$caret = null;
if ($this->dropdown) {
$caret = phutil_tag('span', array('class' => 'caret'), '');
}
if ($this->iconFirst == true) {
return array($icon, $text, $caret);
} else {
return array($text, $icon);
}
}
}
diff --git a/src/view/phui/PHUIHeaderView.php b/src/view/phui/PHUIHeaderView.php
index 8111944c4d..e5e834bef5 100644
--- a/src/view/phui/PHUIHeaderView.php
+++ b/src/view/phui/PHUIHeaderView.php
@@ -1,517 +1,529 @@
<?php
final class PHUIHeaderView extends AphrontTagView {
const PROPERTY_STATUS = 1;
private $header;
private $tags = array();
private $image;
private $imageURL = null;
private $imageEditURL = null;
private $subheader;
private $headerIcon;
private $noBackground;
private $bleedHeader;
private $profileHeader;
private $tall;
private $properties = array();
private $actionLinks = array();
private $buttonBar = null;
private $policyObject;
private $epoch;
private $actionItems = array();
private $badges = array();
private $href;
private $actionList;
+ private $actionListID;
public function setHeader($header) {
$this->header = $header;
return $this;
}
public function setNoBackground($nada) {
$this->noBackground = $nada;
return $this;
}
public function setTall($tall) {
$this->tall = $tall;
return $this;
}
public function addTag(PHUITagView $tag) {
$this->tags[] = $tag;
return $this;
}
public function addBadge(PHUIBadgeMiniView $badge) {
$this->badges[] = $badge;
return $this;
}
public function setImage($uri) {
$this->image = $uri;
return $this;
}
public function setImageURL($url) {
$this->imageURL = $url;
return $this;
}
public function setImageEditURL($url) {
$this->imageEditURL = $url;
return $this;
}
public function setSubheader($subheader) {
$this->subheader = $subheader;
return $this;
}
public function setBleedHeader($bleed) {
$this->bleedHeader = $bleed;
return $this;
}
public function setProfileHeader($bighead) {
$this->profileHeader = $bighead;
return $this;
}
public function setHeaderIcon($icon) {
$this->headerIcon = $icon;
return $this;
}
public function setActionList(PhabricatorActionListView $list) {
$this->actionList = $list;
return $this;
}
+ public function setActionListID($action_list_id) {
+ $this->actionListID = $action_list_id;
+ return $this;
+ }
+
public function setPolicyObject(PhabricatorPolicyInterface $object) {
$this->policyObject = $object;
return $this;
}
public function addProperty($property, $value) {
$this->properties[$property] = $value;
return $this;
}
public function addActionLink(PHUIButtonView $button) {
$this->actionLinks[] = $button;
return $this;
}
public function addActionItem($action) {
$this->actionItems[] = $action;
return $this;
}
public function setButtonBar(PHUIButtonBarView $bb) {
$this->buttonBar = $bb;
return $this;
}
public function setStatus($icon, $color, $name) {
// TODO: Normalize "closed/archived" to constants.
if ($color == 'dark') {
$color = PHUITagView::COLOR_INDIGO;
}
$tag = id(new PHUITagView())
->setName($name)
->setIcon($icon)
->setShade($color)
->setType(PHUITagView::TYPE_SHADE);
return $this->addProperty(self::PROPERTY_STATUS, $tag);
}
public function setEpoch($epoch) {
$age = time() - $epoch;
$age = floor($age / (60 * 60 * 24));
if ($age < 1) {
$when = pht('Today');
} else if ($age == 1) {
$when = pht('Yesterday');
} else {
$when = pht('%s Day(s) Ago', new PhutilNumber($age));
}
$this->setStatus('fa-clock-o bluegrey', null, pht('Updated %s', $when));
return $this;
}
public function setHref($href) {
$this->href = $href;
return $this;
}
public function getHref() {
return $this->href;
}
protected function getTagName() {
return 'div';
}
protected function getTagAttributes() {
require_celerity_resource('phui-header-view-css');
$classes = array();
$classes[] = 'phui-header-shell';
if ($this->noBackground) {
$classes[] = 'phui-header-no-backgound';
}
if ($this->bleedHeader) {
$classes[] = 'phui-bleed-header';
}
if ($this->profileHeader) {
$classes[] = 'phui-profile-header';
}
if ($this->properties || $this->policyObject ||
$this->subheader || $this->tall) {
$classes[] = 'phui-header-tall';
}
return array(
'class' => $classes,
);
}
protected function getTagContent() {
- if ($this->actionList) {
+ if ($this->actionList || $this->actionListID) {
$action_button = id(new PHUIButtonView())
->setTag('a')
->setText(pht('Actions'))
->setHref('#')
->setIcon('fa-bars')
- ->addClass('phui-mobile-menu')
- ->setDropdownMenu($this->actionList);
+ ->addClass('phui-mobile-menu');
+
+ if ($this->actionList) {
+ $action_button->setDropdownMenu($this->actionList);
+ } else if ($this->actionListID) {
+ $action_button->setDropdownMenuID($this->actionListID);
+ }
+
$this->addActionLink($action_button);
}
$image = null;
if ($this->image) {
$image_href = null;
if ($this->imageURL) {
$image_href = $this->imageURL;
} else if ($this->imageEditURL) {
$image_href = $this->imageEditURL;
}
$image = phutil_tag(
'span',
array(
'class' => 'phui-header-image',
'style' => 'background-image: url('.$this->image.')',
));
if ($image_href) {
$edit_view = null;
if ($this->imageEditURL) {
$edit_view = phutil_tag(
'span',
array(
'class' => 'phui-header-image-edit',
),
pht('Edit'));
}
$image = phutil_tag(
'a',
array(
'href' => $image_href,
'class' => 'phui-header-image-href',
),
array(
$image,
$edit_view,
));
}
}
$viewer = $this->getUser();
$left = array();
$right = array();
$space_header = null;
if ($viewer) {
$space_header = id(new PHUISpacesNamespaceContextView())
->setUser($viewer)
->setObject($this->policyObject);
}
if ($this->actionLinks) {
$actions = array();
foreach ($this->actionLinks as $button) {
$button->setColor(PHUIButtonView::GREY);
$button->addClass(PHUI::MARGIN_SMALL_LEFT);
$button->addClass('phui-header-action-link');
$actions[] = $button;
}
$right[] = phutil_tag(
'div',
array(
'class' => 'phui-header-action-links',
),
$actions);
}
if ($this->buttonBar) {
$right[] = phutil_tag(
'div',
array(
'class' => 'phui-header-action-links',
),
$this->buttonBar);
}
if ($this->actionItems) {
$action_list = array();
if ($this->actionItems) {
foreach ($this->actionItems as $item) {
$action_list[] = phutil_tag(
'li',
array(
'class' => 'phui-header-action-item',
),
$item);
}
}
$right[] = phutil_tag(
'ul',
array(
'class' => 'phui-header-action-list',
),
$action_list);
}
$icon = null;
if ($this->headerIcon) {
$icon = id(new PHUIIconView())
->setIcon($this->headerIcon)
->addClass('phui-header-icon');
}
$header_content = $this->header;
$href = $this->getHref();
if ($href !== null) {
$header_content = phutil_tag(
'a',
array(
'href' => $href,
),
$header_content);
}
$left[] = phutil_tag(
'span',
array(
'class' => 'phui-header-header',
),
array(
$space_header,
$icon,
$header_content,
));
if ($this->subheader || $this->badges) {
$badges = null;
if ($this->badges) {
$badges = new PHUIBadgeBoxView();
$badges->addItems($this->badges);
$badges->setCollapsed(true);
}
$left[] = phutil_tag(
'div',
array(
'class' => 'phui-header-subheader',
),
array(
$badges,
$this->subheader,
));
}
if ($this->properties || $this->policyObject || $this->tags) {
$property_list = array();
foreach ($this->properties as $type => $property) {
switch ($type) {
case self::PROPERTY_STATUS:
$property_list[] = $property;
break;
default:
throw new Exception(pht('Incorrect Property Passed'));
break;
}
}
if ($this->policyObject) {
$property_list[] = $this->renderPolicyProperty($this->policyObject);
}
if ($this->tags) {
$property_list[] = $this->tags;
}
$left[] = phutil_tag(
'div',
array(
'class' => 'phui-header-subheader',
),
$property_list);
}
// We here at @phabricator
$header_image = null;
if ($image) {
$header_image = phutil_tag(
'div',
array(
'class' => 'phui-header-col1',
),
$image);
}
// All really love
$header_left = phutil_tag(
'div',
array(
'class' => 'phui-header-col2',
),
$left);
// Tables and Pokemon.
$header_right = phutil_tag(
'div',
array(
'class' => 'phui-header-col3',
),
$right);
$header_row = phutil_tag(
'div',
array(
'class' => 'phui-header-row',
),
array(
$header_image,
$header_left,
$header_right,
));
return phutil_tag(
'h1',
array(
'class' => 'phui-header-view',
),
$header_row);
}
private function renderPolicyProperty(PhabricatorPolicyInterface $object) {
$viewer = $this->getUser();
$policies = PhabricatorPolicyQuery::loadPolicies($viewer, $object);
$view_capability = PhabricatorPolicyCapability::CAN_VIEW;
$policy = idx($policies, $view_capability);
if (!$policy) {
return null;
}
// If an object is in a Space with a strictly stronger (more restrictive)
// policy, we show the more restrictive policy. This better aligns the
// UI hint with the actual behavior.
// NOTE: We'll do this even if the viewer has access to only one space, and
// show them information about the existence of spaces if they click
// through.
$use_space_policy = false;
if ($object instanceof PhabricatorSpacesInterface) {
$space_phid = PhabricatorSpacesNamespaceQuery::getObjectSpacePHID(
$object);
$spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces($viewer);
$space = idx($spaces, $space_phid);
if ($space) {
$space_policies = PhabricatorPolicyQuery::loadPolicies(
$viewer,
$space);
$space_policy = idx($space_policies, $view_capability);
if ($space_policy) {
if ($space_policy->isStrongerThan($policy)) {
$policy = $space_policy;
$use_space_policy = true;
}
}
}
}
$container_classes = array();
$container_classes[] = 'policy-header-callout';
$phid = $object->getPHID();
// If we're going to show the object policy, try to determine if the object
// policy differs from the default policy. If it does, we'll call it out
// as changed.
if (!$use_space_policy) {
$default_policy = PhabricatorPolicyQuery::getDefaultPolicyForObject(
$viewer,
$object,
$view_capability);
if ($default_policy) {
if ($default_policy->getPHID() != $policy->getPHID()) {
$container_classes[] = 'policy-adjusted';
if ($default_policy->isStrongerThan($policy)) {
// The policy has strictly been weakened. For example, the
// default might be "All Users" and the current policy is "Public".
$container_classes[] = 'policy-adjusted-weaker';
} else if ($policy->isStrongerThan($default_policy)) {
// The policy has strictly been strengthened, and is now more
// restrictive than the default. For example, "All Users" has
// been replaced with "No One".
$container_classes[] = 'policy-adjusted-stronger';
} else {
// The policy has been adjusted but not strictly strengthened
// or weakened. For example, "Members of X" has been replaced with
// "Members of Y".
$container_classes[] = 'policy-adjusted-different';
}
}
}
}
$icon = id(new PHUIIconView())
->setIcon($policy->getIcon().' bluegrey');
$link = javelin_tag(
'a',
array(
'class' => 'policy-link',
'href' => '/policy/explain/'.$phid.'/'.$view_capability.'/',
'sigil' => 'workflow',
),
$policy->getShortName());
return phutil_tag(
'span',
array(
'class' => implode(' ', $container_classes),
),
array($icon, $link));
}
}
diff --git a/src/view/phui/PHUITimelineEventView.php b/src/view/phui/PHUITimelineEventView.php
index 08b6cc2aaf..87fee5cfa6 100644
--- a/src/view/phui/PHUITimelineEventView.php
+++ b/src/view/phui/PHUITimelineEventView.php
@@ -1,669 +1,667 @@
<?php
final class PHUITimelineEventView extends AphrontView {
const DELIMITER = " \xC2\xB7 ";
private $userHandle;
private $title;
private $icon;
private $color;
private $classes = array();
private $contentSource;
private $dateCreated;
private $anchor;
private $isEditable;
private $isEdited;
private $isRemovable;
private $transactionPHID;
private $isPreview;
private $eventGroup = array();
private $hideByDefault;
private $token;
private $tokenRemoved;
private $quoteTargetID;
private $isNormalComment;
private $quoteRef;
private $reallyMajorEvent;
private $hideCommentOptions = false;
private $authorPHID;
private $badges = array();
public function setAuthorPHID($author_phid) {
$this->authorPHID = $author_phid;
return $this;
}
public function getAuthorPHID() {
return $this->authorPHID;
}
public function setQuoteRef($quote_ref) {
$this->quoteRef = $quote_ref;
return $this;
}
public function getQuoteRef() {
return $this->quoteRef;
}
public function setQuoteTargetID($quote_target_id) {
$this->quoteTargetID = $quote_target_id;
return $this;
}
public function getQuoteTargetID() {
return $this->quoteTargetID;
}
public function setIsNormalComment($is_normal_comment) {
$this->isNormalComment = $is_normal_comment;
return $this;
}
public function getIsNormalComment() {
return $this->isNormalComment;
}
public function setHideByDefault($hide_by_default) {
$this->hideByDefault = $hide_by_default;
return $this;
}
public function getHideByDefault() {
return $this->hideByDefault;
}
public function setTransactionPHID($transaction_phid) {
$this->transactionPHID = $transaction_phid;
return $this;
}
public function getTransactionPHID() {
return $this->transactionPHID;
}
public function setIsEdited($is_edited) {
$this->isEdited = $is_edited;
return $this;
}
public function getIsEdited() {
return $this->isEdited;
}
public function setIsPreview($is_preview) {
$this->isPreview = $is_preview;
return $this;
}
public function getIsPreview() {
return $this->isPreview;
}
public function setIsEditable($is_editable) {
$this->isEditable = $is_editable;
return $this;
}
public function getIsEditable() {
return $this->isEditable;
}
public function setIsRemovable($is_removable) {
$this->isRemovable = $is_removable;
return $this;
}
public function getIsRemovable() {
return $this->isRemovable;
}
public function setDateCreated($date_created) {
$this->dateCreated = $date_created;
return $this;
}
public function getDateCreated() {
return $this->dateCreated;
}
public function setContentSource(PhabricatorContentSource $content_source) {
$this->contentSource = $content_source;
return $this;
}
public function getContentSource() {
return $this->contentSource;
}
public function setUserHandle(PhabricatorObjectHandle $handle) {
$this->userHandle = $handle;
return $this;
}
public function setAnchor($anchor) {
$this->anchor = $anchor;
return $this;
}
public function getAnchor() {
return $this->anchor;
}
public function setTitle($title) {
$this->title = $title;
return $this;
}
public function addClass($class) {
$this->classes[] = $class;
return $this;
}
public function addBadge(PHUIBadgeMiniView $badge) {
$this->badges[] = $badge;
return $this;
}
public function setIcon($icon) {
$this->icon = $icon;
return $this;
}
public function setColor($color) {
$this->color = $color;
return $this;
}
public function setReallyMajorEvent($me) {
$this->reallyMajorEvent = $me;
return $this;
}
public function setHideCommentOptions($hide_comment_options) {
$this->hideCommentOptions = $hide_comment_options;
return $this;
}
public function getHideCommentOptions() {
return $this->hideCommentOptions;
}
public function setToken($token, $removed = false) {
$this->token = $token;
$this->tokenRemoved = $removed;
return $this;
}
public function getEventGroup() {
return array_merge(array($this), $this->eventGroup);
}
public function addEventToGroup(PHUITimelineEventView $event) {
$this->eventGroup[] = $event;
return $this;
}
protected function shouldRenderEventTitle() {
if ($this->title === null) {
return false;
}
return true;
}
protected function renderEventTitle($force_icon, $has_menu, $extra) {
$title = $this->title;
$title_classes = array();
$title_classes[] = 'phui-timeline-title';
$icon = null;
if ($this->icon || $force_icon) {
$title_classes[] = 'phui-timeline-title-with-icon';
}
if ($has_menu) {
$title_classes[] = 'phui-timeline-title-with-menu';
}
if ($this->icon) {
$fill_classes = array();
$fill_classes[] = 'phui-timeline-icon-fill';
if ($this->color) {
$fill_classes[] = 'fill-has-color';
$fill_classes[] = 'phui-timeline-icon-fill-'.$this->color;
}
$icon = id(new PHUIIconView())
->setIcon($this->icon)
->addClass('phui-timeline-icon');
$icon = phutil_tag(
'span',
array(
'class' => implode(' ', $fill_classes),
),
$icon);
}
$token = null;
if ($this->token) {
$token = id(new PHUIIconView())
->addClass('phui-timeline-token')
->setSpriteSheet(PHUIIconView::SPRITE_TOKENS)
->setSpriteIcon($this->token);
if ($this->tokenRemoved) {
$token->addClass('strikethrough');
}
}
$title = phutil_tag(
'div',
array(
'class' => implode(' ', $title_classes),
),
array($icon, $token, $title, $extra));
return $title;
}
public function render() {
$events = $this->getEventGroup();
// Move events with icons first.
$icon_keys = array();
foreach ($this->getEventGroup() as $key => $event) {
if ($event->icon) {
$icon_keys[] = $key;
}
}
$events = array_select_keys($events, $icon_keys) + $events;
$force_icon = (bool)$icon_keys;
$menu = null;
$items = array();
$has_menu = false;
if (!$this->getIsPreview() && !$this->getHideCommentOptions()) {
foreach ($this->getEventGroup() as $event) {
$items[] = $event->getMenuItems($this->anchor);
if ($event->hasChildren()) {
$has_menu = true;
}
}
$items = array_mergev($items);
}
if ($items || $has_menu) {
$icon = id(new PHUIIconView())
->setIcon('fa-caret-down');
$aural = javelin_tag(
'span',
array(
'aural' => true,
),
pht('Comment Actions'));
if ($items) {
$sigil = 'phui-dropdown-menu';
Javelin::initBehavior('phui-dropdown-menu');
} else {
$sigil = null;
}
$action_list = id(new PhabricatorActionListView())
->setUser($this->getUser());
foreach ($items as $item) {
$action_list->addAction($item);
}
$menu = javelin_tag(
$items ? 'a' : 'span',
array(
'href' => '#',
'class' => 'phui-timeline-menu',
'sigil' => $sigil,
'aria-haspopup' => 'true',
'aria-expanded' => 'false',
- 'meta' => array(
- 'items' => hsprintf('%s', $action_list),
- ),
+ 'meta' => $action_list->getDropdownMenuMetadata(),
),
array(
$aural,
$icon,
));
$has_menu = true;
}
// Render "extra" information (timestamp, etc).
$extra = $this->renderExtra($events);
$show_badges = false;
$group_titles = array();
$group_items = array();
$group_children = array();
foreach ($events as $event) {
if ($event->shouldRenderEventTitle()) {
$group_titles[] = $event->renderEventTitle(
$force_icon,
$has_menu,
$extra);
// Don't render this information more than once.
$extra = null;
}
if ($event->hasChildren()) {
$group_children[] = $event->renderChildren();
$show_badges = true;
}
}
$image_uri = $this->userHandle->getImageURI();
$wedge = phutil_tag(
'div',
array(
'class' => 'phui-timeline-wedge phui-timeline-border',
'style' => (nonempty($image_uri)) ? '' : 'display: none;',
),
'');
$image = null;
$badges = null;
if ($image_uri) {
$image = phutil_tag(
($this->userHandle->getURI()) ? 'a' : 'div',
array(
'style' => 'background-image: url('.$image_uri.')',
'class' => 'phui-timeline-image',
'href' => $this->userHandle->getURI(),
),
'');
if ($this->badges && $show_badges) {
$flex = new PHUIBadgeBoxView();
$flex->addItems($this->badges);
$flex->setCollapsed(true);
$badges = phutil_tag(
'div',
array(
'class' => 'phui-timeline-badges',
),
$flex);
}
}
$content_classes = array();
$content_classes[] = 'phui-timeline-content';
$classes = array();
$classes[] = 'phui-timeline-event-view';
if ($group_children) {
$classes[] = 'phui-timeline-major-event';
$content = phutil_tag(
'div',
array(
'class' => 'phui-timeline-inner-content',
),
array(
$group_titles,
$menu,
phutil_tag(
'div',
array(
'class' => 'phui-timeline-core-content',
),
$group_children),
));
} else {
$classes[] = 'phui-timeline-minor-event';
$content = $group_titles;
}
$content = phutil_tag(
'div',
array(
'class' => 'phui-timeline-group phui-timeline-border',
),
$content);
$content = phutil_tag(
'div',
array(
'class' => implode(' ', $content_classes),
),
array($image, $badges, $wedge, $content));
$outer_classes = $this->classes;
$outer_classes[] = 'phui-timeline-shell';
$color = null;
foreach ($this->getEventGroup() as $event) {
if ($event->color) {
$color = $event->color;
break;
}
}
if ($color) {
$outer_classes[] = 'phui-timeline-'.$color;
}
$sigil = null;
$meta = null;
if ($this->getTransactionPHID()) {
$sigil = 'transaction';
$meta = array(
'phid' => $this->getTransactionPHID(),
'anchor' => $this->anchor,
);
}
$major_event = null;
if ($this->reallyMajorEvent) {
$major_event = phutil_tag(
'div',
array(
'class' => 'phui-timeline-event-view '.
'phui-timeline-spacer '.
'phui-timeline-spacer-bold',
'',
));
}
return array(
javelin_tag(
'div',
array(
'class' => implode(' ', $outer_classes),
'id' => $this->anchor ? 'anchor-'.$this->anchor : null,
'sigil' => $sigil,
'meta' => $meta,
),
phutil_tag(
'div',
array(
'class' => implode(' ', $classes),
),
$content)),
$major_event,
);
}
private function renderExtra(array $events) {
$extra = array();
if ($this->getIsPreview()) {
$extra[] = pht('PREVIEW');
} else {
foreach ($events as $event) {
if ($event->getIsEdited()) {
$extra[] = pht('Edited');
break;
}
}
$source = $this->getContentSource();
$content_source = null;
if ($source) {
$content_source = id(new PhabricatorContentSourceView())
->setContentSource($source)
->setUser($this->getUser());
$content_source = pht('Via %s', $content_source->getSourceName());
}
$date_created = null;
foreach ($events as $event) {
if ($event->getDateCreated()) {
if ($date_created === null) {
$date_created = $event->getDateCreated();
} else {
$date_created = min($event->getDateCreated(), $date_created);
}
}
}
if ($date_created) {
$date = phabricator_datetime(
$date_created,
$this->getUser());
if ($this->anchor) {
Javelin::initBehavior('phabricator-watch-anchor');
Javelin::initBehavior('phabricator-tooltips');
$anchor = id(new PhabricatorAnchorView())
->setAnchorName($this->anchor)
->render();
$date = array(
$anchor,
javelin_tag(
'a',
array(
'href' => '#'.$this->anchor,
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => $content_source,
),
),
$date),
);
}
$extra[] = $date;
}
}
$extra = javelin_tag(
'span',
array(
'class' => 'phui-timeline-extra',
),
phutil_implode_html(
javelin_tag(
'span',
array(
'aural' => false,
),
self::DELIMITER),
$extra));
return $extra;
}
private function getMenuItems($anchor) {
$xaction_phid = $this->getTransactionPHID();
$items = array();
if ($this->getIsEditable()) {
$items[] = id(new PhabricatorActionView())
->setIcon('fa-pencil')
->setHref('/transactions/edit/'.$xaction_phid.'/')
->setName(pht('Edit Comment'))
->addSigil('transaction-edit')
->setMetadata(
array(
'anchor' => $anchor,
));
}
if ($this->getQuoteTargetID()) {
$ref = null;
if ($this->getQuoteRef()) {
$ref = $this->getQuoteRef();
if ($anchor) {
$ref = $ref.'#'.$anchor;
}
}
$items[] = id(new PhabricatorActionView())
->setIcon('fa-quote-left')
->setHref('#')
->setName(pht('Quote'))
->addSigil('transaction-quote')
->setMetadata(
array(
'targetID' => $this->getQuoteTargetID(),
'uri' => '/transactions/quote/'.$xaction_phid.'/',
'ref' => $ref,
));
}
if ($this->getIsNormalComment()) {
$items[] = id(new PhabricatorActionView())
->setIcon('fa-cutlery')
->setHref('/transactions/raw/'.$xaction_phid.'/')
->setName(pht('View Raw'))
->addSigil('transaction-raw')
->setMetadata(
array(
'anchor' => $anchor,
));
$content_source = $this->getContentSource();
$source_email = PhabricatorEmailContentSource::SOURCECONST;
if ($content_source->getSource() == $source_email) {
$source_id = $content_source->getContentSourceParameter('id');
if ($source_id) {
$items[] = id(new PhabricatorActionView())
->setIcon('fa-envelope-o')
->setHref('/transactions/raw/'.$xaction_phid.'/?email')
->setName(pht('View Email Body'))
->addSigil('transaction-raw')
->setMetadata(
array(
'anchor' => $anchor,
));
}
}
}
if ($this->getIsRemovable()) {
$items[] = id(new PhabricatorActionView())
->setIcon('fa-times')
->setHref('/transactions/remove/'.$xaction_phid.'/')
->setName(pht('Remove Comment'))
->addSigil('transaction-remove')
->setMetadata(
array(
'anchor' => $anchor,
));
}
if ($this->getIsEdited()) {
$items[] = id(new PhabricatorActionView())
->setIcon('fa-list')
->setHref('/transactions/history/'.$xaction_phid.'/')
->setName(pht('View Edit History'))
->setWorkflow(true);
}
return $items;
}
}
diff --git a/src/view/phui/PHUITwoColumnView.php b/src/view/phui/PHUITwoColumnView.php
index 819e726309..4ada03240d 100644
--- a/src/view/phui/PHUITwoColumnView.php
+++ b/src/view/phui/PHUITwoColumnView.php
@@ -1,209 +1,209 @@
<?php
final class PHUITwoColumnView extends AphrontTagView {
private $mainColumn;
private $sideColumn = null;
private $navigation;
private $display;
private $fluid;
private $header;
private $subheader;
private $footer;
private $propertySection = array();
private $curtain;
const DISPLAY_LEFT = 'phui-side-column-left';
const DISPLAY_RIGHT = 'phui-side-column-right';
public function setMainColumn($main) {
$this->mainColumn = $main;
return $this;
}
public function setSideColumn($side) {
$this->sideColumn = $side;
return $this;
}
public function setNavigation($nav) {
$this->navigation = $nav;
$this->display = self::DISPLAY_LEFT;
return $this;
}
public function setHeader(PHUIHeaderView $header) {
$this->header = $header;
return $this;
}
public function setSubheader($subheader) {
$this->subheader = $subheader;
return $this;
}
public function setFooter($footer) {
$this->footer = $footer;
return $this;
}
public function addPropertySection($title, $section) {
$this->propertySection[] = array($title, $section);
return $this;
}
public function setCurtain(PHUICurtainView $curtain) {
$this->curtain = $curtain;
return $this;
}
public function getCurtain() {
return $this->curtain;
}
public function setFluid($fluid) {
$this->fluid = $fluid;
return $this;
}
public function setDisplay($display) {
$this->display = $display;
return $this;
}
private function getDisplay() {
if ($this->display) {
return $this->display;
} else {
return self::DISPLAY_RIGHT;
}
}
protected function getTagAttributes() {
$classes = array();
$classes[] = 'phui-two-column-view';
$classes[] = $this->getDisplay();
if ($this->fluid) {
$classes[] = 'phui-two-column-fluid';
}
if ($this->subheader) {
$classes[] = 'with-subheader';
}
return array(
'class' => implode(' ', $classes),
);
}
protected function getTagContent() {
require_celerity_resource('phui-two-column-view-css');
$main = $this->buildMainColumn();
$side = $this->buildSideColumn();
$footer = $this->buildFooter();
$order = array($side, $main);
$inner = phutil_tag_div('phui-two-column-row grouped', $order);
$table = phutil_tag_div('phui-two-column-content', $inner);
$header = null;
if ($this->header) {
$curtain = $this->getCurtain();
if ($curtain) {
$action_list = $curtain->getActionList();
- $this->header->setActionList($action_list);
+ $this->header->setActionListID($action_list->getID());
}
$header = phutil_tag_div(
'phui-two-column-header', $this->header);
}
$subheader = null;
if ($this->subheader) {
$subheader = phutil_tag_div(
'phui-two-column-subheader', $this->subheader);
}
return phutil_tag(
'div',
array(
'class' => 'phui-two-column-container',
),
array(
$header,
$subheader,
$table,
$footer,
));
}
private function buildMainColumn() {
$view = array();
$sections = $this->propertySection;
if ($sections) {
foreach ($sections as $content) {
if ($content[1]) {
$view[] = id(new PHUIObjectBoxView())
->setHeaderText($content[0])
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($content[1]);
}
}
}
return phutil_tag(
'div',
array(
'class' => 'phui-main-column',
),
array(
$view,
$this->mainColumn,
));
}
private function buildSideColumn() {
$classes = array();
$classes[] = 'phui-side-column';
$navigation = null;
if ($this->navigation) {
$classes[] = 'side-has-nav';
$navigation = id(new PHUIObjectBoxView())
->appendChild($this->navigation);
}
$curtain = $this->getCurtain();
return phutil_tag(
'div',
array(
'class' => implode($classes, ' '),
),
array(
$navigation,
$curtain,
$this->sideColumn,
));
}
private function buildFooter() {
$footer = $this->footer;
return phutil_tag(
'div',
array(
'class' => 'phui-two-column-content phui-two-column-footer',
),
array(
$footer,
));
}
}
diff --git a/webroot/rsrc/css/phui/phui-button.css b/webroot/rsrc/css/phui/phui-button.css
index 0e7cfd3ecc..1566585919 100644
--- a/webroot/rsrc/css/phui/phui-button.css
+++ b/webroot/rsrc/css/phui/phui-button.css
@@ -1,378 +1,414 @@
/**
* @provides phui-button-css
*/
button,
a.button {
font: {$basefont};
-webkit-font-smoothing: antialiased;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
button.phabricator-action-view-item {
-webkit-font-smoothing: auto;
}
button::-moz-focus-inner {
padding: 0;
border: 0;
}
button,
a.button,
a.button:visited,
input[type="submit"] {
background-color: #2980b9;
border: 1px solid #2980b9;
background-image: linear-gradient(to bottom, #3498db, #2980b9);
color: white;
cursor: pointer;
font-weight: bold;
font-size: {$normalfontsize};
display: inline-block;
padding: 3px 12px 4px;
text-align: center;
white-space: nowrap;
border-radius: 3px;
}
/* Buttons with images (full size only) */
button.icon,
a.icon,
a.icon:visited {
padding-left: 0;
position: relative;
text-indent: 29px;
}
button.green,
a.green,
a.green:visited {
background-color: {$green};
border-color: {$green};
background-image: linear-gradient(to bottom, #23BB5B, #139543);
}
button.grey,
input[type="submit"].grey,
a.grey,
a.grey:visited {
background-color: #F7F7F9;
background-image: linear-gradient(to bottom, #ffffff, #f1f0f1);
border: 1px solid rgba({$alphablue},.2);
color: {$darkgreytext};
}
button.simple,
input[type="submit"].simple,
a.simple,
a.simple:visited {
background: #fff;
color: {$blue};
border: 1px solid {$blue};
}
a.simple.current {
background: {$lightblue};
}
button.simple .phui-icon-view,
input[type="submit"].simple .phui-icon-view,
a.simple .phui-icon-view,
a.simple:visited .phui-icon-view {
color: {$blue};
}
a.disabled,
button.disabled,
button[disabled] {
filter:alpha(opacity=50);
-moz-opacity: 0.5;
-khtml-opacity: 0.5;
opacity: 0.5;
}
a.phuix-dropdown-open {
color: {$greytext};
}
a.button:hover,
button:hover {
text-decoration: none;
background-color: #2980b9;
background-image: linear-gradient(to bottom, #3498db, #1b6ba0);
border-color: #115988;
transition: 0.1s;
}
a.button.grey:hover,
button.grey:hover {
background-image: linear-gradient(to bottom, #ffffff, #eeebec);
border-color: rgba({$alphablue}, 0.3);
transition: 0.1s;
}
a.button.green:hover,
button.green:hover {
border-color: #127336;
background-color: #0DAD48;
background-image: linear-gradient(to bottom, #23BB5B, #178841);
transition: 0.1s;
}
a.button.simple:hover,
button.simple:hover {
background-color: {$blue};
background-image: linear-gradient(to bottom, {$blue}, {$blue});
color: #fff;
transition: 0.1s;
}
a.button.simple:hover .phui-icon-view,
button.simple:hover .phui-icon-view {
color: #fff;
transition: 0.1s;
}
a.button.simple .phui-icon-view {
border: none;
}
a.button.simple.phuix-dropdown-open {
background-color: #fff;
color: {$blue};
box-shadow: none;
}
a.button.simple.phuix-dropdown-open:hover .phui-icon-view {
color: {$blue};
}
body a.button.disabled:hover,
body button.disabled:hover,
body a.button.disabled:active,
body button.disabled:active {
box-shadow: none;
}
button.small,
a.small,
a.small:visited {
padding: 2px 8px;
height: auto;
font-size: {$smallestfontsize};
line-height: 16px;
}
button.link {
display: inline;
border: none;
background: transparent;
background-image: none;
font-weight: normal;
padding: 0;
margin: 0;
font-size: inherit;
border-bottom: none;
text-decoration: none;
color: #19558D;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
button.link:hover {
text-decoration: underline;
}
.phuix-dropdown-menu {
position: absolute;
width: 240px;
background: #fff;
margin-top: -1px;
padding: 5px 0;
box-shadow: {$dropshadow};
border: 1px solid {$blueborder};
border-radius: 3px;
margin-bottom: 16px;
}
.phuix-dropdown-menu a:focus {
/* We automatically focus links in dropdown menus for assistive devices, but
this is distracting for visual user agents. */
outline: none;
}
a.policy-control {
width: 240px;
text-align: left;
}
a.policy-control .caret {
float: right;
}
.caret {
display: inline-block;
width: 0;
height: 0;
vertical-align: top;
border-top: 5px solid #fff;
border-right: 5px solid transparent;
border-left: 5px solid transparent;
content: "";
}
.caret-right {
display: inline-block;
width: 0;
height: 0;
vertical-align: middle;
border-left: 7px solid {$greytext};
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
content: "";
margin-bottom: 4px;
}
.caret-left {
display: inline-block;
width: 0;
height: 0;
vertical-align: middle;
border-right: 7px solid {$greytext};
border-bottom: 5px solid transparent;
border-top: 5px solid transparent;
content: "";
margin-bottom: 4px;
}
.dropdown .caret {
margin-top: 7px;
margin-left: 6px;
}
.small.dropdown .caret {
margin-top: 6px;
}
.grey.dropdown .caret {
border-top-color: #000;
}
+.phabricator-action-view-submenu .caret-right {
+ float: right;
+ margin-top: 4px;
+ margin-right: 6px;
+ border-left-color: {$lightgreytext};
+}
+
+.phabricator-action-view-submenu .caret {
+ float: right;
+ margin-top: 5px;
+ margin-right: 4px;
+ border-top: 7px solid {$lightgreytext};
+}
+
+.phabricator-action-view-submenu.phui-submenu-open {
+ background: {$greybackground};
+}
+
+.phui-submenu-animate {
+ animation: phui-submenu-summon 0.25s;
+}
+
+@keyframes phui-submenu-summon {
+ 0% {
+ color: {$lightgreytext};
+ margin-left: 0;
+ transform: rotate(12deg);
+ }
+ 60% {
+ margin-left: 24px;
+ transform: rotate(-5deg);
+ margin-top: 18px;
+ }
+}
+
+
/* Icons */
.button.has-icon {
position: relative;
}
.button .phui-icon-view {
display: inline-block;
position: absolute;
top: 6px;
left: 10px;
}
.button.icon-last .phui-icon-view {
left: auto;
right: 10px;
}
.phui-button-bar .button .phui-icon-view {
left: 9px;
}
.button.has-icon .phui-button-text {
margin-left: 16px;
}
.button.has-icon.icon-last .phui-button-text {
margin: 0 16px 0 0;
}
/* Login Buttons */
.button.big.has-icon {
padding: 4px 20px 4px 14px;
border-radius: 4px;
text-align: left;
}
.button.big.has-icon .phui-button-text {
margin-left: 30px;
display: block;
}
.button.big.has-icon .phui-button-subtext {
color: {$greytext};
font-size: {$smallerfontsize};
line-height: 15px;
font-weight: normal;
}
/* PHUI Button Bar */
.phui-button-bar-borderless .button {
border: 0;
background-color: transparent;
background-image: none;
padding-left: 10px;
padding-right: 10px;
}
.phui-button-bar-borderless .button .phui-icon-view {
font-size: 15px;
color: rgba({$alphagrey},.4);
}
.phui-button-bar-borderless .button:hover {
background-color: transparent;
background-image: none;
border-radius: 3px;
}
.phui-button-bar-borderless .button:hover .phui-icon-view {
color: rgba({$alphagrey},.9);
}
.phui-button-bar-borderless .button {
border: 0;
}
.phui-button-bar a.button.has-icon {
display: inline-block;
height: 18px;
width: 6px;
}
.phui-button-bar .phui-button-bar-first {
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;
}
.phui-button-bar .phui-button-bar-middle {
border-radius: 0;
border-left: none;
}
.phui-button-bar .phui-button-bar-last {
border-left: none;
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
}
.phui-button-bar .button.simple:hover {
border-color: {$lightblueborder};
background-color: #fff;
background-image: none;
color: {$sky};
}
.phui-button-bar .button.simple:hover .phui-icon-view {
border-color: {$lightblueborder};
color: {$sky};
background-image: none;
}
diff --git a/webroot/rsrc/js/phui/behavior-phui-dropdown-menu.js b/webroot/rsrc/js/phui/behavior-phui-dropdown-menu.js
index d841c87670..4bde14a307 100644
--- a/webroot/rsrc/js/phui/behavior-phui-dropdown-menu.js
+++ b/webroot/rsrc/js/phui/behavior-phui-dropdown-menu.js
@@ -1,34 +1,59 @@
/**
* @provides javelin-behavior-phui-dropdown-menu
* @requires javelin-behavior
* javelin-stratcom
* javelin-dom
* phuix-dropdown-menu
*/
JX.behavior('phui-dropdown-menu', function() {
JX.Stratcom.listen('click', 'phui-dropdown-menu', function(e) {
var data = e.getNodeData('phui-dropdown-menu');
if (data.menu) {
return;
}
e.kill();
- var list = JX.$H(data.items).getFragment().firstChild;
+ var list;
+ var placeholder;
+ if (data.items) {
+ list = JX.$H(data.items).getFragment().firstChild;
+ } else {
+ list = JX.$(data.menuID);
+ placeholder = JX.$N('span');
+ }
var icon = e.getNode('phui-dropdown-menu');
data.menu = new JX.PHUIXDropdownMenu(icon);
- data.menu.setContent(list);
+
+ data.menu.listen('open', function() {
+ if (placeholder) {
+ JX.DOM.replace(list, placeholder);
+ }
+ data.menu.setContent(list);
+ });
+
+ data.menu.listen('close', function() {
+ if (placeholder) {
+ JX.DOM.replace(placeholder, list);
+ }
+ });
+
data.menu.open();
JX.DOM.listen(list, 'click', 'tag:a', function(e) {
if (!e.isNormalClick()) {
return;
}
+
+ if (JX.Stratcom.pass()) {
+ return;
+ }
+
data.menu.close();
});
});
});
diff --git a/webroot/rsrc/js/phui/behavior-phui-submenu.js b/webroot/rsrc/js/phui/behavior-phui-submenu.js
new file mode 100644
index 0000000000..b391174052
--- /dev/null
+++ b/webroot/rsrc/js/phui/behavior-phui-submenu.js
@@ -0,0 +1,44 @@
+/**
+ * @provides javelin-behavior-phui-submenu
+ * @requires javelin-behavior
+ * javelin-stratcom
+ * javelin-dom
+ */
+
+JX.behavior('phui-submenu', function() {
+
+ JX.Stratcom.listen('click', 'phui-submenu', function(e) {
+ if (!e.isNormalClick()) {
+ return;
+ }
+
+ var node = e.getNode('phui-submenu');
+ var data = e.getNodeData('phui-submenu');
+
+ e.kill();
+
+ data.open = !data.open;
+
+ for (var ii = 0; ii < data.itemIDs.length; ii++) {
+ var id = data.itemIDs[ii];
+ var item = JX.$(id);
+ if (data.open) {
+ JX.DOM.show(item);
+ } else {
+ JX.DOM.hide(item);
+ }
+
+ // Add a class so we can animate zany effects.
+ JX.DOM.alterClass(item, 'phui-submenu-animate', data.open);
+ }
+
+ JX.DOM.alterClass(node, 'phui-submenu-open', data.open);
+
+ // Toggle the caret from ">" to "V" when opening the menu, and back again
+ // when closing it.
+ var caret = JX.$(data.caretID);
+ JX.DOM.alterClass(caret, 'caret', data.open);
+ JX.DOM.alterClass(caret, 'caret-right', !data.open);
+ });
+
+});
diff --git a/webroot/rsrc/js/phuix/PHUIXDropdownMenu.js b/webroot/rsrc/js/phuix/PHUIXDropdownMenu.js
index 3c93af21d2..d9fd1877b8 100644
--- a/webroot/rsrc/js/phuix/PHUIXDropdownMenu.js
+++ b/webroot/rsrc/js/phuix/PHUIXDropdownMenu.js
@@ -1,206 +1,208 @@
/**
* @provides phuix-dropdown-menu
* @requires javelin-install
* javelin-util
* javelin-dom
* javelin-vector
* javelin-stratcom
* @javelin
*/
/**
* Basic interaction for a dropdown menu.
*
* The menu is unaware of the content inside it, so it can not close itself
* when an item is selected. Callers must make a call to @{method:close} after
* an item is chosen in order to close the menu.
*/
JX.install('PHUIXDropdownMenu', {
construct : function(node) {
this._node = node;
JX.DOM.listen(
this._node,
'click',
null,
JX.bind(this, this._onclick));
JX.Stratcom.listen(
'mousedown',
null,
JX.bind(this, this._onanyclick));
JX.Stratcom.listen(
'resize',
null,
JX.bind(this, this._adjustposition));
JX.Stratcom.listen('phuix.dropdown.open', null, JX.bind(this, this.close));
JX.Stratcom.listen('keydown', null, JX.bind(this, this._onkey));
},
- events: ['open'],
+ events: ['open', 'close'],
properties: {
width: null,
align: 'right',
offsetX: 0,
offsetY: 0
},
members: {
_node: null,
_menu: null,
_open: false,
_content: null,
setContent: function(content) {
JX.DOM.setContent(this._getMenuNode(), content);
return this;
},
open: function() {
if (this._open) {
return;
}
this.invoke('open');
JX.Stratcom.invoke('phuix.dropdown.open');
this._open = true;
this._show();
return this;
},
close: function() {
if (!this._open) {
return;
}
this._open = false;
this._hide();
+ this.invoke('close');
+
return this;
},
_getMenuNode: function() {
if (!this._menu) {
var attrs = {
className: 'phuix-dropdown-menu',
role: 'button'
};
var menu = JX.$N('div', attrs);
this._menu = menu;
}
return this._menu;
},
_onclick : function(e) {
if (this._open) {
this.close();
} else {
this.open();
}
e.prevent();
},
_onanyclick : function(e) {
if (!this._open) {
return;
}
if (JX.Stratcom.pass(e)) {
return;
}
var t = e.getTarget();
while (t) {
if (t == this._menu || t == this._node) {
return;
}
t = t.parentNode;
}
this.close();
},
_show : function() {
document.body.appendChild(this._menu);
if (this.getWidth()) {
new JX.Vector(this.getWidth(), null).setDim(this._menu);
}
this._adjustposition();
JX.DOM.alterClass(this._node, 'phuix-dropdown-open', true);
this._node.setAttribute('aria-expanded', 'true');
// Try to highlight the first link in the menu for assistive technologies.
var links = JX.DOM.scry(this._menu, 'a');
if (links[0]) {
JX.DOM.focus(links[0]);
}
},
_hide : function() {
JX.DOM.remove(this._menu);
JX.DOM.alterClass(this._node, 'phuix-dropdown-open', false);
this._node.setAttribute('aria-expanded', 'false');
},
_adjustposition : function() {
if (!this._open) {
return;
}
var m = JX.Vector.getDim(this._menu);
var v = JX.$V(this._node);
var d = JX.Vector.getDim(this._node);
switch (this.getAlign()) {
case 'right':
v = v.add(d)
.add(JX.$V(-m.x, 0));
break;
default:
v = v.add(0, d.y);
break;
}
v = v.add(this.getOffsetX(), this.getOffsetY());
v.setPos(this._menu);
},
_onkey: function(e) {
// When the user presses escape with a menu open, close the menu and
// refocus the button which activates the menu. In particular, this makes
// popups more usable with assistive technologies.
if (!this._open) {
return;
}
if (e.getSpecialKey() != 'esc') {
return;
}
this.close();
JX.DOM.focus(this._node);
e.prevent();
}
}
});

File Metadata

Mime Type
text/x-diff
Expires
Fri, Aug 15, 2:24 PM (6 d, 18 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
197436
Default Alt Text
(183 KB)

Event Timeline