diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 1e3629fe30..d2c7caaa9c 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -1,2274 +1,2274 @@ array( - 'core.pkg.css' => '8378907a', - 'core.pkg.js' => '5058979d', + 'core.pkg.css' => 'cc8abd0e', + 'core.pkg.js' => 'e0379ae5', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '2de124c9', 'differential.pkg.js' => '6223dd9d', 'diffusion.pkg.css' => 'f45955ed', 'diffusion.pkg.js' => 'ca1c8b5a', 'maniphest.pkg.css' => '4845691a', 'maniphest.pkg.js' => '949a7498', 'rsrc/css/aphront/aphront-bars.css' => '231ac33c', 'rsrc/css/aphront/dark-console.css' => '6378ef3d', 'rsrc/css/aphront/dialog-view.css' => 'be0e3a46', 'rsrc/css/aphront/lightbox-attachment.css' => '7acac05d', 'rsrc/css/aphront/list-filter-view.css' => '5d6f0526', 'rsrc/css/aphront/multi-column.css' => 'fd18389d', 'rsrc/css/aphront/notification.css' => '9c279160', 'rsrc/css/aphront/panel-view.css' => '8427b78d', 'rsrc/css/aphront/phabricator-nav-view.css' => 'a24cb589', 'rsrc/css/aphront/table-view.css' => '6d01d468', 'rsrc/css/aphront/tokenizer.css' => '056da01b', 'rsrc/css/aphront/tooltip.css' => '7672b60f', 'rsrc/css/aphront/typeahead-browse.css' => 'd8581d2c', 'rsrc/css/aphront/typeahead.css' => '0e403212', 'rsrc/css/application/almanac/almanac.css' => 'dbb9b3af', 'rsrc/css/application/auth/auth.css' => '0877ed6e', 'rsrc/css/application/base/main-menu-view.css' => '2f670a96', 'rsrc/css/application/base/notification-menu.css' => 'f31c0bde', 'rsrc/css/application/base/phabricator-application-launch-view.css' => '95351601', 'rsrc/css/application/base/phui-theme.css' => '6b451f24', 'rsrc/css/application/base/standard-page-view.css' => '3c99cdf4', 'rsrc/css/application/calendar/calendar-icon.css' => 'c69aa59f', 'rsrc/css/application/chatlog/chatlog.css' => 'd295b020', 'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4', 'rsrc/css/application/config/config-options.css' => '0ede4c9b', 'rsrc/css/application/config/config-template.css' => '8e6c6fcd', 'rsrc/css/application/config/config-welcome.css' => '6abd79be', 'rsrc/css/application/config/setup-issue.css' => 'db7e9c40', 'rsrc/css/application/config/unhandled-exception.css' => '4c96257a', 'rsrc/css/application/conpherence/durable-column.css' => '86396117', 'rsrc/css/application/conpherence/menu.css' => 'f99fee4c', 'rsrc/css/application/conpherence/message-pane.css' => '5897d3ac', 'rsrc/css/application/conpherence/notification.css' => '6cdcc253', 'rsrc/css/application/conpherence/transaction.css' => '85d0974c', 'rsrc/css/application/conpherence/update.css' => 'faf6be09', 'rsrc/css/application/conpherence/widget-pane.css' => '775eaaba', 'rsrc/css/application/contentsource/content-source-view.css' => '4b8b05d4', 'rsrc/css/application/countdown/timer.css' => 'e7544472', 'rsrc/css/application/daemon/bulk-job.css' => 'df9c1d4a', 'rsrc/css/application/dashboard/dashboard.css' => 'eb458607', 'rsrc/css/application/diff/inline-comment-summary.css' => '51efda3a', 'rsrc/css/application/differential/add-comment.css' => 'c47f8c40', 'rsrc/css/application/differential/changeset-view.css' => 'b6b0d1bb', 'rsrc/css/application/differential/core.css' => '7ac3cabc', 'rsrc/css/application/differential/phui-inline-comment.css' => '0fdb3667', 'rsrc/css/application/differential/revision-comment.css' => '14b8565a', 'rsrc/css/application/differential/revision-history.css' => '0e8eb855', 'rsrc/css/application/differential/revision-list.css' => 'f3c47d33', 'rsrc/css/application/differential/table-of-contents.css' => 'ae4b7a55', 'rsrc/css/application/diffusion/diffusion-icons.css' => '2941baf1', 'rsrc/css/application/diffusion/diffusion-readme.css' => '2106ea08', 'rsrc/css/application/diffusion/diffusion-source.css' => '075ba788', 'rsrc/css/application/feed/feed.css' => 'ecd4ec57', 'rsrc/css/application/files/global-drag-and-drop.css' => '697324ad', 'rsrc/css/application/flag/flag.css' => '5337623f', 'rsrc/css/application/harbormaster/harbormaster.css' => 'b0758ca5', 'rsrc/css/application/herald/herald-test.css' => 'a52e323e', 'rsrc/css/application/herald/herald.css' => '826075fa', 'rsrc/css/application/maniphest/batch-editor.css' => 'b0f0b6d5', 'rsrc/css/application/maniphest/report.css' => 'f6931fdf', 'rsrc/css/application/maniphest/task-edit.css' => 'fda62a9b', 'rsrc/css/application/maniphest/task-summary.css' => '11cc5344', 'rsrc/css/application/objectselector/object-selector.css' => '85ee8ce6', 'rsrc/css/application/owners/owners-path-editor.css' => '2f00933b', 'rsrc/css/application/paste/paste.css' => 'a5157c48', 'rsrc/css/application/people/people-profile.css' => '25970776', 'rsrc/css/application/phame/phame.css' => '164515da', 'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee', 'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49', 'rsrc/css/application/pholio/pholio.css' => '95174bdd', 'rsrc/css/application/phortune/phortune-credit-card-form.css' => '8391eb02', 'rsrc/css/application/phortune/phortune.css' => '9149f103', 'rsrc/css/application/phrequent/phrequent.css' => 'ffc185ad', 'rsrc/css/application/phriction/phriction-document-css.css' => 'd1861e06', 'rsrc/css/application/policy/policy-edit.css' => '815c66f7', 'rsrc/css/application/policy/policy-transaction-detail.css' => '82100a43', 'rsrc/css/application/policy/policy.css' => '957ea14c', 'rsrc/css/application/ponder/ponder-view.css' => '7b0df4da', 'rsrc/css/application/projects/project-icon.css' => '4e3eaa5a', 'rsrc/css/application/releeph/releeph-core.css' => '9b3c5733', 'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5', 'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd', 'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae', 'rsrc/css/application/search/search-results.css' => '7dea472c', 'rsrc/css/application/slowvote/slowvote.css' => 'da0afb1b', 'rsrc/css/application/tokens/tokens.css' => '3d0f239e', 'rsrc/css/application/uiexample/example.css' => '528b19de', 'rsrc/css/core/core.css' => 'a76cefc9', 'rsrc/css/core/remarkup.css' => '275e362f', 'rsrc/css/core/syntax.css' => '9fd11da8', 'rsrc/css/core/z-index.css' => '57ddcaa2', 'rsrc/css/diviner/diviner-shared.css' => 'aa3656aa', 'rsrc/css/font/font-aleo.css' => '8bdb2835', 'rsrc/css/font/font-awesome.css' => 'c43323c5', 'rsrc/css/font/font-lato.css' => 'c7ccd872', 'rsrc/css/font/phui-font-icon-base.css' => 'ecbbb4c2', 'rsrc/css/layout/phabricator-filetree-view.css' => 'fccf9f82', 'rsrc/css/layout/phabricator-hovercard-view.css' => '1239cd52', 'rsrc/css/layout/phabricator-side-menu-view.css' => 'bec2458e', 'rsrc/css/layout/phabricator-source-code-view.css' => 'cbeef983', 'rsrc/css/phui/calendar/phui-calendar-day.css' => 'd1cf6f93', 'rsrc/css/phui/calendar/phui-calendar-list.css' => 'c1c7f338', 'rsrc/css/phui/calendar/phui-calendar-month.css' => '476be7e0', 'rsrc/css/phui/calendar/phui-calendar.css' => 'ccabe893', 'rsrc/css/phui/phui-action-list.css' => 'c5eba19d', 'rsrc/css/phui/phui-action-panel.css' => '91c7b835', 'rsrc/css/phui/phui-badge.css' => 'f25c3476', 'rsrc/css/phui/phui-box.css' => 'a5bb366d', 'rsrc/css/phui/phui-button.css' => '16020a60', 'rsrc/css/phui/phui-crumbs-view.css' => '414406b5', 'rsrc/css/phui/phui-document-pro.css' => 'e0fad431', 'rsrc/css/phui/phui-document-summary.css' => '8c1e0aca', 'rsrc/css/phui/phui-document.css' => 'a4a1c3b9', 'rsrc/css/phui/phui-feed-story.css' => 'b7b26d23', 'rsrc/css/phui/phui-fontkit.css' => '9cda225e', 'rsrc/css/phui/phui-form-view.css' => 'cf7da606', - 'rsrc/css/phui/phui-form.css' => 'afdb2c6e', + 'rsrc/css/phui/phui-form.css' => '0b98e572', 'rsrc/css/phui/phui-header-view.css' => '55bb32dd', 'rsrc/css/phui/phui-icon.css' => 'b0a6b1b6', 'rsrc/css/phui/phui-image-mask.css' => '5a8b09c8', 'rsrc/css/phui/phui-info-panel.css' => '27ea50a1', 'rsrc/css/phui/phui-info-view.css' => '6d7c3509', 'rsrc/css/phui/phui-list.css' => '125599df', 'rsrc/css/phui/phui-object-box.css' => '407eaf5a', 'rsrc/css/phui/phui-object-item-list-view.css' => '26c30d3f', 'rsrc/css/phui/phui-pager.css' => 'bea33d23', 'rsrc/css/phui/phui-pinboard-view.css' => '2495140e', 'rsrc/css/phui/phui-property-list-view.css' => '27b2849e', 'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591', 'rsrc/css/phui/phui-spacing.css' => '042804d6', 'rsrc/css/phui/phui-status.css' => '888cedb8', 'rsrc/css/phui/phui-tag-view.css' => 'e60e227b', 'rsrc/css/phui/phui-text.css' => 'cf019f54', 'rsrc/css/phui/phui-timeline-view.css' => '2efceff8', 'rsrc/css/phui/phui-two-column-view.css' => '39ecafb1', 'rsrc/css/phui/phui-workboard-view.css' => '6704d68d', 'rsrc/css/phui/phui-workpanel-view.css' => 'adec7699', 'rsrc/css/sprite-login.css' => '60e8560e', 'rsrc/css/sprite-main-header.css' => 'f07bbb87', 'rsrc/css/sprite-menu.css' => '9dd65b92', 'rsrc/css/sprite-projects.css' => 'e5ad842a', 'rsrc/css/sprite-tokens.css' => '4f399012', 'rsrc/externals/font/aleo/aleo-bold.eot' => 'd3d3bed7', 'rsrc/externals/font/aleo/aleo-bold.svg' => '45899c8e', 'rsrc/externals/font/aleo/aleo-bold.ttf' => '4b08bef0', 'rsrc/externals/font/aleo/aleo-bold.woff' => '93b513a1', 'rsrc/externals/font/aleo/aleo-bold.woff2' => '75fbf322', 'rsrc/externals/font/aleo/aleo-regular.eot' => 'a4e29e2f', 'rsrc/externals/font/aleo/aleo-regular.svg' => '42a86f7a', 'rsrc/externals/font/aleo/aleo-regular.ttf' => '751e7479', 'rsrc/externals/font/aleo/aleo-regular.woff' => 'c3744be9', 'rsrc/externals/font/aleo/aleo-regular.woff2' => '851aa0ee', 'rsrc/externals/font/fontawesome/fontawesome-webfont.eot' => '346fbcc5', 'rsrc/externals/font/fontawesome/fontawesome-webfont.ttf' => '510fccb2', 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff' => '0334f580', 'rsrc/externals/font/fontawesome/fontawesome-webfont.woff2' => '45dca585', 'rsrc/externals/font/lato/lato-bold.eot' => '99fbcf8c', 'rsrc/externals/font/lato/lato-bold.svg' => '2aa83045', 'rsrc/externals/font/lato/lato-bold.ttf' => '0a7141f7', 'rsrc/externals/font/lato/lato-bold.woff' => 'f5db2061', 'rsrc/externals/font/lato/lato-bold.woff2' => '37a94ecd', 'rsrc/externals/font/lato/lato-bolditalic.eot' => 'b93389d0', 'rsrc/externals/font/lato/lato-bolditalic.svg' => '5442e1ef', 'rsrc/externals/font/lato/lato-bolditalic.ttf' => 'dad31252', 'rsrc/externals/font/lato/lato-bolditalic.woff' => 'e53bcf47', 'rsrc/externals/font/lato/lato-bolditalic.woff2' => 'd035007f', 'rsrc/externals/font/lato/lato-italic.eot' => '6a903f5d', 'rsrc/externals/font/lato/lato-italic.svg' => '0dc7cf2f', 'rsrc/externals/font/lato/lato-italic.ttf' => '629f64f0', 'rsrc/externals/font/lato/lato-italic.woff' => '678dc4bb', 'rsrc/externals/font/lato/lato-italic.woff2' => '7c8dd650', 'rsrc/externals/font/lato/lato-regular.eot' => '848dfb1e', 'rsrc/externals/font/lato/lato-regular.svg' => 'cbd5fd6b', 'rsrc/externals/font/lato/lato-regular.ttf' => 'e270165b', 'rsrc/externals/font/lato/lato-regular.woff' => '13d39fe2', 'rsrc/externals/font/lato/lato-regular.woff2' => '57a9f742', 'rsrc/externals/javelin/core/Event.js' => '85ea0626', 'rsrc/externals/javelin/core/Stratcom.js' => '6c53634d', 'rsrc/externals/javelin/core/__tests__/event-stop-and-kill.js' => '717554e4', 'rsrc/externals/javelin/core/__tests__/install.js' => 'c432ee85', 'rsrc/externals/javelin/core/__tests__/stratcom.js' => '88bf7313', 'rsrc/externals/javelin/core/__tests__/util.js' => 'e251703d', 'rsrc/externals/javelin/core/init.js' => '3010e992', 'rsrc/externals/javelin/core/init_node.js' => 'c234aded', 'rsrc/externals/javelin/core/install.js' => '05270951', 'rsrc/externals/javelin/core/util.js' => '93cc50d6', 'rsrc/externals/javelin/docs/Base.js' => '74676256', 'rsrc/externals/javelin/docs/onload.js' => 'e819c479', 'rsrc/externals/javelin/ext/fx/Color.js' => '7e41274a', 'rsrc/externals/javelin/ext/fx/FX.js' => '54b612ba', 'rsrc/externals/javelin/ext/reactor/core/DynVal.js' => 'f6555212', 'rsrc/externals/javelin/ext/reactor/core/Reactor.js' => '2b8de964', 'rsrc/externals/javelin/ext/reactor/core/ReactorNode.js' => '1ad0a787', 'rsrc/externals/javelin/ext/reactor/core/ReactorNodeCalmer.js' => '76f4ebed', 'rsrc/externals/javelin/ext/reactor/dom/RDOM.js' => 'c90a04fc', 'rsrc/externals/javelin/ext/view/HTMLView.js' => 'fe287620', 'rsrc/externals/javelin/ext/view/View.js' => '0f764c35', 'rsrc/externals/javelin/ext/view/ViewInterpreter.js' => 'f829edb3', 'rsrc/externals/javelin/ext/view/ViewPlaceholder.js' => '47830651', 'rsrc/externals/javelin/ext/view/ViewRenderer.js' => '6c2b09a2', 'rsrc/externals/javelin/ext/view/ViewVisitor.js' => 'efe49472', 'rsrc/externals/javelin/ext/view/__tests__/HTMLView.js' => 'f92d7bcb', 'rsrc/externals/javelin/ext/view/__tests__/View.js' => '6450b38b', 'rsrc/externals/javelin/ext/view/__tests__/ViewInterpreter.js' => '7a94d6a5', 'rsrc/externals/javelin/ext/view/__tests__/ViewRenderer.js' => '6ea96ac9', 'rsrc/externals/javelin/lib/Cookie.js' => '62dfea03', 'rsrc/externals/javelin/lib/DOM.js' => '805b806a', 'rsrc/externals/javelin/lib/History.js' => 'd4505101', 'rsrc/externals/javelin/lib/JSON.js' => '69adf288', 'rsrc/externals/javelin/lib/Leader.js' => '331b1611', 'rsrc/externals/javelin/lib/Mask.js' => '8a41885b', 'rsrc/externals/javelin/lib/Quicksand.js' => '6b8ef10b', 'rsrc/externals/javelin/lib/Request.js' => '94b750d2', 'rsrc/externals/javelin/lib/Resource.js' => '44959b73', 'rsrc/externals/javelin/lib/Routable.js' => 'b3e7d692', 'rsrc/externals/javelin/lib/Router.js' => '29274e2b', 'rsrc/externals/javelin/lib/Scrollbar.js' => '087e919c', 'rsrc/externals/javelin/lib/Sound.js' => '949c0fe5', 'rsrc/externals/javelin/lib/URI.js' => 'c989ade3', 'rsrc/externals/javelin/lib/Vector.js' => '2caa8fb8', 'rsrc/externals/javelin/lib/WebSocket.js' => 'e292eaf4', 'rsrc/externals/javelin/lib/Workflow.js' => '5b2e3e2b', 'rsrc/externals/javelin/lib/__tests__/Cookie.js' => '5ed109e8', 'rsrc/externals/javelin/lib/__tests__/DOM.js' => 'c984504b', 'rsrc/externals/javelin/lib/__tests__/JSON.js' => '837a7d68', 'rsrc/externals/javelin/lib/__tests__/URI.js' => '1e45fda9', 'rsrc/externals/javelin/lib/__tests__/behavior.js' => '1ea62783', 'rsrc/externals/javelin/lib/behavior.js' => '61cbc29a', - 'rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js' => 'c431f925', + 'rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js' => '8d3bc1b2', 'rsrc/externals/javelin/lib/control/typeahead/Typeahead.js' => '70baed2f', 'rsrc/externals/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js' => 'e6e25838', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js' => '503e17fd', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js' => '8b3fd187', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js' => '54f314a0', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => '2818f5ce', 'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js' => '6c0e62fa', 'rsrc/externals/raphael/g.raphael.js' => '40dde778', 'rsrc/externals/raphael/g.raphael.line.js' => '40da039e', 'rsrc/externals/raphael/raphael.js' => '51ee6b43', 'rsrc/favicons/apple-touch-icon-120x120.png' => '43742962', 'rsrc/favicons/apple-touch-icon-152x152.png' => '669eaec3', 'rsrc/favicons/apple-touch-icon-76x76.png' => 'ecdef672', 'rsrc/favicons/favicon-128.png' => '47cdff03', 'rsrc/favicons/favicon-16x16.png' => 'ee2523ac', 'rsrc/favicons/favicon-32x32.png' => 'b6a8150e', 'rsrc/favicons/favicon-96x96.png' => '8f7ea177', 'rsrc/favicons/mask-icon.svg' => '0460cb1f', 'rsrc/image/BFCFDA.png' => 'd5ec91f4', 'rsrc/image/actions/edit.png' => '2fc41442', 'rsrc/image/avatar.png' => 'e132bb6a', 'rsrc/image/checker_dark.png' => 'd8e65881', 'rsrc/image/checker_light.png' => 'a0155918', 'rsrc/image/checker_lighter.png' => 'd5da91b6', 'rsrc/image/darkload.gif' => '1ffd3ec6', 'rsrc/image/divot.png' => '94dded62', 'rsrc/image/examples/hero.png' => '979a86ae', 'rsrc/image/grippy_texture.png' => 'aca81e2f', 'rsrc/image/icon/fatcow/arrow_branch.png' => '2537c01c', 'rsrc/image/icon/fatcow/arrow_merge.png' => '21b660e0', 'rsrc/image/icon/fatcow/bullet_black.png' => 'ff190031', 'rsrc/image/icon/fatcow/bullet_orange.png' => 'e273e5bb', 'rsrc/image/icon/fatcow/bullet_red.png' => 'c0b75434', 'rsrc/image/icon/fatcow/calendar_edit.png' => '24632275', 'rsrc/image/icon/fatcow/document_black.png' => '45fe1c60', 'rsrc/image/icon/fatcow/flag_blue.png' => 'a01abb1d', 'rsrc/image/icon/fatcow/flag_finish.png' => '67825cee', 'rsrc/image/icon/fatcow/flag_ghost.png' => '20ca8783', 'rsrc/image/icon/fatcow/flag_green.png' => '7e0eaa7a', 'rsrc/image/icon/fatcow/flag_orange.png' => '9e73df66', 'rsrc/image/icon/fatcow/flag_pink.png' => '7e92f3b2', 'rsrc/image/icon/fatcow/flag_purple.png' => 'cc517522', 'rsrc/image/icon/fatcow/flag_red.png' => '04ec726f', 'rsrc/image/icon/fatcow/flag_yellow.png' => '73946fd4', 'rsrc/image/icon/fatcow/key_question.png' => '52a0c26a', 'rsrc/image/icon/fatcow/link.png' => '7afd4d5e', 'rsrc/image/icon/fatcow/page_white_edit.png' => '39a2eed8', 'rsrc/image/icon/fatcow/page_white_put.png' => '08c95a0c', 'rsrc/image/icon/fatcow/source/conduit.png' => '4ea01d2f', 'rsrc/image/icon/fatcow/source/email.png' => '9bab3239', 'rsrc/image/icon/fatcow/source/fax.png' => '04195e68', 'rsrc/image/icon/fatcow/source/mobile.png' => 'f1321264', 'rsrc/image/icon/fatcow/source/tablet.png' => '49396799', 'rsrc/image/icon/fatcow/source/web.png' => '136ccb5d', 'rsrc/image/icon/lightbox/close-2.png' => 'cc40e7c8', 'rsrc/image/icon/lightbox/close-hover-2.png' => 'fb5d6d9e', 'rsrc/image/icon/lightbox/left-arrow-2.png' => '8426133b', 'rsrc/image/icon/lightbox/left-arrow-hover-2.png' => '701e5ee3', 'rsrc/image/icon/lightbox/right-arrow-2.png' => '6d5519a0', 'rsrc/image/icon/lightbox/right-arrow-hover-2.png' => '3a04aa21', 'rsrc/image/icon/subscribe.png' => 'd03ed5a5', 'rsrc/image/icon/tango/attachment.png' => 'ecc8022e', 'rsrc/image/icon/tango/edit.png' => '929a1363', 'rsrc/image/icon/tango/go-down.png' => '96d95e43', 'rsrc/image/icon/tango/log.png' => 'b08cc63a', 'rsrc/image/icon/tango/upload.png' => '7bbb7984', 'rsrc/image/icon/unsubscribe.png' => '25725013', 'rsrc/image/lightblue-header.png' => '5c168b6d', 'rsrc/image/main_texture.png' => '29a2c5ad', 'rsrc/image/menu_texture.png' => '5a17580d', 'rsrc/image/people/harding.png' => '45aa614e', 'rsrc/image/people/jefferson.png' => 'afca0e53', 'rsrc/image/people/lincoln.png' => '9369126d', 'rsrc/image/people/mckinley.png' => 'fb8f16ce', 'rsrc/image/people/taft.png' => 'd7bc402c', 'rsrc/image/people/user0.png' => '03dacaea', 'rsrc/image/people/user1.png' => '4a4e7702', 'rsrc/image/people/user2.png' => '47a0ee40', 'rsrc/image/people/user3.png' => '835ff627', 'rsrc/image/people/user4.png' => 'b0e830f1', 'rsrc/image/people/user5.png' => '9c95b369', 'rsrc/image/people/user6.png' => 'ba3fbfb0', 'rsrc/image/people/user7.png' => 'da613924', 'rsrc/image/people/user8.png' => 'f1035edf', 'rsrc/image/people/user9.png' => '66730be3', 'rsrc/image/people/washington.png' => '40dd301c', 'rsrc/image/phrequent_active.png' => 'a466a8ed', 'rsrc/image/phrequent_inactive.png' => 'bfc15a69', 'rsrc/image/sprite-login-X2.png' => 'e3991e37', 'rsrc/image/sprite-login.png' => '03d5af29', 'rsrc/image/sprite-main-header.png' => '3673af44', 'rsrc/image/sprite-menu-X2.png' => 'cfd8fca5', 'rsrc/image/sprite-menu.png' => 'd7a99faa', 'rsrc/image/sprite-projects-X2.png' => '853552c7', 'rsrc/image/sprite-projects.png' => 'b9dd74b8', 'rsrc/image/sprite-tokens-X2.png' => '348f1745', 'rsrc/image/sprite-tokens.png' => 'ce0b62be', 'rsrc/image/texture/card-gradient.png' => '815f26e8', 'rsrc/image/texture/dark-menu-hover.png' => '5fa7ece8', 'rsrc/image/texture/dark-menu.png' => '7e22296e', 'rsrc/image/texture/grip.png' => '719404f3', 'rsrc/image/texture/panel-header-gradient.png' => 'e3b8dcfe', 'rsrc/image/texture/phlnx-bg.png' => '8d819209', 'rsrc/image/texture/pholio-background.gif' => 'ba29239c', 'rsrc/image/texture/table_header.png' => '5c433037', 'rsrc/image/texture/table_header_hover.png' => '038ec3b9', 'rsrc/image/texture/table_header_tall.png' => 'd56b434f', 'rsrc/js/application/aphlict/Aphlict.js' => '5359e785', 'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => '031cee25', 'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'fb20ac8d', 'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'ea681761', 'rsrc/js/application/aphlict/behavior-desktop-notifications-control.js' => 'edd1ba66', 'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18', 'rsrc/js/application/calendar/behavior-day-view.js' => '5c46cff2', 'rsrc/js/application/calendar/behavior-event-all-day.js' => '38dcf3c8', 'rsrc/js/application/calendar/behavior-recurring-edit.js' => '5f1c4d5f', 'rsrc/js/application/config/behavior-reorder-fields.js' => 'b6993408', 'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => '01774ab2', 'rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js' => 'cf86d16a', 'rsrc/js/application/conpherence/behavior-durable-column.js' => 'c72aa091', 'rsrc/js/application/conpherence/behavior-menu.js' => '1d45c74d', 'rsrc/js/application/conpherence/behavior-pontificate.js' => '21ba5861', 'rsrc/js/application/conpherence/behavior-quicksand-blacklist.js' => '7927a7d3', 'rsrc/js/application/conpherence/behavior-widget-pane.js' => 'a8458711', 'rsrc/js/application/countdown/timer.js' => 'e4cc26b3', 'rsrc/js/application/daemon/behavior-bulk-job-reload.js' => 'edf8a145', 'rsrc/js/application/dashboard/behavior-dashboard-async-panel.js' => '469c0d9e', 'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => '82439934', 'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '453c5375', 'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => 'd4eecc63', 'rsrc/js/application/differential/ChangesetViewManager.js' => '58562350', 'rsrc/js/application/differential/DifferentialInlineCommentEditor.js' => '64a5550f', 'rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js' => 'e10f8e18', 'rsrc/js/application/differential/behavior-comment-jump.js' => '4fdb476d', 'rsrc/js/application/differential/behavior-comment-preview.js' => 'b064af76', 'rsrc/js/application/differential/behavior-diff-radios.js' => 'e1ff79b1', 'rsrc/js/application/differential/behavior-dropdown-menus.js' => '2035b9cb', 'rsrc/js/application/differential/behavior-edit-inline-comments.js' => '65ef6074', 'rsrc/js/application/differential/behavior-keyboard-nav.js' => '2c426492', 'rsrc/js/application/differential/behavior-populate.js' => '8694b1df', 'rsrc/js/application/differential/behavior-toggle-files.js' => 'ca3f91eb', 'rsrc/js/application/differential/behavior-user-select.js' => 'a8d8459d', 'rsrc/js/application/diffusion/DiffusionLocateFileSource.js' => 'b42eddc7', 'rsrc/js/application/diffusion/behavior-audit-preview.js' => 'd835b03a', 'rsrc/js/application/diffusion/behavior-commit-branches.js' => 'bdaf4d04', 'rsrc/js/application/diffusion/behavior-commit-graph.js' => '9007c197', 'rsrc/js/application/diffusion/behavior-jump-to.js' => '73d09eef', 'rsrc/js/application/diffusion/behavior-load-blame.js' => '42126667', 'rsrc/js/application/diffusion/behavior-locate-file.js' => '6d3e1947', 'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc', 'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => 'e5822781', 'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef', 'rsrc/js/application/files/behavior-icon-composer.js' => '8ef9ab58', 'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888', 'rsrc/js/application/herald/HeraldRuleEditor.js' => '5bd8f385', 'rsrc/js/application/herald/PathTypeahead.js' => 'f7fc67ec', 'rsrc/js/application/herald/herald-rule-editor.js' => '7ebaeed3', 'rsrc/js/application/maniphest/behavior-batch-editor.js' => '782ab6e7', 'rsrc/js/application/maniphest/behavior-batch-selector.js' => '7b98d7c5', 'rsrc/js/application/maniphest/behavior-line-chart.js' => '88f0c5b3', 'rsrc/js/application/maniphest/behavior-list-edit.js' => 'a9f88de2', 'rsrc/js/application/maniphest/behavior-subpriorityeditor.js' => '71237763', 'rsrc/js/application/owners/OwnersPathEditor.js' => 'aa1733d0', 'rsrc/js/application/owners/owners-path-editor.js' => '7a68dda3', 'rsrc/js/application/passphrase/passphrase-credential-control.js' => '3cb0b2fc', 'rsrc/js/application/pholio/behavior-pholio-mock-edit.js' => '246dc085', 'rsrc/js/application/pholio/behavior-pholio-mock-view.js' => 'fbe497e7', 'rsrc/js/application/phortune/behavior-stripe-payment-form.js' => '3f5d6dbf', 'rsrc/js/application/phortune/behavior-test-payment-form.js' => 'fc91ab6c', 'rsrc/js/application/phortune/phortune-credit-card-form.js' => '2290aeef', - 'rsrc/js/application/policy/behavior-policy-control.js' => '7d470398', + 'rsrc/js/application/policy/behavior-policy-control.js' => 'ae45872f', 'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '5e9f347c', 'rsrc/js/application/projects/behavior-project-boards.js' => 'ba4fa35c', 'rsrc/js/application/projects/behavior-project-create.js' => '065227cc', 'rsrc/js/application/projects/behavior-reorder-columns.js' => 'e1d25dfb', 'rsrc/js/application/releeph/releeph-preview-branch.js' => 'b2b4fbaf', 'rsrc/js/application/releeph/releeph-request-state-change.js' => 'a0b57eb8', 'rsrc/js/application/releeph/releeph-request-typeahead.js' => 'de2e896f', 'rsrc/js/application/repository/repository-crossreference.js' => 'e5339c43', 'rsrc/js/application/search/behavior-reorder-queries.js' => 'e9581f08', 'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => '887ad43f', 'rsrc/js/application/transactions/behavior-comment-actions.js' => 'bb0d2d0c', 'rsrc/js/application/transactions/behavior-reorder-configs.js' => 'd7a74243', 'rsrc/js/application/transactions/behavior-reorder-fields.js' => 'b59e1e96', 'rsrc/js/application/transactions/behavior-show-older-transactions.js' => 'dbbf48b6', 'rsrc/js/application/transactions/behavior-transaction-comment-form.js' => 'b23b49e6', 'rsrc/js/application/transactions/behavior-transaction-list.js' => '13c739ea', 'rsrc/js/application/typeahead/behavior-typeahead-browse.js' => '635de1ec', 'rsrc/js/application/typeahead/behavior-typeahead-search.js' => '93d0c9e3', 'rsrc/js/application/uiexample/JavelinViewExample.js' => 'd4a14807', 'rsrc/js/application/uiexample/ReactorButtonExample.js' => 'd19198c8', 'rsrc/js/application/uiexample/ReactorCheckboxExample.js' => '519705ea', 'rsrc/js/application/uiexample/ReactorFocusExample.js' => '40a6a403', 'rsrc/js/application/uiexample/ReactorInputExample.js' => '886fd850', 'rsrc/js/application/uiexample/ReactorMouseoverExample.js' => '47c794d8', 'rsrc/js/application/uiexample/ReactorRadioExample.js' => '988040b4', 'rsrc/js/application/uiexample/ReactorSelectExample.js' => 'a155550f', 'rsrc/js/application/uiexample/ReactorSendClassExample.js' => '1def2711', 'rsrc/js/application/uiexample/ReactorSendPropertiesExample.js' => 'b1f0ccee', 'rsrc/js/application/uiexample/busy-example.js' => '60479091', 'rsrc/js/application/uiexample/gesture-example.js' => '558829c2', 'rsrc/js/application/uiexample/notification-example.js' => '8ce821c5', 'rsrc/js/core/Busy.js' => '59a7976a', 'rsrc/js/core/DragAndDropFileUpload.js' => 'ad10aeac', 'rsrc/js/core/DraggableList.js' => 'a16ec1c6', 'rsrc/js/core/FileUpload.js' => '477359c8', 'rsrc/js/core/Hovercard.js' => '14ac66f5', 'rsrc/js/core/KeyboardShortcut.js' => '1ae869f2', 'rsrc/js/core/KeyboardShortcutManager.js' => 'c1700f6f', 'rsrc/js/core/MultirowRowManager.js' => 'b5d57730', 'rsrc/js/core/Notification.js' => 'ccf1cbf8', - 'rsrc/js/core/Prefab.js' => 'be38fe4e', + 'rsrc/js/core/Prefab.js' => '666c80c5', 'rsrc/js/core/ShapedRequest.js' => '7cbe244b', 'rsrc/js/core/TextAreaUtils.js' => '5c93c52c', 'rsrc/js/core/Title.js' => 'df5e11d2', 'rsrc/js/core/ToolTip.js' => '1d298e3a', 'rsrc/js/core/behavior-active-nav.js' => 'e379b58e', 'rsrc/js/core/behavior-audio-source.js' => '59b251eb', 'rsrc/js/core/behavior-autofocus.js' => '7319e029', 'rsrc/js/core/behavior-choose-control.js' => 'dfaafb14', 'rsrc/js/core/behavior-crop.js' => 'fa0f4fc2', 'rsrc/js/core/behavior-dark-console.js' => 'f411b6ae', 'rsrc/js/core/behavior-device.js' => 'a205cf28', 'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '6d49590e', 'rsrc/js/core/behavior-error-log.js' => '6882e80a', 'rsrc/js/core/behavior-fancy-datepicker.js' => '8ae55229', 'rsrc/js/core/behavior-file-tree.js' => '88236f00', 'rsrc/js/core/behavior-form.js' => '5c54cbf3', 'rsrc/js/core/behavior-gesture.js' => '3ab51e2c', 'rsrc/js/core/behavior-global-drag-and-drop.js' => 'c8e57404', 'rsrc/js/core/behavior-high-security-warning.js' => 'a464fe03', 'rsrc/js/core/behavior-history-install.js' => '7ee2b591', 'rsrc/js/core/behavior-hovercard.js' => 'f36e01af', 'rsrc/js/core/behavior-keyboard-pager.js' => 'a8da01f0', 'rsrc/js/core/behavior-keyboard-shortcuts.js' => 'd75709e6', 'rsrc/js/core/behavior-lightbox-attachments.js' => 'f8ba29d7', 'rsrc/js/core/behavior-line-linker.js' => '1499a8cb', 'rsrc/js/core/behavior-more.js' => 'a80d0378', 'rsrc/js/core/behavior-object-selector.js' => '49b73b36', 'rsrc/js/core/behavior-oncopy.js' => '2926fff2', 'rsrc/js/core/behavior-phabricator-nav.js' => '56a1ca03', - 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'eeaa9e5a', + 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => 'c14b5995', 'rsrc/js/core/behavior-refresh-csrf.js' => 'ab2f381b', 'rsrc/js/core/behavior-remarkup-preview.js' => 'f7379f45', 'rsrc/js/core/behavior-reorder-applications.js' => '76b9fc3e', 'rsrc/js/core/behavior-reveal-content.js' => '60821bc7', 'rsrc/js/core/behavior-scrollbar.js' => '834a1173', 'rsrc/js/core/behavior-search-typeahead.js' => '048330fa', 'rsrc/js/core/behavior-select-on-click.js' => '4e3e79a6', 'rsrc/js/core/behavior-time-typeahead.js' => 'f80d6bf0', 'rsrc/js/core/behavior-toggle-class.js' => '5d7c9f33', 'rsrc/js/core/behavior-tokenizer.js' => 'b3a4b884', 'rsrc/js/core/behavior-tooltip.js' => '3ee3408b', 'rsrc/js/core/behavior-watch-anchor.js' => '9f36c42d', 'rsrc/js/core/behavior-workflow.js' => '0a3f3021', 'rsrc/js/core/phtize.js' => 'd254d646', 'rsrc/js/phui/behavior-phui-dropdown-menu.js' => '54733475', 'rsrc/js/phui/behavior-phui-object-box-tabs.js' => '2bfa2836', 'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8', 'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262', 'rsrc/js/phuix/PHUIXDropdownMenu.js' => 'bd4c8dca', 'rsrc/js/phuix/PHUIXFormControl.js' => '8fba1997', 'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b', ), 'symbols' => array( 'almanac-css' => 'dbb9b3af', 'aphront-bars' => '231ac33c', 'aphront-dark-console-css' => '6378ef3d', 'aphront-dialog-view-css' => 'be0e3a46', 'aphront-list-filter-view-css' => '5d6f0526', 'aphront-multi-column-view-css' => 'fd18389d', 'aphront-panel-view-css' => '8427b78d', 'aphront-table-view-css' => '6d01d468', 'aphront-tokenizer-control-css' => '056da01b', 'aphront-tooltip-css' => '7672b60f', 'aphront-typeahead-control-css' => '0e403212', 'auth-css' => '0877ed6e', 'bulk-job-css' => 'df9c1d4a', 'calendar-icon-css' => 'c69aa59f', 'changeset-view-manager' => '58562350', 'conduit-api-css' => '7bc725c4', 'config-options-css' => '0ede4c9b', 'config-welcome-css' => '6abd79be', 'conpherence-durable-column-view' => '86396117', 'conpherence-menu-css' => 'f99fee4c', 'conpherence-message-pane-css' => '5897d3ac', 'conpherence-notification-css' => '6cdcc253', 'conpherence-thread-manager' => '01774ab2', 'conpherence-transaction-css' => '85d0974c', 'conpherence-update-css' => 'faf6be09', 'conpherence-widget-pane-css' => '775eaaba', 'differential-changeset-view-css' => 'b6b0d1bb', 'differential-core-view-css' => '7ac3cabc', 'differential-inline-comment-editor' => '64a5550f', 'differential-revision-add-comment-css' => 'c47f8c40', 'differential-revision-comment-css' => '14b8565a', 'differential-revision-history-css' => '0e8eb855', 'differential-revision-list-css' => 'f3c47d33', 'differential-table-of-contents-css' => 'ae4b7a55', 'diffusion-icons-css' => '2941baf1', 'diffusion-readme-css' => '2106ea08', 'diffusion-source-css' => '075ba788', 'diviner-shared-css' => 'aa3656aa', 'font-aleo' => '8bdb2835', 'font-fontawesome' => 'c43323c5', 'font-lato' => 'c7ccd872', 'global-drag-and-drop-css' => '697324ad', 'harbormaster-css' => 'b0758ca5', 'herald-css' => '826075fa', 'herald-rule-editor' => '5bd8f385', 'herald-test-css' => 'a52e323e', 'inline-comment-summary-css' => '51efda3a', 'javelin-aphlict' => '5359e785', 'javelin-behavior' => '61cbc29a', 'javelin-behavior-aphlict-dropdown' => '031cee25', 'javelin-behavior-aphlict-listen' => 'fb20ac8d', 'javelin-behavior-aphlict-status' => 'ea681761', 'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884', 'javelin-behavior-aphront-crop' => 'fa0f4fc2', 'javelin-behavior-aphront-drag-and-drop-textarea' => '6d49590e', 'javelin-behavior-aphront-form-disable-on-submit' => '5c54cbf3', 'javelin-behavior-aphront-more' => 'a80d0378', 'javelin-behavior-audio-source' => '59b251eb', 'javelin-behavior-audit-preview' => 'd835b03a', 'javelin-behavior-bulk-job-reload' => 'edf8a145', 'javelin-behavior-choose-control' => 'dfaafb14', 'javelin-behavior-comment-actions' => 'bb0d2d0c', 'javelin-behavior-config-reorder-fields' => 'b6993408', 'javelin-behavior-conpherence-drag-and-drop-photo' => 'cf86d16a', 'javelin-behavior-conpherence-menu' => '1d45c74d', 'javelin-behavior-conpherence-pontificate' => '21ba5861', 'javelin-behavior-conpherence-widget-pane' => 'a8458711', 'javelin-behavior-countdown-timer' => 'e4cc26b3', 'javelin-behavior-dark-console' => 'f411b6ae', 'javelin-behavior-dashboard-async-panel' => '469c0d9e', 'javelin-behavior-dashboard-move-panels' => '82439934', 'javelin-behavior-dashboard-query-panel-select' => '453c5375', 'javelin-behavior-dashboard-tab-panel' => 'd4eecc63', 'javelin-behavior-day-view' => '5c46cff2', 'javelin-behavior-desktop-notifications-control' => 'edd1ba66', 'javelin-behavior-device' => 'a205cf28', 'javelin-behavior-differential-add-reviewers-and-ccs' => 'e10f8e18', 'javelin-behavior-differential-comment-jump' => '4fdb476d', 'javelin-behavior-differential-diff-radios' => 'e1ff79b1', 'javelin-behavior-differential-dropdown-menus' => '2035b9cb', 'javelin-behavior-differential-edit-inline-comments' => '65ef6074', 'javelin-behavior-differential-feedback-preview' => 'b064af76', 'javelin-behavior-differential-keyboard-navigation' => '2c426492', 'javelin-behavior-differential-populate' => '8694b1df', 'javelin-behavior-differential-toggle-files' => 'ca3f91eb', 'javelin-behavior-differential-user-select' => 'a8d8459d', 'javelin-behavior-diffusion-commit-branches' => 'bdaf4d04', 'javelin-behavior-diffusion-commit-graph' => '9007c197', 'javelin-behavior-diffusion-jump-to' => '73d09eef', 'javelin-behavior-diffusion-locate-file' => '6d3e1947', 'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc', 'javelin-behavior-doorkeeper-tag' => 'e5822781', 'javelin-behavior-drydock-live-operation-status' => '901935ef', 'javelin-behavior-durable-column' => 'c72aa091', 'javelin-behavior-editengine-reorder-configs' => 'd7a74243', 'javelin-behavior-editengine-reorder-fields' => 'b59e1e96', 'javelin-behavior-error-log' => '6882e80a', 'javelin-behavior-event-all-day' => '38dcf3c8', 'javelin-behavior-fancy-datepicker' => '8ae55229', 'javelin-behavior-global-drag-and-drop' => 'c8e57404', 'javelin-behavior-herald-rule-editor' => '7ebaeed3', 'javelin-behavior-high-security-warning' => 'a464fe03', 'javelin-behavior-history-install' => '7ee2b591', 'javelin-behavior-icon-composer' => '8ef9ab58', 'javelin-behavior-launch-icon-composer' => '48086888', 'javelin-behavior-lightbox-attachments' => 'f8ba29d7', 'javelin-behavior-line-chart' => '88f0c5b3', 'javelin-behavior-load-blame' => '42126667', 'javelin-behavior-maniphest-batch-editor' => '782ab6e7', 'javelin-behavior-maniphest-batch-selector' => '7b98d7c5', 'javelin-behavior-maniphest-list-editor' => 'a9f88de2', 'javelin-behavior-maniphest-subpriority-editor' => '71237763', 'javelin-behavior-owners-path-editor' => '7a68dda3', 'javelin-behavior-passphrase-credential-control' => '3cb0b2fc', 'javelin-behavior-persona-login' => '9414ff18', 'javelin-behavior-phabricator-active-nav' => 'e379b58e', 'javelin-behavior-phabricator-autofocus' => '7319e029', 'javelin-behavior-phabricator-busy-example' => '60479091', 'javelin-behavior-phabricator-file-tree' => '88236f00', 'javelin-behavior-phabricator-gesture' => '3ab51e2c', 'javelin-behavior-phabricator-gesture-example' => '558829c2', 'javelin-behavior-phabricator-hovercards' => 'f36e01af', 'javelin-behavior-phabricator-keyboard-pager' => 'a8da01f0', 'javelin-behavior-phabricator-keyboard-shortcuts' => 'd75709e6', 'javelin-behavior-phabricator-line-linker' => '1499a8cb', 'javelin-behavior-phabricator-nav' => '56a1ca03', 'javelin-behavior-phabricator-notification-example' => '8ce821c5', 'javelin-behavior-phabricator-object-selector' => '49b73b36', 'javelin-behavior-phabricator-oncopy' => '2926fff2', - 'javelin-behavior-phabricator-remarkup-assist' => 'eeaa9e5a', + 'javelin-behavior-phabricator-remarkup-assist' => 'c14b5995', 'javelin-behavior-phabricator-reveal-content' => '60821bc7', 'javelin-behavior-phabricator-search-typeahead' => '048330fa', 'javelin-behavior-phabricator-show-older-transactions' => 'dbbf48b6', 'javelin-behavior-phabricator-tooltips' => '3ee3408b', 'javelin-behavior-phabricator-transaction-comment-form' => 'b23b49e6', 'javelin-behavior-phabricator-transaction-list' => '13c739ea', 'javelin-behavior-phabricator-watch-anchor' => '9f36c42d', 'javelin-behavior-pholio-mock-edit' => '246dc085', 'javelin-behavior-pholio-mock-view' => 'fbe497e7', 'javelin-behavior-phui-dropdown-menu' => '54733475', 'javelin-behavior-phui-object-box-tabs' => '2bfa2836', - 'javelin-behavior-policy-control' => '7d470398', + 'javelin-behavior-policy-control' => 'ae45872f', 'javelin-behavior-policy-rule-editor' => '5e9f347c', 'javelin-behavior-project-boards' => 'ba4fa35c', 'javelin-behavior-project-create' => '065227cc', 'javelin-behavior-quicksand-blacklist' => '7927a7d3', 'javelin-behavior-recurring-edit' => '5f1c4d5f', 'javelin-behavior-refresh-csrf' => 'ab2f381b', 'javelin-behavior-releeph-preview-branch' => 'b2b4fbaf', 'javelin-behavior-releeph-request-state-change' => 'a0b57eb8', 'javelin-behavior-releeph-request-typeahead' => 'de2e896f', 'javelin-behavior-remarkup-preview' => 'f7379f45', 'javelin-behavior-reorder-applications' => '76b9fc3e', 'javelin-behavior-reorder-columns' => 'e1d25dfb', 'javelin-behavior-repository-crossreference' => 'e5339c43', 'javelin-behavior-scrollbar' => '834a1173', 'javelin-behavior-search-reorder-queries' => 'e9581f08', 'javelin-behavior-select-on-click' => '4e3e79a6', 'javelin-behavior-slowvote-embed' => '887ad43f', 'javelin-behavior-stripe-payment-form' => '3f5d6dbf', 'javelin-behavior-test-payment-form' => 'fc91ab6c', 'javelin-behavior-time-typeahead' => 'f80d6bf0', 'javelin-behavior-toggle-class' => '5d7c9f33', 'javelin-behavior-typeahead-browse' => '635de1ec', 'javelin-behavior-typeahead-search' => '93d0c9e3', 'javelin-behavior-view-placeholder' => '47830651', 'javelin-behavior-workflow' => '0a3f3021', 'javelin-color' => '7e41274a', 'javelin-cookie' => '62dfea03', 'javelin-diffusion-locate-file-source' => 'b42eddc7', 'javelin-dom' => '805b806a', 'javelin-dynval' => 'f6555212', 'javelin-event' => '85ea0626', 'javelin-fx' => '54b612ba', 'javelin-history' => 'd4505101', 'javelin-install' => '05270951', 'javelin-json' => '69adf288', 'javelin-leader' => '331b1611', 'javelin-magical-init' => '3010e992', 'javelin-mask' => '8a41885b', 'javelin-quicksand' => '6b8ef10b', 'javelin-reactor' => '2b8de964', 'javelin-reactor-dom' => 'c90a04fc', 'javelin-reactor-node-calmer' => '76f4ebed', 'javelin-reactornode' => '1ad0a787', 'javelin-request' => '94b750d2', 'javelin-resource' => '44959b73', 'javelin-routable' => 'b3e7d692', 'javelin-router' => '29274e2b', 'javelin-scrollbar' => '087e919c', 'javelin-sound' => '949c0fe5', 'javelin-stratcom' => '6c53634d', - 'javelin-tokenizer' => 'c431f925', + 'javelin-tokenizer' => '8d3bc1b2', 'javelin-typeahead' => '70baed2f', 'javelin-typeahead-composite-source' => '503e17fd', 'javelin-typeahead-normalizer' => 'e6e25838', 'javelin-typeahead-ondemand-source' => '8b3fd187', 'javelin-typeahead-preloaded-source' => '54f314a0', 'javelin-typeahead-source' => '2818f5ce', 'javelin-typeahead-static-source' => '6c0e62fa', 'javelin-uri' => 'c989ade3', 'javelin-util' => '93cc50d6', 'javelin-vector' => '2caa8fb8', 'javelin-view' => '0f764c35', 'javelin-view-html' => 'fe287620', 'javelin-view-interpreter' => 'f829edb3', 'javelin-view-renderer' => '6c2b09a2', 'javelin-view-visitor' => 'efe49472', 'javelin-websocket' => 'e292eaf4', 'javelin-workflow' => '5b2e3e2b', 'lightbox-attachment-css' => '7acac05d', 'maniphest-batch-editor' => 'b0f0b6d5', 'maniphest-report-css' => 'f6931fdf', 'maniphest-task-edit-css' => 'fda62a9b', 'maniphest-task-summary-css' => '11cc5344', 'multirow-row-manager' => 'b5d57730', 'owners-path-editor' => 'aa1733d0', 'owners-path-editor-css' => '2f00933b', 'paste-css' => 'a5157c48', 'path-typeahead' => 'f7fc67ec', 'people-profile-css' => '25970776', 'phabricator-action-list-view-css' => 'c5eba19d', 'phabricator-application-launch-view-css' => '95351601', 'phabricator-busy' => '59a7976a', 'phabricator-chatlog-css' => 'd295b020', 'phabricator-content-source-view-css' => '4b8b05d4', 'phabricator-core-css' => 'a76cefc9', 'phabricator-countdown-css' => 'e7544472', 'phabricator-dashboard-css' => 'eb458607', 'phabricator-drag-and-drop-file-upload' => 'ad10aeac', 'phabricator-draggable-list' => 'a16ec1c6', 'phabricator-fatal-config-template-css' => '8e6c6fcd', 'phabricator-feed-css' => 'ecd4ec57', 'phabricator-file-upload' => '477359c8', 'phabricator-filetree-view-css' => 'fccf9f82', 'phabricator-flag-css' => '5337623f', 'phabricator-hovercard' => '14ac66f5', 'phabricator-hovercard-view-css' => '1239cd52', 'phabricator-keyboard-shortcut' => '1ae869f2', 'phabricator-keyboard-shortcut-manager' => 'c1700f6f', 'phabricator-main-menu-view' => '2f670a96', 'phabricator-nav-view-css' => 'a24cb589', 'phabricator-notification' => 'ccf1cbf8', 'phabricator-notification-css' => '9c279160', 'phabricator-notification-menu-css' => 'f31c0bde', 'phabricator-object-selector-css' => '85ee8ce6', 'phabricator-phtize' => 'd254d646', - 'phabricator-prefab' => 'be38fe4e', + 'phabricator-prefab' => '666c80c5', 'phabricator-remarkup-css' => '275e362f', 'phabricator-search-results-css' => '7dea472c', 'phabricator-shaped-request' => '7cbe244b', 'phabricator-side-menu-view-css' => 'bec2458e', 'phabricator-slowvote-css' => 'da0afb1b', 'phabricator-source-code-view-css' => 'cbeef983', 'phabricator-standard-page-view' => '3c99cdf4', 'phabricator-textareautils' => '5c93c52c', 'phabricator-title' => 'df5e11d2', 'phabricator-tooltip' => '1d298e3a', 'phabricator-ui-example-css' => '528b19de', 'phabricator-uiexample-javelin-view' => 'd4a14807', 'phabricator-uiexample-reactor-button' => 'd19198c8', 'phabricator-uiexample-reactor-checkbox' => '519705ea', 'phabricator-uiexample-reactor-focus' => '40a6a403', 'phabricator-uiexample-reactor-input' => '886fd850', 'phabricator-uiexample-reactor-mouseover' => '47c794d8', 'phabricator-uiexample-reactor-radio' => '988040b4', 'phabricator-uiexample-reactor-select' => 'a155550f', 'phabricator-uiexample-reactor-sendclass' => '1def2711', 'phabricator-uiexample-reactor-sendproperties' => 'b1f0ccee', 'phabricator-zindex-css' => '57ddcaa2', 'phame-css' => '164515da', 'pholio-css' => '95174bdd', 'pholio-edit-css' => '3ad9d1ee', 'pholio-inline-comments-css' => '8e545e49', 'phortune-credit-card-form' => '2290aeef', 'phortune-credit-card-form-css' => '8391eb02', 'phortune-css' => '9149f103', 'phrequent-css' => 'ffc185ad', 'phriction-document-css' => 'd1861e06', 'phui-action-panel-css' => '91c7b835', 'phui-badge-view-css' => 'f25c3476', 'phui-box-css' => 'a5bb366d', 'phui-button-css' => '16020a60', 'phui-calendar-css' => 'ccabe893', 'phui-calendar-day-css' => 'd1cf6f93', 'phui-calendar-list-css' => 'c1c7f338', 'phui-calendar-month-css' => '476be7e0', 'phui-crumbs-view-css' => '414406b5', 'phui-document-summary-view-css' => '8c1e0aca', 'phui-document-view-css' => 'a4a1c3b9', 'phui-document-view-pro-css' => 'e0fad431', 'phui-feed-story-css' => 'b7b26d23', 'phui-font-icon-base-css' => 'ecbbb4c2', 'phui-fontkit-css' => '9cda225e', - 'phui-form-css' => 'afdb2c6e', + 'phui-form-css' => '0b98e572', 'phui-form-view-css' => 'cf7da606', 'phui-header-view-css' => '55bb32dd', 'phui-icon-view-css' => 'b0a6b1b6', 'phui-image-mask-css' => '5a8b09c8', 'phui-info-panel-css' => '27ea50a1', 'phui-info-view-css' => '6d7c3509', 'phui-inline-comment-view-css' => '0fdb3667', 'phui-list-view-css' => '125599df', 'phui-object-box-css' => '407eaf5a', 'phui-object-item-list-view-css' => '26c30d3f', 'phui-pager-css' => 'bea33d23', 'phui-pinboard-view-css' => '2495140e', 'phui-property-list-view-css' => '27b2849e', 'phui-remarkup-preview-css' => '1a8f2591', 'phui-spacing-css' => '042804d6', 'phui-status-list-view-css' => '888cedb8', 'phui-tag-view-css' => 'e60e227b', 'phui-text-css' => 'cf019f54', 'phui-theme-css' => '6b451f24', 'phui-timeline-view-css' => '2efceff8', 'phui-two-column-view-css' => '39ecafb1', 'phui-workboard-view-css' => '6704d68d', 'phui-workpanel-view-css' => 'adec7699', 'phuix-action-list-view' => 'b5c256b8', 'phuix-action-view' => '8cf6d262', 'phuix-dropdown-menu' => 'bd4c8dca', 'phuix-form-control-view' => '8fba1997', 'phuix-icon-view' => 'bff6884b', 'policy-css' => '957ea14c', 'policy-edit-css' => '815c66f7', 'policy-transaction-detail-css' => '82100a43', 'ponder-view-css' => '7b0df4da', 'project-icon-css' => '4e3eaa5a', 'raphael-core' => '51ee6b43', 'raphael-g' => '40dde778', 'raphael-g-line' => '40da039e', 'releeph-core' => '9b3c5733', 'releeph-preview-branch' => 'b7a6f4a5', 'releeph-request-differential-create-dialog' => '8d8b92cd', 'releeph-request-typeahead-css' => '667a48ae', 'setup-issue-css' => 'db7e9c40', 'sprite-login-css' => '60e8560e', 'sprite-main-header-css' => 'f07bbb87', 'sprite-menu-css' => '9dd65b92', 'sprite-projects-css' => 'e5ad842a', 'sprite-tokens-css' => '4f399012', 'syntax-highlighting-css' => '9fd11da8', 'tokens-css' => '3d0f239e', 'typeahead-browse-css' => 'd8581d2c', 'unhandled-exception-css' => '4c96257a', ), 'requires' => array( '01774ab2' => array( 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-install', 'javelin-aphlict', 'javelin-workflow', 'javelin-router', 'javelin-behavior-device', 'javelin-vector', ), '031cee25' => array( 'javelin-behavior', 'javelin-request', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', 'javelin-uri', 'javelin-behavior-device', 'phabricator-title', ), '048330fa' => array( 'javelin-behavior', 'javelin-typeahead-ondemand-source', 'javelin-typeahead', 'javelin-dom', 'javelin-uri', 'javelin-util', 'javelin-stratcom', 'phabricator-prefab', ), '05270951' => array( 'javelin-util', 'javelin-magical-init', ), '056da01b' => array( 'aphront-typeahead-control-css', 'phui-tag-view-css', ), '065227cc' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', ), '087e919c' => array( 'javelin-install', 'javelin-dom', 'javelin-stratcom', 'javelin-vector', ), '0a3f3021' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'javelin-router', ), '0f764c35' => array( 'javelin-install', 'javelin-util', ), '13c739ea' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'javelin-uri', 'phabricator-textareautils', ), '1499a8cb' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-history', ), '14ac66f5' => array( 'javelin-install', 'javelin-dom', 'javelin-vector', 'javelin-request', 'javelin-uri', ), '1ad0a787' => array( 'javelin-install', 'javelin-reactor', 'javelin-util', 'javelin-reactor-node-calmer', ), '1ae869f2' => array( 'javelin-install', 'javelin-util', 'phabricator-keyboard-shortcut-manager', ), '1d298e3a' => array( 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-vector', ), '1d45c74d' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-workflow', 'javelin-behavior-device', 'javelin-history', 'javelin-vector', 'javelin-scrollbar', 'phabricator-title', 'phabricator-shaped-request', 'conpherence-thread-manager', ), '1def2711' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), '2035b9cb' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-workflow', 'phuix-dropdown-menu', 'phuix-action-list-view', 'phuix-action-view', 'phabricator-phtize', 'changeset-view-manager', ), '21ba5861' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-stratcom', 'conpherence-thread-manager', ), '2290aeef' => array( 'javelin-install', 'javelin-dom', 'javelin-json', 'javelin-workflow', 'javelin-util', ), '246dc085' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-workflow', 'javelin-quicksand', 'phabricator-phtize', 'phabricator-drag-and-drop-file-upload', 'phabricator-draggable-list', ), '2818f5ce' => array( 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-typeahead-normalizer', ), '2926fff2' => array( 'javelin-behavior', 'javelin-dom', ), '29274e2b' => array( 'javelin-install', 'javelin-util', ), '2b8de964' => array( 'javelin-install', 'javelin-util', ), '2bfa2836' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '2c426492' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'phabricator-keyboard-shortcut', ), '2caa8fb8' => array( 'javelin-install', 'javelin-event', ), '2f670a96' => array( 'phui-theme-css', ), '331b1611' => array( 'javelin-install', ), '3ab51e2c' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', 'javelin-magical-init', ), '3cb0b2fc' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-util', 'javelin-uri', ), '3ee3408b' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'phabricator-tooltip', ), '3f5d6dbf' => array( 'javelin-behavior', 'javelin-dom', 'phortune-credit-card-form', ), '40a6a403' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), 42126667 => array( 'javelin-behavior', 'javelin-dom', 'javelin-request', ), '44959b73' => array( 'javelin-util', 'javelin-uri', 'javelin-install', ), '453c5375' => array( 'javelin-behavior', 'javelin-dom', ), '469c0d9e' => array( 'javelin-behavior', 'javelin-dom', 'javelin-workflow', ), '477359c8' => array( 'javelin-install', 'javelin-dom', 'phabricator-notification', ), 47830651 => array( 'javelin-behavior', 'javelin-dom', 'javelin-view-renderer', 'javelin-install', ), '47c794d8' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), 48086888 => array( 'javelin-behavior', 'javelin-dom', 'javelin-workflow', ), '49b73b36' => array( 'javelin-behavior', 'javelin-dom', 'javelin-request', 'javelin-util', ), '4e3e79a6' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '4fdb476d' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '503e17fd' => array( 'javelin-install', 'javelin-typeahead-source', 'javelin-util', ), '519705ea' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), '5359e785' => array( 'javelin-install', 'javelin-util', 'javelin-websocket', 'javelin-leader', 'javelin-json', ), 54733475 => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phuix-dropdown-menu', ), '54b612ba' => array( 'javelin-color', 'javelin-install', 'javelin-util', ), '54f314a0' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-typeahead-source', ), '558829c2' => array( 'javelin-stratcom', 'javelin-behavior', 'javelin-vector', 'javelin-dom', ), '56a1ca03' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'javelin-dom', 'javelin-magical-init', 'javelin-vector', 'javelin-request', 'javelin-util', ), 58562350 => array( 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-install', 'javelin-workflow', 'javelin-router', 'javelin-behavior-device', 'javelin-vector', ), '59a7976a' => array( 'javelin-install', 'javelin-dom', 'javelin-fx', ), '59b251eb' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', ), '5b2e3e2b' => array( 'javelin-stratcom', 'javelin-request', 'javelin-dom', 'javelin-vector', 'javelin-install', 'javelin-util', 'javelin-mask', 'javelin-uri', 'javelin-routable', ), '5bd8f385' => array( 'multirow-row-manager', 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-stratcom', 'javelin-json', 'phabricator-prefab', ), '5c54cbf3' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '5c93c52c' => array( 'javelin-install', 'javelin-dom', 'javelin-vector', ), '5d7c9f33' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '5e9f347c' => array( 'javelin-behavior', 'multirow-row-manager', 'javelin-dom', 'javelin-util', 'phabricator-prefab', 'javelin-json', ), 60479091 => array( 'phabricator-busy', 'javelin-behavior', ), '60821bc7' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), '61cbc29a' => array( 'javelin-magical-init', 'javelin-util', ), '62dfea03' => array( 'javelin-install', 'javelin-util', ), '635de1ec' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', ), '64a5550f' => array( 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-install', 'javelin-request', 'javelin-workflow', ), '65ef6074' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-util', 'javelin-vector', 'differential-inline-comment-editor', ), + '666c80c5' => 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', + ), '6882e80a' => array( 'javelin-dom', ), '69adf288' => array( 'javelin-install', ), '6b8ef10b' => array( 'javelin-install', ), '6c0e62fa' => array( 'javelin-install', 'javelin-typeahead-source', ), '6c2b09a2' => array( 'javelin-install', 'javelin-util', ), '6c53634d' => array( 'javelin-install', 'javelin-event', 'javelin-util', 'javelin-magical-init', ), '6d3e1947' => array( 'javelin-behavior', 'javelin-diffusion-locate-file-source', 'javelin-dom', 'javelin-typeahead', 'javelin-uri', ), '6d49590e' => array( 'javelin-behavior', 'javelin-dom', 'phabricator-drag-and-drop-file-upload', 'phabricator-textareautils', ), '70baed2f' => array( 'javelin-install', 'javelin-dom', 'javelin-vector', 'javelin-util', ), 71237763 => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'phabricator-draggable-list', ), '7319e029' => array( 'javelin-behavior', 'javelin-dom', ), '73d09eef' => array( 'javelin-behavior', 'javelin-vector', 'javelin-dom', ), '76b9fc3e' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), '76f4ebed' => array( 'javelin-install', 'javelin-reactor', 'javelin-util', ), '782ab6e7' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phabricator-prefab', 'multirow-row-manager', 'javelin-json', ), '7927a7d3' => array( 'javelin-behavior', 'javelin-quicksand', ), '7a68dda3' => array( 'owners-path-editor', 'javelin-behavior', ), '7b98d7c5' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-util', ), '7cbe244b' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-router', ), - '7d470398' => array( - 'javelin-behavior', - 'javelin-dom', - 'javelin-util', - 'phuix-dropdown-menu', - 'phuix-action-list-view', - 'phuix-action-view', - 'javelin-workflow', - ), '7e41274a' => array( 'javelin-install', ), '7ebaeed3' => array( 'herald-rule-editor', 'javelin-behavior', ), '7ee2b591' => array( 'javelin-behavior', 'javelin-history', ), '805b806a' => array( 'javelin-magical-init', 'javelin-install', 'javelin-util', 'javelin-vector', 'javelin-stratcom', ), 82439934 => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-stratcom', 'javelin-workflow', 'phabricator-draggable-list', ), '834a1173' => array( 'javelin-behavior', 'javelin-scrollbar', ), '85ea0626' => array( 'javelin-install', ), '85ee8ce6' => array( 'aphront-dialog-view-css', ), '8694b1df' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'phabricator-tooltip', 'changeset-view-manager', ), '88236f00' => array( 'javelin-behavior', 'phabricator-keyboard-shortcut', 'javelin-stratcom', ), '886fd850' => array( 'javelin-install', 'javelin-reactor-dom', 'javelin-view-html', 'javelin-view-interpreter', 'javelin-view-renderer', ), '887ad43f' => array( 'javelin-behavior', 'javelin-request', 'javelin-stratcom', 'javelin-dom', ), '88f0c5b3' => array( 'javelin-behavior', 'javelin-dom', 'javelin-vector', ), '8a41885b' => array( 'javelin-install', 'javelin-dom', ), '8ae55229' => array( 'javelin-behavior', 'javelin-util', 'javelin-dom', 'javelin-stratcom', 'javelin-vector', ), '8b3fd187' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-typeahead-source', ), '8bdb2835' => array( 'phui-fontkit-css', ), '8ce821c5' => array( 'phabricator-notification', 'javelin-stratcom', 'javelin-behavior', ), '8cf6d262' => array( 'javelin-install', 'javelin-dom', 'javelin-util', ), + '8d3bc1b2' => array( + 'javelin-dom', + 'javelin-util', + 'javelin-stratcom', + 'javelin-install', + ), '8ef9ab58' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), '8fba1997' => array( 'javelin-install', 'javelin-dom', ), '9007c197' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), '901935ef' => array( 'javelin-behavior', 'javelin-dom', 'javelin-request', ), '93d0c9e3' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', ), '9414ff18' => array( 'javelin-behavior', 'javelin-resource', 'javelin-stratcom', 'javelin-workflow', 'javelin-util', ), '949c0fe5' => array( 'javelin-install', ), '94b750d2' => array( 'javelin-install', 'javelin-stratcom', 'javelin-util', 'javelin-behavior', 'javelin-json', 'javelin-dom', 'javelin-resource', 'javelin-routable', ), '988040b4' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), '9f36c42d' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', ), 'a0b57eb8' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-util', 'phabricator-keyboard-shortcut', ), 'a155550f' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), 'a16ec1c6' => array( 'javelin-install', 'javelin-dom', 'javelin-stratcom', 'javelin-util', 'javelin-vector', 'javelin-magical-init', ), 'a205cf28' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', 'javelin-install', ), 'a464fe03' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-notification', ), 'a80d0378' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'a8458711' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-util', 'phabricator-notification', 'javelin-behavior-device', 'phuix-dropdown-menu', 'phuix-action-list-view', 'phuix-action-view', 'conpherence-thread-manager', ), 'a8d8459d' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), 'a8da01f0' => array( 'javelin-behavior', 'javelin-uri', 'phabricator-keyboard-shortcut', ), 'a9f88de2' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-workflow', 'javelin-fx', 'javelin-util', ), 'aa1733d0' => array( 'multirow-row-manager', 'javelin-install', 'path-typeahead', 'javelin-dom', 'javelin-util', 'phabricator-prefab', ), 'ab2f381b' => array( 'javelin-request', 'javelin-behavior', 'javelin-dom', 'javelin-router', 'javelin-util', 'phabricator-busy', ), 'ad10aeac' => array( 'javelin-install', 'javelin-util', 'javelin-request', 'javelin-dom', 'javelin-uri', 'phabricator-file-upload', ), + 'ae45872f' => array( + 'javelin-behavior', + 'javelin-dom', + 'javelin-util', + 'phuix-dropdown-menu', + 'phuix-action-list-view', + 'phuix-action-view', + 'javelin-workflow', + ), 'b064af76' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-request', 'javelin-util', 'phabricator-shaped-request', ), 'b1f0ccee' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), 'b23b49e6' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-request', 'phabricator-shaped-request', ), 'b2b4fbaf' => array( 'javelin-behavior', 'javelin-dom', 'javelin-uri', 'javelin-request', ), 'b3a4b884' => array( 'javelin-behavior', 'phabricator-prefab', ), 'b3e7d692' => array( 'javelin-install', ), 'b42eddc7' => array( 'javelin-install', 'javelin-dom', 'javelin-typeahead-preloaded-source', 'javelin-util', ), 'b59e1e96' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'b5c256b8' => array( 'javelin-install', 'javelin-dom', ), 'b5d57730' => array( 'javelin-install', 'javelin-stratcom', 'javelin-dom', 'javelin-util', ), 'b6993408' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-json', 'phabricator-draggable-list', ), 'b6b0d1bb' => array( 'phui-inline-comment-view-css', ), 'ba4fa35c' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-vector', 'javelin-stratcom', 'javelin-workflow', 'phabricator-draggable-list', ), 'bb0d2d0c' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phuix-form-control-view', 'phuix-icon-view', ), 'bd4c8dca' => array( 'javelin-install', 'javelin-util', 'javelin-dom', 'javelin-vector', 'javelin-stratcom', ), 'bdaf4d04' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-request', ), - 'be38fe4e' => array( + 'bff6884b' => 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', ), - 'bff6884b' => array( - 'javelin-install', + 'c14b5995' => array( + 'javelin-behavior', + 'javelin-stratcom', 'javelin-dom', + 'phabricator-phtize', + 'phabricator-textareautils', + 'javelin-workflow', + 'javelin-vector', ), 'c1700f6f' => array( 'javelin-install', 'javelin-util', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', ), - 'c431f925' => array( - 'javelin-dom', - 'javelin-util', - 'javelin-stratcom', - 'javelin-install', - ), 'c72aa091' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-behavior-device', 'javelin-scrollbar', 'javelin-quicksand', 'phabricator-keyboard-shortcut', 'conpherence-thread-manager', ), 'c7ccd872' => array( 'phui-fontkit-css', ), 'c8e57404' => array( 'javelin-behavior', 'javelin-dom', 'javelin-uri', 'javelin-mask', 'phabricator-drag-and-drop-file-upload', ), 'c90a04fc' => array( 'javelin-dom', 'javelin-dynval', 'javelin-reactor', 'javelin-reactornode', 'javelin-install', 'javelin-util', ), 'c989ade3' => array( 'javelin-install', 'javelin-util', 'javelin-stratcom', ), 'ca3f91eb' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'phabricator-phtize', ), 'ccf1cbf8' => array( 'javelin-install', 'javelin-dom', 'javelin-stratcom', 'javelin-util', 'phabricator-notification-css', ), 'cf86d16a' => array( 'javelin-behavior', 'javelin-dom', 'javelin-workflow', 'phabricator-drag-and-drop-file-upload', ), 'd19198c8' => array( 'javelin-install', 'javelin-dom', 'javelin-util', 'javelin-dynval', 'javelin-reactor-dom', ), 'd254d646' => array( 'javelin-util', ), 'd4505101' => array( 'javelin-stratcom', 'javelin-install', 'javelin-uri', 'javelin-util', ), 'd4a14807' => array( 'javelin-install', 'javelin-dom', 'javelin-view', ), 'd4eecc63' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', ), 'd75709e6' => array( 'javelin-behavior', 'javelin-workflow', 'javelin-json', 'javelin-dom', 'phabricator-keyboard-shortcut', ), 'd7a74243' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'd835b03a' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phabricator-shaped-request', ), 'dbbf48b6' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'phabricator-busy', ), 'de2e896f' => array( 'javelin-behavior', 'javelin-dom', 'javelin-typeahead', 'javelin-typeahead-ondemand-source', 'javelin-dom', ), 'df5e11d2' => array( 'javelin-install', ), 'dfaafb14' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-workflow', ), 'e10f8e18' => array( 'javelin-behavior', 'javelin-dom', 'phabricator-prefab', ), 'e1d25dfb' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'e1ff79b1' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', ), 'e292eaf4' => array( 'javelin-install', ), 'e379b58e' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-vector', 'javelin-dom', 'javelin-uri', ), 'e4cc26b3' => array( 'javelin-behavior', 'javelin-dom', ), 'e5339c43' => array( 'javelin-behavior', 'javelin-dom', 'javelin-stratcom', 'javelin-uri', ), 'e5822781' => array( 'javelin-behavior', 'javelin-dom', 'javelin-json', 'javelin-workflow', 'javelin-magical-init', ), 'e6e25838' => array( 'javelin-install', ), 'e9581f08' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-workflow', 'javelin-dom', 'phabricator-draggable-list', ), 'ea681761' => array( 'javelin-behavior', 'javelin-aphlict', 'phabricator-phtize', 'javelin-dom', ), 'edd1ba66' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-uri', 'phabricator-notification', ), 'edf8a145' => array( 'javelin-behavior', 'javelin-uri', ), - 'eeaa9e5a' => array( - 'javelin-behavior', - 'javelin-stratcom', - 'javelin-dom', - 'phabricator-phtize', - 'phabricator-textareautils', - 'javelin-workflow', - 'javelin-vector', - ), 'efe49472' => array( 'javelin-install', 'javelin-util', ), 'f01586dc' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'javelin-workflow', 'javelin-json', ), 'f36e01af' => array( 'javelin-behavior', 'javelin-behavior-device', 'javelin-stratcom', 'javelin-vector', 'phabricator-hovercard', ), 'f411b6ae' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-util', 'javelin-dom', 'javelin-request', 'phabricator-keyboard-shortcut', ), 'f6555212' => array( 'javelin-install', 'javelin-reactornode', 'javelin-util', 'javelin-reactor', ), 'f7379f45' => array( 'javelin-behavior', 'javelin-dom', 'javelin-util', 'phabricator-shaped-request', ), 'f7fc67ec' => array( 'javelin-install', 'javelin-typeahead', 'javelin-dom', 'javelin-request', 'javelin-typeahead-ondemand-source', 'javelin-util', ), 'f80d6bf0' => array( 'javelin-behavior', 'javelin-util', 'javelin-dom', 'javelin-stratcom', 'javelin-vector', 'javelin-typeahead-static-source', ), 'f829edb3' => array( 'javelin-view', 'javelin-install', 'javelin-dom', ), 'f8ba29d7' => array( 'javelin-behavior', 'javelin-stratcom', 'javelin-dom', 'javelin-mask', 'javelin-util', 'phabricator-busy', ), 'fa0f4fc2' => array( 'javelin-behavior', 'javelin-dom', 'javelin-vector', 'javelin-magical-init', ), 'fb20ac8d' => array( 'javelin-behavior', 'javelin-aphlict', 'javelin-stratcom', 'javelin-request', 'javelin-uri', 'javelin-dom', 'javelin-json', 'javelin-router', 'javelin-util', 'javelin-leader', 'javelin-sound', 'phabricator-notification', ), 'fbe497e7' => array( 'javelin-behavior', 'javelin-util', 'javelin-stratcom', 'javelin-dom', 'javelin-vector', 'javelin-magical-init', 'javelin-request', 'javelin-history', 'javelin-workflow', 'javelin-mask', 'javelin-behavior-device', 'phabricator-keyboard-shortcut', ), 'fc91ab6c' => array( 'javelin-behavior', 'javelin-dom', 'phortune-credit-card-form', ), 'fe287620' => array( 'javelin-install', 'javelin-dom', 'javelin-view-visitor', 'javelin-util', ), ), 'packages' => array( 'core.pkg.css' => array( 'phabricator-core-css', 'phabricator-zindex-css', 'phui-button-css', 'phabricator-standard-page-view', 'aphront-dialog-view-css', 'phui-form-view-css', 'aphront-panel-view-css', 'aphront-table-view-css', 'aphront-tokenizer-control-css', 'aphront-typeahead-control-css', 'aphront-list-filter-view-css', 'phabricator-remarkup-css', 'syntax-highlighting-css', 'phui-pager-css', 'aphront-tooltip-css', 'phabricator-flag-css', 'phui-info-view-css', 'sprite-menu-css', 'phabricator-main-menu-view', 'phabricator-notification-css', 'phabricator-notification-menu-css', 'lightbox-attachment-css', 'phui-header-view-css', 'phabricator-filetree-view-css', 'phabricator-nav-view-css', 'phabricator-side-menu-view-css', 'phui-crumbs-view-css', 'phui-object-item-list-view-css', 'global-drag-and-drop-css', 'phui-spacing-css', 'phui-form-css', 'phui-icon-view-css', 'phabricator-application-launch-view-css', 'phabricator-action-list-view-css', 'phui-property-list-view-css', 'phui-tag-view-css', 'phui-list-view-css', 'font-fontawesome', 'phui-font-icon-base-css', 'phui-box-css', 'phui-object-box-css', 'phui-timeline-view-css', 'sprite-tokens-css', 'tokens-css', 'phui-status-list-view-css', 'phui-feed-story-css', 'phabricator-feed-css', 'phabricator-dashboard-css', 'aphront-multi-column-view-css', 'conpherence-durable-column-view', ), 'core.pkg.js' => array( 'javelin-util', 'javelin-install', 'javelin-event', 'javelin-stratcom', 'javelin-behavior', 'javelin-resource', 'javelin-request', 'javelin-vector', 'javelin-dom', 'javelin-json', 'javelin-uri', 'javelin-workflow', 'javelin-mask', 'javelin-typeahead', 'javelin-typeahead-normalizer', 'javelin-typeahead-source', 'javelin-typeahead-preloaded-source', 'javelin-typeahead-ondemand-source', 'javelin-tokenizer', 'javelin-history', 'javelin-router', 'javelin-routable', 'javelin-behavior-aphront-basic-tokenizer', 'javelin-behavior-workflow', 'javelin-behavior-aphront-form-disable-on-submit', 'phabricator-keyboard-shortcut-manager', 'phabricator-keyboard-shortcut', 'javelin-behavior-phabricator-keyboard-shortcuts', 'javelin-behavior-refresh-csrf', 'javelin-behavior-phabricator-watch-anchor', 'javelin-behavior-phabricator-autofocus', 'phuix-dropdown-menu', 'phuix-action-list-view', 'phuix-action-view', 'phabricator-phtize', 'javelin-behavior-phabricator-oncopy', 'phabricator-tooltip', 'javelin-behavior-phabricator-tooltips', 'phabricator-prefab', 'javelin-behavior-device', 'javelin-behavior-toggle-class', 'javelin-behavior-lightbox-attachments', 'phabricator-busy', 'javelin-aphlict', 'phabricator-notification', 'javelin-behavior-aphlict-listen', 'javelin-behavior-phabricator-search-typeahead', 'javelin-behavior-aphlict-dropdown', 'javelin-behavior-history-install', 'javelin-behavior-phabricator-gesture', 'javelin-behavior-phabricator-active-nav', 'javelin-behavior-phabricator-nav', 'javelin-behavior-phabricator-remarkup-assist', 'phabricator-textareautils', 'phabricator-file-upload', 'javelin-behavior-global-drag-and-drop', 'javelin-behavior-phabricator-reveal-content', 'phabricator-hovercard', 'javelin-behavior-phabricator-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-scrollbar', 'javelin-behavior-scrollbar', 'javelin-behavior-durable-column', 'conpherence-thread-manager', ), 'darkconsole.pkg.js' => array( 'javelin-behavior-dark-console', 'javelin-behavior-error-log', ), 'differential.pkg.css' => array( 'differential-core-view-css', 'differential-changeset-view-css', 'differential-revision-history-css', 'differential-revision-list-css', 'differential-table-of-contents-css', 'differential-revision-comment-css', 'differential-revision-add-comment-css', 'phabricator-object-selector-css', 'phabricator-content-source-view-css', 'inline-comment-summary-css', 'phui-inline-comment-view-css', ), 'differential.pkg.js' => array( 'phabricator-drag-and-drop-file-upload', 'phabricator-shaped-request', 'javelin-behavior-differential-feedback-preview', 'javelin-behavior-differential-edit-inline-comments', 'javelin-behavior-differential-populate', 'javelin-behavior-differential-diff-radios', 'javelin-behavior-differential-comment-jump', 'javelin-behavior-differential-add-reviewers-and-ccs', 'javelin-behavior-differential-keyboard-navigation', 'javelin-behavior-aphront-drag-and-drop-textarea', 'javelin-behavior-phabricator-object-selector', 'javelin-behavior-repository-crossreference', 'javelin-behavior-load-blame', 'differential-inline-comment-editor', 'javelin-behavior-differential-dropdown-menus', 'javelin-behavior-differential-toggle-files', 'javelin-behavior-differential-user-select', 'javelin-behavior-aphront-more', 'changeset-view-manager', ), 'diffusion.pkg.css' => array( 'diffusion-icons-css', ), 'diffusion.pkg.js' => array( 'javelin-behavior-diffusion-pull-lastmodified', 'javelin-behavior-diffusion-commit-graph', 'javelin-behavior-audit-preview', ), 'maniphest.pkg.css' => array( 'maniphest-task-summary-css', ), 'maniphest.pkg.js' => array( 'javelin-behavior-maniphest-batch-selector', 'javelin-behavior-maniphest-subpriority-editor', 'javelin-behavior-maniphest-list-editor', ), ), ); diff --git a/src/view/form/control/AphrontFormPolicyControl.php b/src/view/form/control/AphrontFormPolicyControl.php index 4201091d2b..c78d72f25f 100644 --- a/src/view/form/control/AphrontFormPolicyControl.php +++ b/src/view/form/control/AphrontFormPolicyControl.php @@ -1,360 +1,362 @@ object = $object; return $this; } public function setPolicies(array $policies) { assert_instances_of($policies, 'PhabricatorPolicy'); $this->policies = $policies; return $this; } public function setSpacePHID($space_phid) { $this->spacePHID = $space_phid; return $this; } public function getSpacePHID() { return $this->spacePHID; } public function setTemplatePHIDType($type) { $this->templatePHIDType = $type; return $this; } public function setTemplateObject($object) { $this->templateObject = $object; return $this; } public function getSerializedValue() { return json_encode(array( $this->getValue(), $this->getSpacePHID(), )); } public function readSerializedValue($value) { $decoded = phutil_json_decode($value); $policy_value = $decoded[0]; $space_phid = $decoded[1]; $this->setValue($policy_value); $this->setSpacePHID($space_phid); return $this; } public function readValueFromDictionary(array $dictionary) { // TODO: This is a little hacky but will only get us into trouble if we // have multiple view policy controls in multiple paged form views on the // same page, which seems unlikely. $this->setSpacePHID(idx($dictionary, 'spacePHID')); return parent::readValueFromDictionary($dictionary); } public function readValueFromRequest(AphrontRequest $request) { // See note in readValueFromDictionary(). $this->setSpacePHID($request->getStr('spacePHID')); return parent::readValueFromRequest($request); } public function setCapability($capability) { $this->capability = $capability; $labels = array( PhabricatorPolicyCapability::CAN_VIEW => pht('Visible To'), PhabricatorPolicyCapability::CAN_EDIT => pht('Editable By'), PhabricatorPolicyCapability::CAN_JOIN => pht('Joinable By'), ); if (isset($labels[$capability])) { $label = $labels[$capability]; } else { $capobj = PhabricatorPolicyCapability::getCapabilityByKey($capability); if ($capobj) { $label = $capobj->getCapabilityName(); } else { $label = pht('Capability "%s"', $capability); } } $this->setLabel($label); return $this; } protected function getCustomControlClass() { return 'aphront-form-control-policy'; } protected function getOptions() { $capability = $this->capability; $policies = $this->policies; // Exclude object policies which don't make sense here. This primarily // filters object policies associated from template capabilities (like // "Default Task View Policy" being set to "Task Author") so they aren't // made available on non-template capabilities (like "Can Bulk Edit"). foreach ($policies as $key => $policy) { if ($policy->getType() != PhabricatorPolicyType::TYPE_OBJECT) { continue; } $rule = PhabricatorPolicyQuery::getObjectPolicyRule($policy->getPHID()); if (!$rule) { continue; } $target = nonempty($this->templateObject, $this->object); if (!$rule->canApplyToObject($target)) { unset($policies[$key]); continue; } } $options = array(); foreach ($policies as $policy) { if ($policy->getPHID() == PhabricatorPolicies::POLICY_PUBLIC) { // Never expose "Public" for capabilities which don't support it. $capobj = PhabricatorPolicyCapability::getCapabilityByKey($capability); if (!$capobj || !$capobj->shouldAllowPublicPolicySetting()) { continue; } } $policy_short_name = id(new PhutilUTF8StringTruncator()) ->setMaximumGlyphs(28) ->truncateString($policy->getName()); $options[$policy->getType()][$policy->getPHID()] = array( 'name' => $policy_short_name, 'full' => $policy->getName(), 'icon' => $policy->getIcon(), ); } // If we were passed several custom policy options, throw away the ones // which aren't the value for this capability. For example, an object might // have a custom view pollicy and a custom edit policy. When we render // the selector for "Can View", we don't want to show the "Can Edit" // custom policy -- if we did, the menu would look like this: // // Custom // Custom Policy // Custom Policy // // ...where one is the "view" custom policy, and one is the "edit" custom // policy. $type_custom = PhabricatorPolicyType::TYPE_CUSTOM; if (!empty($options[$type_custom])) { $options[$type_custom] = array_select_keys( $options[$type_custom], array($this->getValue())); } // If there aren't any custom policies, add a placeholder policy so we // render a menu item. This allows the user to switch to a custom policy. if (empty($options[$type_custom])) { $placeholder = new PhabricatorPolicy(); $placeholder->setName(pht('Custom Policy...')); $options[$type_custom][$this->getCustomPolicyPlaceholder()] = array( 'name' => $placeholder->getName(), 'full' => $placeholder->getName(), 'icon' => $placeholder->getIcon(), ); } $options = array_select_keys( $options, array( PhabricatorPolicyType::TYPE_GLOBAL, PhabricatorPolicyType::TYPE_OBJECT, PhabricatorPolicyType::TYPE_USER, PhabricatorPolicyType::TYPE_CUSTOM, PhabricatorPolicyType::TYPE_PROJECT, )); return $options; } protected function renderInput() { if (!$this->object) { throw new PhutilInvalidStateException('setPolicyObject'); } if (!$this->capability) { throw new PhutilInvalidStateException('setCapability'); } $policy = $this->object->getPolicy($this->capability); if (!$policy) { // TODO: Make this configurable. $policy = PhabricatorPolicies::POLICY_USER; } if (!$this->getValue()) { $this->setValue($policy); } $control_id = celerity_generate_unique_node_id(); $input_id = celerity_generate_unique_node_id(); $caret = phutil_tag( 'span', array( 'class' => 'caret', )); $input = phutil_tag( 'input', array( 'type' => 'hidden', 'id' => $input_id, 'name' => $this->getName(), 'value' => $this->getValue(), )); $options = $this->getOptions(); $order = array(); $labels = array(); foreach ($options as $key => $values) { $order[$key] = array_keys($values); $labels[$key] = PhabricatorPolicyType::getPolicyTypeName($key); } $flat_options = array_mergev($options); $icons = array(); foreach (igroup($flat_options, 'icon') as $icon => $ignored) { $icons[$icon] = id(new PHUIIconView()) ->setIconFont($icon); } if ($this->templatePHIDType) { $context_path = 'template/'.$this->templatePHIDType.'/'; } else { $object_phid = $this->object->getPHID(); if ($object_phid) { $context_path = 'object/'.$object_phid.'/'; } else { $object_type = phid_get_type($this->object->generatePHID()); $context_path = 'type/'.$object_type.'/'; } } Javelin::initBehavior( 'policy-control', array( 'controlID' => $control_id, 'inputID' => $input_id, 'options' => $flat_options, 'groups' => array_keys($options), 'order' => $order, 'icons' => $icons, 'labels' => $labels, 'value' => $this->getValue(), 'capability' => $this->capability, 'editURI' => '/policy/edit/'.$context_path, 'customPlaceholder' => $this->getCustomPolicyPlaceholder(), + 'disabled' => $this->getDisabled(), )); $selected = idx($flat_options, $this->getValue(), array()); $selected_icon = idx($selected, 'icon'); $selected_name = idx($selected, 'name'); $spaces_control = $this->buildSpacesControl(); return phutil_tag( 'div', array( ), array( $spaces_control, javelin_tag( 'a', array( 'class' => 'grey button dropdown has-icon policy-control', 'href' => '#', 'mustcapture' => true, 'sigil' => 'policy-control', 'id' => $control_id, ), array( $caret, javelin_tag( 'span', array( 'sigil' => 'policy-label', 'class' => 'phui-button-text', ), array( idx($icons, $selected_icon), $selected_name, )), )), $input, )); return AphrontFormSelectControl::renderSelectTag( $this->getValue(), $this->getOptions(), array( 'name' => $this->getName(), 'disabled' => $this->getDisabled() ? 'disabled' : null, 'id' => $this->getID(), )); } private function getCustomPolicyPlaceholder() { return 'custom:placeholder'; } private function buildSpacesControl() { if ($this->capability != PhabricatorPolicyCapability::CAN_VIEW) { return null; } if (!($this->object instanceof PhabricatorSpacesInterface)) { return null; } $viewer = $this->getUser(); if (!PhabricatorSpacesNamespaceQuery::getViewerSpacesExist($viewer)) { return null; } $space_phid = $this->getSpacePHID(); if ($space_phid === null) { $space_phid = $viewer->getDefaultSpacePHID(); } $select = AphrontFormSelectControl::renderSelectTag( $space_phid, PhabricatorSpacesNamespaceQuery::getSpaceOptionsForViewer( $viewer, $space_phid), array( + 'disabled' => $this->getDisabled(), 'name' => 'spacePHID', 'class' => 'aphront-space-select-control-knob', )); return $select; } } diff --git a/src/view/form/control/AphrontFormTokenizerControl.php b/src/view/form/control/AphrontFormTokenizerControl.php index 4994d89834..3f24dd1348 100644 --- a/src/view/form/control/AphrontFormTokenizerControl.php +++ b/src/view/form/control/AphrontFormTokenizerControl.php @@ -1,149 +1,150 @@ datasource = $datasource; return $this; } public function setDisableBehavior($disable) { $this->disableBehavior = $disable; return $this; } protected function getCustomControlClass() { return 'aphront-form-control-tokenizer'; } public function setLimit($limit) { $this->limit = $limit; return $this; } public function setPlaceholder($placeholder) { $this->placeholder = $placeholder; return $this; } public function setInitialValue(array $initial_value) { $this->initialValue = $initial_value; return $this; } public function getInitialValue() { return $this->initialValue; } public function willRender() { // Load the handles now so we'll get a bulk load later on when we actually // render them. $this->loadHandles(); } protected function renderInput() { $name = $this->getName(); $handles = $this->loadHandles(); $handles = iterator_to_array($handles); if ($this->getID()) { $id = $this->getID(); } else { $id = celerity_generate_unique_node_id(); } $datasource = $this->datasource; if (!$datasource) { throw new Exception( pht('You must set a datasource to use a TokenizerControl.')); } $datasource->setViewer($this->getUser()); $placeholder = null; if (!strlen($this->placeholder)) { $placeholder = $datasource->getPlaceholderText(); } $values = nonempty($this->getValue(), array()); $tokens = $datasource->renderTokens($values); foreach ($tokens as $token) { $token->setInputName($this->getName()); } $template = id(new AphrontTokenizerTemplateView()) ->setName($name) ->setID($id) ->setValue($tokens); $initial_value = $this->getInitialValue(); if ($initial_value !== null) { $template->setInitialValue($initial_value); } $username = null; if ($this->user) { $username = $this->user->getUsername(); } $datasource_uri = $datasource->getDatasourceURI(); $browse_uri = $datasource->getBrowseURI(); if ($browse_uri) { $template->setBrowseURI($browse_uri); } if (!$this->disableBehavior) { Javelin::initBehavior('aphront-basic-tokenizer', array( 'id' => $id, 'src' => $datasource_uri, 'value' => mpull($tokens, 'getValue', 'getKey'), 'icons' => mpull($tokens, 'getIcon', 'getKey'), 'types' => mpull($tokens, 'getTokenType', 'getKey'), 'colors' => mpull($tokens, 'getColor', 'getKey'), 'limit' => $this->limit, 'username' => $username, 'placeholder' => $placeholder, 'browseURI' => $browse_uri, + 'disabled' => $this->getDisabled(), )); } return $template->render(); } private function loadHandles() { if ($this->handles === null) { $viewer = $this->getUser(); if (!$viewer) { throw new Exception( pht( 'Call %s before rendering tokenizers. '. 'Use %s on %s to do this easily.', 'setUser()', 'appendControl()', 'AphrontFormView')); } $values = nonempty($this->getValue(), array()); $phids = array(); foreach ($values as $value) { if (!PhabricatorTypeaheadDatasource::isFunctionToken($value)) { $phids[] = $value; } } $this->handles = $viewer->loadHandles($phids); } return $this->handles; } } diff --git a/src/view/form/control/PhabricatorRemarkupControl.php b/src/view/form/control/PhabricatorRemarkupControl.php index 40823eabc7..693b2d7ea2 100644 --- a/src/view/form/control/PhabricatorRemarkupControl.php +++ b/src/view/form/control/PhabricatorRemarkupControl.php @@ -1,230 +1,240 @@ disableMacro = $disable; return $this; } public function setDisableFullScreen($disable) { $this->disableFullScreen = $disable; return $this; } protected function renderInput() { $id = $this->getID(); if (!$id) { $id = celerity_generate_unique_node_id(); $this->setID($id); } $viewer = $this->getUser(); if (!$viewer) { throw new PhutilInvalidStateException('setUser'); } // We need to have this if previews render images, since Ajax can not // currently ship JS or CSS. require_celerity_resource('lightbox-attachment-css'); - Javelin::initBehavior( - 'aphront-drag-and-drop-textarea', - array( - 'target' => $id, - 'activatedClass' => 'aphront-textarea-drag-and-drop', - 'uri' => '/file/dropupload/', - 'chunkThreshold' => PhabricatorFileStorageEngine::getChunkThreshold(), - )); + if (!$this->getDisabled()) { + Javelin::initBehavior( + 'aphront-drag-and-drop-textarea', + array( + 'target' => $id, + 'activatedClass' => 'aphront-textarea-drag-and-drop', + 'uri' => '/file/dropupload/', + 'chunkThreshold' => PhabricatorFileStorageEngine::getChunkThreshold(), + )); + } Javelin::initBehavior( 'phabricator-remarkup-assist', array( 'pht' => array( 'bold text' => pht('bold text'), 'italic text' => pht('italic text'), 'monospaced text' => pht('monospaced text'), 'List Item' => pht('List Item'), 'Quoted Text' => pht('Quoted Text'), 'data' => pht('data'), 'name' => pht('name'), 'URL' => pht('URL'), ), + 'disabled' => $this->getDisabled(), )); Javelin::initBehavior('phabricator-tooltips', array()); $actions = array( 'fa-bold' => array( 'tip' => pht('Bold'), ), 'fa-italic' => array( 'tip' => pht('Italics'), ), 'fa-text-width' => array( 'tip' => pht('Monospaced'), ), 'fa-link' => array( 'tip' => pht('Link'), ), array( 'spacer' => true, ), 'fa-list-ul' => array( 'tip' => pht('Bulleted List'), ), 'fa-list-ol' => array( 'tip' => pht('Numbered List'), ), 'fa-code' => array( 'tip' => pht('Code Block'), ), 'fa-quote-right' => array( 'tip' => pht('Quote'), ), 'fa-table' => array( 'tip' => pht('Table'), ), 'fa-cloud-upload' => array( 'tip' => pht('Upload File'), ), ); $can_use_macros = (!$this->disableMacro) && (function_exists('imagettftext')); if ($can_use_macros) { $can_use_macros = PhabricatorApplication::isClassInstalledForViewer( 'PhabricatorMacroApplication', $viewer); } if ($can_use_macros) { $actions[] = array( 'spacer' => true, ); $actions['fa-meh-o'] = array( 'tip' => pht('Meme'), ); } $actions['fa-life-bouy'] = array( 'tip' => pht('Help'), 'align' => 'right', 'href' => PhabricatorEnv::getDoclink('Remarkup Reference'), ); if (!$this->disableFullScreen) { $actions[] = array( 'spacer' => true, 'align' => 'right', ); $actions['fa-arrows-alt'] = array( 'tip' => pht('Fullscreen Mode'), 'align' => 'right', ); } $buttons = array(); foreach ($actions as $action => $spec) { $classes = array(); if (idx($spec, 'align') == 'right') { $classes[] = 'remarkup-assist-right'; } if (idx($spec, 'spacer')) { $classes[] = 'remarkup-assist-separator'; $buttons[] = phutil_tag( 'span', array( 'class' => implode(' ', $classes), ), ''); continue; } else { $classes[] = 'remarkup-assist-button'; } $href = idx($spec, 'href', '#'); if ($href == '#') { $meta = array('action' => $action); $mustcapture = true; $target = null; } else { $meta = array(); $mustcapture = null; $target = '_blank'; } $content = null; $tip = idx($spec, 'tip'); if ($tip) { $meta['tip'] = $tip; $content = javelin_tag( 'span', array( 'aural' => true, ), $tip); } + $sigils = array(); + $sigils[] = 'remarkup-assist'; + if (!$this->getDisabled()) { + $sigils[] = 'has-tooltip'; + } + $buttons[] = javelin_tag( 'a', array( 'class' => implode(' ', $classes), 'href' => $href, - 'sigil' => 'remarkup-assist has-tooltip', + 'sigil' => implode(' ', $sigils), 'meta' => $meta, 'mustcapture' => $mustcapture, 'target' => $target, 'tabindex' => -1, ), phutil_tag( 'div', array( 'class' => 'remarkup-assist phui-icon-view phui-font-fa bluegrey '.$action, ), $content)); } $buttons = phutil_tag( 'div', array( 'class' => 'remarkup-assist-bar', ), $buttons); $monospaced_textareas = null; $monospaced_textareas_class = null; $monospaced_textareas = $viewer ->loadPreferences() ->getPreference( PhabricatorUserPreferences::PREFERENCE_MONOSPACED_TEXTAREAS); if ($monospaced_textareas == 'enabled') { $monospaced_textareas_class = 'PhabricatorMonospaced'; } $this->setCustomClass( 'remarkup-assist-textarea '.$monospaced_textareas_class); return javelin_tag( 'div', array( 'sigil' => 'remarkup-assist-control', + 'class' => $this->getDisabled() ? 'disabled-control' : null, ), array( $buttons, parent::renderInput(), )); } } diff --git a/webroot/rsrc/css/phui/phui-form.css b/webroot/rsrc/css/phui/phui-form.css index cb8c0a7752..52f41e4ab6 100644 --- a/webroot/rsrc/css/phui/phui-form.css +++ b/webroot/rsrc/css/phui/phui-form.css @@ -1,155 +1,157 @@ /** * @provides phui-form-css */ select, textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"], div.jx-tokenizer-container { display: inline-block; height: 28px; line-height: 18px; color: #333; vertical-align: middle; font: {$basefont}; -webkit-font-smoothing: antialiased; } textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"], div.jx-tokenizer-container { padding: 4px 6px; background-color: #ffffff; border: 1px solid {$blueborder}; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -webkit-transition: border linear .05s, box-shadow linear .05s; -moz-transition: border linear .05s, box-shadow linear .05s; -o-transition: border linear .05s, box-shadow linear .05s; transition: border linear .05s, box-shadow linear .05s; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; /* iOS Safari */ -webkit-appearance: none; border-radius: 0; } textarea:focus, input[type="text"]:focus, input[type="password"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="date"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, input[type="number"]:focus, input[type="email"]:focus, input[type="url"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="color"]:focus, div.jx-tokenizer-container-focused { border-color: rgba(82, 168, 236, 0.8); outline: 0; /* IE6-9 */ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6); -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6); box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6); } input[type="radio"], input[type="checkbox"] { margin: 4px 0 0; margin-top: 1px \9; /* IE8-9 */ line-height: normal; } select { height: 24px; line-height: 24px; border: 1px solid {$lightgreyborder}; background-color: #ffffff; min-width: 140px; } select[multiple], select[size] { height: auto; } select:focus, input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } input:-moz-placeholder, textarea:-moz-placeholder { color: {$lightgreytext}; } input:-ms-input-placeholder, textarea:-ms-input-placeholder { color: {$lightgreytext}; } input::-webkit-input-placeholder, textarea::-webkit-input-placeholder { color: {$lightgreytext}; } select[disabled], -input[disabled] { +input[disabled], +textarea[disabled], +.disabled-control { opacity: 0.5; } .aphront-space-select-control-knob { margin: 2px 8px 2px 0; } .device .aphront-space-select-control-knob { margin-bottom: 8px; } diff --git a/webroot/rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js b/webroot/rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js index 34af63992c..a60c91e528 100644 --- a/webroot/rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js +++ b/webroot/rsrc/externals/javelin/lib/control/tokenizer/Tokenizer.js @@ -1,523 +1,529 @@ /** * @requires javelin-dom * javelin-util * javelin-stratcom * javelin-install * @provides javelin-tokenizer * @javelin */ /** * A tokenizer is a UI component similar to a text input, except that it * allows the user to input a list of items ("tokens"), generally from a fixed * set of results. A familiar example of this UI is the "To:" field of most * email clients, where the control autocompletes addresses from the user's * address book. * * @{JX.Tokenizer} is built on top of @{JX.Typeahead}, and primarily adds the * ability to choose multiple items. * * To build a @{JX.Tokenizer}, you need to do four things: * * 1. Construct it, padding a DOM node for it to attach to. See the constructor * for more information. * 2. Build a {@JX.Typeahead} and configure it with setTypeahead(). * 3. Configure any special options you want. * 4. Call start(). * * If you do this correctly, the input should suggest items and enter them as * tokens as the user types. * * When the tokenizer is focused, the CSS class `jx-tokenizer-container-focused` * is added to the container node. */ JX.install('Tokenizer', { construct : function(containerNode) { this._containerNode = containerNode; }, events : [ /** * Emitted when the value of the tokenizer changes, similar to an 'onchange' * from a . */ 'change'], properties : { limit : null, renderTokenCallback : null, - browseURI: null + browseURI: null, + disabled: false }, members : { _containerNode : null, _root : null, _frame: null, _focus : null, _orig : null, _typeahead : null, _tokenid : 0, _tokens : null, _tokenMap : null, _initialValue : null, _seq : 0, _lastvalue : null, _placeholder : null, start : function() { + if (this.getDisabled()) { + JX.DOM.alterClass(this._containerNode, 'disabled-control', true); + return; + } + if (__DEV__) { if (!this._typeahead) { throw new Error( 'JX.Tokenizer.start(): ' + 'No typeahead configured! Use setTypeahead() to provide a ' + 'typeahead.'); } } this._orig = JX.DOM.find(this._containerNode, 'input', 'tokenizer-input'); this._tokens = []; this._tokenMap = {}; try { this._frame = JX.DOM.findAbove(this._orig, 'div', 'tokenizer-frame'); } catch (e) { // Ignore, this tokenizer doesn't have a frame. } if (this._frame) { JX.DOM.alterClass(this._frame, 'has-browse', !!this.getBrowseURI()); JX.DOM.listen( this._frame, 'click', 'tokenizer-browse', JX.bind(this, this._onbrowse)); } var focus = this.buildInput(this._orig.value); this._focus = focus; var input_container = JX.DOM.scry( this._containerNode, 'div', 'tokenizer-input-container' ); input_container = input_container[0] || this._containerNode; JX.DOM.listen( focus, ['click', 'focus', 'blur', 'keydown', 'keypress', 'paste'], null, JX.bind(this, this.handleEvent)); // NOTE: Safari on the iPhone does not normally delegate click events on //
tags. This causes the event to fire. We want a click (in this // case, a touch) anywhere in the div to trigger this event so that we // can focus the input. Without this, you must tap an arbitrary area on // the left side of the input to focus it. // // http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html input_container.onclick = JX.bag; JX.DOM.listen( input_container, 'click', null, JX.bind( this, function(e) { if (e.getNode('remove')) { this._remove(e.getNodeData('token').key, true); } else if (e.getTarget() == this._root) { this.focus(); } })); var root = JX.$N('div'); root.id = this._orig.id; JX.DOM.alterClass(root, 'jx-tokenizer', true); root.style.cursor = 'text'; this._root = root; root.appendChild(focus); var typeahead = this._typeahead; typeahead.setInputNode(this._focus); typeahead.start(); setTimeout(JX.bind(this, function() { var container = this._orig.parentNode; JX.DOM.setContent(container, root); var map = this._initialValue || {}; for (var k in map) { this.addToken(k, map[k]); } JX.DOM.appendContent( root, JX.$N('div', {style: {clear: 'both'}}) ); this._redraw(); }), 0); }, setInitialValue : function(map) { this._initialValue = map; return this; }, setTypeahead : function(typeahead) { typeahead.setAllowNullSelection(false); typeahead.removeListener(); typeahead.listen( 'choose', JX.bind(this, function(result) { JX.Stratcom.context().prevent(); if (this.addToken(result.rel, result.name)) { if (this.shouldHideResultsOnChoose()) { this._typeahead.hide(); } this._typeahead.clear(); this._redraw(); this.focus(); } }) ); typeahead.listen( 'query', JX.bind( this, function(query) { // TODO: We should emit a 'query' event here to allow the caller to // generate tokens on the fly, e.g. email addresses or other freeform // or algorithmic tokens. // Then do this if something handles the event. // this._focus.value = ''; // this._redraw(); // this.focus(); if (query.length) { // Prevent this event if there's any text, so that we don't submit // the form (either we created a token or we failed to create a // token; in either case we shouldn't submit). If the query is // empty, allow the event so that the form submission takes place. JX.Stratcom.context().prevent(); } })); this._typeahead = typeahead; return this; }, shouldHideResultsOnChoose : function() { return true; }, handleEvent : function(e) { this._typeahead.handleEvent(e); if (e.getPrevented()) { return; } if (e.getType() == 'click') { if (e.getTarget() == this._root) { this.focus(); e.prevent(); return; } } else if (e.getType() == 'keydown') { this._onkeydown(e); } else if (e.getType() == 'blur') { this._didblur(); // Explicitly update the placeholder since we just wiped the field // value. this._typeahead.updatePlaceholder(); } else if (e.getType() == 'focus') { this._didfocus(); } else if (e.getType() == 'paste') { setTimeout(JX.bind(this, this._redraw), 0); } }, refresh : function() { this._redraw(true); return this; }, _redraw : function(force) { // If there are tokens in the tokenizer, never show a placeholder. // Otherwise, show one if one is configured. if (JX.keys(this._tokenMap).length) { this._typeahead.setPlaceholder(null); } else { this._typeahead.setPlaceholder(this._placeholder); } var focus = this._focus; if (focus.value === this._lastvalue && !force) { return; } this._lastvalue = focus.value; var metrics = JX.DOM.textMetrics( this._focus, 'jx-tokenizer-metrics'); metrics.y = null; metrics.x += 24; metrics.setDim(focus); // NOTE: Once, long ago, we set "focus.value = focus.value;" here to fix // an issue with copy/paste in Firefox not redrawing correctly. However, // this breaks input of Japanese glyphs in Chrome, and I can't reproduce // the original issue in modern Firefox. // // If future changes muck around with things here, test that Japanese // inputs still work. Example: // // - Switch to Hiragana mode. // - Type "ni". // - This should produce a glyph, not the value "n". // // With the assignment, Chrome loses the partial input on the "n" when // the value is assigned. }, setPlaceholder : function(string) { this._placeholder = string; return this; }, addToken : function(key, value) { if (key in this._tokenMap) { return false; } var focus = this._focus; var root = this._root; var token = this.buildToken(key, value); this._tokenMap[key] = { value : value, key : key, node : token }; this._tokens.push(key); root.insertBefore(token, focus); this._didChangeValue(); return true; }, removeToken : function(key) { return this._remove(key, false); }, buildInput: function(value) { return JX.$N('input', { className: 'jx-tokenizer-input', type: 'text', autocomplete: 'off', value: value }); }, /** * Generate a token based on a key and value. The "token" and "remove" * sigils are observed by a listener in start(). */ buildToken: function(key, value) { var input = JX.$N('input', { type: 'hidden', value: key, name: this._orig.name + '[' + (this._seq++) + ']' }); var remove = JX.$N('a', { className: 'jx-tokenizer-x', sigil: 'remove' }, '\u00d7'); // U+00D7 multiplication sign var display_token = value; var attrs = { className: 'jx-tokenizer-token', sigil: 'token', meta: {key: key} }; var container = JX.$N('a', attrs); var render_callback = this.getRenderTokenCallback(); if (render_callback) { display_token = render_callback(value, key, container); } JX.DOM.setContent(container, [display_token, input, remove]); return container; }, getTokens : function() { var result = {}; for (var key in this._tokenMap) { result[key] = this._tokenMap[key].value; } return result; }, _onkeydown : function(e) { var raw = e.getRawEvent(); if (raw.ctrlKey || raw.metaKey || raw.altKey) { return; } switch (e.getSpecialKey()) { case 'tab': var completed = this._typeahead.submit(); if (!completed) { this._focus.value = ''; } break; case 'delete': if (!this._focus.value.length) { var tok; while ((tok = this._tokens.pop())) { if (this._remove(tok, true)) { break; } } } break; case 'return': // Don't subject this to token limits. break; default: if (this.getLimit() && JX.keys(this._tokenMap).length == this.getLimit()) { e.prevent(); } setTimeout(JX.bind(this, this._redraw), 0); break; } }, _remove : function(index, focus) { if (!this._tokenMap[index]) { return false; } JX.DOM.remove(this._tokenMap[index].node); delete this._tokenMap[index]; this._redraw(true); focus && this.focus(); this._didChangeValue(); return true; }, _didChangeValue: function() { if (this.getBrowseURI()) { var button = JX.DOM.find(this._frame, 'a', 'tokenizer-browse'); JX.DOM.alterClass(button, 'disabled', !!this._shouldLockBrowse()); } this.invoke('change', this); }, _shouldLockBrowse: function() { var limit = this.getLimit(); if (!limit) { // If there's no limit, never lock the browse button. return false; } if (limit == 1) { // If the limit is 1, we'll replace the current token if the // user selects a new one, so we never need to lock the button. return false; } if (limit > JX.keys(this.getTokens()).length) { return false; } return true; }, focus : function() { var focus = this._focus; JX.DOM.show(focus); // NOTE: We must fire this focus event immediately (during event // handling) for the iPhone to bring up the keyboard. Previously this // focus was wrapped in setTimeout(), but it's unclear why that was // necessary. If this is adjusted later, make sure tapping the inactive // area of the tokenizer to focus it on the iPhone still brings up the // keyboard. JX.DOM.focus(focus); }, _didfocus : function() { JX.DOM.alterClass( this._containerNode, 'jx-tokenizer-container-focused', true); }, _didblur : function() { JX.DOM.alterClass( this._containerNode, 'jx-tokenizer-container-focused', false); this._focus.value = ''; this._redraw(); }, _onbrowse: function(e) { e.kill(); var uri = this.getBrowseURI(); if (!uri) { return; } if (this._shouldLockBrowse()) { return; } new JX.Workflow(uri, {exclude: JX.keys(this.getTokens()).join(',')}) .setHandler( JX.bind(this, function(r) { var source = this._typeahead.getDatasource(); source.addResult(r.token); var result = source.getResult(r.key); // If we have a limit of 1 token, replace the current token with // the new token if we currently have a token. if (this.getLimit() == 1) { for (var k in this.getTokens()) { this.removeToken(k); } } this.addToken(r.key, result.name); this.focus(); })) .start(); } } }); diff --git a/webroot/rsrc/js/application/policy/behavior-policy-control.js b/webroot/rsrc/js/application/policy/behavior-policy-control.js index ea66761191..9696a09dc8 100644 --- a/webroot/rsrc/js/application/policy/behavior-policy-control.js +++ b/webroot/rsrc/js/application/policy/behavior-policy-control.js @@ -1,130 +1,138 @@ /** * @provides javelin-behavior-policy-control * @requires javelin-behavior * javelin-dom * javelin-util * phuix-dropdown-menu * phuix-action-list-view * phuix-action-view * javelin-workflow * @javelin */ JX.behavior('policy-control', function(config) { var control = JX.$(config.controlID); var input = JX.$(config.inputID); var value = config.value; + if (config.disabled) { + JX.DOM.alterClass(control, 'disabled-control', true); + JX.DOM.listen(control, 'click', null, function(e) { + e.kill(); + }); + return; + } + var menu = new JX.PHUIXDropdownMenu(control) .setWidth(260) .setAlign('left'); menu.listen('open', function() { var list = new JX.PHUIXActionListView(); for (var ii = 0; ii < config.groups.length; ii++) { var group = config.groups[ii]; list.addItem( new JX.PHUIXActionView() .setName(config.labels[group]) .setLabel(true)); for (var jj = 0; jj < config.order[group].length; jj++) { var phid = config.order[group][jj]; var onselect; if (group == 'custom') { onselect = JX.bind(null, function(phid) { var uri = get_custom_uri(phid, config.capability); new JX.Workflow(uri) .setHandler(function(response) { if (!response.phid) { return; } replace_policy(phid, response.phid, response.info); select_policy(response.phid); }) .start(); }, phid); } else { onselect = JX.bind(null, select_policy, phid); } var option = config.options[phid]; var item = new JX.PHUIXActionView() .setName(option.name) .setIcon(option.icon + ' darkgreytext') .setHandler(JX.bind(null, function(fn, e) { e.prevent(); menu.close(); fn(); }, onselect)); if (phid == value) { item.setSelected(true); } list.addItem(item); } } menu.setContent(list.getNode()); }); var select_policy = function(phid) { JX.DOM.setContent( JX.DOM.find(control, 'span', 'policy-label'), render_option(phid)); input.value = phid; value = phid; }; var render_option = function(phid, with_title) { var option = config.options[phid]; var name = option.name; if (with_title && (option.full != option.name)) { name = JX.$N('span', {title: option.full}, name); } return [JX.$H(config.icons[option.icon]), name]; }; /** * Get the workflow URI to create or edit a policy with a given PHID. */ var get_custom_uri = function(phid, capability) { var uri = config.editURI; if (phid != config.customPlaceholder) { uri += phid + '/'; } uri += '?capability=' + capability; return uri; }; /** * Replace an existing policy option with a new one. Used to swap out custom * policies after the user edits them. */ var replace_policy = function(old_phid, new_phid, info) { config.options[new_phid] = info; for (var k in config.order) { for (var ii = 0; ii < config.order[k].length; ii++) { if (config.order[k][ii] == old_phid) { config.order[k][ii] = new_phid; return; } } } }; }); diff --git a/webroot/rsrc/js/core/Prefab.js b/webroot/rsrc/js/core/Prefab.js index 347c2b7e48..d48b295f0d 100644 --- a/webroot/rsrc/js/core/Prefab.js +++ b/webroot/rsrc/js/core/Prefab.js @@ -1,336 +1,340 @@ /** * @provides phabricator-prefab * @requires javelin-install * javelin-util * javelin-dom * javelin-typeahead * javelin-tokenizer * javelin-typeahead-preloaded-source * javelin-typeahead-ondemand-source * javelin-dom * javelin-stratcom * javelin-util * @javelin */ /** * Utilities for client-side rendering (the greatest thing in the world). */ JX.install('Prefab', { statics : { renderSelect : function(map, selected, attrs, order) { var select = JX.$N('select', attrs || {}); // Callers may optionally pass "order" to force options into a specific // order. Although most browsers do retain order, maps in Javascript // aren't technically ordered. Safari, at least, will reorder maps with // numeric keys. order = order || JX.keys(map); var k; for (var ii = 0; ii < order.length; ii++) { k = order[ii]; select.options[select.options.length] = new Option(map[k], k); if (k == selected) { select.value = k; } } select.value = select.value || order[0]; return select; }, newTokenizerFromTemplate: function(markup, config) { var template = JX.$H(markup).getFragment().firstChild; var container = JX.DOM.find(template, 'div', 'tokenizer-container'); container.id = ''; config.root = container; var build = JX.Prefab.buildTokenizer(config); build.node = template; return build; }, /** * Build a Phabricator tokenizer out of a configuration with application * sorting, datasource and placeholder rules. * * - `id` Root tokenizer ID (alternatively, pass `root`). * - `root` Root tokenizer node (replaces `id`). * - `src` Datasource URI. * - `ondemand` Optional, use an ondemand source. * - `value` Optional, initial value. * - `limit` Optional, token limit. * - `placeholder` Optional, placeholder text. * - `username` Optional, username to sort first (i.e., viewer). * - `icons` Optional, map of icons. * */ buildTokenizer : function(config) { config.icons = config.icons || {}; var root; try { root = config.root || JX.$(config.id); } catch (ex) { // If the root element does not exist, just return without building // anything. This happens in some cases -- like Conpherence -- where we // may load a tokenizer but not put it in the document. return; } var datasource; // Default to an ondemand source if no alternate configuration is // provided. var ondemand = true; if ('ondemand' in config) { ondemand = config.ondemand; } if (ondemand) { datasource = new JX.TypeaheadOnDemandSource(config.src); } else { datasource = new JX.TypeaheadPreloadedSource(config.src); } // Sort results so that the viewing user always comes up first; after // that, prefer unixname matches to realname matches. var sort_handler = function(value, list, cmp) { var priority_hits = {}; var self_hits = {}; var tokens = this.tokenize(value); for (var ii = 0; ii < list.length; ii++) { var item = list[ii]; for (var jj = 0; jj < tokens.length; jj++) { if (item.name.indexOf(tokens[jj]) === 0) { priority_hits[item.id] = true; } } if (!item.priority) { continue; } if (config.username && item.priority == config.username) { self_hits[item.id] = true; } for (var hh = 0; hh < tokens.length; hh++) { if (item.priority.substr(0, tokens[hh].length) == tokens[hh]) { priority_hits[item.id] = true; } } } list.sort(function(u, v) { if (self_hits[u.id] != self_hits[v.id]) { return self_hits[v.id] ? 1 : -1; } // If one result is open and one is closed, show the open result // first. The "!" tricks here are becaused closed values are display // strings, so the value is either `null` or some truthy string. If // we compare the values directly, we'll apply this rule to two // objects which are both closed but for different reasons, like // "Archived" and "Disabled". var u_open = !u.closed; var v_open = !v.closed; if (u_open != v_open) { if (u_open) { return -1; } else { return 1; } } if (priority_hits[u.id] != priority_hits[v.id]) { return priority_hits[v.id] ? 1 : -1; } // Sort users ahead of other result types. if (u.priorityType != v.priorityType) { if (u.priorityType == 'user') { return -1; } if (v.priorityType == 'user') { return 1; } } return cmp(u, v); }); }; datasource.setSortHandler(JX.bind(datasource, sort_handler)); datasource.setFilterHandler(JX.Prefab.filterClosedResults); datasource.setTransformer(JX.Prefab.transformDatasourceResults); var typeahead = new JX.Typeahead( root, JX.DOM.find(root, 'input', 'tokenizer-input')); typeahead.setDatasource(datasource); var tokenizer = new JX.Tokenizer(root); tokenizer.setTypeahead(typeahead); tokenizer.setRenderTokenCallback(function(value, key, container) { var result; if (value && (typeof value == 'object') && ('id' in value)) { // TODO: In this case, we've been passed the decoded wire format // dictionary directly. Token rendering is kind of a huge mess that // should be cleaned up and made more consistent. Just force our // way through for now. result = value; } else { result = datasource.getResult(key); } var icon; var type; var color; if (result) { icon = result.icon; value = result.displayName; type = result.tokenType; color = result.color; } else { icon = (config.icons || {})[key]; type = (config.types || {})[key]; color = (config.colors || {})[key]; } if (icon) { icon = JX.Prefab._renderIcon(icon); } type = type || 'object'; JX.DOM.alterClass(container, 'jx-tokenizer-token-' + type, true); if (color) { JX.DOM.alterClass(container, color, true); } return [icon, value]; }); if (config.placeholder) { tokenizer.setPlaceholder(config.placeholder); } if (config.limit) { tokenizer.setLimit(config.limit); } if (config.value) { tokenizer.setInitialValue(config.value); } if (config.browseURI) { tokenizer.setBrowseURI(config.browseURI); } + if (config.disabled) { + tokenizer.setDisabled(true); + } + JX.Stratcom.addData(root, {'tokenizer' : tokenizer}); return { tokenizer: tokenizer }; }, /** * Filter callback for tokenizers and typeaheads which filters out closed * or disabled objects unless they are the only options. */ filterClosedResults: function(value, list) { // Look for any open result. var has_open = false; var ii; for (ii = 0; ii < list.length; ii++) { if (!list[ii].closed) { has_open = true; break; } } if (!has_open) { // Everything is closed, so just use it as-is. return list; } // Otherwise, only display the open results. var results = []; for (ii = 0; ii < list.length; ii++) { if (!list[ii].closed) { results.push(list[ii]); } } return results; }, /** * Transform results from a wire format into a usable format in a standard * way. */ transformDatasourceResults: function(fields) { var closed = fields[9]; var closed_ui; if (closed) { closed_ui = JX.$N( 'div', {className: 'tokenizer-closed'}, closed); } var icon = fields[8]; var icon_ui; if (icon) { icon_ui = JX.Prefab._renderIcon(icon); } var display = JX.$N( 'div', {className: 'tokenizer-result'}, [icon_ui, fields[4] || fields[0], closed_ui]); if (closed) { JX.DOM.alterClass(display, 'tokenizer-result-closed', true); } return { name: fields[0], displayName: fields[4] || fields[0], display: display, uri: fields[1], id: fields[2], priority: fields[3], priorityType: fields[7], imageURI: fields[6], icon: icon, closed: closed, type: fields[5], sprite: fields[10], color: fields[11], tokenType: fields[12], unique: fields[13] || false }; }, _renderIcon: function(icon) { return JX.$N( 'span', {className: 'phui-icon-view phui-font-fa ' + icon}); } } }); diff --git a/webroot/rsrc/js/core/behavior-phabricator-remarkup-assist.js b/webroot/rsrc/js/core/behavior-phabricator-remarkup-assist.js index 266d2ecd37..e1407cd9f5 100644 --- a/webroot/rsrc/js/core/behavior-phabricator-remarkup-assist.js +++ b/webroot/rsrc/js/core/behavior-phabricator-remarkup-assist.js @@ -1,205 +1,209 @@ /** * @provides javelin-behavior-phabricator-remarkup-assist * @requires javelin-behavior * javelin-stratcom * javelin-dom * phabricator-phtize * phabricator-textareautils * javelin-workflow * javelin-vector */ JX.behavior('phabricator-remarkup-assist', function(config) { var pht = JX.phtize(config.pht); var edit_mode = 'normal'; var edit_root = null; function set_edit_mode(root, mode) { if (mode == edit_mode) { return; } // First, disable any active mode. if (edit_root) { if (edit_mode == 'fa-arrows-alt') { JX.DOM.alterClass(edit_root, 'remarkup-control-fullscreen-mode', false); JX.DOM.alterClass(document.body, 'remarkup-fullscreen-mode', false); } JX.DOM.find(edit_root, 'textarea').style.height = ''; } edit_root = root; edit_mode = mode; // Now, apply the new mode. if (mode == 'fa-arrows-alt') { JX.DOM.alterClass(edit_root, 'remarkup-control-fullscreen-mode', true); JX.DOM.alterClass(document.body, 'remarkup-fullscreen-mode', true); resizearea(); } JX.DOM.focus(JX.DOM.find(edit_root, 'textarea')); } function resizearea() { if (!edit_root) { return; } if (edit_mode != 'fa-arrows-alt') { return; } // In Firefox, a textarea with position "absolute" or "fixed", anchored // "top" and "bottom", and height "auto" renders as two lines high. Force // it to the correct height with Javascript. var area = JX.DOM.find(edit_root, 'textarea'); var v = JX.Vector.getViewport(); v.x = null; v.y -= 26; v.setDim(area); } JX.Stratcom.listen('resize', null, resizearea); JX.Stratcom.listen('keydown', null, function(e) { if (e.getSpecialKey() != 'esc') { return; } if (edit_mode != 'fa-arrows-alt') { return; } e.kill(); set_edit_mode(edit_root, 'normal'); }); function update(area, l, m, r) { // Replace the selection with the entire assisted text. JX.TextAreaUtils.setSelectionText(area, l + m + r); // Now, select just the middle part. For instance, if the user clicked // "B" to create bold text, we insert '**bold**' but just select the word // "bold" so if they type stuff they'll be editing the bold text. var range = JX.TextAreaUtils.getSelectionRange(area); JX.TextAreaUtils.setSelectionRange( area, range.start + l.length, range.start + l.length + m.length); } function prepend_char_to_lines(ch, sel, def) { if (sel) { sel = sel.split('\n'); } else { sel = [def]; } if (ch === '>') { for(var i=0; i < sel.length; i++) { if (sel[i][0] === '>') { ch = '>'; } else { ch = '> '; } sel[i] = ch + sel[i]; } return sel.join('\n'); } return sel.join('\n' + ch); } function assist(area, action, root) { // If the user has some text selected, we'll try to use that (for example, // if they have a word selected and want to bold it). Otherwise we'll insert // generic text. var sel = JX.TextAreaUtils.getSelectionText(area); var r = JX.TextAreaUtils.getSelectionRange(area); var ch; switch (action) { case 'fa-bold': update(area, '**', sel || pht('bold text'), '**'); break; case 'fa-italic': update(area, '//', sel || pht('italic text'), '//'); break; case 'fa-link': var name = pht('name'); if (/^https?:/i.test(sel)) { update(area, '[[ ' + sel + ' | ', name, ' ]]'); } else { update(area, '[[ ', pht('URL'), ' | ' + (sel || name) + ' ]]'); } break; case 'fa-text-width': update(area, '`', sel || pht('monospaced text'), '`'); break; case 'fa-list-ul': case 'fa-list-ol': ch = (action == 'fa-list-ol') ? ' # ' : ' - '; sel = prepend_char_to_lines(ch, sel, pht('List Item')); update(area, ((r.start === 0) ? '' : '\n\n') + ch, sel, '\n\n'); break; case 'fa-code': sel = sel || 'foreach ($list as $item) {\n work_miracles($item);\n}'; var code_prefix = (r.start === 0) ? '' : '\n'; update(area, code_prefix + '```\n', sel, '\n```'); break; case 'fa-quote-right': ch = '>'; sel = prepend_char_to_lines(ch, sel, pht('Quoted Text')); update(area, ((r.start === 0) ? '' : '\n\n'), sel, '\n\n'); break; case 'fa-table': var table_prefix = (r.start === 0 ? '' : '\n\n'); update(area, table_prefix + '| ', sel || pht('data'), ' |'); break; case 'fa-meh-o': new JX.Workflow('/macro/meme/create/') .setHandler(function(response) { update( area, '', sel, (r.start === 0 ? '' : '\n\n') + response.text + '\n\n'); }) .start(); break; case 'fa-cloud-upload': new JX.Workflow('/file/uploaddialog/').start(); break; case 'fa-arrows-alt': if (edit_mode == 'fa-arrows-alt') { set_edit_mode(root, 'normal'); } else { set_edit_mode(root, 'fa-arrows-alt'); } break; } } JX.Stratcom.listen( ['click'], 'remarkup-assist', function(e) { var data = e.getNodeData('remarkup-assist'); if (!data.action) { return; } e.kill(); + if (config.disabled) { + return; + } + var root = e.getNode('remarkup-assist-control'); var area = JX.DOM.find(root, 'textarea'); assist(area, data.action, root); }); });