diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 20d648f549..ce47a59e07 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -1,2406 +1,2406 @@ array( 'conpherence.pkg.css' => '3c8a0668', 'conpherence.pkg.js' => '020aebcf', - 'core.pkg.css' => '7e6e954b', + 'core.pkg.css' => 'a1c2d49b', 'core.pkg.js' => 'a747b035', 'differential.pkg.css' => '8d8360fb', 'differential.pkg.js' => '67e02996', 'diffusion.pkg.css' => '42c75c37', 'diffusion.pkg.js' => 'a98c0bf7', 'maniphest.pkg.css' => '35995d6d', 'maniphest.pkg.js' => 'c9308721', 'rsrc/audio/basic/alert.mp3' => '17889334', 'rsrc/audio/basic/bing.mp3' => 'a817a0c3', 'rsrc/audio/basic/pock.mp3' => '0fa843d0', 'rsrc/audio/basic/tap.mp3' => '02d16994', 'rsrc/audio/basic/ting.mp3' => 'a6b6540e', 'rsrc/css/aphront/aphront-bars.css' => '4a327b4a', 'rsrc/css/aphront/dark-console.css' => '7f06cda2', 'rsrc/css/aphront/dialog-view.css' => 'b70c70df', 'rsrc/css/aphront/list-filter-view.css' => 'feb64255', 'rsrc/css/aphront/multi-column.css' => 'fbc00ba3', 'rsrc/css/aphront/notification.css' => '30240bd2', 'rsrc/css/aphront/panel-view.css' => '46923d46', 'rsrc/css/aphront/phabricator-nav-view.css' => 'f8a0c1bf', 'rsrc/css/aphront/table-view.css' => '7dc3a9c2', 'rsrc/css/aphront/tokenizer.css' => 'b52d0668', 'rsrc/css/aphront/tooltip.css' => 'e3f2412f', 'rsrc/css/aphront/typeahead-browse.css' => 'b7ed02d2', 'rsrc/css/aphront/typeahead.css' => '8779483d', 'rsrc/css/application/almanac/almanac.css' => '2e050f4f', 'rsrc/css/application/auth/auth.css' => 'add92fd8', 'rsrc/css/application/base/main-menu-view.css' => '8e2d9a28', 'rsrc/css/application/base/notification-menu.css' => '4df1ee30', 'rsrc/css/application/base/phui-theme.css' => '35883b37', 'rsrc/css/application/base/standard-page-view.css' => '8a295cb9', 'rsrc/css/application/chatlog/chatlog.css' => 'abdc76ee', 'rsrc/css/application/conduit/conduit-api.css' => 'ce2cfc41', 'rsrc/css/application/config/config-options.css' => '16c920ae', 'rsrc/css/application/config/config-template.css' => '20babf50', 'rsrc/css/application/config/setup-issue.css' => '5eed85b2', 'rsrc/css/application/config/unhandled-exception.css' => '9ecfc00d', 'rsrc/css/application/conpherence/color.css' => 'b17746b0', 'rsrc/css/application/conpherence/durable-column.css' => '2d57072b', 'rsrc/css/application/conpherence/header-pane.css' => 'c9a3db8e', 'rsrc/css/application/conpherence/menu.css' => '67f4680d', 'rsrc/css/application/conpherence/message-pane.css' => 'd244db1e', 'rsrc/css/application/conpherence/notification.css' => '6a3d4e58', 'rsrc/css/application/conpherence/participant-pane.css' => '69e0058a', 'rsrc/css/application/conpherence/transaction.css' => '3a3f5e7e', 'rsrc/css/application/contentsource/content-source-view.css' => 'cdf0d579', 'rsrc/css/application/countdown/timer.css' => 'bff8012f', 'rsrc/css/application/daemon/bulk-job.css' => '73af99f5', 'rsrc/css/application/dashboard/dashboard.css' => '4267d6c6', 'rsrc/css/application/diff/inline-comment-summary.css' => '81eb368d', 'rsrc/css/application/differential/add-comment.css' => '7e5900d9', 'rsrc/css/application/differential/changeset-view.css' => 'bde53589', 'rsrc/css/application/differential/core.css' => '7300a73e', 'rsrc/css/application/differential/phui-inline-comment.css' => '48acce5b', 'rsrc/css/application/differential/revision-comment.css' => '7dbc8d1d', 'rsrc/css/application/differential/revision-history.css' => '8aa3eac5', 'rsrc/css/application/differential/revision-list.css' => '93d2df7d', 'rsrc/css/application/differential/table-of-contents.css' => '0e3364c7', 'rsrc/css/application/diffusion/diffusion-icons.css' => '23b31a1b', 'rsrc/css/application/diffusion/diffusion-readme.css' => 'b68a76e4', 'rsrc/css/application/diffusion/diffusion-repository.css' => 'b89e8c6c', 'rsrc/css/application/diffusion/diffusion.css' => 'b54c77b0', 'rsrc/css/application/feed/feed.css' => 'd8b6e3f8', 'rsrc/css/application/files/global-drag-and-drop.css' => '1d2713a4', 'rsrc/css/application/flag/flag.css' => '2b77be8d', 'rsrc/css/application/harbormaster/harbormaster.css' => '8dfe16b2', 'rsrc/css/application/herald/herald-test.css' => 'e004176f', 'rsrc/css/application/herald/herald.css' => '648d39e2', 'rsrc/css/application/maniphest/report.css' => '3d53188b', 'rsrc/css/application/maniphest/task-edit.css' => '272daa84', 'rsrc/css/application/maniphest/task-summary.css' => '61d1667e', 'rsrc/css/application/objectselector/object-selector.css' => 'ee77366f', 'rsrc/css/application/owners/owners-path-editor.css' => 'fa7c13ef', 'rsrc/css/application/paste/paste.css' => 'b37bcd38', 'rsrc/css/application/people/people-picture-menu-item.css' => 'fe8e07cf', 'rsrc/css/application/people/people-profile.css' => '2ea2daa1', 'rsrc/css/application/phame/phame.css' => '799febf9', 'rsrc/css/application/pholio/pholio-edit.css' => '4df55b3b', 'rsrc/css/application/pholio/pholio-inline-comments.css' => '722b48c2', 'rsrc/css/application/pholio/pholio.css' => '88ef5ef1', 'rsrc/css/application/phortune/phortune-credit-card-form.css' => '3b9868a8', 'rsrc/css/application/phortune/phortune-invoice.css' => '4436b241', 'rsrc/css/application/phortune/phortune.css' => '12e8251a', 'rsrc/css/application/phrequent/phrequent.css' => 'bd79cc67', 'rsrc/css/application/phriction/phriction-document-css.css' => '03380da0', 'rsrc/css/application/policy/policy-edit.css' => '8794e2ed', 'rsrc/css/application/policy/policy-transaction-detail.css' => 'c02b8384', 'rsrc/css/application/policy/policy.css' => 'ceb56a08', 'rsrc/css/application/ponder/ponder-view.css' => '05a09d0a', 'rsrc/css/application/project/project-card-view.css' => '4e7371cd', 'rsrc/css/application/project/project-triggers.css' => 'cb866c2d', 'rsrc/css/application/project/project-view.css' => '567858b3', 'rsrc/css/application/releeph/releeph-core.css' => 'f81ff2db', 'rsrc/css/application/releeph/releeph-preview-branch.css' => '22db5c07', 'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '0ac1ea31', 'rsrc/css/application/releeph/releeph-request-typeahead.css' => 'bce37359', 'rsrc/css/application/search/application-search-view.css' => '0f7c06d8', 'rsrc/css/application/search/search-results.css' => '9ea70ace', 'rsrc/css/application/slowvote/slowvote.css' => '1694baed', 'rsrc/css/application/tokens/tokens.css' => 'ce5a50bd', 'rsrc/css/application/uiexample/example.css' => 'b4795059', 'rsrc/css/core/core.css' => '1b29ed61', 'rsrc/css/core/remarkup.css' => '9e627d41', 'rsrc/css/core/syntax.css' => '4234f572', 'rsrc/css/core/z-index.css' => '99c0f5eb', 'rsrc/css/diviner/diviner-shared.css' => '4bd263b0', 'rsrc/css/font/font-awesome.css' => '3883938a', 'rsrc/css/font/font-lato.css' => '23631304', 'rsrc/css/font/phui-font-icon-base.css' => 'd7994e06', 'rsrc/css/layout/phabricator-filetree-view.css' => '56cdd875', 'rsrc/css/layout/phabricator-source-code-view.css' => '03d7ac28', 'rsrc/css/phui/button/phui-button-bar.css' => 'a4aa75c4', 'rsrc/css/phui/button/phui-button-simple.css' => '1ff278aa', 'rsrc/css/phui/button/phui-button.css' => 'ea704902', 'rsrc/css/phui/calendar/phui-calendar-day.css' => '9597d706', 'rsrc/css/phui/calendar/phui-calendar-list.css' => 'ccd7e4e2', 'rsrc/css/phui/calendar/phui-calendar-month.css' => 'cb758c42', 'rsrc/css/phui/calendar/phui-calendar.css' => 'f11073aa', 'rsrc/css/phui/object-item/phui-oi-big-ui.css' => '534f1757', 'rsrc/css/phui/object-item/phui-oi-color.css' => 'b517bfa0', 'rsrc/css/phui/object-item/phui-oi-drag-ui.css' => 'da15d3dc', 'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '490e2e2e', - 'rsrc/css/phui/object-item/phui-oi-list-view.css' => 'a65865a7', + 'rsrc/css/phui/object-item/phui-oi-list-view.css' => 'f14f2422', 'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => '6a30fa46', 'rsrc/css/phui/phui-action-list.css' => 'c4972757', 'rsrc/css/phui/phui-action-panel.css' => '6c386cbf', 'rsrc/css/phui/phui-badge.css' => '666e25ad', 'rsrc/css/phui/phui-basic-nav-view.css' => '56ebd66d', 'rsrc/css/phui/phui-big-info-view.css' => '362ad37b', 'rsrc/css/phui/phui-box.css' => '5ed3b8cb', 'rsrc/css/phui/phui-bulk-editor.css' => '374d5e30', 'rsrc/css/phui/phui-chart.css' => '7853a69b', 'rsrc/css/phui/phui-cms.css' => '8c05c41e', 'rsrc/css/phui/phui-comment-form.css' => '68a2d99a', 'rsrc/css/phui/phui-comment-panel.css' => 'ec4e31c0', 'rsrc/css/phui/phui-crumbs-view.css' => '614f43cf', 'rsrc/css/phui/phui-curtain-view.css' => '68c5efb6', 'rsrc/css/phui/phui-document-pro.css' => 'b9613a10', 'rsrc/css/phui/phui-document-summary.css' => 'b068eed1', 'rsrc/css/phui/phui-document.css' => '52b748a5', 'rsrc/css/phui/phui-feed-story.css' => 'a0c05029', 'rsrc/css/phui/phui-fontkit.css' => '9b714a5e', 'rsrc/css/phui/phui-form-view.css' => '01b796c0', 'rsrc/css/phui/phui-form.css' => '159e2d9c', 'rsrc/css/phui/phui-head-thing.css' => 'd7f293df', 'rsrc/css/phui/phui-header-view.css' => '285c9139', 'rsrc/css/phui/phui-hovercard.css' => '6ca90fa0', 'rsrc/css/phui/phui-icon-set-selector.css' => '7aa5f3ec', 'rsrc/css/phui/phui-icon.css' => '4cbc684a', 'rsrc/css/phui/phui-image-mask.css' => '62c7f4d2', 'rsrc/css/phui/phui-info-view.css' => '37b8d9ce', 'rsrc/css/phui/phui-invisible-character-view.css' => 'c694c4a4', 'rsrc/css/phui/phui-left-right.css' => '68513c34', 'rsrc/css/phui/phui-lightbox.css' => '4ebf22da', 'rsrc/css/phui/phui-list.css' => '470b1adb', 'rsrc/css/phui/phui-object-box.css' => 'f434b6be', 'rsrc/css/phui/phui-pager.css' => 'd022c7ad', 'rsrc/css/phui/phui-pinboard-view.css' => '1f08f5d8', 'rsrc/css/phui/phui-property-list-view.css' => 'cad62236', 'rsrc/css/phui/phui-remarkup-preview.css' => '91767007', 'rsrc/css/phui/phui-segment-bar-view.css' => '5166b370', 'rsrc/css/phui/phui-spacing.css' => 'b05cadc3', 'rsrc/css/phui/phui-status.css' => 'e5ff8be0', 'rsrc/css/phui/phui-tag-view.css' => '29409667', 'rsrc/css/phui/phui-timeline-view.css' => '1e348e4b', 'rsrc/css/phui/phui-two-column-view.css' => '01e6991e', 'rsrc/css/phui/workboards/phui-workboard-color.css' => 'e86de308', 'rsrc/css/phui/workboards/phui-workboard.css' => '74fc9d98', 'rsrc/css/phui/workboards/phui-workcard.css' => '9e9eb0df', 'rsrc/css/phui/workboards/phui-workpanel.css' => '3ae89b20', 'rsrc/css/sprite-login.css' => '18b368a6', 'rsrc/css/sprite-tokens.css' => 'f1896dc5', 'rsrc/css/syntax/syntax-default.css' => '055fc231', 'rsrc/externals/d3/d3.min.js' => 'd67475f5', 'rsrc/externals/font/fontawesome/fontawesome-webfont.eot' => '23f8c698', 'rsrc/externals/font/fontawesome/fontawesome-webfont.ttf' => '70983df0', 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff' => 'cd02f93b', 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff2' => '351fd46a', 'rsrc/externals/font/lato/lato-bold.eot' => '7367aa5e', 'rsrc/externals/font/lato/lato-bold.svg' => '681aa4f5', 'rsrc/externals/font/lato/lato-bold.ttf' => '66d3c296', 'rsrc/externals/font/lato/lato-bold.woff' => '89d9fba7', 'rsrc/externals/font/lato/lato-bold.woff2' => '389fcdb1', 'rsrc/externals/font/lato/lato-bolditalic.eot' => '03eeb4da', 'rsrc/externals/font/lato/lato-bolditalic.svg' => 'f56fa11c', 'rsrc/externals/font/lato/lato-bolditalic.ttf' => '9c3aec21', 'rsrc/externals/font/lato/lato-bolditalic.woff' => 'bfbd0616', 'rsrc/externals/font/lato/lato-bolditalic.woff2' => 'bc7d1274', 'rsrc/externals/font/lato/lato-italic.eot' => '7db5b247', 'rsrc/externals/font/lato/lato-italic.svg' => 'b1ae496f', 'rsrc/externals/font/lato/lato-italic.ttf' => '43eed813', 'rsrc/externals/font/lato/lato-italic.woff' => 'c28975e1', 'rsrc/externals/font/lato/lato-italic.woff2' => 'fffc0d8c', 'rsrc/externals/font/lato/lato-regular.eot' => '06e0c291', 'rsrc/externals/font/lato/lato-regular.svg' => '3ad95f53', 'rsrc/externals/font/lato/lato-regular.ttf' => 'e2e9c398', 'rsrc/externals/font/lato/lato-regular.woff' => '0b13d332', 'rsrc/externals/font/lato/lato-regular.woff2' => '8f846797', 'rsrc/externals/javelin/core/Event.js' => 'c03f2fb4', 'rsrc/externals/javelin/core/Stratcom.js' => '0889b835', 'rsrc/externals/javelin/core/__tests__/event-stop-and-kill.js' => '048472d2', 'rsrc/externals/javelin/core/__tests__/install.js' => '14a7e671', 'rsrc/externals/javelin/core/__tests__/stratcom.js' => 'a28464bb', 'rsrc/externals/javelin/core/__tests__/util.js' => 'e29a4354', 'rsrc/externals/javelin/core/init.js' => '98e6504a', 'rsrc/externals/javelin/core/init_node.js' => '16961339', 'rsrc/externals/javelin/core/install.js' => '5902260c', 'rsrc/externals/javelin/core/util.js' => '22ae1776', 'rsrc/externals/javelin/docs/Base.js' => '5a401d7d', 'rsrc/externals/javelin/docs/onload.js' => 'ee58fb62', 'rsrc/externals/javelin/ext/fx/Color.js' => '78f811c9', 'rsrc/externals/javelin/ext/fx/FX.js' => '34450586', 'rsrc/externals/javelin/ext/reactor/core/DynVal.js' => '202a2e85', 'rsrc/externals/javelin/ext/reactor/core/Reactor.js' => '1c850a26', 'rsrc/externals/javelin/ext/reactor/core/ReactorNode.js' => '72960bc1', 'rsrc/externals/javelin/ext/reactor/core/ReactorNodeCalmer.js' => '225bbb98', 'rsrc/externals/javelin/ext/reactor/dom/RDOM.js' => '6cfa0008', 'rsrc/externals/javelin/ext/view/HTMLView.js' => 'f8c4e135', 'rsrc/externals/javelin/ext/view/View.js' => '289bf236', 'rsrc/externals/javelin/ext/view/ViewInterpreter.js' => '876506b6', 'rsrc/externals/javelin/ext/view/ViewPlaceholder.js' => 'a9942052', 'rsrc/externals/javelin/ext/view/ViewRenderer.js' => '9aae2b66', 'rsrc/externals/javelin/ext/view/ViewVisitor.js' => '308f9fe4', 'rsrc/externals/javelin/ext/view/__tests__/HTMLView.js' => '6e50a13f', 'rsrc/externals/javelin/ext/view/__tests__/View.js' => 'd284be5d', 'rsrc/externals/javelin/ext/view/__tests__/ViewInterpreter.js' => 'a9f35511', 'rsrc/externals/javelin/ext/view/__tests__/ViewRenderer.js' => '3a1b81f6', 'rsrc/externals/javelin/lib/Cookie.js' => '05d290ef', 'rsrc/externals/javelin/lib/DOM.js' => '94681e22', 'rsrc/externals/javelin/lib/History.js' => '030b4f7a', 'rsrc/externals/javelin/lib/JSON.js' => '541f81c3', 'rsrc/externals/javelin/lib/Leader.js' => '0d2490ce', 'rsrc/externals/javelin/lib/Mask.js' => '7c4d8998', 'rsrc/externals/javelin/lib/Quicksand.js' => 'd3799cb4', 'rsrc/externals/javelin/lib/Request.js' => '91863989', 'rsrc/externals/javelin/lib/Resource.js' => '740956e1', 'rsrc/externals/javelin/lib/Routable.js' => '6a18c42e', 'rsrc/externals/javelin/lib/Router.js' => '32755edb', 'rsrc/externals/javelin/lib/Scrollbar.js' => 'a43ae2ae', 'rsrc/externals/javelin/lib/Sound.js' => 'd4cc2d2a', 'rsrc/externals/javelin/lib/URI.js' => '2e255291', 'rsrc/externals/javelin/lib/Vector.js' => 'e9c80beb', 'rsrc/externals/javelin/lib/WebSocket.js' => 'fdc13e4e', 'rsrc/externals/javelin/lib/Workflow.js' => '958e9045', 'rsrc/externals/javelin/lib/__tests__/Cookie.js' => 'ca686f71', 'rsrc/externals/javelin/lib/__tests__/DOM.js' => '4566e249', 'rsrc/externals/javelin/lib/__tests__/JSON.js' => '710377ae', 'rsrc/externals/javelin/lib/__tests__/URI.js' => '6fff0c2b', 'rsrc/externals/javelin/lib/__tests__/behavior.js' => '8426ebeb', 'rsrc/externals/javelin/lib/behavior.js' => 'fce5d170', 'rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js' => '89a1ae3a', 'rsrc/externals/javelin/lib/control/typeahead/Typeahead.js' => 'a4356cde', 'rsrc/externals/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js' => 'a241536a', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js' => '22ee68a5', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js' => '23387297', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js' => '5a79f6c3', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => '8badee71', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js' => '80bff3af', 'rsrc/favicons/favicon-16x16.png' => '4c51a03a', 'rsrc/favicons/mask-icon.svg' => 'db699fe1', 'rsrc/image/BFCFDA.png' => '74b5c88b', 'rsrc/image/actions/edit.png' => 'fd987dff', 'rsrc/image/avatar.png' => '0d17c6c4', 'rsrc/image/checker_dark.png' => '7fc8fa7b', 'rsrc/image/checker_light.png' => '3157a202', 'rsrc/image/checker_lighter.png' => 'c45928c1', 'rsrc/image/chevron-in.png' => '1aa2f88f', 'rsrc/image/chevron-out.png' => 'c815e272', 'rsrc/image/controls/checkbox-checked.png' => '1770d7a0', 'rsrc/image/controls/checkbox-unchecked.png' => 'e1deba0a', 'rsrc/image/d5d8e1.png' => '6764616e', 'rsrc/image/darkload.gif' => '5bd41a89', 'rsrc/image/divot.png' => '0fbe2453', 'rsrc/image/examples/hero.png' => '5d8c4b21', 'rsrc/image/grippy_texture.png' => 'a7d222b5', 'rsrc/image/icon/fatcow/arrow_branch.png' => '98149d9f', 'rsrc/image/icon/fatcow/arrow_merge.png' => 'e142f4f8', 'rsrc/image/icon/fatcow/calendar_edit.png' => '5ff44a08', 'rsrc/image/icon/fatcow/document_black.png' => 'd3515fa5', 'rsrc/image/icon/fatcow/flag_blue.png' => '54db2e5c', 'rsrc/image/icon/fatcow/flag_finish.png' => '2953a51b', 'rsrc/image/icon/fatcow/flag_ghost.png' => '7d9ada92', 'rsrc/image/icon/fatcow/flag_green.png' => '010f7161', 'rsrc/image/icon/fatcow/flag_orange.png' => '6c384ca5', 'rsrc/image/icon/fatcow/flag_pink.png' => '11ac6b12', 'rsrc/image/icon/fatcow/flag_purple.png' => 'c4f423a4', 'rsrc/image/icon/fatcow/flag_red.png' => '9e6d8817', 'rsrc/image/icon/fatcow/flag_yellow.png' => '906733f4', 'rsrc/image/icon/fatcow/key_question.png' => 'c10c26db', 'rsrc/image/icon/fatcow/link.png' => '8edbf327', 'rsrc/image/icon/fatcow/page_white_edit.png' => '17ef5625', 'rsrc/image/icon/fatcow/page_white_put.png' => '82430c91', 'rsrc/image/icon/fatcow/source/conduit.png' => '5b55130c', 'rsrc/image/icon/fatcow/source/email.png' => '8a32b77f', 'rsrc/image/icon/fatcow/source/fax.png' => '8bc2a49b', 'rsrc/image/icon/fatcow/source/mobile.png' => '0a918412', 'rsrc/image/icon/fatcow/source/tablet.png' => 'fc50b050', 'rsrc/image/icon/fatcow/source/web.png' => '70433af3', 'rsrc/image/icon/subscribe.png' => '07ef454e', 'rsrc/image/icon/tango/attachment.png' => 'bac9032d', 'rsrc/image/icon/tango/edit.png' => 'e6296206', 'rsrc/image/icon/tango/go-down.png' => '0b903712', 'rsrc/image/icon/tango/log.png' => '86b6a6f4', 'rsrc/image/icon/tango/upload.png' => '3fe6b92d', 'rsrc/image/icon/unsubscribe.png' => 'db04378a', 'rsrc/image/lightblue-header.png' => 'e6d483c6', 'rsrc/image/logo/light-eye.png' => '72337472', 'rsrc/image/main_texture.png' => '894d03c4', 'rsrc/image/menu_texture.png' => '896c9ade', 'rsrc/image/people/harding.png' => '95b2db63', 'rsrc/image/people/jefferson.png' => 'e883a3a2', 'rsrc/image/people/lincoln.png' => 'be2c07c5', 'rsrc/image/people/mckinley.png' => '6af510a0', 'rsrc/image/people/taft.png' => 'b15ab07e', 'rsrc/image/people/user0.png' => '4bc64b40', 'rsrc/image/people/user1.png' => '8063f445', 'rsrc/image/people/user2.png' => 'd28246c0', 'rsrc/image/people/user3.png' => 'fb1ac12d', 'rsrc/image/people/user4.png' => 'fe4fac8f', 'rsrc/image/people/user5.png' => '3d07065c', 'rsrc/image/people/user6.png' => 'e4bd47c8', 'rsrc/image/people/user7.png' => '71d8fe8b', 'rsrc/image/people/user8.png' => '85f86bf7', 'rsrc/image/people/user9.png' => '523db8aa', 'rsrc/image/people/washington.png' => '86159e68', 'rsrc/image/phrequent_active.png' => 'de66dc50', 'rsrc/image/phrequent_inactive.png' => '79c61baf', 'rsrc/image/resize.png' => '9cc83373', 'rsrc/image/sprite-login-X2.png' => '604545f6', 'rsrc/image/sprite-login.png' => '7a001a9a', 'rsrc/image/sprite-tokens-X2.png' => '21621dd9', 'rsrc/image/sprite-tokens.png' => 'bede2580', 'rsrc/image/texture/card-gradient.png' => 'e6892cb4', 'rsrc/image/texture/dark-menu-hover.png' => '390a4fa1', 'rsrc/image/texture/dark-menu.png' => '542f699c', 'rsrc/image/texture/grip.png' => 'bc80753a', 'rsrc/image/texture/panel-header-gradient.png' => '65004dbf', 'rsrc/image/texture/phlnx-bg.png' => '6c9cd31d', 'rsrc/image/texture/pholio-background.gif' => '84910bfc', 'rsrc/image/texture/table_header.png' => '7652d1ad', 'rsrc/image/texture/table_header_hover.png' => '12ea5236', 'rsrc/image/texture/table_header_tall.png' => '5cc420c4', 'rsrc/js/application/aphlict/Aphlict.js' => '022516b4', 'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => 'e9a2940f', 'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => '4e61fa88', 'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'c3703a16', 'rsrc/js/application/aphlict/behavior-desktop-notifications-control.js' => '070679fe', 'rsrc/js/application/calendar/behavior-day-view.js' => '727a5a61', 'rsrc/js/application/calendar/behavior-event-all-day.js' => '0b1bc990', 'rsrc/js/application/calendar/behavior-month-view.js' => '158c64e0', 'rsrc/js/application/config/behavior-reorder-fields.js' => '2539f834', 'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => 'aec8e38c', 'rsrc/js/application/conpherence/behavior-conpherence-search.js' => '91befbcc', 'rsrc/js/application/conpherence/behavior-durable-column.js' => 'fa6f30b2', 'rsrc/js/application/conpherence/behavior-menu.js' => '8c2ed2bf', 'rsrc/js/application/conpherence/behavior-participant-pane.js' => '43ba89a2', 'rsrc/js/application/conpherence/behavior-pontificate.js' => '4ae58b5a', 'rsrc/js/application/conpherence/behavior-quicksand-blacklist.js' => '5a6f6a06', 'rsrc/js/application/conpherence/behavior-toggle-widget.js' => '8f959ad0', 'rsrc/js/application/countdown/timer.js' => '6a162524', 'rsrc/js/application/daemon/behavior-bulk-job-reload.js' => '3829a3cf', 'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => '09ecf50c', 'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => '076bd092', 'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '1e413dc9', 'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '9b1cbd76', 'rsrc/js/application/diff/DiffChangeset.js' => 'd0a85a85', 'rsrc/js/application/diff/DiffChangesetList.js' => '04023d82', 'rsrc/js/application/diff/DiffInline.js' => 'a4a14a94', 'rsrc/js/application/diff/behavior-preview-link.js' => 'f51e9c17', 'rsrc/js/application/differential/behavior-diff-radios.js' => '925fe8cd', 'rsrc/js/application/differential/behavior-populate.js' => 'dfa1d313', 'rsrc/js/application/diffusion/DiffusionLocateFileSource.js' => '94243d89', 'rsrc/js/application/diffusion/behavior-audit-preview.js' => 'b7b73831', 'rsrc/js/application/diffusion/behavior-commit-branches.js' => '4b671572', 'rsrc/js/application/diffusion/behavior-commit-graph.js' => 'ef836bf2', 'rsrc/js/application/diffusion/behavior-locate-file.js' => '87428eb2', 'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'c715c123', 'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => '6a85bc5a', 'rsrc/js/application/drydock/drydock-live-operation-status.js' => '47a0728b', 'rsrc/js/application/files/behavior-document-engine.js' => '243d6c22', 'rsrc/js/application/files/behavior-icon-composer.js' => '38a6cedb', 'rsrc/js/application/files/behavior-launch-icon-composer.js' => 'a17b84f1', 'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => 'b347a301', 'rsrc/js/application/herald/HeraldRuleEditor.js' => '27daef73', 'rsrc/js/application/herald/PathTypeahead.js' => 'ad486db3', 'rsrc/js/application/herald/herald-rule-editor.js' => '0922e81d', 'rsrc/js/application/maniphest/behavior-batch-selector.js' => '139ef688', 'rsrc/js/application/maniphest/behavior-line-chart.js' => 'c8147a20', 'rsrc/js/application/maniphest/behavior-list-edit.js' => 'c687e867', 'rsrc/js/application/owners/OwnersPathEditor.js' => '2a8b62d9', 'rsrc/js/application/owners/owners-path-editor.js' => 'ff688a7a', 'rsrc/js/application/passphrase/passphrase-credential-control.js' => '48fe33d0', 'rsrc/js/application/pholio/behavior-pholio-mock-edit.js' => '3eed1f2b', 'rsrc/js/application/pholio/behavior-pholio-mock-view.js' => '5aa1544e', 'rsrc/js/application/phortune/behavior-stripe-payment-form.js' => '02cb4398', 'rsrc/js/application/phortune/behavior-test-payment-form.js' => '4a7fb02b', 'rsrc/js/application/phortune/phortune-credit-card-form.js' => 'd12d214f', 'rsrc/js/application/policy/behavior-policy-control.js' => '0eaa33a9', 'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '9347f172', 'rsrc/js/application/projects/WorkboardBoard.js' => 'c02a5497', 'rsrc/js/application/projects/WorkboardCard.js' => '0392a5d8', 'rsrc/js/application/projects/WorkboardCardTemplate.js' => '2a61f8d4', 'rsrc/js/application/projects/WorkboardColumn.js' => 'c3d24e63', 'rsrc/js/application/projects/WorkboardController.js' => '42c7a5a7', 'rsrc/js/application/projects/WorkboardDropEffect.js' => '8e0aa661', 'rsrc/js/application/projects/WorkboardHeader.js' => '111bfd2d', 'rsrc/js/application/projects/WorkboardHeaderTemplate.js' => 'ebe83a6b', 'rsrc/js/application/projects/WorkboardOrderTemplate.js' => '03e8891f', 'rsrc/js/application/projects/behavior-project-boards.js' => 'aad45445', 'rsrc/js/application/projects/behavior-project-create.js' => '34c53422', 'rsrc/js/application/projects/behavior-reorder-columns.js' => '8ac32fd9', 'rsrc/js/application/releeph/releeph-preview-branch.js' => '75184d68', 'rsrc/js/application/releeph/releeph-request-state-change.js' => '9f081f05', 'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'aa3a100c', 'rsrc/js/application/repository/repository-crossreference.js' => 'c15122b4', 'rsrc/js/application/search/behavior-reorder-profile-menu-items.js' => 'e5bdb730', 'rsrc/js/application/search/behavior-reorder-queries.js' => 'b86f297f', 'rsrc/js/application/transactions/behavior-comment-actions.js' => '4dffaeb2', 'rsrc/js/application/transactions/behavior-reorder-configs.js' => '4842f137', 'rsrc/js/application/transactions/behavior-reorder-fields.js' => '0ad8d31f', 'rsrc/js/application/transactions/behavior-show-older-transactions.js' => '600f440c', 'rsrc/js/application/transactions/behavior-transaction-comment-form.js' => '2bdadf1a', 'rsrc/js/application/transactions/behavior-transaction-list.js' => '9cec214e', 'rsrc/js/application/trigger/TriggerRule.js' => '1c60c3fc', 'rsrc/js/application/trigger/TriggerRuleControl.js' => '5faf27b9', 'rsrc/js/application/trigger/TriggerRuleEditor.js' => 'b49fd60c', 'rsrc/js/application/trigger/TriggerRuleType.js' => '4feea7d3', 'rsrc/js/application/trigger/trigger-rule-editor.js' => '398fdf13', 'rsrc/js/application/typeahead/behavior-typeahead-browse.js' => '70245195', 'rsrc/js/application/typeahead/behavior-typeahead-search.js' => '7b139193', 'rsrc/js/application/uiexample/gesture-example.js' => '242dedd0', 'rsrc/js/application/uiexample/notification-example.js' => '29819b75', 'rsrc/js/core/Busy.js' => '5202e831', 'rsrc/js/core/DragAndDropFileUpload.js' => '4370900d', 'rsrc/js/core/DraggableList.js' => 'c9ad6f70', 'rsrc/js/core/Favicon.js' => '7930776a', 'rsrc/js/core/FileUpload.js' => 'ab85e184', 'rsrc/js/core/Hovercard.js' => '074f0783', 'rsrc/js/core/KeyboardShortcut.js' => 'c9749dcd', 'rsrc/js/core/KeyboardShortcutManager.js' => '37b8a04a', 'rsrc/js/core/MultirowRowManager.js' => '5b54c823', 'rsrc/js/core/Notification.js' => 'a9b91e3f', 'rsrc/js/core/Prefab.js' => '5793d835', 'rsrc/js/core/ShapedRequest.js' => 'abf88db8', 'rsrc/js/core/TextAreaUtils.js' => 'f340a484', 'rsrc/js/core/Title.js' => '43bc9360', 'rsrc/js/core/ToolTip.js' => '83754533', 'rsrc/js/core/behavior-active-nav.js' => '7353f43d', 'rsrc/js/core/behavior-audio-source.js' => '3dc5ad43', 'rsrc/js/core/behavior-autofocus.js' => '65bb0011', 'rsrc/js/core/behavior-badge-view.js' => '92cdd7b6', 'rsrc/js/core/behavior-bulk-editor.js' => 'aa6d2308', 'rsrc/js/core/behavior-choose-control.js' => '04f8a1e3', 'rsrc/js/core/behavior-copy.js' => 'cf32921f', 'rsrc/js/core/behavior-detect-timezone.js' => '78bc5d94', 'rsrc/js/core/behavior-device.js' => '0cf79f45', 'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '7ad020a5', 'rsrc/js/core/behavior-fancy-datepicker.js' => '956f3eeb', 'rsrc/js/core/behavior-file-tree.js' => 'ee82cedb', 'rsrc/js/core/behavior-form.js' => '55d7b788', 'rsrc/js/core/behavior-gesture.js' => 'b58d1a2a', 'rsrc/js/core/behavior-global-drag-and-drop.js' => '1cab0e9a', 'rsrc/js/core/behavior-high-security-warning.js' => 'dae2d55b', 'rsrc/js/core/behavior-history-install.js' => '6a1583a8', 'rsrc/js/core/behavior-hovercard.js' => '6c379000', 'rsrc/js/core/behavior-keyboard-pager.js' => '1325b731', 'rsrc/js/core/behavior-keyboard-shortcuts.js' => '2cc87f49', 'rsrc/js/core/behavior-lightbox-attachments.js' => 'c7e748bf', 'rsrc/js/core/behavior-line-linker.js' => 'e15c8b1f', 'rsrc/js/core/behavior-linked-container.js' => '74446546', 'rsrc/js/core/behavior-more.js' => '506aa3f4', 'rsrc/js/core/behavior-object-selector.js' => 'a4af0b4a', 'rsrc/js/core/behavior-oncopy.js' => 'ff7b3f22', 'rsrc/js/core/behavior-phabricator-nav.js' => 'f166c949', 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '2f80333f', 'rsrc/js/core/behavior-read-only-warning.js' => 'b9109f8f', 'rsrc/js/core/behavior-redirect.js' => '407ee861', 'rsrc/js/core/behavior-refresh-csrf.js' => '46116c01', 'rsrc/js/core/behavior-remarkup-load-image.js' => '202bfa3f', 'rsrc/js/core/behavior-remarkup-preview.js' => 'd8a86cfb', 'rsrc/js/core/behavior-reorder-applications.js' => 'aa371860', 'rsrc/js/core/behavior-reveal-content.js' => 'b105a3a6', 'rsrc/js/core/behavior-scrollbar.js' => '92388bae', 'rsrc/js/core/behavior-search-typeahead.js' => '1cb7d027', 'rsrc/js/core/behavior-select-content.js' => 'e8240b50', 'rsrc/js/core/behavior-select-on-click.js' => '66365ee2', 'rsrc/js/core/behavior-setup-check-https.js' => '01384686', 'rsrc/js/core/behavior-time-typeahead.js' => '5803b9e7', 'rsrc/js/core/behavior-toggle-class.js' => '32db8374', 'rsrc/js/core/behavior-tokenizer.js' => '3b4899b0', 'rsrc/js/core/behavior-tooltip.js' => '73ecc1f8', 'rsrc/js/core/behavior-user-menu.js' => '60cd9241', 'rsrc/js/core/behavior-watch-anchor.js' => '0e6d261f', 'rsrc/js/core/behavior-workflow.js' => '9623adc1', 'rsrc/js/core/darkconsole/DarkLog.js' => '3b869402', 'rsrc/js/core/darkconsole/DarkMessage.js' => '26cd4b73', 'rsrc/js/core/darkconsole/behavior-dark-console.js' => 'f39d968b', 'rsrc/js/core/phtize.js' => '2f1db1ed', 'rsrc/js/phui/behavior-phui-dropdown-menu.js' => '5cf0501a', 'rsrc/js/phui/behavior-phui-file-upload.js' => 'e150bd50', 'rsrc/js/phui/behavior-phui-selectable-list.js' => 'b26a41e4', 'rsrc/js/phui/behavior-phui-submenu.js' => 'b5e9bff9', 'rsrc/js/phui/behavior-phui-tab-group.js' => '242aa08b', 'rsrc/js/phui/behavior-phui-timer-control.js' => 'f84bcbf4', 'rsrc/js/phuix/PHUIXActionListView.js' => 'c68f183f', 'rsrc/js/phuix/PHUIXActionView.js' => 'aaa08f3b', 'rsrc/js/phuix/PHUIXAutocomplete.js' => '2fbe234d', 'rsrc/js/phuix/PHUIXButtonView.js' => '55a24e84', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bdce4d78', 'rsrc/js/phuix/PHUIXExample.js' => 'c2c500a7', 'rsrc/js/phuix/PHUIXFormControl.js' => '38c1f3fb', 'rsrc/js/phuix/PHUIXIconView.js' => 'a5257c4e', ), 'symbols' => array( 'almanac-css' => '2e050f4f', 'aphront-bars' => '4a327b4a', 'aphront-dark-console-css' => '7f06cda2', 'aphront-dialog-view-css' => 'b70c70df', 'aphront-list-filter-view-css' => 'feb64255', 'aphront-multi-column-view-css' => 'fbc00ba3', 'aphront-panel-view-css' => '46923d46', 'aphront-table-view-css' => '7dc3a9c2', 'aphront-tokenizer-control-css' => 'b52d0668', 'aphront-tooltip-css' => 'e3f2412f', 'aphront-typeahead-control-css' => '8779483d', 'application-search-view-css' => '0f7c06d8', 'auth-css' => 'add92fd8', 'bulk-job-css' => '73af99f5', 'conduit-api-css' => 'ce2cfc41', 'config-options-css' => '16c920ae', 'conpherence-color-css' => 'b17746b0', 'conpherence-durable-column-view' => '2d57072b', 'conpherence-header-pane-css' => 'c9a3db8e', 'conpherence-menu-css' => '67f4680d', 'conpherence-message-pane-css' => 'd244db1e', 'conpherence-notification-css' => '6a3d4e58', 'conpherence-participant-pane-css' => '69e0058a', 'conpherence-thread-manager' => 'aec8e38c', 'conpherence-transaction-css' => '3a3f5e7e', 'd3' => 'd67475f5', 'differential-changeset-view-css' => 'bde53589', 'differential-core-view-css' => '7300a73e', 'differential-revision-add-comment-css' => '7e5900d9', 'differential-revision-comment-css' => '7dbc8d1d', 'differential-revision-history-css' => '8aa3eac5', 'differential-revision-list-css' => '93d2df7d', 'differential-table-of-contents-css' => '0e3364c7', 'diffusion-css' => 'b54c77b0', 'diffusion-icons-css' => '23b31a1b', 'diffusion-readme-css' => 'b68a76e4', 'diffusion-repository-css' => 'b89e8c6c', 'diviner-shared-css' => '4bd263b0', 'font-fontawesome' => '3883938a', 'font-lato' => '23631304', 'global-drag-and-drop-css' => '1d2713a4', 'harbormaster-css' => '8dfe16b2', 'herald-css' => '648d39e2', 'herald-rule-editor' => '27daef73', 'herald-test-css' => 'e004176f', 'inline-comment-summary-css' => '81eb368d', 'javelin-aphlict' => '022516b4', 'javelin-behavior' => 'fce5d170', 'javelin-behavior-aphlict-dropdown' => 'e9a2940f', 'javelin-behavior-aphlict-listen' => '4e61fa88', 'javelin-behavior-aphlict-status' => 'c3703a16', 'javelin-behavior-aphront-basic-tokenizer' => '3b4899b0', 'javelin-behavior-aphront-drag-and-drop-textarea' => '7ad020a5', 'javelin-behavior-aphront-form-disable-on-submit' => '55d7b788', 'javelin-behavior-aphront-more' => '506aa3f4', 'javelin-behavior-audio-source' => '3dc5ad43', 'javelin-behavior-audit-preview' => 'b7b73831', 'javelin-behavior-badge-view' => '92cdd7b6', 'javelin-behavior-bulk-editor' => 'aa6d2308', 'javelin-behavior-bulk-job-reload' => '3829a3cf', 'javelin-behavior-calendar-month-view' => '158c64e0', 'javelin-behavior-choose-control' => '04f8a1e3', 'javelin-behavior-comment-actions' => '4dffaeb2', 'javelin-behavior-config-reorder-fields' => '2539f834', 'javelin-behavior-conpherence-menu' => '8c2ed2bf', 'javelin-behavior-conpherence-participant-pane' => '43ba89a2', 'javelin-behavior-conpherence-pontificate' => '4ae58b5a', 'javelin-behavior-conpherence-search' => '91befbcc', 'javelin-behavior-countdown-timer' => '6a162524', 'javelin-behavior-dark-console' => 'f39d968b', 'javelin-behavior-dashboard-async-panel' => '09ecf50c', 'javelin-behavior-dashboard-move-panels' => '076bd092', 'javelin-behavior-dashboard-query-panel-select' => '1e413dc9', 'javelin-behavior-dashboard-tab-panel' => '9b1cbd76', 'javelin-behavior-day-view' => '727a5a61', 'javelin-behavior-desktop-notifications-control' => '070679fe', 'javelin-behavior-detect-timezone' => '78bc5d94', 'javelin-behavior-device' => '0cf79f45', 'javelin-behavior-diff-preview-link' => 'f51e9c17', 'javelin-behavior-differential-diff-radios' => '925fe8cd', 'javelin-behavior-differential-populate' => 'dfa1d313', 'javelin-behavior-diffusion-commit-branches' => '4b671572', 'javelin-behavior-diffusion-commit-graph' => 'ef836bf2', 'javelin-behavior-diffusion-locate-file' => '87428eb2', 'javelin-behavior-diffusion-pull-lastmodified' => 'c715c123', 'javelin-behavior-document-engine' => '243d6c22', 'javelin-behavior-doorkeeper-tag' => '6a85bc5a', 'javelin-behavior-drydock-live-operation-status' => '47a0728b', 'javelin-behavior-durable-column' => 'fa6f30b2', 'javelin-behavior-editengine-reorder-configs' => '4842f137', 'javelin-behavior-editengine-reorder-fields' => '0ad8d31f', 'javelin-behavior-event-all-day' => '0b1bc990', 'javelin-behavior-fancy-datepicker' => '956f3eeb', 'javelin-behavior-global-drag-and-drop' => '1cab0e9a', 'javelin-behavior-harbormaster-log' => 'b347a301', 'javelin-behavior-herald-rule-editor' => '0922e81d', 'javelin-behavior-high-security-warning' => 'dae2d55b', 'javelin-behavior-history-install' => '6a1583a8', 'javelin-behavior-icon-composer' => '38a6cedb', 'javelin-behavior-launch-icon-composer' => 'a17b84f1', 'javelin-behavior-lightbox-attachments' => 'c7e748bf', 'javelin-behavior-line-chart' => 'c8147a20', 'javelin-behavior-linked-container' => '74446546', 'javelin-behavior-maniphest-batch-selector' => '139ef688', 'javelin-behavior-maniphest-list-editor' => 'c687e867', 'javelin-behavior-owners-path-editor' => 'ff688a7a', 'javelin-behavior-passphrase-credential-control' => '48fe33d0', 'javelin-behavior-phabricator-active-nav' => '7353f43d', 'javelin-behavior-phabricator-autofocus' => '65bb0011', 'javelin-behavior-phabricator-clipboard-copy' => 'cf32921f', 'javelin-behavior-phabricator-file-tree' => 'ee82cedb', 'javelin-behavior-phabricator-gesture' => 'b58d1a2a', 'javelin-behavior-phabricator-gesture-example' => '242dedd0', 'javelin-behavior-phabricator-keyboard-pager' => '1325b731', 'javelin-behavior-phabricator-keyboard-shortcuts' => '2cc87f49', 'javelin-behavior-phabricator-line-linker' => 'e15c8b1f', 'javelin-behavior-phabricator-nav' => 'f166c949', 'javelin-behavior-phabricator-notification-example' => '29819b75', 'javelin-behavior-phabricator-object-selector' => 'a4af0b4a', 'javelin-behavior-phabricator-oncopy' => 'ff7b3f22', 'javelin-behavior-phabricator-remarkup-assist' => '2f80333f', 'javelin-behavior-phabricator-reveal-content' => 'b105a3a6', 'javelin-behavior-phabricator-search-typeahead' => '1cb7d027', 'javelin-behavior-phabricator-show-older-transactions' => '600f440c', 'javelin-behavior-phabricator-tooltips' => '73ecc1f8', 'javelin-behavior-phabricator-transaction-comment-form' => '2bdadf1a', 'javelin-behavior-phabricator-transaction-list' => '9cec214e', 'javelin-behavior-phabricator-watch-anchor' => '0e6d261f', 'javelin-behavior-pholio-mock-edit' => '3eed1f2b', 'javelin-behavior-pholio-mock-view' => '5aa1544e', 'javelin-behavior-phui-dropdown-menu' => '5cf0501a', 'javelin-behavior-phui-file-upload' => 'e150bd50', 'javelin-behavior-phui-hovercards' => '6c379000', 'javelin-behavior-phui-selectable-list' => 'b26a41e4', 'javelin-behavior-phui-submenu' => 'b5e9bff9', 'javelin-behavior-phui-tab-group' => '242aa08b', 'javelin-behavior-phui-timer-control' => 'f84bcbf4', 'javelin-behavior-phuix-example' => 'c2c500a7', 'javelin-behavior-policy-control' => '0eaa33a9', 'javelin-behavior-policy-rule-editor' => '9347f172', 'javelin-behavior-project-boards' => 'aad45445', 'javelin-behavior-project-create' => '34c53422', 'javelin-behavior-quicksand-blacklist' => '5a6f6a06', 'javelin-behavior-read-only-warning' => 'b9109f8f', 'javelin-behavior-redirect' => '407ee861', 'javelin-behavior-refresh-csrf' => '46116c01', 'javelin-behavior-releeph-preview-branch' => '75184d68', 'javelin-behavior-releeph-request-state-change' => '9f081f05', 'javelin-behavior-releeph-request-typeahead' => 'aa3a100c', 'javelin-behavior-remarkup-load-image' => '202bfa3f', 'javelin-behavior-remarkup-preview' => 'd8a86cfb', 'javelin-behavior-reorder-applications' => 'aa371860', 'javelin-behavior-reorder-columns' => '8ac32fd9', 'javelin-behavior-reorder-profile-menu-items' => 'e5bdb730', 'javelin-behavior-repository-crossreference' => 'c15122b4', 'javelin-behavior-scrollbar' => '92388bae', 'javelin-behavior-search-reorder-queries' => 'b86f297f', 'javelin-behavior-select-content' => 'e8240b50', 'javelin-behavior-select-on-click' => '66365ee2', 'javelin-behavior-setup-check-https' => '01384686', 'javelin-behavior-stripe-payment-form' => '02cb4398', 'javelin-behavior-test-payment-form' => '4a7fb02b', 'javelin-behavior-time-typeahead' => '5803b9e7', 'javelin-behavior-toggle-class' => '32db8374', 'javelin-behavior-toggle-widget' => '8f959ad0', 'javelin-behavior-trigger-rule-editor' => '398fdf13', 'javelin-behavior-typeahead-browse' => '70245195', 'javelin-behavior-typeahead-search' => '7b139193', 'javelin-behavior-user-menu' => '60cd9241', 'javelin-behavior-view-placeholder' => 'a9942052', 'javelin-behavior-workflow' => '9623adc1', 'javelin-color' => '78f811c9', 'javelin-cookie' => '05d290ef', 'javelin-diffusion-locate-file-source' => '94243d89', 'javelin-dom' => '94681e22', 'javelin-dynval' => '202a2e85', 'javelin-event' => 'c03f2fb4', 'javelin-fx' => '34450586', 'javelin-history' => '030b4f7a', 'javelin-install' => '5902260c', 'javelin-json' => '541f81c3', 'javelin-leader' => '0d2490ce', 'javelin-magical-init' => '98e6504a', 'javelin-mask' => '7c4d8998', 'javelin-quicksand' => 'd3799cb4', 'javelin-reactor' => '1c850a26', 'javelin-reactor-dom' => '6cfa0008', 'javelin-reactor-node-calmer' => '225bbb98', 'javelin-reactornode' => '72960bc1', 'javelin-request' => '91863989', 'javelin-resource' => '740956e1', 'javelin-routable' => '6a18c42e', 'javelin-router' => '32755edb', 'javelin-scrollbar' => 'a43ae2ae', 'javelin-sound' => 'd4cc2d2a', 'javelin-stratcom' => '0889b835', 'javelin-tokenizer' => '89a1ae3a', 'javelin-typeahead' => 'a4356cde', 'javelin-typeahead-composite-source' => '22ee68a5', 'javelin-typeahead-normalizer' => 'a241536a', 'javelin-typeahead-ondemand-source' => '23387297', 'javelin-typeahead-preloaded-source' => '5a79f6c3', 'javelin-typeahead-source' => '8badee71', 'javelin-typeahead-static-source' => '80bff3af', 'javelin-uri' => '2e255291', 'javelin-util' => '22ae1776', 'javelin-vector' => 'e9c80beb', 'javelin-view' => '289bf236', 'javelin-view-html' => 'f8c4e135', 'javelin-view-interpreter' => '876506b6', 'javelin-view-renderer' => '9aae2b66', 'javelin-view-visitor' => '308f9fe4', 'javelin-websocket' => 'fdc13e4e', 'javelin-workboard-board' => 'c02a5497', 'javelin-workboard-card' => '0392a5d8', 'javelin-workboard-card-template' => '2a61f8d4', 'javelin-workboard-column' => 'c3d24e63', 'javelin-workboard-controller' => '42c7a5a7', 'javelin-workboard-drop-effect' => '8e0aa661', 'javelin-workboard-header' => '111bfd2d', 'javelin-workboard-header-template' => 'ebe83a6b', 'javelin-workboard-order-template' => '03e8891f', 'javelin-workflow' => '958e9045', 'maniphest-report-css' => '3d53188b', 'maniphest-task-edit-css' => '272daa84', 'maniphest-task-summary-css' => '61d1667e', 'multirow-row-manager' => '5b54c823', 'owners-path-editor' => '2a8b62d9', 'owners-path-editor-css' => 'fa7c13ef', 'paste-css' => 'b37bcd38', 'path-typeahead' => 'ad486db3', 'people-picture-menu-item-css' => 'fe8e07cf', 'people-profile-css' => '2ea2daa1', 'phabricator-action-list-view-css' => 'c4972757', 'phabricator-busy' => '5202e831', 'phabricator-chatlog-css' => 'abdc76ee', 'phabricator-content-source-view-css' => 'cdf0d579', 'phabricator-core-css' => '1b29ed61', 'phabricator-countdown-css' => 'bff8012f', 'phabricator-darklog' => '3b869402', 'phabricator-darkmessage' => '26cd4b73', 'phabricator-dashboard-css' => '4267d6c6', 'phabricator-diff-changeset' => 'd0a85a85', 'phabricator-diff-changeset-list' => '04023d82', 'phabricator-diff-inline' => 'a4a14a94', 'phabricator-drag-and-drop-file-upload' => '4370900d', 'phabricator-draggable-list' => 'c9ad6f70', 'phabricator-fatal-config-template-css' => '20babf50', 'phabricator-favicon' => '7930776a', 'phabricator-feed-css' => 'd8b6e3f8', 'phabricator-file-upload' => 'ab85e184', 'phabricator-filetree-view-css' => '56cdd875', 'phabricator-flag-css' => '2b77be8d', 'phabricator-keyboard-shortcut' => 'c9749dcd', 'phabricator-keyboard-shortcut-manager' => '37b8a04a', 'phabricator-main-menu-view' => '8e2d9a28', 'phabricator-nav-view-css' => 'f8a0c1bf', 'phabricator-notification' => 'a9b91e3f', 'phabricator-notification-css' => '30240bd2', 'phabricator-notification-menu-css' => '4df1ee30', 'phabricator-object-selector-css' => 'ee77366f', 'phabricator-phtize' => '2f1db1ed', 'phabricator-prefab' => '5793d835', 'phabricator-remarkup-css' => '9e627d41', 'phabricator-search-results-css' => '9ea70ace', 'phabricator-shaped-request' => 'abf88db8', 'phabricator-slowvote-css' => '1694baed', 'phabricator-source-code-view-css' => '03d7ac28', 'phabricator-standard-page-view' => '8a295cb9', 'phabricator-textareautils' => 'f340a484', 'phabricator-title' => '43bc9360', 'phabricator-tooltip' => '83754533', 'phabricator-ui-example-css' => 'b4795059', 'phabricator-zindex-css' => '99c0f5eb', 'phame-css' => '799febf9', 'pholio-css' => '88ef5ef1', 'pholio-edit-css' => '4df55b3b', 'pholio-inline-comments-css' => '722b48c2', 'phortune-credit-card-form' => 'd12d214f', 'phortune-credit-card-form-css' => '3b9868a8', 'phortune-css' => '12e8251a', 'phortune-invoice-css' => '4436b241', 'phrequent-css' => 'bd79cc67', 'phriction-document-css' => '03380da0', 'phui-action-panel-css' => '6c386cbf', 'phui-badge-view-css' => '666e25ad', 'phui-basic-nav-view-css' => '56ebd66d', 'phui-big-info-view-css' => '362ad37b', 'phui-box-css' => '5ed3b8cb', 'phui-bulk-editor-css' => '374d5e30', 'phui-button-bar-css' => 'a4aa75c4', 'phui-button-css' => 'ea704902', 'phui-button-simple-css' => '1ff278aa', 'phui-calendar-css' => 'f11073aa', 'phui-calendar-day-css' => '9597d706', 'phui-calendar-list-css' => 'ccd7e4e2', 'phui-calendar-month-css' => 'cb758c42', 'phui-chart-css' => '7853a69b', 'phui-cms-css' => '8c05c41e', 'phui-comment-form-css' => '68a2d99a', 'phui-comment-panel-css' => 'ec4e31c0', 'phui-crumbs-view-css' => '614f43cf', 'phui-curtain-view-css' => '68c5efb6', 'phui-document-summary-view-css' => 'b068eed1', 'phui-document-view-css' => '52b748a5', 'phui-document-view-pro-css' => 'b9613a10', 'phui-feed-story-css' => 'a0c05029', 'phui-font-icon-base-css' => 'd7994e06', 'phui-fontkit-css' => '9b714a5e', 'phui-form-css' => '159e2d9c', 'phui-form-view-css' => '01b796c0', 'phui-head-thing-view-css' => 'd7f293df', 'phui-header-view-css' => '285c9139', 'phui-hovercard' => '074f0783', 'phui-hovercard-view-css' => '6ca90fa0', 'phui-icon-set-selector-css' => '7aa5f3ec', 'phui-icon-view-css' => '4cbc684a', 'phui-image-mask-css' => '62c7f4d2', 'phui-info-view-css' => '37b8d9ce', 'phui-inline-comment-view-css' => '48acce5b', 'phui-invisible-character-view-css' => 'c694c4a4', 'phui-left-right-css' => '68513c34', 'phui-lightbox-css' => '4ebf22da', 'phui-list-view-css' => '470b1adb', 'phui-object-box-css' => 'f434b6be', 'phui-oi-big-ui-css' => '534f1757', 'phui-oi-color-css' => 'b517bfa0', 'phui-oi-drag-ui-css' => 'da15d3dc', 'phui-oi-flush-ui-css' => '490e2e2e', - 'phui-oi-list-view-css' => 'a65865a7', + 'phui-oi-list-view-css' => 'f14f2422', 'phui-oi-simple-ui-css' => '6a30fa46', 'phui-pager-css' => 'd022c7ad', 'phui-pinboard-view-css' => '1f08f5d8', 'phui-property-list-view-css' => 'cad62236', 'phui-remarkup-preview-css' => '91767007', 'phui-segment-bar-view-css' => '5166b370', 'phui-spacing-css' => 'b05cadc3', 'phui-status-list-view-css' => 'e5ff8be0', 'phui-tag-view-css' => '29409667', 'phui-theme-css' => '35883b37', 'phui-timeline-view-css' => '1e348e4b', 'phui-two-column-view-css' => '01e6991e', 'phui-workboard-color-css' => 'e86de308', 'phui-workboard-view-css' => '74fc9d98', 'phui-workcard-view-css' => '9e9eb0df', 'phui-workpanel-view-css' => '3ae89b20', 'phuix-action-list-view' => 'c68f183f', 'phuix-action-view' => 'aaa08f3b', 'phuix-autocomplete' => '2fbe234d', 'phuix-button-view' => '55a24e84', 'phuix-dropdown-menu' => 'bdce4d78', 'phuix-form-control-view' => '38c1f3fb', 'phuix-icon-view' => 'a5257c4e', 'policy-css' => 'ceb56a08', 'policy-edit-css' => '8794e2ed', 'policy-transaction-detail-css' => 'c02b8384', 'ponder-view-css' => '05a09d0a', 'project-card-view-css' => '4e7371cd', 'project-triggers-css' => 'cb866c2d', 'project-view-css' => '567858b3', 'releeph-core' => 'f81ff2db', 'releeph-preview-branch' => '22db5c07', 'releeph-request-differential-create-dialog' => '0ac1ea31', 'releeph-request-typeahead-css' => 'bce37359', 'setup-issue-css' => '5eed85b2', 'sprite-login-css' => '18b368a6', 'sprite-tokens-css' => 'f1896dc5', 'syntax-default-css' => '055fc231', 'syntax-highlighting-css' => '4234f572', 'tokens-css' => 'ce5a50bd', 'trigger-rule' => '1c60c3fc', 'trigger-rule-control' => '5faf27b9', 'trigger-rule-editor' => 'b49fd60c', 'trigger-rule-type' => '4feea7d3', 'typeahead-browse-css' => 'b7ed02d2', 'unhandled-exception-css' => '9ecfc00d', ), 'requires' => array( '01384686' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-notification', ), '022516b4' => array( 'javelin-install', 'javelin-util', 'javelin-websocket', 'javelin-leader', 'javelin-json', ), '02cb4398' => array( 'javelin-behavior', 'javelin-dom', 'phortune-credit-card-form', ), '030b4f7a' => array( 'javelin-stratcom', 'javelin-install', 'javelin-uri', 'javelin-util', ), '0392a5d8' => array( 'javelin-install', ), '03e8891f' => array( 'javelin-install', ), '04023d82' => array( 'javelin-install', 'phuix-button-view', ), '04f8a1e3' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-workflow', ), '05d290ef' => array( 'javelin-install', 'javelin-util', ), '070679fe' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-uri', 'phabricator-notification', ), '074f0783' => array( 'javelin-install', 'javelin-dom', 'javelin-vector', 'javelin-request', 'javelin-uri', ), '076bd092' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-workflow', 'phabricator-draggable-list', ), '0889b835' => array( 'javelin-install', 'javelin-event', 'javelin-util', 'javelin-magical-init', ), '0922e81d' => array( 'herald-rule-editor', 'javelin-behavior', ), '09ecf50c' => array( 'javelin-behavior', 'javelin-dom', 'javelin-workflow', ), '0ad8d31f' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), '0cf79f45' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', 'javelin-install', ), '0d2490ce' => array( 'javelin-install', ), '0e6d261f' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', ), '0eaa33a9' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phuix-dropdown-menu', 'phuix-action-list-view', 'phuix-action-view', 'javelin-workflow', 'phuix-icon-view', ), '111bfd2d' => array( 'javelin-install', ), '1325b731' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-keyboard-shortcut', ), '139ef688' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-util', ), '1c850a26' => array( 'javelin-install', 'javelin-util', ), '1cab0e9a' => array( 'javelin-behavior', 'javelin-dom', 'javelin-uri', 'javelin-mask', 'phabricator-drag-and-drop-file-upload', ), '1cb7d027' => array( 'javelin-behavior', 'javelin-typeahead-ondemand-source', 'javelin-typeahead', 'javelin-dom', 'javelin-uri', 'javelin-util', 'javelin-stratcom', 'phabricator-prefab', 'phuix-icon-view', ), '1e413dc9' => array( 'javelin-behavior', 'javelin-dom', ), '1ff278aa' => array( 'phui-button-css', ), '202a2e85' => array( 'javelin-install', 'javelin-reactornode', 'javelin-util', 'javelin-reactor', ), '202bfa3f' => array( 'javelin-behavior', 'javelin-request', ), '225bbb98' => array( 'javelin-install', 'javelin-reactor', 'javelin-util', ), '22ee68a5' => array( 'javelin-install', 'javelin-typeahead-source', 'javelin-util', ), 23387297 => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-typeahead-source', ), 23631304 => array( 'phui-fontkit-css', ), '242aa08b' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '242dedd0' => array( 'javelin-stratcom', 'javelin-behavior', 'javelin-vector', 'javelin-dom', ), '243d6c22' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), '2539f834' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-json', 'phabricator-draggable-list', ), '27daef73' => array( 'multirow-row-manager', 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-stratcom', 'javelin-json', 'phabricator-prefab', ), '289bf236' => array( 'javelin-install', 'javelin-util', ), '29819b75' => array( 'phabricator-notification', 'javelin-stratcom', 'javelin-behavior', ), '2a61f8d4' => array( 'javelin-install', ), '2a8b62d9' => array( 'multirow-row-manager', 'javelin-install', 'path-typeahead', 'javelin-dom', 'javelin-util', 'phabricator-prefab', 'phuix-form-control-view', ), '2bdadf1a' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-request', 'phabricator-shaped-request', ), '2cc87f49' => array( 'javelin-behavior', 'javelin-workflow', 'javelin-json', 'javelin-dom', 'phabricator-keyboard-shortcut', ), '2e255291' => array( 'javelin-install', 'javelin-util', 'javelin-stratcom', ), '2f1db1ed' => array( 'javelin-util', ), '2f80333f' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phabricator-phtize', 'phabricator-textareautils', 'javelin-workflow', 'javelin-vector', 'phuix-autocomplete', 'javelin-mask', ), '2fbe234d' => array( 'javelin-install', 'javelin-dom', 'phuix-icon-view', 'phabricator-prefab', ), '308f9fe4' => array( 'javelin-install', 'javelin-util', ), '32755edb' => array( 'javelin-install', 'javelin-util', ), '32db8374' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 34450586 => array( 'javelin-color', 'javelin-install', 'javelin-util', ), '34c53422' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', ), '37b8a04a' => array( 'javelin-install', 'javelin-util', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', ), '3829a3cf' => array( 'javelin-behavior', 'javelin-uri', ), '38a6cedb' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), '38c1f3fb' => array( 'javelin-install', 'javelin-dom', ), '398fdf13' => array( 'javelin-behavior', 'trigger-rule-editor', 'trigger-rule', 'trigger-rule-type', ), '3ae89b20' => array( 'phui-workcard-view-css', ), '3b4899b0' => array( 'javelin-behavior', 'phabricator-prefab', ), '3dc5ad43' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', ), '3eed1f2b' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-workflow', 'javelin-quicksand', 'phabricator-phtize', 'phabricator-drag-and-drop-file-upload', 'phabricator-draggable-list', ), '407ee861' => array( 'javelin-behavior', 'javelin-uri', ), '4234f572' => array( 'syntax-default-css', ), '42c7a5a7' => array( 'javelin-install', 'javelin-dom', 'javelin-util', 'javelin-vector', 'javelin-stratcom', 'javelin-workflow', 'phabricator-drag-and-drop-file-upload', 'javelin-workboard-board', ), '4370900d' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-dom', 'javelin-uri', 'phabricator-file-upload', ), '43ba89a2' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-util', 'phabricator-notification', 'conpherence-thread-manager', ), '43bc9360' => array( 'javelin-install', ), '46116c01' => array( 'javelin-request', 'javelin-behavior', 'javelin-dom', 'javelin-router', 'javelin-util', 'phabricator-busy', ), '47a0728b' => array( 'javelin-behavior', 'javelin-dom', 'javelin-request', ), '4842f137' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), '48fe33d0' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-util', 'javelin-uri', ), '490e2e2e' => array( 'phui-oi-list-view-css', ), '4a7fb02b' => array( 'javelin-behavior', 'javelin-dom', 'phortune-credit-card-form', ), '4ae58b5a' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-stratcom', 'conpherence-thread-manager', ), '4b671572' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-request', ), '4dffaeb2' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phuix-form-control-view', 'phuix-icon-view', 'javelin-behavior-phabricator-gesture', ), '4e61fa88' => 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', ), '4feea7d3' => array( 'trigger-rule-control', ), '506aa3f4' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '5202e831' => array( 'javelin-install', 'javelin-dom', 'javelin-fx', ), '534f1757' => array( 'phui-oi-list-view-css', ), '541f81c3' => array( 'javelin-install', ), '55a24e84' => array( 'javelin-install', 'javelin-dom', ), '55d7b788' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '5793d835' => 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', ), '5803b9e7' => array( 'javelin-behavior', 'javelin-util', 'javelin-dom', 'javelin-stratcom', 'javelin-vector', 'javelin-typeahead-static-source', ), '5902260c' => array( 'javelin-util', 'javelin-magical-init', ), '5a6f6a06' => array( 'javelin-behavior', 'javelin-quicksand', ), '5a79f6c3' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-typeahead-source', ), '5aa1544e' => 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', ), '5b54c823' => array( 'javelin-install', 'javelin-stratcom', 'javelin-dom', 'javelin-util', ), '5cf0501a' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phuix-dropdown-menu', ), '5faf27b9' => array( 'phuix-form-control-view', ), '600f440c' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phabricator-busy', ), '60cd9241' => array( 'javelin-behavior', ), '65bb0011' => array( 'javelin-behavior', 'javelin-dom', ), '66365ee2' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '6a1583a8' => array( 'javelin-behavior', 'javelin-history', ), '6a162524' => array( 'javelin-behavior', 'javelin-dom', ), '6a18c42e' => array( 'javelin-install', ), '6a30fa46' => array( 'phui-oi-list-view-css', ), '6a85bc5a' => array( 'javelin-behavior', 'javelin-dom', 'javelin-json', 'javelin-workflow', 'javelin-magical-init', ), '6c379000' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'javelin-vector', 'phui-hovercard', ), '6cfa0008' => array( 'javelin-dom', 'javelin-dynval', 'javelin-reactor', 'javelin-reactornode', 'javelin-install', 'javelin-util', ), 70245195 => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', ), '727a5a61' => array( 'phuix-icon-view', ), '72960bc1' => array( 'javelin-install', 'javelin-reactor', 'javelin-util', 'javelin-reactor-node-calmer', ), '7353f43d' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', 'javelin-uri', ), '73ecc1f8' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'phabricator-tooltip', ), '740956e1' => array( 'javelin-util', 'javelin-uri', 'javelin-install', ), 74446546 => array( 'javelin-behavior', 'javelin-dom', ), '75184d68' => array( 'javelin-behavior', 'javelin-dom', 'javelin-uri', 'javelin-request', ), '78bc5d94' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-notification', ), '78f811c9' => array( 'javelin-install', ), '7930776a' => array( 'javelin-install', 'javelin-dom', ), '7ad020a5' => array( 'javelin-behavior', 'javelin-dom', 'phabricator-drag-and-drop-file-upload', 'phabricator-textareautils', ), '7b139193' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', ), '7c4d8998' => array( 'javelin-install', 'javelin-dom', ), '80bff3af' => array( 'javelin-install', 'javelin-typeahead-source', ), 83754533 => array( 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-vector', ), '87428eb2' => array( 'javelin-behavior', 'javelin-diffusion-locate-file-source', 'javelin-dom', 'javelin-typeahead', 'javelin-uri', ), '876506b6' => array( 'javelin-view', 'javelin-install', 'javelin-dom', ), '89a1ae3a' => array( 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-install', ), '8ac32fd9' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), '8badee71' => array( 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-typeahead-normalizer', ), '8c2ed2bf' => 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', ), '8e0aa661' => array( 'javelin-install', 'javelin-dom', ), '8e2d9a28' => array( 'phui-theme-css', ), '8f959ad0' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-stratcom', ), 91863989 => array( 'javelin-install', 'javelin-stratcom', 'javelin-util', 'javelin-behavior', 'javelin-json', 'javelin-dom', 'javelin-resource', 'javelin-routable', ), '91befbcc' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-stratcom', ), '92388bae' => array( 'javelin-behavior', 'javelin-scrollbar', ), '925fe8cd' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '92cdd7b6' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '9347f172' => array( 'javelin-behavior', 'multirow-row-manager', 'javelin-dom', 'javelin-util', 'phabricator-prefab', 'javelin-json', ), '94243d89' => array( 'javelin-install', 'javelin-dom', 'javelin-typeahead-preloaded-source', 'javelin-util', ), '94681e22' => array( 'javelin-magical-init', 'javelin-install', 'javelin-util', 'javelin-vector', 'javelin-stratcom', ), '956f3eeb' => array( 'javelin-behavior', 'javelin-util', 'javelin-dom', 'javelin-stratcom', 'javelin-vector', ), '958e9045' => array( 'javelin-stratcom', 'javelin-request', 'javelin-dom', 'javelin-vector', 'javelin-install', 'javelin-util', 'javelin-mask', 'javelin-uri', 'javelin-routable', ), '9623adc1' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'javelin-router', ), '9aae2b66' => array( 'javelin-install', 'javelin-util', ), '9b1cbd76' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), '9cec214e' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'javelin-uri', 'phabricator-textareautils', ), '9f081f05' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-util', 'phabricator-keyboard-shortcut', ), 'a17b84f1' => array( 'javelin-behavior', 'javelin-dom', 'javelin-workflow', ), 'a241536a' => array( 'javelin-install', ), 'a4356cde' => array( 'javelin-install', 'javelin-dom', 'javelin-vector', 'javelin-util', ), 'a43ae2ae' => array( 'javelin-install', 'javelin-dom', 'javelin-stratcom', 'javelin-vector', ), 'a4a14a94' => array( 'javelin-dom', ), 'a4aa75c4' => array( 'phui-button-css', 'phui-button-simple-css', ), 'a4af0b4a' => array( 'javelin-behavior', 'javelin-dom', 'javelin-request', 'javelin-util', ), 'a5257c4e' => array( 'javelin-install', 'javelin-dom', ), 'a9942052' => array( 'javelin-behavior', 'javelin-dom', 'javelin-view-renderer', 'javelin-install', ), 'a9b91e3f' => array( 'javelin-install', 'javelin-dom', 'javelin-stratcom', 'javelin-util', 'phabricator-notification-css', ), 'aa371860' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'aa3a100c' => array( 'javelin-behavior', 'javelin-dom', 'javelin-typeahead', 'javelin-typeahead-ondemand-source', 'javelin-dom', ), 'aa6d2308' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'multirow-row-manager', 'javelin-json', 'phuix-form-control-view', ), 'aaa08f3b' => array( 'javelin-install', 'javelin-dom', 'javelin-util', ), 'aad45445' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-vector', 'javelin-stratcom', 'javelin-workflow', 'javelin-workboard-controller', 'javelin-workboard-drop-effect', ), 'ab85e184' => array( 'javelin-install', 'javelin-dom', 'phabricator-notification', ), 'abf88db8' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-router', ), 'ad486db3' => array( 'javelin-install', 'javelin-typeahead', 'javelin-dom', 'javelin-request', 'javelin-typeahead-ondemand-source', 'javelin-util', ), 'aec8e38c' => array( 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-install', 'javelin-aphlict', 'javelin-workflow', 'javelin-router', 'javelin-behavior-device', 'javelin-vector', ), 'b105a3a6' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'b26a41e4' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'b347a301' => array( 'javelin-behavior', ), 'b49fd60c' => array( 'multirow-row-manager', 'trigger-rule', ), 'b517bfa0' => array( 'phui-oi-list-view-css', ), 'b52d0668' => array( 'aphront-typeahead-control-css', 'phui-tag-view-css', ), 'b58d1a2a' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', 'javelin-magical-init', ), 'b5e9bff9' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'b7b73831' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phabricator-shaped-request', ), 'b86f297f' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'b9109f8f' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-notification', ), 'bdce4d78' => array( 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-vector', 'javelin-stratcom', ), 'bde53589' => array( 'phui-inline-comment-view-css', ), 'c02a5497' => array( 'javelin-install', 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-workflow', 'phabricator-draggable-list', 'javelin-workboard-column', 'javelin-workboard-header-template', 'javelin-workboard-card-template', 'javelin-workboard-order-template', ), 'c03f2fb4' => array( 'javelin-install', ), 'c15122b4' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-uri', ), 'c2c500a7' => array( 'javelin-install', 'javelin-dom', 'phuix-button-view', ), 'c3703a16' => array( 'javelin-behavior', 'javelin-aphlict', 'phabricator-phtize', 'javelin-dom', ), 'c3d24e63' => array( 'javelin-install', 'javelin-workboard-card', 'javelin-workboard-header', ), 'c687e867' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-fx', 'javelin-util', ), 'c68f183f' => array( 'javelin-install', 'javelin-dom', ), 'c715c123' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-json', ), 'c7e748bf' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-mask', 'javelin-util', 'phuix-icon-view', 'phabricator-busy', ), 'c8147a20' => array( 'javelin-behavior', 'javelin-dom', 'javelin-vector', 'phui-chart-css', ), 'c9749dcd' => array( 'javelin-install', 'javelin-util', 'phabricator-keyboard-shortcut-manager', ), 'c9ad6f70' => array( 'javelin-install', 'javelin-dom', 'javelin-stratcom', 'javelin-util', 'javelin-vector', 'javelin-magical-init', ), 'cf32921f' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), 'd0a85a85' => array( 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-install', 'javelin-workflow', 'javelin-router', 'javelin-behavior-device', 'javelin-vector', 'phabricator-diff-inline', ), 'd12d214f' => array( 'javelin-install', 'javelin-dom', 'javelin-json', 'javelin-workflow', 'javelin-util', ), 'd3799cb4' => array( 'javelin-install', ), 'd4cc2d2a' => array( 'javelin-install', ), 'd8a86cfb' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phabricator-shaped-request', ), 'da15d3dc' => array( 'phui-oi-list-view-css', ), 'dae2d55b' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-notification', ), 'dfa1d313' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'phabricator-tooltip', 'phabricator-diff-changeset-list', 'phabricator-diff-changeset', ), 'e150bd50' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phuix-dropdown-menu', ), 'e15c8b1f' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-history', ), 'e5bdb730' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'e8240b50' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'e9a2940f' => array( 'javelin-behavior', 'javelin-request', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', 'javelin-uri', 'javelin-behavior-device', 'phabricator-title', 'phabricator-favicon', ), 'e9c80beb' => array( 'javelin-install', 'javelin-event', ), 'ebe83a6b' => array( 'javelin-install', ), 'ec4e31c0' => array( 'phui-timeline-view-css', ), 'ee77366f' => array( 'aphront-dialog-view-css', ), 'ee82cedb' => array( 'javelin-behavior', 'phabricator-keyboard-shortcut', 'javelin-stratcom', ), 'ef836bf2' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), 'f166c949' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'javelin-dom', 'javelin-magical-init', 'javelin-vector', 'javelin-request', 'javelin-util', ), 'f340a484' => array( 'javelin-install', 'javelin-dom', 'javelin-vector', ), 'f39d968b' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-util', 'javelin-dom', 'javelin-request', 'phabricator-keyboard-shortcut', 'phabricator-darklog', 'phabricator-darkmessage', ), 'f51e9c17' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'f84bcbf4' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'f8c4e135' => array( 'javelin-install', 'javelin-dom', 'javelin-view-visitor', 'javelin-util', ), 'fa6f30b2' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-behavior-device', 'javelin-scrollbar', 'javelin-quicksand', 'phabricator-keyboard-shortcut', 'conpherence-thread-manager', ), 'fce5d170' => array( 'javelin-magical-init', 'javelin-util', ), 'fdc13e4e' => array( 'javelin-install', ), 'ff688a7a' => array( 'owners-path-editor', 'javelin-behavior', ), 'ff7b3f22' => array( 'javelin-behavior', 'javelin-dom', ), ), 'packages' => array( 'conpherence.pkg.css' => array( 'conpherence-durable-column-view', 'conpherence-menu-css', 'conpherence-color-css', 'conpherence-message-pane-css', 'conpherence-notification-css', 'conpherence-transaction-css', 'conpherence-participant-pane-css', 'conpherence-header-pane-css', ), 'conpherence.pkg.js' => array( 'javelin-behavior-conpherence-menu', 'javelin-behavior-conpherence-participant-pane', 'javelin-behavior-conpherence-pontificate', 'javelin-behavior-toggle-widget', ), 'core.pkg.css' => array( 'phabricator-core-css', 'phabricator-zindex-css', 'phui-button-css', 'phui-button-simple-css', 'phui-theme-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', 'application-search-view-css', 'phabricator-remarkup-css', 'syntax-highlighting-css', 'syntax-default-css', 'phui-pager-css', 'aphront-tooltip-css', 'phabricator-flag-css', 'phui-info-view-css', 'phabricator-main-menu-view', 'phabricator-notification-css', 'phabricator-notification-menu-css', 'phui-lightbox-css', 'phui-comment-panel-css', 'phui-header-view-css', 'phabricator-nav-view-css', 'phui-basic-nav-view-css', 'phui-crumbs-view-css', 'phui-oi-list-view-css', 'phui-oi-color-css', 'phui-oi-big-ui-css', 'phui-oi-drag-ui-css', 'phui-oi-simple-ui-css', 'phui-oi-flush-ui-css', 'global-drag-and-drop-css', 'phui-spacing-css', 'phui-form-css', 'phui-icon-view-css', 'phabricator-action-list-view-css', 'phui-property-list-view-css', 'phui-tag-view-css', 'phui-list-view-css', 'font-fontawesome', 'font-lato', 'phui-font-icon-base-css', 'phui-fontkit-css', 'phui-box-css', 'phui-object-box-css', 'phui-timeline-view-css', 'phui-two-column-view-css', 'phui-curtain-view-css', 'sprite-login-css', 'sprite-tokens-css', 'tokens-css', 'auth-css', 'phui-status-list-view-css', 'phui-feed-story-css', 'phabricator-feed-css', 'phabricator-dashboard-css', 'aphront-multi-column-view-css', ), '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', 'phuix-icon-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-sound', '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', 'javelin-behavior-aphlict-status', 'javelin-behavior-user-menu', 'phabricator-favicon', ), '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', 'phabricator-filetree-view-css', ), 'differential.pkg.js' => array( 'phabricator-drag-and-drop-file-upload', 'phabricator-shaped-request', 'javelin-behavior-differential-populate', 'javelin-behavior-differential-diff-radios', 'javelin-behavior-aphront-drag-and-drop-textarea', 'javelin-behavior-phabricator-object-selector', 'javelin-behavior-repository-crossreference', 'javelin-behavior-aphront-more', 'phabricator-diff-inline', 'phabricator-diff-changeset', 'phabricator-diff-changeset-list', ), '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-list-editor', ), ), ); diff --git a/src/applications/dashboard/engine/PhabricatorDashboardPortalProfileMenuEngine.php b/src/applications/dashboard/engine/PhabricatorDashboardPortalProfileMenuEngine.php index 18184952e4..a5c99a05d0 100644 --- a/src/applications/dashboard/engine/PhabricatorDashboardPortalProfileMenuEngine.php +++ b/src/applications/dashboard/engine/PhabricatorDashboardPortalProfileMenuEngine.php @@ -1,38 +1,39 @@ getProfileObject(); return $portal->getURI().$path; } protected function getBuiltinProfileItems($object) { $items = array(); $items[] = $this->newManageItem(); $items[] = $this->newItem() ->setMenuItemKey(PhabricatorDashboardPortalMenuItem::MENUITEMKEY) - ->setBuiltinKey('manage'); + ->setBuiltinKey('manage') + ->setIsTailItem(true); return $items; } protected function newNoMenuItemsView() { return $this->newEmptyView( pht('New Portal'), pht('Use "Edit Menu" to add menu items to this portal.')); } } diff --git a/src/applications/dashboard/menuitem/PhabricatorDashboardPortalMenuItem.php b/src/applications/dashboard/menuitem/PhabricatorDashboardPortalMenuItem.php index 655f67058a..da8498891e 100644 --- a/src/applications/dashboard/menuitem/PhabricatorDashboardPortalMenuItem.php +++ b/src/applications/dashboard/menuitem/PhabricatorDashboardPortalMenuItem.php @@ -1,117 +1,117 @@ getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( PhabricatorProfileMenuItemConfiguration $config) { $viewer = $this->getViewer(); if (!$viewer->isLoggedIn()) { return array(); } $href = $this->getItemViewURI($config); $name = $this->getDisplayName($config); $icon = 'fa-pencil'; $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon); return array( $item, ); } public function newPageContent( PhabricatorProfileMenuItemConfiguration $config) { $viewer = $this->getViewer(); $engine = $this->getEngine(); $portal = $engine->getProfileObject(); $controller = $engine->getController(); $header = id(new PHUIHeaderView()) ->setHeader(pht('Manage Portal')); $edit_uri = urisprintf( '/portal/edit/%d/', $portal->getID()); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $portal, PhabricatorPolicyCapability::CAN_EDIT); $curtain = $controller->newCurtainView($portal) ->addAction( id(new PhabricatorActionView()) ->setName(pht('Edit Portal')) ->setIcon('fa-pencil') ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit) ->setHref($edit_uri)); $timeline = $controller->newTimelineView() ->setShouldTerminate(true); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setCurtain($curtain) ->setMainColumn( array( $timeline, )); return $view; } } diff --git a/src/applications/home/menuitem/PhabricatorHomeLauncherProfileMenuItem.php b/src/applications/home/menuitem/PhabricatorHomeLauncherProfileMenuItem.php index a727fbced6..e077ac7ba4 100644 --- a/src/applications/home/menuitem/PhabricatorHomeLauncherProfileMenuItem.php +++ b/src/applications/home/menuitem/PhabricatorHomeLauncherProfileMenuItem.php @@ -1,66 +1,70 @@ getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( PhabricatorProfileMenuItemConfiguration $config) { $viewer = $this->getViewer(); $name = $this->getDisplayName($config); - $icon = 'fa-globe'; + $icon = 'fa-ellipsis-h'; $href = '/applications/'; $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon); return array( $item, ); } } diff --git a/src/applications/home/menuitem/PhabricatorHomeProfileMenuItem.php b/src/applications/home/menuitem/PhabricatorHomeProfileMenuItem.php index 8b3eb4fe2d..f4f3cb8733 100644 --- a/src/applications/home/menuitem/PhabricatorHomeProfileMenuItem.php +++ b/src/applications/home/menuitem/PhabricatorHomeProfileMenuItem.php @@ -1,69 +1,73 @@ getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function newPageContent( PhabricatorProfileMenuItemConfiguration $config) { $viewer = $this->getViewer(); return id(new PHUIHomeView()) ->setViewer($viewer); } public function buildEditEngineFields( PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( PhabricatorProfileMenuItemConfiguration $config) { $viewer = $this->getViewer(); $name = $this->getDisplayName($config); $icon = 'fa-home'; $href = $this->getItemViewURI($config); $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon); return array( $item, ); } } diff --git a/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php b/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php index 77b69443da..813cd01781 100644 --- a/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php +++ b/src/applications/project/engine/PhabricatorProjectProfileMenuEngine.php @@ -1,55 +1,57 @@ getProfileObject(); $id = $project->getID(); return "/project/{$id}/item/{$path}"; } protected function getBuiltinProfileItems($object) { $items = array(); $items[] = $this->newItem() ->setBuiltinKey(PhabricatorProject::ITEM_PICTURE) - ->setMenuItemKey(PhabricatorProjectPictureProfileMenuItem::MENUITEMKEY); + ->setMenuItemKey(PhabricatorProjectPictureProfileMenuItem::MENUITEMKEY) + ->setIsHeadItem(true); $items[] = $this->newItem() ->setBuiltinKey(PhabricatorProject::ITEM_PROFILE) ->setMenuItemKey(PhabricatorProjectDetailsProfileMenuItem::MENUITEMKEY); $items[] = $this->newItem() ->setBuiltinKey(PhabricatorProject::ITEM_POINTS) ->setMenuItemKey(PhabricatorProjectPointsProfileMenuItem::MENUITEMKEY); $items[] = $this->newItem() ->setBuiltinKey(PhabricatorProject::ITEM_WORKBOARD) ->setMenuItemKey(PhabricatorProjectWorkboardProfileMenuItem::MENUITEMKEY); $items[] = $this->newItem() ->setBuiltinKey(PhabricatorProject::ITEM_MEMBERS) ->setMenuItemKey(PhabricatorProjectMembersProfileMenuItem::MENUITEMKEY); $items[] = $this->newItem() ->setBuiltinKey(PhabricatorProject::ITEM_SUBPROJECTS) ->setMenuItemKey( PhabricatorProjectSubprojectsProfileMenuItem::MENUITEMKEY); $items[] = $this->newItem() ->setBuiltinKey(PhabricatorProject::ITEM_MANAGE) - ->setMenuItemKey(PhabricatorProjectManageProfileMenuItem::MENUITEMKEY); + ->setMenuItemKey(PhabricatorProjectManageProfileMenuItem::MENUITEMKEY) + ->setIsTailItem(true); return $items; } } diff --git a/src/applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php b/src/applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php index b779f4be90..536165e3ef 100644 --- a/src/applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php +++ b/src/applications/project/menuitem/PhabricatorProjectDetailsProfileMenuItem.php @@ -1,69 +1,73 @@ getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); $id = $project->getID(); $name = $project->getName(); $icon = $project->getDisplayIconIcon(); $href = "/project/profile/{$id}/"; $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon); return array( $item, ); } } diff --git a/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php b/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php index 1bd7e796dc..b20bc777ae 100644 --- a/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php +++ b/src/applications/project/menuitem/PhabricatorProjectManageProfileMenuItem.php @@ -1,69 +1,73 @@ getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); $id = $project->getID(); $name = $this->getDisplayName($config); $icon = 'fa-gears'; $href = "/project/manage/{$id}/"; $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon); return array( $item, ); } } diff --git a/src/applications/project/menuitem/PhabricatorProjectMembersProfileMenuItem.php b/src/applications/project/menuitem/PhabricatorProjectMembersProfileMenuItem.php index 580aacb635..b13543312d 100644 --- a/src/applications/project/menuitem/PhabricatorProjectMembersProfileMenuItem.php +++ b/src/applications/project/menuitem/PhabricatorProjectMembersProfileMenuItem.php @@ -1,59 +1,63 @@ getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); $id = $project->getID(); $name = $this->getDisplayName($config); $icon = 'fa-group'; $href = "/project/members/{$id}/"; $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon); return array( $item, ); } } diff --git a/src/applications/project/menuitem/PhabricatorProjectPictureProfileMenuItem.php b/src/applications/project/menuitem/PhabricatorProjectPictureProfileMenuItem.php index 2201687c81..b5c203402d 100644 --- a/src/applications/project/menuitem/PhabricatorProjectPictureProfileMenuItem.php +++ b/src/applications/project/menuitem/PhabricatorProjectPictureProfileMenuItem.php @@ -1,69 +1,73 @@ getDefaultName(); } public function buildEditEngineFields( PhabricatorProfileMenuItemConfiguration $config) { return array(); } protected function newNavigationMenuItems( PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); require_celerity_resource('people-picture-menu-item-css'); $picture = $project->getProfileImageURI(); $href = $project->getProfileURI(); $classes = array(); $classes[] = 'people-menu-image'; if ($project->isArchived()) { $classes[] = 'phui-image-disabled'; } $photo = phutil_tag( 'img', array( 'src' => $picture, 'class' => implode(' ', $classes), )); $view = phutil_tag_div('people-menu-image-container', $photo); $view = phutil_tag( 'a', array( 'href' => $href, ), $view); $item = $this->newItem() ->appendChild($view); return array( $item, ); } } diff --git a/src/applications/project/menuitem/PhabricatorProjectSubprojectsProfileMenuItem.php b/src/applications/project/menuitem/PhabricatorProjectSubprojectsProfileMenuItem.php index 6b43210274..da43e30bb8 100644 --- a/src/applications/project/menuitem/PhabricatorProjectSubprojectsProfileMenuItem.php +++ b/src/applications/project/menuitem/PhabricatorProjectSubprojectsProfileMenuItem.php @@ -1,66 +1,70 @@ isMilestone()) { return false; } return true; } public function getDisplayName( PhabricatorProfileMenuItemConfiguration $config) { $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); $id = $project->getID(); $name = $this->getDisplayName($config); $icon = 'fa-sitemap'; $href = "/project/subprojects/{$id}/"; $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon); return array( $item, ); } } diff --git a/src/applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php b/src/applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php index 38b9632d93..1485f1ef8a 100644 --- a/src/applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php +++ b/src/applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php @@ -1,73 +1,77 @@ getViewer(); // Workboards are only available if Maniphest is installed. $class = 'PhabricatorManiphestApplication'; if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { return false; } return true; } public function getDisplayName( PhabricatorProfileMenuItemConfiguration $config) { $name = $config->getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( PhabricatorProfileMenuItemConfiguration $config) { $project = $config->getProfileObject(); $id = $project->getID(); $href = $project->getWorkboardURI(); $name = $this->getDisplayName($config); $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon('fa-columns'); return array( $item, ); } } diff --git a/src/applications/search/engine/PhabricatorProfileMenuEngine.php b/src/applications/search/engine/PhabricatorProfileMenuEngine.php index e2439a341b..abb6de789b 100644 --- a/src/applications/search/engine/PhabricatorProfileMenuEngine.php +++ b/src/applications/search/engine/PhabricatorProfileMenuEngine.php @@ -1,1469 +1,1496 @@ viewer = $viewer; return $this; } public function getViewer() { return $this->viewer; } public function setProfileObject($profile_object) { $this->profileObject = $profile_object; return $this; } public function getProfileObject() { return $this->profileObject; } public function setCustomPHID($custom_phid) { $this->customPHID = $custom_phid; return $this; } public function getCustomPHID() { return $this->customPHID; } private function getEditModeCustomPHID() { $mode = $this->getEditMode(); switch ($mode) { case self::MODE_CUSTOM: $custom_phid = $this->getCustomPHID(); break; case self::MODE_GLOBAL: $custom_phid = null; break; } return $custom_phid; } public function setController(PhabricatorController $controller) { $this->controller = $controller; return $this; } public function getController() { return $this->controller; } private function setDefaultItem( PhabricatorProfileMenuItemConfiguration $default_item) { $this->defaultItem = $default_item; return $this; } public function getDefaultItem() { return $this->pickDefaultItem($this->getItems()); } public function setShowNavigation($show) { $this->showNavigation = $show; return $this; } public function getShowNavigation() { return $this->showNavigation; } public function addContentPageClass($class) { $this->pageClasses[] = $class; return $this; } public function setShowContentCrumbs($show_content_crumbs) { $this->showContentCrumbs = $show_content_crumbs; return $this; } public function getShowContentCrumbs() { return $this->showContentCrumbs; } abstract public function getItemURI($path); abstract protected function isMenuEngineConfigurable(); abstract protected function getBuiltinProfileItems($object); protected function getBuiltinCustomProfileItems( $object, $custom_phid) { return array(); } protected function getEditMode() { return $this->editMode; } public function buildResponse() { $controller = $this->getController(); $viewer = $controller->getViewer(); $this->setViewer($viewer); $request = $controller->getRequest(); $item_action = $request->getURIData('itemAction'); if (!$item_action) { $item_action = 'view'; } $is_view = ($item_action == 'view'); // If the engine is not configurable, don't respond to any of the editing // or configuration routes. if (!$this->isMenuEngineConfigurable()) { if (!$is_view) { return new Aphront404Response(); } } $item_id = $request->getURIData('itemID'); // If we miss on the MenuEngine route, try the EditEngine route. This will // be populated while editing items. if (!$item_id) { $item_id = $request->getURIData('id'); } $item_list = $this->getItems(); $selected_item = $this->pickSelectedItem( $item_list, $item_id, $is_view); switch ($item_action) { case 'view': // If we were not able to select an item, we're still going to render // a page state. For example, this happens when you create a new // portal for the first time. break; case 'info': case 'hide': case 'default': case 'builtin': if (!$selected_item) { return new Aphront404Response(); } break; case 'edit': if (!$request->getURIData('id')) { // If we continue along the "edit" pathway without an ID, we hit an // unrelated exception because we can not build a new menu item out // of thin air. For menus, new items are created via the "new" // action. Just catch this case and 404 early since there's currently // no clean way to make EditEngine aware of this. return new Aphront404Response(); } break; } $navigation = $this->buildNavigation($selected_item); $crumbs = $controller->buildApplicationCrumbsForEditEngine(); if (!$is_view) { $navigation->selectFilter(self::ITEM_MANAGE); if ($selected_item) { if ($selected_item->getCustomPHID()) { $edit_mode = 'custom'; } else { $edit_mode = 'global'; } } else { $edit_mode = $request->getURIData('itemEditMode'); } $available_modes = $this->getViewerEditModes(); if ($available_modes) { $available_modes = array_fuse($available_modes); if (isset($available_modes[$edit_mode])) { $this->editMode = $edit_mode; } else { if ($item_action != 'configure') { return new Aphront404Response(); } } } $page_title = pht('Configure Menu'); } else { if ($selected_item) { $page_title = $selected_item->getDisplayName(); } else { $page_title = pht('Empty'); } } switch ($item_action) { case 'view': if ($selected_item) { try { $content = $this->buildItemViewContent($selected_item); } catch (Exception $ex) { $content = id(new PHUIInfoView()) ->setTitle(pht('Unable to Render Dashboard')) ->setErrors(array($ex->getMessage())); } $crumbs->addTextCrumb($selected_item->getDisplayName()); } else { $content = $this->newNoMenuItemsView(); } if (!$content) { $content = $this->newEmptyView( pht('Empty'), pht('There is nothing here.')); } break; case 'configure': $mode = $this->getEditMode(); if (!$mode) { $crumbs->addTextCrumb(pht('Configure Menu')); $content = $this->buildMenuEditModeContent(); } else { if (count($available_modes) > 1) { $crumbs->addTextCrumb( pht('Configure Menu'), $this->getItemURI('configure/')); switch ($mode) { case self::MODE_CUSTOM: $crumbs->addTextCrumb(pht('Personal')); break; case self::MODE_GLOBAL: $crumbs->addTextCrumb(pht('Global')); break; } } else { $crumbs->addTextCrumb(pht('Configure Menu')); } $edit_list = $this->loadItems($mode); $content = $this->buildItemConfigureContent($edit_list); } break; case 'reorder': $mode = $this->getEditMode(); $edit_list = $this->loadItems($mode); $content = $this->buildItemReorderContent($edit_list); break; case 'new': $item_key = $request->getURIData('itemKey'); $mode = $this->getEditMode(); $content = $this->buildItemNewContent($item_key, $mode); break; case 'builtin': $content = $this->buildItemBuiltinContent($selected_item); break; case 'hide': $content = $this->buildItemHideContent($selected_item); break; case 'default': if (!$this->isMenuEnginePinnable()) { return new Aphront404Response(); } $content = $this->buildItemDefaultContent( $selected_item, $item_list); break; case 'edit': $content = $this->buildItemEditContent(); break; default: throw new Exception( pht( 'Unsupported item action "%s".', $item_action)); } if ($content instanceof AphrontResponse) { return $content; } if ($content instanceof AphrontResponseProducerInterface) { return $content; } $crumbs->setBorder(true); $page = $controller->newPage() ->setTitle($page_title) ->appendChild($content); if (!$is_view || $this->getShowContentCrumbs()) { $page->setCrumbs($crumbs); } if ($this->getShowNavigation()) { $page->setNavigation($navigation); } if ($is_view) { foreach ($this->pageClasses as $class) { $page->addClass($class); } } return $page; } public function buildNavigation( PhabricatorProfileMenuItemConfiguration $selected_item = null) { if ($this->navigation) { return $this->navigation; } $nav = id(new AphrontSideNavFilterView()) ->setIsProfileMenu(true) ->setBaseURI(new PhutilURI($this->getItemURI(''))); $menu_items = $this->getItems(); $filtered_items = array(); foreach ($menu_items as $menu_item) { if ($menu_item->isDisabled()) { continue; } $filtered_items[] = $menu_item; } $filtered_groups = mgroup($filtered_items, 'getMenuItemKey'); foreach ($filtered_groups as $group) { $first_item = head($group); $first_item->willBuildNavigationItems($group); } $has_items = false; foreach ($menu_items as $menu_item) { if ($menu_item->isDisabled()) { continue; } $items = $menu_item->buildNavigationMenuItems(); foreach ($items as $item) { $this->validateNavigationMenuItem($item); } // If the item produced only a single item which does not otherwise // have a key, try to automatically assign it a reasonable key. This // makes selecting the correct item simpler. if (count($items) == 1) { $item = head($items); if ($item->getKey() === null) { $default_key = $menu_item->getDefaultMenuItemKey(); $item->setKey($default_key); } } foreach ($items as $item) { $nav->addMenuItem($item); $has_items = true; } } if (!$has_items) { // If the navigation menu has no items, add an empty label item to // force it to render something. $empty_item = id(new PHUIListItemView()) ->setType(PHUIListItemView::TYPE_LABEL); $nav->addMenuItem($empty_item); } $nav->selectFilter(null); $navigation_items = $nav->getMenu()->getItems(); $select_key = $this->pickHighlightedMenuItem( $navigation_items, $selected_item); $nav->selectFilter($select_key); $this->navigation = $nav; return $this->navigation; } private function getItems() { if ($this->items === null) { $this->items = $this->loadItems(self::MODE_COMBINED); } return $this->items; } private function loadItems($mode) { $viewer = $this->getViewer(); $object = $this->getProfileObject(); $items = $this->loadBuiltinProfileItems($mode); $query = id(new PhabricatorProfileMenuItemConfigurationQuery()) ->setViewer($viewer) ->withProfilePHIDs(array($object->getPHID())); switch ($mode) { case self::MODE_GLOBAL: $query->withCustomPHIDs(array(), true); break; case self::MODE_CUSTOM: $query->withCustomPHIDs(array($this->getCustomPHID()), false); break; case self::MODE_COMBINED: $query->withCustomPHIDs(array($this->getCustomPHID()), true); break; } $stored_items = $query->execute(); foreach ($stored_items as $stored_item) { $impl = $stored_item->getMenuItem(); $impl->setViewer($viewer); $impl->setEngine($this); } // Merge the stored items into the builtin items. If a builtin item has // a stored version, replace the defaults with the stored changes. foreach ($stored_items as $stored_item) { if (!$stored_item->shouldEnableForObject($object)) { continue; } $builtin_key = $stored_item->getBuiltinKey(); if ($builtin_key !== null) { // If this builtin actually exists, replace the builtin with the // stored configuration. Otherwise, we're just going to drop the // stored config: it corresponds to an out-of-date or uninstalled // item. if (isset($items[$builtin_key])) { + $builtin_item = $items[$builtin_key]; + + // Copy runtime properties from the builtin item to the stored item. + $stored_item->setIsHeadItem($builtin_item->getIsHeadItem()); + $stored_item->setIsTailItem($builtin_item->getIsTailItem()); + $items[$builtin_key] = $stored_item; } else { continue; } } else { $items[] = $stored_item; } } return $this->arrangeItems($items, $mode); } private function loadBuiltinProfileItems($mode) { $object = $this->getProfileObject(); switch ($mode) { case self::MODE_GLOBAL: $builtins = $this->getBuiltinProfileItems($object); break; case self::MODE_CUSTOM: $builtins = $this->getBuiltinCustomProfileItems( $object, $this->getCustomPHID()); break; case self::MODE_COMBINED: $builtins = array(); $builtins[] = $this->getBuiltinCustomProfileItems( $object, $this->getCustomPHID()); $builtins[] = $this->getBuiltinProfileItems($object); $builtins = array_mergev($builtins); break; } $items = PhabricatorProfileMenuItem::getAllMenuItems(); $viewer = $this->getViewer(); $order = 1; $map = array(); foreach ($builtins as $builtin) { $builtin_key = $builtin->getBuiltinKey(); if (!$builtin_key) { throw new Exception( pht( 'Object produced a builtin item with no builtin item key! '. 'Builtin items must have a unique key.')); } if (isset($map[$builtin_key])) { throw new Exception( pht( 'Object produced two items with the same builtin key ("%s"). '. 'Each item must have a unique builtin key.', $builtin_key)); } $item_key = $builtin->getMenuItemKey(); $item = idx($items, $item_key); if (!$item) { throw new Exception( pht( 'Builtin item ("%s") specifies a bad item key ("%s"); there '. 'is no corresponding item implementation available.', $builtin_key, $item_key)); } $item = clone $item; $item->setViewer($viewer); $item->setEngine($this); $builtin ->setProfilePHID($object->getPHID()) ->attachMenuItem($item) ->attachProfileObject($object) ->setMenuItemOrder($order); if (!$builtin->shouldEnableForObject($object)) { continue; } $map[$builtin_key] = $builtin; $order++; } return $map; } private function validateNavigationMenuItem($item) { if (!($item instanceof PHUIListItemView)) { throw new Exception( pht( 'Expected buildNavigationMenuItems() to return a list of '. 'PHUIListItemView objects, but got a surprise.')); } } public function getConfigureURI() { $mode = $this->getEditMode(); switch ($mode) { case self::MODE_CUSTOM: return $this->getItemURI('configure/custom/'); case self::MODE_GLOBAL: return $this->getItemURI('configure/global/'); } return $this->getItemURI('configure/'); } private function buildItemReorderContent(array $items) { $viewer = $this->getViewer(); $object = $this->getProfileObject(); // If you're reordering global items, you need to be able to edit the // object the menu appears on. If you're reordering custom items, you only // need to be able to edit the custom object. Currently, the custom object // is always the viewing user's own user object. $custom_phid = $this->getEditModeCustomPHID(); if (!$custom_phid) { PhabricatorPolicyFilter::requireCapability( $viewer, $object, PhabricatorPolicyCapability::CAN_EDIT); } else { $policy_object = id(new PhabricatorObjectQuery()) ->setViewer($viewer) ->withPHIDs(array($custom_phid)) ->executeOne(); if (!$policy_object) { throw new Exception( pht( 'Failed to load custom PHID "%s"!', $custom_phid)); } PhabricatorPolicyFilter::requireCapability( $viewer, $policy_object, PhabricatorPolicyCapability::CAN_EDIT); } $controller = $this->getController(); $request = $controller->getRequest(); $request->validateCSRF(); $order = $request->getStrList('order'); $by_builtin = array(); $by_id = array(); foreach ($items as $key => $item) { $id = $item->getID(); if ($id) { $by_id[$id] = $key; continue; } $builtin_key = $item->getBuiltinKey(); if ($builtin_key) { $by_builtin[$builtin_key] = $key; continue; } } $key_order = array(); foreach ($order as $order_item) { if (isset($by_id[$order_item])) { $key_order[] = $by_id[$order_item]; continue; } if (isset($by_builtin[$order_item])) { $key_order[] = $by_builtin[$order_item]; continue; } } $items = array_select_keys($items, $key_order) + $items; $type_order = PhabricatorProfileMenuItemConfigurationTransaction::TYPE_ORDER; $order = 1; foreach ($items as $item) { $xactions = array(); $xactions[] = id(new PhabricatorProfileMenuItemConfigurationTransaction()) ->setTransactionType($type_order) ->setNewValue($order); $editor = id(new PhabricatorProfileMenuEditor()) ->setContentSourceFromRequest($request) ->setActor($viewer) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true) ->applyTransactions($item, $xactions); $order++; } return id(new AphrontRedirectResponse()) ->setURI($this->getConfigureURI()); } protected function buildItemViewContent( PhabricatorProfileMenuItemConfiguration $item) { return $item->newPageContent(); } private function getViewerEditModes() { $modes = array(); $viewer = $this->getViewer(); if ($viewer->isLoggedIn() && $this->isMenuEnginePersonalizable()) { $modes[] = self::MODE_CUSTOM; } $object = $this->getProfileObject(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $object, PhabricatorPolicyCapability::CAN_EDIT); if ($can_edit) { $modes[] = self::MODE_GLOBAL; } return $modes; } protected function isMenuEnginePersonalizable() { return true; } /** * Does this engine support pinning items? * * Personalizable menus disable pinning by default since it creates a number * of weird edge cases without providing many benefits for current menus. * * @return bool True if items may be pinned as default items. */ protected function isMenuEnginePinnable() { return !$this->isMenuEnginePersonalizable(); } private function buildMenuEditModeContent() { $viewer = $this->getViewer(); $modes = $this->getViewerEditModes(); if (!$modes) { return new Aphront404Response(); } if (count($modes) == 1) { $mode = head($modes); return id(new AphrontRedirectResponse()) ->setURI($this->getItemURI("configure/{$mode}/")); } $menu = id(new PHUIObjectItemListView()) ->setUser($viewer); $modes = array_fuse($modes); if (isset($modes['custom'])) { $menu->addItem( id(new PHUIObjectItemView()) ->setHeader(pht('Personal Menu Items')) ->setHref($this->getItemURI('configure/custom/')) ->setImageURI($viewer->getProfileImageURI()) ->addAttribute(pht('Edit the menu for your personal account.'))); } if (isset($modes['global'])) { $icon = id(new PHUIIconView()) ->setIcon('fa-globe') ->setBackground('bg-blue'); $menu->addItem( id(new PHUIObjectItemView()) ->setHeader(pht('Global Menu Items')) ->setHref($this->getItemURI('configure/global/')) ->setImageIcon($icon) ->addAttribute(pht('Edit the global default menu for all users.'))); } $box = id(new PHUIObjectBoxView()) ->setObjectList($menu); $header = id(new PHUIHeaderView()) ->setHeader(pht('Manage Menu')) ->setHeaderIcon('fa-list'); return id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter($box); } private function buildItemConfigureContent(array $items) { $viewer = $this->getViewer(); $object = $this->getProfileObject(); $filtered_groups = mgroup($items, 'getMenuItemKey'); foreach ($filtered_groups as $group) { $first_item = head($group); $first_item->willBuildNavigationItems($group); } // Users only need to be able to edit the object which this menu appears // on if they're editing global menu items. For example, users do not need // to be able to edit the Favorites application to add new items to the // Favorites menu. if (!$this->getCustomPHID()) { PhabricatorPolicyFilter::requireCapability( $viewer, $object, PhabricatorPolicyCapability::CAN_EDIT); } $list_id = celerity_generate_unique_node_id(); $mode = $this->getEditMode(); Javelin::initBehavior( 'reorder-profile-menu-items', array( 'listID' => $list_id, 'orderURI' => $this->getItemURI("reorder/{$mode}/"), )); $list = id(new PHUIObjectItemListView()) ->setID($list_id) ->setNoDataString(pht('This menu currently has no items.')); + $any_draggable = false; foreach ($items as $item) { $id = $item->getID(); $builtin_key = $item->getBuiltinKey(); $can_edit = PhabricatorPolicyFilter::hasCapability( $viewer, $item, PhabricatorPolicyCapability::CAN_EDIT); $view = id(new PHUIObjectItemView()); $name = $item->getDisplayName(); $type = $item->getMenuItemTypeName(); if (!strlen(trim($name))) { $name = pht('Untitled "%s" Item', $type); } $view->setHeader($name); $view->addAttribute($type); + $icon = $item->getMenuItem()->getMenuItemTypeIcon(); + if ($icon !== null) { + $view->setStatusIcon($icon); + } + if ($can_edit) { - $view - ->setGrippable(true) - ->addSigil('profile-menu-item') - ->setMetadata( - array( - 'key' => nonempty($id, $builtin_key), - )); + $can_move = (!$item->getIsHeadItem() && !$item->getIsTailItem()); + if ($can_move) { + $view + ->setGrippable(true) + ->addSigil('profile-menu-item') + ->setMetadata( + array( + 'key' => nonempty($id, $builtin_key), + )); + $any_draggable = true; + } else { + $view->setGrippable(false); + } if ($id) { $default_uri = $this->getItemURI("default/{$id}/"); } else { $default_uri = $this->getItemURI("default/{$builtin_key}/"); } $default_text = null; if ($this->isMenuEnginePinnable()) { if ($item->isDefault()) { $default_icon = 'fa-thumb-tack green'; $default_text = pht('Current Default'); } else if ($item->canMakeDefault()) { $default_icon = 'fa-thumb-tack'; $default_text = pht('Make Default'); } } if ($default_text !== null) { $view->addAction( id(new PHUIListItemView()) ->setHref($default_uri) ->setWorkflow(true) ->setName($default_text) ->setIcon($default_icon)); } if ($id) { $view->setHref($this->getItemURI("edit/{$id}/")); $hide_uri = $this->getItemURI("hide/{$id}/"); } else { $view->setHref($this->getItemURI("builtin/{$builtin_key}/")); $hide_uri = $this->getItemURI("hide/{$builtin_key}/"); } if ($item->isDisabled()) { $hide_icon = 'fa-plus'; $hide_text = pht('Enable'); } else if ($item->getBuiltinKey() !== null) { $hide_icon = 'fa-times'; $hide_text = pht('Disable'); } else { $hide_icon = 'fa-times'; $hide_text = pht('Delete'); } $can_disable = $item->canHideMenuItem(); $view->addAction( id(new PHUIListItemView()) ->setHref($hide_uri) ->setWorkflow(true) ->setDisabled(!$can_disable) ->setName($hide_text) ->setIcon($hide_icon)); } if ($item->isDisabled()) { $view->setDisabled(true); } $list->addItem($view); } $item_types = PhabricatorProfileMenuItem::getAllMenuItems(); $object = $this->getProfileObject(); $action_list = id(new PhabricatorActionListView()) ->setViewer($viewer); // See T12167. This makes the "Actions" dropdown button show up in the // page header. $action_list->setID(celerity_generate_unique_node_id()); $action_list->addAction( id(new PhabricatorActionView()) ->setLabel(true) ->setName(pht('Add New Menu Item...'))); foreach ($item_types as $item_type) { if (!$item_type->canAddToObject($object)) { continue; } $item_key = $item_type->getMenuItemKey(); $edit_mode = $this->getEditMode(); $action_list->addAction( id(new PhabricatorActionView()) ->setIcon($item_type->getMenuItemTypeIcon()) ->setName($item_type->getMenuItemTypeName()) ->setHref($this->getItemURI("new/{$edit_mode}/{$item_key}/")) ->setWorkflow(true)); } $action_list->addAction( id(new PhabricatorActionView()) ->setLabel(true) ->setName(pht('Documentation'))); $doc_link = PhabricatorEnv::getDoclink('Profile Menu User Guide'); $doc_name = pht('Profile Menu User Guide'); $action_list->addAction( id(new PhabricatorActionView()) ->setIcon('fa-book') ->setHref($doc_link) ->setName($doc_name)); $header = id(new PHUIHeaderView()) ->setHeader(pht('Menu Items')) ->setHeaderIcon('fa-list'); + $list_header = id(new PHUIHeaderView()) + ->setHeader(pht('Current Menu Items')); + + if ($any_draggable) { + $list_header->setSubheader( + pht('Drag items in this list to reorder them.')); + } + $box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Current Menu Items')) + ->setHeader($list_header) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setObjectList($list); $curtain = id(new PHUICurtainView()) ->setViewer($viewer) ->setActionList($action_list); $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setCurtain($curtain) ->setMainColumn( array( $box, )); return $view; } private function buildItemNewContent($item_key, $mode) { $item_types = PhabricatorProfileMenuItem::getAllMenuItems(); $item_type = idx($item_types, $item_key); if (!$item_type) { return new Aphront404Response(); } $object = $this->getProfileObject(); if (!$item_type->canAddToObject($object)) { return new Aphront404Response(); } $custom_phid = $this->getEditModeCustomPHID(); $configuration = PhabricatorProfileMenuItemConfiguration::initializeNewItem( $object, $item_type, $custom_phid); $viewer = $this->getViewer(); PhabricatorPolicyFilter::requireCapability( $viewer, $configuration, PhabricatorPolicyCapability::CAN_EDIT); $controller = $this->getController(); return id(new PhabricatorProfileMenuEditEngine()) ->setMenuEngine($this) ->setProfileObject($object) ->setNewMenuItemConfiguration($configuration) ->setCustomPHID($custom_phid) ->setController($controller) ->buildResponse(); } private function buildItemEditContent() { $viewer = $this->getViewer(); $object = $this->getProfileObject(); $controller = $this->getController(); $custom_phid = $this->getEditModeCustomPHID(); return id(new PhabricatorProfileMenuEditEngine()) ->setMenuEngine($this) ->setProfileObject($object) ->setController($controller) ->setCustomPHID($custom_phid) ->buildResponse(); } private function buildItemBuiltinContent( PhabricatorProfileMenuItemConfiguration $configuration) { // If this builtin item has already been persisted, redirect to the // edit page. $id = $configuration->getID(); if ($id) { return id(new AphrontRedirectResponse()) ->setURI($this->getItemURI("edit/{$id}/")); } // Otherwise, act like we're creating a new item, we're just starting // with the builtin template. $viewer = $this->getViewer(); PhabricatorPolicyFilter::requireCapability( $viewer, $configuration, PhabricatorPolicyCapability::CAN_EDIT); $object = $this->getProfileObject(); $controller = $this->getController(); $custom_phid = $this->getEditModeCustomPHID(); return id(new PhabricatorProfileMenuEditEngine()) ->setIsBuiltin(true) ->setMenuEngine($this) ->setProfileObject($object) ->setNewMenuItemConfiguration($configuration) ->setController($controller) ->setCustomPHID($custom_phid) ->buildResponse(); } private function buildItemHideContent( PhabricatorProfileMenuItemConfiguration $configuration) { $controller = $this->getController(); $request = $controller->getRequest(); $viewer = $this->getViewer(); PhabricatorPolicyFilter::requireCapability( $viewer, $configuration, PhabricatorPolicyCapability::CAN_EDIT); if (!$configuration->canHideMenuItem()) { return $controller->newDialog() ->setTitle(pht('Mandatory Item')) ->appendParagraph( pht('This menu item is very important, and can not be disabled.')) ->addCancelButton($this->getConfigureURI()); } if ($configuration->getBuiltinKey() === null) { $new_value = null; $title = pht('Delete Menu Item'); $body = pht('Delete this menu item?'); $button = pht('Delete Menu Item'); } else if ($configuration->isDisabled()) { $new_value = PhabricatorProfileMenuItemConfiguration::VISIBILITY_VISIBLE; $title = pht('Enable Menu Item'); $body = pht( 'Enable this menu item? It will appear in the menu again.'); $button = pht('Enable Menu Item'); } else { $new_value = PhabricatorProfileMenuItemConfiguration::VISIBILITY_DISABLED; $title = pht('Disable Menu Item'); $body = pht( 'Disable this menu item? It will no longer appear in the menu, but '. 'you can re-enable it later.'); $button = pht('Disable Menu Item'); } $v_visibility = $configuration->getVisibility(); if ($request->isFormPost()) { if ($new_value === null) { $configuration->delete(); } else { $type_visibility = PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY; $xactions = array(); $xactions[] = id(new PhabricatorProfileMenuItemConfigurationTransaction()) ->setTransactionType($type_visibility) ->setNewValue($new_value); $editor = id(new PhabricatorProfileMenuEditor()) ->setContentSourceFromRequest($request) ->setActor($viewer) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true) ->applyTransactions($configuration, $xactions); } return id(new AphrontRedirectResponse()) ->setURI($this->getConfigureURI()); } return $controller->newDialog() ->setTitle($title) ->appendParagraph($body) ->addCancelButton($this->getConfigureURI()) ->addSubmitButton($button); } private function buildItemDefaultContent( PhabricatorProfileMenuItemConfiguration $configuration, array $items) { $controller = $this->getController(); $request = $controller->getRequest(); $viewer = $this->getViewer(); PhabricatorPolicyFilter::requireCapability( $viewer, $configuration, PhabricatorPolicyCapability::CAN_EDIT); $done_uri = $this->getConfigureURI(); if (!$configuration->canMakeDefault()) { return $controller->newDialog() ->setTitle(pht('Not Defaultable')) ->appendParagraph( pht( 'This item can not be set as the default item. This is usually '. 'because the item has no page of its own, or links to an '. 'external page.')) ->addCancelButton($done_uri); } if ($configuration->isDefault()) { return $controller->newDialog() ->setTitle(pht('Already Default')) ->appendParagraph( pht( 'This item is already set as the default item for this menu.')) ->addCancelButton($done_uri); } if ($request->isFormPost()) { $key = $configuration->getID(); if (!$key) { $key = $configuration->getBuiltinKey(); } $this->adjustDefault($key); return id(new AphrontRedirectResponse()) ->setURI($done_uri); } return $controller->newDialog() ->setTitle(pht('Make Default')) ->appendParagraph( pht( 'Set this item as the default for this menu? Users arriving on '. 'this page will be shown the content of this item by default.')) ->addCancelButton($done_uri) ->addSubmitButton(pht('Make Default')); } protected function newItem() { return PhabricatorProfileMenuItemConfiguration::initializeNewBuiltin(); } protected function newManageItem() { return $this->newItem() ->setBuiltinKey(self::ITEM_MANAGE) - ->setMenuItemKey(PhabricatorManageProfileMenuItem::MENUITEMKEY); + ->setMenuItemKey(PhabricatorManageProfileMenuItem::MENUITEMKEY) + ->setIsTailItem(true); } public function adjustDefault($key) { $controller = $this->getController(); $request = $controller->getRequest(); $viewer = $request->getViewer(); $items = $this->loadItems(self::MODE_COMBINED); // To adjust the default item, we first change any existing items that // are marked as defaults to "visible", then make the new default item // the default. $default = array(); $visible = array(); foreach ($items as $item) { $builtin_key = $item->getBuiltinKey(); $id = $item->getID(); $is_target = (($builtin_key !== null) && ($builtin_key === $key)) || (($id !== null) && ((int)$id === (int)$key)); if ($is_target) { if (!$item->isDefault()) { $default[] = $item; } } else { if ($item->isDefault()) { $visible[] = $item; } } } $type_visibility = PhabricatorProfileMenuItemConfigurationTransaction::TYPE_VISIBILITY; $v_visible = PhabricatorProfileMenuItemConfiguration::VISIBILITY_VISIBLE; $v_default = PhabricatorProfileMenuItemConfiguration::VISIBILITY_DEFAULT; $apply = array( array($v_visible, $visible), array($v_default, $default), ); foreach ($apply as $group) { list($value, $items) = $group; foreach ($items as $item) { $xactions = array(); $xactions[] = id(new PhabricatorProfileMenuItemConfigurationTransaction()) ->setTransactionType($type_visibility) ->setNewValue($value); $editor = id(new PhabricatorProfileMenuEditor()) ->setContentSourceFromRequest($request) ->setActor($viewer) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true) ->applyTransactions($item, $xactions); } } return $this; } private function arrangeItems(array $items, $mode) { // Sort the items. $items = msortv($items, 'getSortVector'); $object = $this->getProfileObject(); // If we have some global items and some custom items and are in "combined" // mode, put a hard-coded divider item between them. if ($mode == self::MODE_COMBINED) { $list = array(); $seen_custom = false; $seen_global = false; foreach ($items as $item) { if ($item->getCustomPHID()) { $seen_custom = true; } else { if ($seen_custom && !$seen_global) { $list[] = $this->newItem() ->setBuiltinKey(self::ITEM_CUSTOM_DIVIDER) ->setMenuItemKey(PhabricatorDividerProfileMenuItem::MENUITEMKEY) ->attachProfileObject($object) ->attachMenuItem( new PhabricatorDividerProfileMenuItem()); } $seen_global = true; } $list[] = $item; } $items = $list; } // Normalize keys since callers shouldn't rely on this array being // partially keyed. $items = array_values($items); return $items; } final protected function newEmptyView($title, $message) { return id(new PHUIInfoView()) ->setTitle($title) ->setSeverity(PHUIInfoView::SEVERITY_NODATA) ->setErrors( array( $message, )); } protected function newNoMenuItemsView() { return $this->newEmptyView( pht('No Menu Items'), pht('There are no menu items.')); } private function pickDefaultItem(array $items) { // Remove all the items which can not be the default item. foreach ($items as $key => $item) { if (!$item->canMakeDefault()) { unset($items[$key]); continue; } if ($item->isDisabled()) { unset($items[$key]); continue; } } // If this engine supports pinning items and a valid item is pinned, // pick that item as the default. if ($this->isMenuEnginePinnable()) { foreach ($items as $key => $item) { if ($item->isDefault()) { return $item; } } } // If we have some other valid items, pick the first one as the default. if ($items) { return head($items); } return null; } private function pickSelectedItem(array $items, $item_id, $is_view) { if (strlen($item_id)) { $item_id_int = (int)$item_id; foreach ($items as $item) { if ($item_id_int) { if ((int)$item->getID() === $item_id_int) { return $item; } } $builtin_key = $item->getBuiltinKey(); if ($builtin_key === (string)$item_id) { return $item; } } // Nothing matches the selected item ID, so we don't have a valid // selection. return null; } if ($is_view) { return $this->pickDefaultItem($items); } return null; } private function pickHighlightedMenuItem( array $items, PhabricatorProfileMenuItemConfiguration $selected_item = null) { assert_instances_of($items, 'PHUIListItemView'); $default_key = null; if ($selected_item) { $default_key = $selected_item->getDefaultMenuItemKey(); } $controller = $this->getController(); // In some rare cases, when like building the "Favorites" menu on a // 404 page, we may not have a controller. Just accept whatever default // behavior we'd otherwise end up with. if (!$controller) { return $default_key; } $request = $controller->getRequest(); // See T12949. If one of the menu items is a link to the same URI that // the page was accessed with, we want to highlight that item. For example, // this allows you to add links to a menu that apply filters to a // workboard. $matches = array(); foreach ($items as $item) { $href = $item->getHref(); if ($this->isMatchForRequestURI($request, $href)) { $matches[] = $item; } } foreach ($matches as $match) { if ($match->getKey() === $default_key) { return $default_key; } } if ($matches) { return head($matches)->getKey(); } return $default_key; } private function isMatchForRequestURI(AphrontRequest $request, $item_uri) { $request_uri = $request->getAbsoluteRequestURI(); $item_uri = new PhutilURI($item_uri); // If the request URI and item URI don't have matching paths, they // do not match. if ($request_uri->getPath() !== $item_uri->getPath()) { return false; } // If the request URI and item URI don't have matching parameters, they // also do not match. We're specifically trying to let "?filter=X" work // on Workboards, among other use cases, so this is important. $request_params = $request_uri->getQueryParamsAsPairList(); $item_params = $item_uri->getQueryParamsAsPairList(); if ($request_params !== $item_params) { return false; } // If the paths and parameters match, the item domain must be: empty; or // match the request domain; or match the production domain. $request_domain = $request_uri->getDomain(); $production_uri = PhabricatorEnv::getProductionURI('/'); $production_domain = id(new PhutilURI($production_uri)) ->getDomain(); $allowed_domains = array( '', $request_domain, $production_domain, ); $allowed_domains = array_fuse($allowed_domains); $item_domain = $item_uri->getDomain(); $item_domain = (string)$item_domain; if (isset($allowed_domains[$item_domain])) { return true; } return false; } } diff --git a/src/applications/search/menuitem/PhabricatorLabelProfileMenuItem.php b/src/applications/search/menuitem/PhabricatorLabelProfileMenuItem.php index 1f769905d7..605098f216 100644 --- a/src/applications/search/menuitem/PhabricatorLabelProfileMenuItem.php +++ b/src/applications/search/menuitem/PhabricatorLabelProfileMenuItem.php @@ -1,75 +1,75 @@ getLabelName($config); } public function buildEditEngineFields( PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey(self::FIELD_NAME) ->setLabel(pht('Name')) ->setIsRequired(true) ->setValue($this->getLabelName($config)), ); } private function getLabelName( PhabricatorProfileMenuItemConfiguration $config) { return $config->getMenuItemProperty('name'); } protected function newNavigationMenuItems( PhabricatorProfileMenuItemConfiguration $config) { $name = $this->getLabelName($config); $item = $this->newItem() ->setName($name) ->setType(PHUIListItemView::TYPE_LABEL); return array( $item, ); } public function validateTransactions( PhabricatorProfileMenuItemConfiguration $config, $field_key, $value, array $xactions) { $viewer = $this->getViewer(); $errors = array(); if ($field_key == self::FIELD_NAME) { if ($this->isEmptyTransaction($value, $xactions)) { $errors[] = $this->newRequiredError( pht('You must choose a label name.'), $field_key); } } return $errors; } } diff --git a/src/applications/search/menuitem/PhabricatorManageProfileMenuItem.php b/src/applications/search/menuitem/PhabricatorManageProfileMenuItem.php index d5de555975..2d882ae2c8 100644 --- a/src/applications/search/menuitem/PhabricatorManageProfileMenuItem.php +++ b/src/applications/search/menuitem/PhabricatorManageProfileMenuItem.php @@ -1,72 +1,76 @@ getMenuItemProperty('name'); if (strlen($name)) { return $name; } return $this->getDefaultName(); } public function buildEditEngineFields( PhabricatorProfileMenuItemConfiguration $config) { return array( id(new PhabricatorTextEditField()) ->setKey('name') ->setLabel(pht('Name')) ->setPlaceholder($this->getDefaultName()) ->setValue($config->getMenuItemProperty('name')), ); } protected function newNavigationMenuItems( PhabricatorProfileMenuItemConfiguration $config) { $viewer = $this->getViewer(); if (!$viewer->isLoggedIn()) { return array(); } $engine = $this->getEngine(); $href = $engine->getItemURI('configure/'); $name = $this->getDisplayName($config); $icon = 'fa-pencil'; $item = $this->newItem() ->setHref($href) ->setName($name) ->setIcon($icon); return array( $item, ); } } diff --git a/src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php b/src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php index 8520cac1bd..4a23655d54 100644 --- a/src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php +++ b/src/applications/search/storage/PhabricatorProfileMenuItemConfiguration.php @@ -1,272 +1,303 @@ setVisibility(self::VISIBILITY_VISIBLE); } public static function initializeNewItem( $profile_object, PhabricatorProfileMenuItem $item, $custom_phid) { return self::initializeNewBuiltin() ->setProfilePHID($profile_object->getPHID()) ->setMenuItemKey($item->getMenuItemKey()) ->attachMenuItem($item) ->attachProfileObject($profile_object) ->setCustomPHID($custom_phid); } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_SERIALIZATION => array( 'menuItemProperties' => self::SERIALIZATION_JSON, ), self::CONFIG_COLUMN_SCHEMA => array( 'menuItemKey' => 'text64', 'builtinKey' => 'text64?', 'menuItemOrder' => 'uint32?', 'customPHID' => 'phid?', 'visibility' => 'text32', ), self::CONFIG_KEY_SCHEMA => array( 'key_profile' => array( 'columns' => array('profilePHID', 'menuItemOrder'), ), ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorProfileMenuItemPHIDType::TYPECONST); } public function attachMenuItem(PhabricatorProfileMenuItem $item) { $this->menuItem = $item; return $this; } public function getMenuItem() { return $this->assertAttached($this->menuItem); } public function attachProfileObject($profile_object) { $this->profileObject = $profile_object; return $this; } public function getProfileObject() { return $this->assertAttached($this->profileObject); } public function setMenuItemProperty($key, $value) { $this->menuItemProperties[$key] = $value; return $this; } public function getMenuItemProperty($key, $default = null) { return idx($this->menuItemProperties, $key, $default); } public function buildNavigationMenuItems() { return $this->getMenuItem()->buildNavigationMenuItems($this); } public function getMenuItemTypeName() { return $this->getMenuItem()->getMenuItemTypeName(); } public function getDisplayName() { return $this->getMenuItem()->getDisplayName($this); } public function canMakeDefault() { return $this->getMenuItem()->canMakeDefault($this); } public function canHideMenuItem() { return $this->getMenuItem()->canHideMenuItem($this); } public function shouldEnableForObject($object) { return $this->getMenuItem()->shouldEnableForObject($object); } public function willBuildNavigationItems(array $items) { return $this->getMenuItem()->willBuildNavigationItems($items); } public function validateTransactions(array $map) { $item = $this->getMenuItem(); $fields = $item->buildEditEngineFields($this); $errors = array(); foreach ($fields as $field) { $field_key = $field->getKey(); $xactions = idx($map, $field_key, array()); $value = $this->getMenuItemProperty($field_key); $field_errors = $item->validateTransactions( $this, $field_key, $value, $xactions); foreach ($field_errors as $error) { $errors[] = $error; } } return $errors; } public function getSortVector() { // Sort custom items above global items. if ($this->getCustomPHID()) { $is_global = 0; } else { $is_global = 1; } + // Sort "head" items above other items and "tail" items after other items. + if ($this->getIsHeadItem()) { + $force_position = 0; + } else if ($this->getIsTailItem()) { + $force_position = 2; + } else { + $force_position = 1; + } + // Sort items with an explicit order above items without an explicit order, // so any newly created builtins go to the bottom. $order = $this->getMenuItemOrder(); if ($order !== null) { $has_order = 0; } else { $has_order = 1; } return id(new PhutilSortVector()) ->addInt($is_global) + ->addInt($force_position) ->addInt($has_order) ->addInt((int)$order) ->addInt((int)$this->getID()); } public function isDisabled() { if (!$this->canHideMenuItem()) { return false; } return ($this->getVisibility() === self::VISIBILITY_DISABLED); } public function isDefault() { return ($this->getVisibility() === self::VISIBILITY_DEFAULT); } public function getItemIdentifier() { $id = $this->getID(); if ($id) { return (int)$id; } return $this->getBuiltinKey(); } public function getDefaultMenuItemKey() { if ($this->getBuiltinKey()) { return $this->getBuiltinKey(); } return $this->getPHID(); } public function newPageContent() { return $this->getMenuItem()->newPageContent($this); } + public function setIsHeadItem($is_head_item) { + $this->isHeadItem = $is_head_item; + return $this; + } + + public function getIsHeadItem() { + return $this->isHeadItem; + } + + public function setIsTailItem($is_tail_item) { + $this->isTailItem = $is_tail_item; + return $this; + } + + public function getIsTailItem() { + return $this->isTailItem; + } + + /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { return PhabricatorPolicies::getMostOpenPolicy(); } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return $this->getProfileObject()->hasAutomaticCapability( $capability, $viewer); } /* -( PhabricatorExtendedPolicyInterface )--------------------------------- */ public function getExtendedPolicy($capability, PhabricatorUser $viewer) { // If this is an item with a custom PHID (like a personal menu item), // we only require that the user can edit the corresponding custom // object (usually their own user profile), not the object that the // menu appears on (which may be an Application like Favorites or Home). if ($capability == PhabricatorPolicyCapability::CAN_EDIT) { if ($this->getCustomPHID()) { return array( array( $this->getCustomPHID(), $capability, ), ); } } return array( array( $this->getProfileObject(), $capability, ), ); } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new PhabricatorProfileMenuEditor(); } public function getApplicationTransactionTemplate() { return new PhabricatorProfileMenuItemConfigurationTransaction(); } } diff --git a/src/view/phui/PHUIObjectItemView.php b/src/view/phui/PHUIObjectItemView.php index 463f34a2a0..40dd8f0a4b 100644 --- a/src/view/phui/PHUIObjectItemView.php +++ b/src/view/phui/PHUIObjectItemView.php @@ -1,843 +1,849 @@ disabled = $disabled; return $this; } public function getDisabled() { return $this->disabled; } public function addHeadIcon($icon) { $this->headIcons[] = $icon; return $this; } public function setObjectName($name) { $this->objectName = $name; return $this; } public function setGrippable($grippable) { $this->grippable = $grippable; return $this; } public function getGrippable() { return $this->grippable; } public function setEffect($effect) { $this->effect = $effect; return $this; } public function getEffect() { return $this->effect; } public function setObject($object) { $this->object = $object; return $this; } public function getObject() { return $this->object; } public function setHref($href) { $this->href = $href; return $this; } public function getHref() { return $this->href; } public function setHeader($header) { $this->header = $header; return $this; } public function setSubHead($subhead) { $this->subhead = $subhead; return $this; } public function setBadge(PHUIBadgeMiniView $badge) { $this->badge = $badge; return $this; } public function setCountdown($num, $noun) { $this->countdownNum = $num; $this->countdownNoun = $noun; return $this; } public function setTitleText($title_text) { $this->titleText = $title_text; return $this; } public function getTitleText() { return $this->titleText; } public function getHeader() { return $this->header; } public function addByline($byline) { $this->bylines[] = $byline; return $this; } public function setImageURI($image_uri) { $this->imageURI = $image_uri; return $this; } public function setImageHref($image_href) { $this->imageHref = $image_href; return $this; } public function getImageURI() { return $this->imageURI; } public function setImageIcon($image_icon) { if (!$image_icon instanceof PHUIIconView) { $image_icon = id(new PHUIIconView()) ->setIcon($image_icon); } $this->imageIcon = $image_icon; return $this; } public function getImageIcon() { return $this->imageIcon; } public function setCoverImage($image) { $this->coverImage = $image; return $this; } public function setDescription($description) { $this->description = $description; return $this; } public function setSelectable( $name, $value, $is_selected, $is_forbidden = false) { $this->selectableName = $name; $this->selectableValue = $value; $this->isSelected = $is_selected; $this->isForbidden = $is_forbidden; return $this; } public function setClickable($clickable) { $this->clickable = $clickable; return $this; } public function getClickable() { return $this->clickable; } public function setEpoch($epoch) { $date = phabricator_datetime($epoch, $this->getUser()); $this->addIcon('none', $date); return $this; } public function addAction(PHUIListItemView $action) { if (count($this->actions) >= 3) { throw new Exception(pht('Limit 3 actions per item.')); } $this->actions[] = $action; return $this; } public function addIcon($icon, $label = null, $attributes = array()) { $this->icons[] = array( 'icon' => $icon, 'label' => $label, 'attributes' => $attributes, ); return $this; } /** * This method has been deprecated, use @{method:setImageIcon} instead. * * @deprecated */ public function setIcon($icon) { phlog( pht('Deprecated call to setIcon(), use setImageIcon() instead.')); return $this->setImageIcon($icon); } public function setStatusIcon($icon, $label = null) { $this->statusIcon = array( 'icon' => $icon, 'label' => $label, ); return $this; } public function addHandleIcon( PhabricatorObjectHandle $handle, $label = null) { $this->handleIcons[] = array( 'icon' => $handle, 'label' => $label, ); return $this; } public function setBarColor($bar_color) { $this->barColor = $bar_color; return $this; } public function getBarColor() { return $this->barColor; } public function addAttribute($attribute) { if (!empty($attribute)) { $this->attributes[] = $attribute; } return $this; } public function setSideColumn($column) { $this->sideColumn = $column; return $this; } protected function getTagName() { return 'li'; } protected function getTagAttributes() { $sigils = array(); $item_classes = array(); $item_classes[] = 'phui-oi'; if ($this->icons) { $item_classes[] = 'phui-oi-with-icons'; } if ($this->attributes) { $item_classes[] = 'phui-oi-with-attrs'; } if ($this->handleIcons) { $item_classes[] = 'phui-oi-with-handle-icons'; } if ($this->barColor) { $item_classes[] = 'phui-oi-bar-color-'.$this->barColor; } else { $item_classes[] = 'phui-oi-no-bar'; } if ($this->actions) { $n = count($this->actions); $item_classes[] = 'phui-oi-with-actions'; $item_classes[] = 'phui-oi-with-'.$n.'-actions'; } if ($this->disabled) { $item_classes[] = 'phui-oi-disabled'; } switch ($this->effect) { case 'highlighted': $item_classes[] = 'phui-oi-highlighted'; break; case 'selected': $item_classes[] = 'phui-oi-selected'; break; case 'visited': $item_classes[] = 'phui-oi-visited'; break; case null: break; default: throw new Exception(pht('Invalid effect!')); } if ($this->isForbidden) { $item_classes[] = 'phui-oi-forbidden'; } else if ($this->isSelected) { $item_classes[] = 'phui-oi-selected'; } if ($this->selectableName !== null && !$this->isForbidden) { $item_classes[] = 'phui-oi-selectable'; $sigils[] = 'phui-oi-selectable'; Javelin::initBehavior('phui-selectable-list'); } - if ($this->getGrippable()) { - $item_classes[] = 'phui-oi-grippable'; + $is_grippable = $this->getGrippable(); + if ($is_grippable !== null) { + $item_classes[] = 'phui-oi-has-grip'; + if ($is_grippable) { + $item_classes[] = 'phui-oi-grippable'; + } else { + $item_classes[] = 'phui-oi-ungrippable'; + } } if ($this->getImageURI()) { $item_classes[] = 'phui-oi-with-image'; } if ($this->getImageIcon()) { $item_classes[] = 'phui-oi-with-image-icon'; } if ($this->getClickable()) { Javelin::initBehavior('linked-container'); $item_classes[] = 'phui-oi-linked-container'; $sigils[] = 'linked-container'; } return array( 'class' => $item_classes, 'sigil' => $sigils, ); } protected function getTagContent() { $viewer = $this->getUser(); $content_classes = array(); $content_classes[] = 'phui-oi-content'; $header_name = array(); if ($viewer) { $header_name[] = id(new PHUISpacesNamespaceContextView()) ->setUser($viewer) ->setObject($this->object); } if ($this->objectName) { $header_name[] = array( phutil_tag( 'span', array( 'class' => 'phui-oi-objname', ), $this->objectName), ' ', ); } $title_text = null; if ($this->titleText) { $title_text = $this->titleText; } else if ($this->href) { $title_text = $this->header; } $header_link = phutil_tag( $this->href ? 'a' : 'div', array( 'href' => $this->href, 'class' => 'phui-oi-link', 'title' => $title_text, ), $this->header); $description_tag = null; if ($this->description) { $decription_id = celerity_generate_unique_node_id(); $description_tag = id(new PHUITagView()) ->setIcon('fa-ellipsis-h') ->addClass('phui-oi-description-tag') ->setType(PHUITagView::TYPE_SHADE) ->setColor(PHUITagView::COLOR_GREY) ->addSigil('jx-toggle-class') ->setSlimShady(true) ->setMetaData(array( 'map' => array( $decription_id => 'phui-oi-description-reveal', ), )); } $header = phutil_tag( 'div', array( 'class' => 'phui-oi-name', ), array( $this->headIcons, $header_name, $header_link, $description_tag, )); $icons = array(); if ($this->icons) { $icon_list = array(); foreach ($this->icons as $spec) { $icon = $spec['icon']; $icon = id(new PHUIIconView()) ->setIcon($icon) ->addClass('phui-oi-icon-image'); if (isset($spec['attributes']['tip'])) { $sigil = 'has-tooltip'; $meta = array( 'tip' => $spec['attributes']['tip'], 'align' => 'W', ); $icon->addSigil($sigil); $icon->setMetadata($meta); } $label = phutil_tag( 'span', array( 'class' => 'phui-oi-icon-label', ), $spec['label']); $classes = array(); $classes[] = 'phui-oi-icon'; if (isset($spec['attributes']['class'])) { $classes[] = $spec['attributes']['class']; } $icon_list[] = javelin_tag( 'li', array( 'class' => implode(' ', $classes), ), array( $icon, $label, )); } $icons[] = phutil_tag( 'ul', array( 'class' => 'phui-oi-icons', ), $icon_list); } $handle_bar = null; if ($this->handleIcons) { $handle_bar = array(); foreach ($this->handleIcons as $handleicon) { $handle_bar[] = $this->renderHandleIcon($handleicon['icon'], $handleicon['label']); } $handle_bar = phutil_tag( 'li', array( 'class' => 'phui-oi-handle-icons', ), $handle_bar); } $bylines = array(); if ($this->bylines) { foreach ($this->bylines as $byline) { $bylines[] = phutil_tag( 'div', array( 'class' => 'phui-oi-byline', ), $byline); } $bylines = phutil_tag( 'div', array( 'class' => 'phui-oi-bylines', ), $bylines); } $subhead = null; if ($this->subhead) { $subhead = phutil_tag( 'div', array( 'class' => 'phui-oi-subhead', ), $this->subhead); } if ($this->description) { $subhead = phutil_tag( 'div', array( 'class' => 'phui-oi-subhead phui-oi-description', 'id' => $decription_id, ), $this->description); } if ($icons) { $icons = phutil_tag( 'div', array( 'class' => 'phui-object-icon-pane', ), $icons); } $attrs = null; if ($this->attributes || $handle_bar) { $attrs = array(); $spacer = phutil_tag( 'span', array( 'class' => 'phui-oi-attribute-spacer', ), "\xC2\xB7"); $first = true; foreach ($this->attributes as $attribute) { $attrs[] = phutil_tag( 'li', array( 'class' => 'phui-oi-attribute', ), array( ($first ? null : $spacer), $attribute, )); $first = false; } $attrs = phutil_tag( 'ul', array( 'class' => 'phui-oi-attributes', ), array( $handle_bar, $attrs, )); } $status = null; if ($this->statusIcon) { $icon = $this->statusIcon; $status = $this->renderStatusIcon($icon['icon'], $icon['label']); } $grippable = null; - if ($this->getGrippable()) { + if ($this->getGrippable() !== null) { $grippable = phutil_tag( 'div', array( 'class' => 'phui-oi-grip', ), ''); } $content = phutil_tag( 'div', array( 'class' => implode(' ', $content_classes), ), array( $subhead, $attrs, $this->renderChildren(), )); $image = null; if ($this->getImageURI()) { $image = phutil_tag( 'div', array( 'class' => 'phui-oi-image', 'style' => 'background-image: url('.$this->getImageURI().')', ), ''); } else if ($this->getImageIcon()) { $image = phutil_tag( 'div', array( 'class' => 'phui-oi-image-icon', ), $this->getImageIcon()); } if ($image && (strlen($this->href) || strlen($this->imageHref))) { $image_href = ($this->imageHref) ? $this->imageHref : $this->href; $image = phutil_tag( 'a', array( 'href' => $image_href, ), $image); } /* Build a fake table */ $column0 = null; if ($status) { $column0 = phutil_tag( 'div', array( 'class' => 'phui-oi-col0', ), $status); } if ($this->badge) { $column0 = phutil_tag( 'div', array( 'class' => 'phui-oi-col0 phui-oi-badge', ), $this->badge); } if ($this->countdownNum) { $countdown = phutil_tag( 'div', array( 'class' => 'phui-oi-countdown-number', ), array( phutil_tag_div('', $this->countdownNum), phutil_tag_div('', $this->countdownNoun), )); $column0 = phutil_tag( 'div', array( 'class' => 'phui-oi-col0 phui-oi-countdown', ), $countdown); } if ($this->selectableName !== null) { if (!$this->isForbidden) { $checkbox = phutil_tag( 'input', array( 'type' => 'checkbox', 'name' => $this->selectableName, 'value' => $this->selectableValue, 'checked' => ($this->isSelected ? 'checked' : null), )); } else { $checkbox = null; } $column0 = phutil_tag( 'div', array( 'class' => 'phui-oi-col0 phui-oi-checkbox', ), $checkbox); } $column1 = phutil_tag( 'div', array( 'class' => 'phui-oi-col1', ), array( $header, $content, )); $column2 = null; if ($icons || $bylines) { $column2 = phutil_tag( 'div', array( 'class' => 'phui-oi-col2', ), array( $icons, $bylines, )); } /* Fixed width, right column container. */ $column3 = null; if ($this->sideColumn) { $column3 = phutil_tag( 'div', array( 'class' => 'phui-oi-col2 phui-oi-side-column', ), array( $this->sideColumn, )); } $table = phutil_tag( 'div', array( 'class' => 'phui-oi-table', ), phutil_tag_div( 'phui-oi-table-row', array( $column0, $column1, $column2, $column3, ))); $box = phutil_tag( 'div', array( 'class' => 'phui-oi-content-box', ), array( $grippable, $table, )); $actions = array(); if ($this->actions) { Javelin::initBehavior('phabricator-tooltips'); foreach (array_reverse($this->actions) as $action) { $action->setRenderNameAsTooltip(true); $actions[] = $action; } $actions = phutil_tag( 'ul', array( 'class' => 'phui-oi-actions', ), $actions); } $frame_content = phutil_tag( 'div', array( 'class' => 'phui-oi-frame-content', ), array( $actions, $image, $box, )); $frame_cover = null; if ($this->coverImage) { $cover_image = phutil_tag( 'img', array( 'src' => $this->coverImage, 'class' => 'phui-oi-cover-image', )); $frame_cover = phutil_tag( 'div', array( 'class' => 'phui-oi-frame-cover', ), $cover_image); } $frame = phutil_tag( 'div', array( 'class' => 'phui-oi-frame', ), array( $frame_cover, $frame_content, )); return $frame; } private function renderStatusIcon($icon, $label) { Javelin::initBehavior('phabricator-tooltips'); $icon = id(new PHUIIconView()) ->setIcon($icon); $options = array( 'class' => 'phui-oi-status-icon', ); if (strlen($label)) { $options['sigil'] = 'has-tooltip'; $options['meta'] = array('tip' => $label, 'size' => 300); } return javelin_tag('div', $options, $icon); } private function renderHandleIcon(PhabricatorObjectHandle $handle, $label) { Javelin::initBehavior('phabricator-tooltips'); $options = array( 'class' => 'phui-oi-handle-icon', 'style' => 'background-image: url('.$handle->getImageURI().')', ); if (strlen($label)) { $options['sigil'] = 'has-tooltip'; $options['meta'] = array('tip' => $label, 'align' => 'E'); } return javelin_tag('span', $options, ''); } } diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css b/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css index 67d0682aa7..d8ac3a8bbb 100644 --- a/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css +++ b/webroot/rsrc/css/phui/object-item/phui-oi-list-view.css @@ -1,728 +1,732 @@ /** * @provides phui-oi-list-view-css */ .phui-oi { border-left-width: 0; } ul.phui-oi-list-view { padding: 8px; list-style: none; } .device-desktop .phui-oi-list-view { padding: 16px; } .phui-oi-list-view + .phui-oi-list-view { padding-top: 0; } .phui-object-box .phui-oi-list-view .phui-oi { margin: 0; } .phui-oi-list-view .phui-info-view { margin: 0; } .phui-object-box .phui-oi-list-view .phui-info-view { color: {$greytext}; border: none; } .phui-oi { border-style: solid; border-color: {$lightgreyborder}; margin: 5px 0; overflow: hidden; background: {$page.content}; margin-bottom: 4px; } .phui-oi .phui-icon-view { display: inline-block; } .phui-oi-frame { border-color: {$lightblueborder}; border-width: 1px 1px 1px 0; border-style: solid; position: relative; min-height: 33px; overflow: hidden; } .phui-oi-cover-image { display: none; } .phui-oi-no-bar .phui-oi-frame { border-width: 1px; } .device-desktop .phui-oi { margin: 0 0 4px 0; } .phui-object-box .phui-oi-list-view { margin: 0; } .phui-oi-status-icon { font-weight: bold; padding: 3px; font-size: 16px; } .phui-oi-list-view .phui-oi-col0 .phui-icon-view { width: 17px; text-align: center; overflow: visible; position: relative; left: -1px; } .phui-oi-name { padding: 8px 8px 0; white-space: nowrap; word-wrap: break-word; overflow: hidden; text-overflow: ellipsis; font-weight: bold; -webkit-font-smoothing: antialiased; } .device-phone .phui-oi-name { overflow: normal; white-space: normal; font-weight: bold; } .phui-oi-link { display: inline; } .phui-oi-objname { color: {$blacktext}; cursor: text; font-weight: bold; } .phui-oi-content { margin: 4px 8px 2px 0; overflow: hidden; } .phui-oi-grippable { cursor: move; } .device .phui-oi-grippable { cursor: normal; } .phui-oi-grip { position: absolute; top: 0; bottom: 0; left: 0; width: 20px; background: url('/rsrc/image/texture/grip.png') center center no-repeat; } +.phui-oi-ungrippable .phui-oi-grip { + opacity: 0.25; +} + .device .phui-oi-grip { display: none; } -.phui-oi-grippable .phui-oi-frame { +.phui-oi-has-grip .phui-oi-frame { padding-left: 16px; } .device .phui-oi-grippable .phui-oi-frame { padding-left: 0; } .phui-oi-list-header { padding: 0 0 8px 0; color: {$darkgreytext}; } .phui-oi-table { display: table; table-layout: fixed; width: 100%; } .phui-oi-table-row { display: table-row; } .phui-oi-col0 { width: 20px; display: table-cell; vertical-align: middle; padding-left: 4px; } .device-phone .phui-oi-col0 { vertical-align: top; padding-top: 8px; } .phui-oi-col1 { display: table-cell; vertical-align: top; } .phui-oi-col2 { width: 160px; display: table-cell; vertical-align: top; } .phui-oi-col2.phui-oi-side-column { width: 200px; } .device-phone .phui-oi-col1, .device-phone .phui-oi-col2 { display: block; width: auto; } /* - Item Actions -------------------------------------------------------------- Action buttons, like "Edit" and "Delete". */ .phui-oi-actions { position: absolute; right: 4px; top: 4px; bottom: 4px; vertical-align: middle; text-align: right; } .phui-oi-actions .phui-list-item-view { float: right; height: 100%; width: 24px; display: inline-block; position: relative; } .phui-oi-actions .phui-list-item-href { display: inline-block; position: relative; width: 24px; height: 100%; } .device-desktop .phui-oi-actions .phui-list-item-href:hover { background: {$hoverblue}; border-radius: 3px; } .phui-oi-actions .phui-list-item-icon { width: 14px; height: 14px; position: absolute; display: block; top: 50%; margin-top: -7px; left: 3px; } .phui-oi-actions .phui-list-item-name { display: none; } .phui-oi-with-1-actions .phui-oi-content-box { margin-right: 28px; overflow: hidden; } .phui-oi-with-2-actions .phui-oi-content-box { margin-right: 54px; overflow: hidden; } .phui-oi-with-3-actions .phui-oi-content-box { margin-right: 76px; overflow: hidden; } /* - Object Box List ----------------------------------------------------------- Tighter, stacking list when inside an Object Box */ .phui-object-box .phui-oi-list-view { padding: 0; border: none; } .phui-object-box .phui-oi-frame { border-right: none; } .phui-object-box .phui-oi:last-child .phui-oi-frame { border-bottom: none; } /* - Subhead ------------------------------------------------------------------- Descriptive Text or Links under the main header, before attributes. */ .phui-oi-subhead { color: {$greytext}; padding: 0 8px 6px; } .phui-oi-description { display: none; } .phui-oi-description.phui-oi-description-reveal { display: block; } .phui-oi-description-tag { margin-left: 4px; } .phui-oi-description-tag:hover .phui-tag-core { cursor: pointer; background: {$darkgreybackground}; } .phui-oi-description-tag .phui-tag-core { border: none; } .phui-oi-description-tag.phui-tag-view .phui-icon-view { margin: 2px; } /* - Attribute List ------------------------------------------------------------ Object attributes, commonly used to render created date, etc. */ .phui-oi-attributes { padding: 0 8px 6px; line-height: 18px; min-height: 21px; } .phui-oi-attribute { display: inline-block; color: {$greytext}; vertical-align: top; margin-right: 4px; } .phui-oi-attribute-spacer { padding: 0 4px; } /* - Icons --------------------------------------------------------------------- Icons, which show object state. On mobile, they are rendered without labels to save space. */ .phui-object-icon-pane { margin: 8px 0 4px; } .device-phone .phui-object-icon-pane { margin: 0 0 4px; } .phui-oi-icons { padding: 0 4px 0 0; } .device-phone .phui-oi-icons { padding: 0 0 0 8px; } ul.phui-oi-icons { margin: 0; } .phui-oi-icon { vertical-align: middle; font-size: {$smallerfontsize}; color: {$greytext}; text-align: right; white-space: nowrap; overflow: hidden; min-height: 18px; line-height: 18px; } .device-phone .phui-oi-icon { text-align: left; font-size: 13px; } /* * Items with icon 'none' still have on mobile, thus creating a weird vertical * margin for elements which follow */ .device-phone .phui-oi-icon .none { display: none; } .phui-oi-icon-image { width: 14px; height: 14px; font-size: 13px; margin-right: 4px; } /* - Disabled ------------------------------------------------------------------ Disabled/inactive objects. */ .phui-oi.phui-oi-disabled .phui-oi-link, .phui-oi.phui-oi-disabled .phui-oi-link a { color: {$lightgreytext}; } .phui-oi.phui-oi-disabled .phui-oi-frame { border-color: #d7d7d7; } .phui-oi.phui-oi-disabled .phui-oi-objname { color: {$greytext}; text-decoration: line-through; } .phui-oi.phui-oi-disabled .phui-oi-image { opacity: .8; -webkit-filter: grayscale(100%); filter: grayscale(100%); } .phui-oi.phui-oi-disabled .phui-oi-attribute, .phui-oi.phui-oi-disabled .phui-oi-attribute > .phui-icon-view { color: {$lightgreytext}; } /* - Effects ------------------------------------------------------------------- Effects like highlighted items. */ .phui-oi.phui-oi-highlighted { background: {$sh-yellowbackground}; } ul.phui-oi-list-view .phui-oi-highlighted .phui-oi-frame { border-color: {$sh-yellowborder}; } .phui-oi-selected { background: {$sh-bluebackground}; } ul.phui-oi-list-view .phui-oi-selected .phui-oi-frame { border-color: {$sh-blueborder}; } .phui-oi-forbidden { background: {$sh-redbackground}; } /* - Handle Icons -------------------------------------------------------------- Shows owners, reviewers, etc., using profile picture icons. */ .phui-oi-handle-icons { bottom: 0; right: 4px; position: absolute; } .phui-oi-handle-icon { width: 24px; height: 24px; display: inline-block; background-size: 100%; border-radius: 3px; background-repeat: no-repeat; } /* - Bylines ------------------------------------------------------------------- Shows owners, authors, reviewers, etc., in text. */ .phui-oi-bylines { padding: 0 4px 0 8px; margin: 4px 0 8px; font-size: {$smallerfontsize}; color: {$greytext}; text-align: right; } .phui-oi-byline { white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } .device-phone .phui-oi-bylines { float: none; text-align: left; padding: 0 8px; font-size: {$normalfontsize}; } /* - Draggable List ------------------------------------------------------------ These classes are applied by and/or provided for use with JX.DraggableList. */ .drag-ghost { position: relative; background: {$sh-indigobackground}; border-radius: 3px; margin-bottom: 4px; border: 1px dashed {$sh-indigoborder}; } .drag-dragging { opacity: 0.25; } .drag-sending { opacity: 0.5; } .drag-clone, .drag-frame { /* This allows mousewheel events to pass through the clone and frame while they are being dragged. Without this, the mousewheel does not work during a drag operation. */ pointer-events: none; } .drag-frame { position: fixed; overflow: hidden; left: 0; right: 0; top: 0; bottom: 0; } .drag-clone { position: absolute; list-style: none; } /* - Badges ---------------------------------------------------------------- */ .phui-oi-col0.phui-oi-badge { width: 28px; } .phui-oi-col0.phui-oi-badge .phui-icon-view { left: 0; } /* - Countdowns ------------------------------------------------------------ */ .phui-oi-col0.phui-oi-countdown { width: 52px; padding: 0; } .phui-oi-countdown .phui-oi-countdown-number { border-right: 1px solid {$thinblueborder}; text-align: center; color: {$bluetext}; } /* - Dashboards ------------------------------------------------------------ */ .phui-object-box .phui-oi-list-view .phui-oi-frame { border: none; border-bottom: 1px solid {$thinblueborder}; } .drag-clone.phui-oi-standard .phui-oi-frame { border: none; opacity: 0.8; background: {$sh-bluebackground}; } .phui-object-box .phui-oi-list-header { font-size: {$normalfontsize}; color: {$darkbluetext}; border-top: 1px solid {$thinblueborder}; border-bottom: 1px solid {$thinblueborder}; padding: 8px 12px; background-color: {$lightgreybackground}; } .phui-object-box .phui-header-shell + .phui-oi-list-view .phui-oi-list-header, .phui-object-box .phui-object-box-hidden-content + .phui-oi-list-view .phui-oi-list-header, .phui-object-box .phui-object-box-hidden-content + .phui-oi-list-header { border-top: none; } .dashboard-pane .phui-oi-empty .phui-info-view { border: none; margin: 0; } .device-desktop .aphront-multi-column-fluid .aphront-multi-column-2-up .aphront-multi-column-column-outer.third .phui-oi-col2 { display: none; } /* - Launcher List ---------------------------------------------------------- */ .phui-oi-image-icon { background: none; width: 40px; height: 40px; margin: 8px 6px; position: absolute; } .phui-oi-image-icon .phui-icon-view { position: absolute; width: 40px; height: 40px; font-size: 26px; text-align: center; line-height: 36px; } .phui-oi-image { width: 40px; height: 40px; border-radius: 3px; background-size: 100%; margin: 8px 6px; position: absolute; } .phui-oi-with-image-icon .phui-oi-frame, .phui-oi-with-image .phui-oi-frame { min-height: 52px; } .phui-oi-with-image-icon .phui-oi-content-box, .phui-oi-with-image .phui-oi-content-box { margin-left: 46px; } /* - Launcher Button -------------------------------------------------------- */ .phui-oi-col2.phui-oi-side-column { text-align: right; vertical-align: middle; padding-right: 4px; } .device-phone .phui-oi-col2.phui-oi-side-column { padding: 0 8px 8px; text-align: left; } .phui-oi-col0.phui-oi-checkbox { width: 28px; text-align: center; } .phui-oi-selectable { cursor: pointer; user-select: none; -webkit-user-select: none; } /* When the list selection state can be toggled on the client (as in the bulk editor), keep the border color consistent to make the interaction feel more robust. */ ul.phui-oi-list-view .phui-oi-selectable .phui-oi-frame { border-color: {$blueborder}; } .differential-revision-size { padding: 0 4px; border-radius: 4px; background: {$lightgreybackground}; cursor: pointer; } .differential-revision-size .phui-icon-view { margin: 0 1px 0 1px; font-size: 7px; position: relative; top: -2px; color: {$lightbluetext}; } .differential-revision-large { background: {$sh-orangebackground}; } /* NOTE: These are intentionally using nonstandard colors, see T13127. */ .differential-revision-large .phui-icon-view { color: #e5ae7e; } .differential-revision-small { background: #f2f7ff; } .differential-revision-small .phui-icon-view { color: #6699ba; } .phui-oi-tail { text-align: center; padding: 8px 0; background: linear-gradient({$lightbluebackground}, #fff 66%, #fff); }