1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-03 20:22:46 +01:00

(stable) Promote 2017 Week 3

This commit is contained in:
epriestley 2017-01-21 06:12:08 -08:00
commit 307b166207
93 changed files with 1833 additions and 1878 deletions

View file

@ -9,8 +9,8 @@ return array(
'names' => array(
'conpherence.pkg.css' => '0b64e988',
'conpherence.pkg.js' => '6249a1cf',
'core.pkg.css' => '9c725fa0',
'core.pkg.js' => 'a2ead3fe',
'core.pkg.css' => 'e75e4f9d',
'core.pkg.js' => '2291d3b2',
'darkconsole.pkg.js' => 'e7393ebb',
'differential.pkg.css' => '9535a7e6',
'differential.pkg.js' => 'ddfeb49b',
@ -21,7 +21,7 @@ return array(
'maniphest.pkg.js' => '5ab2753f',
'rsrc/css/aphront/aphront-bars.css' => '231ac33c',
'rsrc/css/aphront/dark-console.css' => 'f54bf286',
'rsrc/css/aphront/dialog-view.css' => '938f52c5',
'rsrc/css/aphront/dialog-view.css' => '5e5aa60b',
'rsrc/css/aphront/list-filter-view.css' => '5d6f0526',
'rsrc/css/aphront/multi-column.css' => '84cc6640',
'rsrc/css/aphront/notification.css' => '3f6c89c9',
@ -34,8 +34,8 @@ return array(
'rsrc/css/aphront/typeahead.css' => 'd4f16145',
'rsrc/css/application/almanac/almanac.css' => 'dbb9b3af',
'rsrc/css/application/auth/auth.css' => '0877ed6e',
'rsrc/css/application/base/main-menu-view.css' => 'f03e17be',
'rsrc/css/application/base/notification-menu.css' => '1e055865',
'rsrc/css/application/base/main-menu-view.css' => '8eac4166',
'rsrc/css/application/base/notification-menu.css' => '6a697e43',
'rsrc/css/application/base/phabricator-application-launch-view.css' => '95351601',
'rsrc/css/application/base/phui-theme.css' => '798c69b8',
'rsrc/css/application/base/standard-page-view.css' => '894d8a25',
@ -96,7 +96,7 @@ return array(
'rsrc/css/application/policy/policy-transaction-detail.css' => '82100a43',
'rsrc/css/application/policy/policy.css' => '957ea14c',
'rsrc/css/application/ponder/ponder-view.css' => 'fbd45f96',
'rsrc/css/application/project/project-card-view.css' => '9418c97d',
'rsrc/css/application/project/project-card-view.css' => 'd27c67ae',
'rsrc/css/application/project/project-view.css' => '1e6f7072',
'rsrc/css/application/releeph/releeph-core.css' => '9b3c5733',
'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5',
@ -108,7 +108,7 @@ return array(
'rsrc/css/application/tokens/tokens.css' => '3d0f239e',
'rsrc/css/application/uiexample/example.css' => '528b19de',
'rsrc/css/core/core.css' => 'd0801452',
'rsrc/css/core/remarkup.css' => 'aebc1180',
'rsrc/css/core/remarkup.css' => '4a2de2bb',
'rsrc/css/core/syntax.css' => '769d3498',
'rsrc/css/core/z-index.css' => '5e72c4e0',
'rsrc/css/diviner/diviner-shared.css' => 'aa3656aa',
@ -128,29 +128,29 @@ return array(
'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '9d9685d6',
'rsrc/css/phui/object-item/phui-oi-list-view.css' => 'bff632a4',
'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => 'a8beebea',
'rsrc/css/phui/phui-action-list.css' => 'e1d48300',
'rsrc/css/phui/phui-action-list.css' => '5679229f',
'rsrc/css/phui/phui-action-panel.css' => '91c7b835',
'rsrc/css/phui/phui-badge.css' => '3baef8db',
'rsrc/css/phui/phui-basic-nav-view.css' => '7093573b',
'rsrc/css/phui/phui-big-info-view.css' => 'bd903741',
'rsrc/css/phui/phui-box.css' => '33b629f8',
'rsrc/css/phui/phui-button.css' => '43f4912e',
'rsrc/css/phui/phui-button.css' => '9718cb0c',
'rsrc/css/phui/phui-chart.css' => '6bf6f78e',
'rsrc/css/phui/phui-cms.css' => 'be43c8a8',
'rsrc/css/phui/phui-comment-form.css' => '48fbd65d',
'rsrc/css/phui/phui-comment-panel.css' => 'f50152ad',
'rsrc/css/phui/phui-crumbs-view.css' => 'f82868f2',
'rsrc/css/phui/phui-curtain-view.css' => '947bf1a4',
'rsrc/css/phui/phui-document-pro.css' => 'c354e312',
'rsrc/css/phui/phui-document-pro.css' => 'f56738ed',
'rsrc/css/phui/phui-document-summary.css' => '9ca48bdf',
'rsrc/css/phui/phui-document.css' => 'c32e8dec',
'rsrc/css/phui/phui-feed-story.css' => '44a9c8e9',
'rsrc/css/phui/phui-fontkit.css' => '9cda225e',
'rsrc/css/phui/phui-form-view.css' => '04cc4771',
'rsrc/css/phui/phui-form-view.css' => 'adca31ce',
'rsrc/css/phui/phui-form.css' => '2342b0e5',
'rsrc/css/phui/phui-head-thing.css' => 'fd311e5f',
'rsrc/css/phui/phui-header-view.css' => '6ec8f155',
'rsrc/css/phui/phui-hovercard.css' => 'de1a2119',
'rsrc/css/phui/phui-hovercard.css' => 'e904f5dc',
'rsrc/css/phui/phui-icon-set-selector.css' => '1ab67aad',
'rsrc/css/phui/phui-icon.css' => '09f46dd9',
'rsrc/css/phui/phui-image-mask.css' => 'a8498f9c',
@ -162,7 +162,7 @@ return array(
'rsrc/css/phui/phui-object-box.css' => '6b487c57',
'rsrc/css/phui/phui-pager.css' => 'bea33d23',
'rsrc/css/phui/phui-pinboard-view.css' => '2495140e',
'rsrc/css/phui/phui-profile-menu.css' => '4768721a',
'rsrc/css/phui/phui-profile-menu.css' => 'c71ecdcd',
'rsrc/css/phui/phui-property-list-view.css' => '6d8e58ac',
'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591',
'rsrc/css/phui/phui-segment-bar-view.css' => '46342871',
@ -170,10 +170,10 @@ return array(
'rsrc/css/phui/phui-status.css' => 'd5263e49',
'rsrc/css/phui/phui-tag-view.css' => '84d65f26',
'rsrc/css/phui/phui-timeline-view.css' => 'bc523970',
'rsrc/css/phui/phui-two-column-view.css' => '7babf5b9',
'rsrc/css/phui/phui-two-column-view.css' => 'a0d3858a',
'rsrc/css/phui/workboards/phui-workboard-color.css' => 'b60ef38a',
'rsrc/css/phui/workboards/phui-workboard.css' => '16441d5e',
'rsrc/css/phui/workboards/phui-workcard.css' => '00979e40',
'rsrc/css/phui/workboards/phui-workboard.css' => 'c88912ee',
'rsrc/css/phui/workboards/phui-workcard.css' => 'cca5fa92',
'rsrc/css/phui/workboards/phui-workpanel.css' => 'a3a63478',
'rsrc/css/sprite-login.css' => '587d92d7',
'rsrc/css/sprite-tokens.css' => '9cdfd599',
@ -374,7 +374,7 @@ return array(
'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' => '2a171a9d',
'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => 'caade6f2',
'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'fb20ac8d',
'rsrc/js/application/aphlict/behavior-aphlict-status.js' => '5e2634b9',
'rsrc/js/application/aphlict/behavior-desktop-notifications-control.js' => 'edd1ba66',
@ -443,7 +443,7 @@ return array(
'rsrc/js/application/projects/WorkboardCard.js' => 'c587b80f',
'rsrc/js/application/projects/WorkboardColumn.js' => '21df4ff5',
'rsrc/js/application/projects/WorkboardController.js' => '55baf5ed',
'rsrc/js/application/projects/behavior-project-boards.js' => '14a1faae',
'rsrc/js/application/projects/behavior-project-boards.js' => '93ae974f',
'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',
@ -453,7 +453,7 @@ return array(
'rsrc/js/application/search/behavior-reorder-profile-menu-items.js' => 'e2e0a072',
'rsrc/js/application/search/behavior-reorder-queries.js' => 'e9581f08',
'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => '887ad43f',
'rsrc/js/application/transactions/behavior-comment-actions.js' => 'b52947eb',
'rsrc/js/application/transactions/behavior-comment-actions.js' => '9a6dd75c',
'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' => '94c65b72',
@ -530,18 +530,18 @@ return array(
'rsrc/js/core/behavior-toggle-class.js' => '92b9ec77',
'rsrc/js/core/behavior-tokenizer.js' => 'b3a4b884',
'rsrc/js/core/behavior-tooltip.js' => '42fcb747',
'rsrc/js/core/behavior-user-menu.js' => '31420f77',
'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' => '1aa4c968',
'rsrc/js/phui/behavior-phui-dropdown-menu.js' => 'b95d6f7d',
'rsrc/js/phui/behavior-phui-file-upload.js' => 'b003d4fb',
'rsrc/js/phui/behavior-phui-profile-menu.js' => '12884df9',
'rsrc/js/phui/behavior-phui-submenu.js' => 'a6f7a73b',
'rsrc/js/phui/behavior-phui-tab-group.js' => '0a0b10e9',
'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8',
'rsrc/js/phuix/PHUIXActionView.js' => '8cf6d262',
'rsrc/js/phuix/PHUIXActionView.js' => 'b3465b9b',
'rsrc/js/phuix/PHUIXAutocomplete.js' => '6d86ce8b',
'rsrc/js/phuix/PHUIXDropdownMenu.js' => '82e270da',
'rsrc/js/phuix/PHUIXDropdownMenu.js' => '8018ee50',
'rsrc/js/phuix/PHUIXFormControl.js' => 'bbece68d',
'rsrc/js/phuix/PHUIXIconView.js' => 'bff6884b',
),
@ -549,7 +549,7 @@ return array(
'almanac-css' => 'dbb9b3af',
'aphront-bars' => '231ac33c',
'aphront-dark-console-css' => 'f54bf286',
'aphront-dialog-view-css' => '938f52c5',
'aphront-dialog-view-css' => '5e5aa60b',
'aphront-list-filter-view-css' => '5d6f0526',
'aphront-multi-column-view-css' => '84cc6640',
'aphront-panel-view-css' => '8427b78d',
@ -596,7 +596,7 @@ return array(
'inline-comment-summary-css' => '51efda3a',
'javelin-aphlict' => '5359e785',
'javelin-behavior' => '61cbc29a',
'javelin-behavior-aphlict-dropdown' => '2a171a9d',
'javelin-behavior-aphlict-dropdown' => 'caade6f2',
'javelin-behavior-aphlict-listen' => 'fb20ac8d',
'javelin-behavior-aphlict-status' => '5e2634b9',
'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884',
@ -609,7 +609,7 @@ return array(
'javelin-behavior-bulk-job-reload' => 'edf8a145',
'javelin-behavior-calendar-month-view' => 'fe33e256',
'javelin-behavior-choose-control' => '327a00d1',
'javelin-behavior-comment-actions' => 'b52947eb',
'javelin-behavior-comment-actions' => '9a6dd75c',
'javelin-behavior-config-reorder-fields' => 'b6993408',
'javelin-behavior-conpherence-menu' => '7524fcfa',
'javelin-behavior-conpherence-participant-pane' => '8604caa8',
@ -687,15 +687,14 @@ return array(
'javelin-behavior-phabricator-watch-anchor' => '9f36c42d',
'javelin-behavior-pholio-mock-edit' => 'bee502c8',
'javelin-behavior-pholio-mock-view' => 'fbe497e7',
'javelin-behavior-phui-dropdown-menu' => '1aa4c968',
'javelin-behavior-phui-dropdown-menu' => 'b95d6f7d',
'javelin-behavior-phui-file-upload' => 'b003d4fb',
'javelin-behavior-phui-hovercards' => 'bcaccd64',
'javelin-behavior-phui-profile-menu' => '12884df9',
'javelin-behavior-phui-submenu' => 'a6f7a73b',
'javelin-behavior-phui-tab-group' => '0a0b10e9',
'javelin-behavior-policy-control' => 'd0c516d5',
'javelin-behavior-policy-rule-editor' => '5e9f347c',
'javelin-behavior-project-boards' => '14a1faae',
'javelin-behavior-project-boards' => '93ae974f',
'javelin-behavior-project-create' => '065227cc',
'javelin-behavior-quicksand-blacklist' => '7927a7d3',
'javelin-behavior-read-only-warning' => 'ba158207',
@ -721,6 +720,7 @@ return array(
'javelin-behavior-toggle-widget' => '3dbf94d5',
'javelin-behavior-typeahead-browse' => '635de1ec',
'javelin-behavior-typeahead-search' => '93d0c9e3',
'javelin-behavior-user-menu' => '31420f77',
'javelin-behavior-view-placeholder' => '47830651',
'javelin-behavior-workflow' => '0a3f3021',
'javelin-color' => '7e41274a',
@ -780,7 +780,7 @@ return array(
'paste-css' => '1898e534',
'path-typeahead' => 'f7fc67ec',
'people-profile-css' => '2473d929',
'phabricator-action-list-view-css' => 'e1d48300',
'phabricator-action-list-view-css' => '5679229f',
'phabricator-application-launch-view-css' => '95351601',
'phabricator-busy' => '59a7976a',
'phabricator-chatlog-css' => 'd295b020',
@ -798,15 +798,15 @@ return array(
'phabricator-flag-css' => 'bba8f811',
'phabricator-keyboard-shortcut' => '1ae869f2',
'phabricator-keyboard-shortcut-manager' => '4a021c10',
'phabricator-main-menu-view' => 'f03e17be',
'phabricator-main-menu-view' => '8eac4166',
'phabricator-nav-view-css' => 'b29426e9',
'phabricator-notification' => 'ccf1cbf8',
'phabricator-notification-css' => '3f6c89c9',
'phabricator-notification-menu-css' => '1e055865',
'phabricator-notification-menu-css' => '6a697e43',
'phabricator-object-selector-css' => '85ee8ce6',
'phabricator-phtize' => 'd254d646',
'phabricator-prefab' => '8d40ae75',
'phabricator-remarkup-css' => 'aebc1180',
'phabricator-remarkup-css' => '4a2de2bb',
'phabricator-search-results-css' => '64ad079a',
'phabricator-shaped-request' => '7cbe244b',
'phabricator-slowvote-css' => 'a94b7230',
@ -842,7 +842,7 @@ return array(
'phui-basic-nav-view-css' => '7093573b',
'phui-big-info-view-css' => 'bd903741',
'phui-box-css' => '33b629f8',
'phui-button-css' => '43f4912e',
'phui-button-css' => '9718cb0c',
'phui-calendar-css' => '477acfaa',
'phui-calendar-day-css' => '572b1893',
'phui-calendar-list-css' => 'fcc9fb41',
@ -855,16 +855,16 @@ return array(
'phui-curtain-view-css' => '947bf1a4',
'phui-document-summary-view-css' => '9ca48bdf',
'phui-document-view-css' => 'c32e8dec',
'phui-document-view-pro-css' => 'c354e312',
'phui-document-view-pro-css' => 'f56738ed',
'phui-feed-story-css' => '44a9c8e9',
'phui-font-icon-base-css' => '870a7360',
'phui-fontkit-css' => '9cda225e',
'phui-form-css' => '2342b0e5',
'phui-form-view-css' => '04cc4771',
'phui-form-view-css' => 'adca31ce',
'phui-head-thing-view-css' => 'fd311e5f',
'phui-header-view-css' => '6ec8f155',
'phui-hovercard' => '1bd28176',
'phui-hovercard-view-css' => 'de1a2119',
'phui-hovercard-view-css' => 'e904f5dc',
'phui-icon-set-selector-css' => '1ab67aad',
'phui-icon-view-css' => '09f46dd9',
'phui-image-mask-css' => 'a8498f9c',
@ -883,7 +883,7 @@ return array(
'phui-oi-simple-ui-css' => 'a8beebea',
'phui-pager-css' => 'bea33d23',
'phui-pinboard-view-css' => '2495140e',
'phui-profile-menu-css' => '4768721a',
'phui-profile-menu-css' => 'c71ecdcd',
'phui-property-list-view-css' => '6d8e58ac',
'phui-remarkup-preview-css' => '1a8f2591',
'phui-segment-bar-view-css' => '46342871',
@ -892,22 +892,22 @@ return array(
'phui-tag-view-css' => '84d65f26',
'phui-theme-css' => '798c69b8',
'phui-timeline-view-css' => 'bc523970',
'phui-two-column-view-css' => '7babf5b9',
'phui-two-column-view-css' => 'a0d3858a',
'phui-workboard-color-css' => 'b60ef38a',
'phui-workboard-view-css' => '16441d5e',
'phui-workcard-view-css' => '00979e40',
'phui-workboard-view-css' => 'c88912ee',
'phui-workcard-view-css' => 'cca5fa92',
'phui-workpanel-view-css' => 'a3a63478',
'phuix-action-list-view' => 'b5c256b8',
'phuix-action-view' => '8cf6d262',
'phuix-action-view' => 'b3465b9b',
'phuix-autocomplete' => '6d86ce8b',
'phuix-dropdown-menu' => '82e270da',
'phuix-dropdown-menu' => '8018ee50',
'phuix-form-control-view' => 'bbece68d',
'phuix-icon-view' => 'bff6884b',
'policy-css' => '957ea14c',
'policy-edit-css' => '815c66f7',
'policy-transaction-detail-css' => '82100a43',
'ponder-view-css' => 'fbd45f96',
'project-card-view-css' => '9418c97d',
'project-card-view-css' => 'd27c67ae',
'project-view-css' => '1e6f7072',
'releeph-core' => '9b3c5733',
'releeph-preview-branch' => 'b7a6f4a5',
@ -1030,11 +1030,6 @@ return array(
'javelin-dom',
'javelin-typeahead-normalizer',
),
'12884df9' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
),
'13c739ea' => array(
'javelin-behavior',
'javelin-stratcom',
@ -1049,27 +1044,12 @@ return array(
'javelin-dom',
'javelin-history',
),
'14a1faae' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-vector',
'javelin-stratcom',
'javelin-workflow',
'javelin-workboard-controller',
),
'185bbd53' => array(
'javelin-install',
),
'19f9369b' => array(
'phui-oi-list-view-css',
),
'1aa4c968' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'phuix-dropdown-menu',
),
'1ad0a787' => array(
'javelin-install',
'javelin-reactor',
@ -1127,17 +1107,6 @@ return array(
'javelin-install',
'javelin-util',
),
'2a171a9d' => array(
'javelin-behavior',
'javelin-request',
'javelin-stratcom',
'javelin-vector',
'javelin-dom',
'javelin-uri',
'javelin-behavior-device',
'phabricator-title',
'phabricator-favicon',
),
'2b8de964' => array(
'javelin-install',
'javelin-util',
@ -1157,6 +1126,9 @@ return array(
'2ee659ce' => array(
'javelin-install',
),
'31420f77' => array(
'javelin-behavior',
),
'320810c8' => array(
'javelin-install',
'javelin-dom',
@ -1538,6 +1510,13 @@ return array(
'javelin-behavior',
'javelin-history',
),
'8018ee50' => array(
'javelin-install',
'javelin-util',
'javelin-dom',
'javelin-vector',
'javelin-stratcom',
),
'805b806a' => array(
'javelin-magical-init',
'javelin-install',
@ -1545,13 +1524,6 @@ return array(
'javelin-vector',
'javelin-stratcom',
),
'82e270da' => array(
'javelin-install',
'javelin-util',
'javelin-dom',
'javelin-vector',
'javelin-stratcom',
),
'834a1173' => array(
'javelin-behavior',
'javelin-scrollbar',
@ -1610,11 +1582,6 @@ return array(
'javelin-stratcom',
'javelin-behavior',
),
'8cf6d262' => array(
'javelin-install',
'javelin-dom',
'javelin-util',
),
'8d3bc1b2' => array(
'javelin-dom',
'javelin-util',
@ -1633,6 +1600,9 @@ return array(
'javelin-stratcom',
'javelin-util',
),
'8eac4166' => array(
'phui-theme-css',
),
'8ff5e24c' => array(
'javelin-behavior',
'javelin-stratcom',
@ -1654,6 +1624,15 @@ return array(
'javelin-stratcom',
'javelin-dom',
),
'93ae974f' => array(
'javelin-behavior',
'javelin-dom',
'javelin-util',
'javelin-vector',
'javelin-stratcom',
'javelin-workflow',
'javelin-workboard-controller',
),
'93d0c9e3' => array(
'javelin-behavior',
'javelin-stratcom',
@ -1703,6 +1682,15 @@ return array(
'phabricator-phtize',
'changeset-view-manager',
),
'9a6dd75c' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-workflow',
'javelin-dom',
'phuix-form-control-view',
'phuix-icon-view',
'javelin-behavior-phabricator-gesture',
),
'9a8cb501' => array(
'aphront-typeahead-control-css',
'phui-tag-view-css',
@ -1859,6 +1847,11 @@ return array(
'javelin-uri',
'javelin-request',
),
'b3465b9b' => array(
'javelin-install',
'javelin-dom',
'javelin-util',
),
'b3a4b884' => array(
'javelin-behavior',
'phabricator-prefab',
@ -1872,15 +1865,6 @@ return array(
'javelin-typeahead-preloaded-source',
'javelin-util',
),
'b52947eb' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-workflow',
'javelin-dom',
'phuix-form-control-view',
'phuix-icon-view',
'javelin-behavior-phabricator-gesture',
),
'b59e1e96' => array(
'javelin-behavior',
'javelin-stratcom',
@ -1911,6 +1895,12 @@ return array(
'javelin-json',
'phabricator-draggable-list',
),
'b95d6f7d' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'phuix-dropdown-menu',
),
'ba158207' => array(
'javelin-behavior',
'javelin-uri',
@ -2003,6 +1993,17 @@ return array(
'javelin-stratcom',
'phabricator-phtize',
),
'caade6f2' => array(
'javelin-behavior',
'javelin-request',
'javelin-stratcom',
'javelin-vector',
'javelin-dom',
'javelin-uri',
'javelin-behavior-device',
'phabricator-title',
'phabricator-favicon',
),
'ccf1cbf8' => array(
'javelin-install',
'javelin-dom',
@ -2168,9 +2169,6 @@ return array(
'javelin-workflow',
'javelin-json',
),
'f03e17be' => array(
'phui-theme-css',
),
'f12cbc9f' => array(
'phui-oi-list-view-css',
),
@ -2429,6 +2427,9 @@ return array(
'conpherence-thread-manager',
'javelin-behavior-detect-timezone',
'javelin-behavior-setup-check-https',
'javelin-behavior-aphlict-status',
'javelin-behavior-user-menu',
'phabricator-favicon',
),
'darkconsole.pkg.js' => array(
'javelin-behavior-dark-console',

View file

@ -84,6 +84,9 @@ return array(
'conpherence-thread-manager',
'javelin-behavior-detect-timezone',
'javelin-behavior-setup-check-https',
'javelin-behavior-aphlict-status',
'javelin-behavior-user-menu',
'phabricator-favicon',
),
'core.pkg.css' => array(
'phabricator-core-css',

View file

@ -0,0 +1,9 @@
<?php
$table = new PhabricatorProfileMenuItemConfiguration();
$conn_w = $table->establishConnection('w');
queryfx(
$conn_w,
'DELETE FROM %T WHERE menuItemKey = "motivator"',
$table->getTableName());

View file

@ -617,6 +617,7 @@ phutil_register_library_map(array(
'DiffusionCommitActionTransaction' => 'applications/diffusion/xaction/DiffusionCommitActionTransaction.php',
'DiffusionCommitAffectedFilesHeraldField' => 'applications/diffusion/herald/DiffusionCommitAffectedFilesHeraldField.php',
'DiffusionCommitAuditTransaction' => 'applications/diffusion/xaction/DiffusionCommitAuditTransaction.php',
'DiffusionCommitAuditorsHeraldField' => 'applications/diffusion/herald/DiffusionCommitAuditorsHeraldField.php',
'DiffusionCommitAuditorsTransaction' => 'applications/diffusion/xaction/DiffusionCommitAuditorsTransaction.php',
'DiffusionCommitAuthorHeraldField' => 'applications/diffusion/herald/DiffusionCommitAuthorHeraldField.php',
'DiffusionCommitAutocloseHeraldField' => 'applications/diffusion/herald/DiffusionCommitAutocloseHeraldField.php',
@ -629,6 +630,7 @@ phutil_register_library_map(array(
'DiffusionCommitDiffContentHeraldField' => 'applications/diffusion/herald/DiffusionCommitDiffContentHeraldField.php',
'DiffusionCommitDiffContentRemovedHeraldField' => 'applications/diffusion/herald/DiffusionCommitDiffContentRemovedHeraldField.php',
'DiffusionCommitDiffEnormousHeraldField' => 'applications/diffusion/herald/DiffusionCommitDiffEnormousHeraldField.php',
'DiffusionCommitDraftEngine' => 'applications/diffusion/engine/DiffusionCommitDraftEngine.php',
'DiffusionCommitEditConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionCommitEditConduitAPIMethod.php',
'DiffusionCommitEditController' => 'applications/diffusion/controller/DiffusionCommitEditController.php',
'DiffusionCommitEditEngine' => 'applications/diffusion/editor/DiffusionCommitEditEngine.php',
@ -1697,7 +1699,6 @@ phutil_register_library_map(array(
'PHUIListItemView' => 'view/phui/PHUIListItemView.php',
'PHUIListView' => 'view/phui/PHUIListView.php',
'PHUIListViewTestCase' => 'view/layout/__tests__/PHUIListViewTestCase.php',
'PHUIMainMenuView' => 'view/phui/PHUIMainMenuView.php',
'PHUIObjectBoxView' => 'view/phui/PHUIObjectBoxView.php',
'PHUIObjectItemListExample' => 'applications/uiexample/examples/PHUIObjectItemListExample.php',
'PHUIObjectItemListView' => 'view/phui/PHUIObjectItemListView.php',
@ -2591,7 +2592,6 @@ phutil_register_library_map(array(
'PhabricatorEditEngineConfigurationTransactionQuery' => 'applications/transactions/query/PhabricatorEditEngineConfigurationTransactionQuery.php',
'PhabricatorEditEngineConfigurationViewController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php',
'PhabricatorEditEngineController' => 'applications/transactions/controller/PhabricatorEditEngineController.php',
'PhabricatorEditEngineCreateQuickActions' => 'applications/settings/quickmenu/PhabricatorEditEngineCreateQuickActions.php',
'PhabricatorEditEngineDatasource' => 'applications/transactions/typeahead/PhabricatorEditEngineDatasource.php',
'PhabricatorEditEngineExtension' => 'applications/transactions/engineextension/PhabricatorEditEngineExtension.php',
'PhabricatorEditEngineExtensionModule' => 'applications/transactions/engineextension/PhabricatorEditEngineExtensionModule.php',
@ -2669,10 +2669,8 @@ phutil_register_library_map(array(
'PhabricatorFactSpec' => 'applications/fact/spec/PhabricatorFactSpec.php',
'PhabricatorFactUpdateIterator' => 'applications/fact/extract/PhabricatorFactUpdateIterator.php',
'PhabricatorFavoritesApplication' => 'applications/favorites/application/PhabricatorFavoritesApplication.php',
'PhabricatorFavoritesConstants' => 'applications/favorites/constants/PhabricatorFavoritesConstants.php',
'PhabricatorFavoritesController' => 'applications/favorites/controller/PhabricatorFavoritesController.php',
'PhabricatorFavoritesMainController' => 'applications/favorites/controller/PhabricatorFavoritesMainController.php',
'PhabricatorFavoritesManageProfileMenuItem' => 'applications/favorites/menuitem/PhabricatorFavoritesManageProfileMenuItem.php',
'PhabricatorFavoritesMenuItemController' => 'applications/favorites/controller/PhabricatorFavoritesMenuItemController.php',
'PhabricatorFavoritesProfileMenuEngine' => 'applications/favorites/engine/PhabricatorFavoritesProfileMenuEngine.php',
'PhabricatorFaxContentSource' => 'infrastructure/contentsource/PhabricatorFaxContentSource.php',
@ -2827,7 +2825,6 @@ phutil_register_library_map(array(
'PhabricatorHelpDocumentationController' => 'applications/help/controller/PhabricatorHelpDocumentationController.php',
'PhabricatorHelpEditorProtocolController' => 'applications/help/controller/PhabricatorHelpEditorProtocolController.php',
'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/PhabricatorHelpKeyboardShortcutController.php',
'PhabricatorHelpMainMenuBarExtension' => 'applications/help/extension/PhabricatorHelpMainMenuBarExtension.php',
'PhabricatorHeraldApplication' => 'applications/herald/application/PhabricatorHeraldApplication.php',
'PhabricatorHeraldContentSource' => 'applications/herald/contentsource/PhabricatorHeraldContentSource.php',
'PhabricatorHighSecurityRequestExceptionHandler' => 'aphront/handler/PhabricatorHighSecurityRequestExceptionHandler.php',
@ -2840,7 +2837,6 @@ phutil_register_library_map(array(
'PhabricatorHomeMenuItemController' => 'applications/home/controller/PhabricatorHomeMenuItemController.php',
'PhabricatorHomePreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorHomePreferencesSettingsPanel.php',
'PhabricatorHomeProfileMenuEngine' => 'applications/home/engine/PhabricatorHomeProfileMenuEngine.php',
'PhabricatorHomeQuickCreateController' => 'applications/home/controller/PhabricatorHomeQuickCreateController.php',
'PhabricatorHovercardEngineExtension' => 'applications/search/engineextension/PhabricatorHovercardEngineExtension.php',
'PhabricatorHovercardEngineExtensionModule' => 'applications/search/engineextension/PhabricatorHovercardEngineExtensionModule.php',
'PhabricatorIDsSearchEngineExtension' => 'applications/search/engineextension/PhabricatorIDsSearchEngineExtension.php',
@ -3024,7 +3020,6 @@ phutil_register_library_map(array(
'PhabricatorModularTransactionType' => 'applications/transactions/storage/PhabricatorModularTransactionType.php',
'PhabricatorMonospacedFontSetting' => 'applications/settings/setting/PhabricatorMonospacedFontSetting.php',
'PhabricatorMonospacedTextareasSetting' => 'applications/settings/setting/PhabricatorMonospacedTextareasSetting.php',
'PhabricatorMotivatorProfileMenuItem' => 'applications/search/menuitem/PhabricatorMotivatorProfileMenuItem.php',
'PhabricatorMultiColumnUIExample' => 'applications/uiexample/examples/PhabricatorMultiColumnUIExample.php',
'PhabricatorMultiFactorSettingsPanel' => 'applications/settings/panel/PhabricatorMultiFactorSettingsPanel.php',
'PhabricatorMultimeterApplication' => 'applications/multimeter/application/PhabricatorMultimeterApplication.php',
@ -3316,7 +3311,6 @@ phutil_register_library_map(array(
'PhabricatorPeopleLogQuery' => 'applications/people/query/PhabricatorPeopleLogQuery.php',
'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php',
'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php',
'PhabricatorPeopleMainMenuBarExtension' => 'applications/people/extension/PhabricatorPeopleMainMenuBarExtension.php',
'PhabricatorPeopleManageProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php',
'PhabricatorPeopleNewController' => 'applications/people/controller/PhabricatorPeopleNewController.php',
'PhabricatorPeopleNoOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleNoOwnerDatasource.php',
@ -3422,7 +3416,6 @@ phutil_register_library_map(array(
'PhabricatorPolicyTestObject' => 'applications/policy/__tests__/PhabricatorPolicyTestObject.php',
'PhabricatorPolicyType' => 'applications/policy/constants/PhabricatorPolicyType.php',
'PhabricatorPonderApplication' => 'applications/ponder/application/PhabricatorPonderApplication.php',
'PhabricatorProfileMenuCollapsedSetting' => 'applications/settings/setting/PhabricatorProfileMenuCollapsedSetting.php',
'PhabricatorProfileMenuEditEngine' => 'applications/search/editor/PhabricatorProfileMenuEditEngine.php',
'PhabricatorProfileMenuEditor' => 'applications/search/editor/PhabricatorProfileMenuEditor.php',
'PhabricatorProfileMenuEngine' => 'applications/search/engine/PhabricatorProfileMenuEngine.php',
@ -3562,7 +3555,6 @@ phutil_register_library_map(array(
'PhabricatorQueryOrderItem' => 'infrastructure/query/order/PhabricatorQueryOrderItem.php',
'PhabricatorQueryOrderTestCase' => 'infrastructure/query/order/__tests__/PhabricatorQueryOrderTestCase.php',
'PhabricatorQueryOrderVector' => 'infrastructure/query/order/PhabricatorQueryOrderVector.php',
'PhabricatorQuickActions' => 'applications/settings/quickmenu/PhabricatorQuickActions.php',
'PhabricatorRateLimitRequestExceptionHandler' => 'aphront/handler/PhabricatorRateLimitRequestExceptionHandler.php',
'PhabricatorRecaptchaConfigOptions' => 'applications/config/option/PhabricatorRecaptchaConfigOptions.php',
'PhabricatorRecipientHasBadgeEdgeType' => 'applications/badges/edge/PhabricatorRecipientHasBadgeEdgeType.php',
@ -3771,7 +3763,6 @@ phutil_register_library_map(array(
'PhabricatorSettingsListController' => 'applications/settings/controller/PhabricatorSettingsListController.php',
'PhabricatorSettingsLogsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsLogsPanelGroup.php',
'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php',
'PhabricatorSettingsMainMenuBarExtension' => 'applications/settings/extension/PhabricatorSettingsMainMenuBarExtension.php',
'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php',
'PhabricatorSettingsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsPanelGroup.php',
'PhabricatorSettingsTimezoneController' => 'applications/settings/controller/PhabricatorSettingsTimezoneController.php',
@ -5330,6 +5321,7 @@ phutil_register_library_map(array(
'DiffusionCommitActionTransaction' => 'DiffusionCommitTransactionType',
'DiffusionCommitAffectedFilesHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitAuditTransaction' => 'DiffusionCommitActionTransaction',
'DiffusionCommitAuditorsHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitAuditorsTransaction' => 'DiffusionCommitTransactionType',
'DiffusionCommitAuthorHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitAutocloseHeraldField' => 'DiffusionCommitHeraldField',
@ -5342,6 +5334,7 @@ phutil_register_library_map(array(
'DiffusionCommitDiffContentHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitDiffContentRemovedHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitDiffEnormousHeraldField' => 'DiffusionCommitHeraldField',
'DiffusionCommitDraftEngine' => 'PhabricatorDraftEngine',
'DiffusionCommitEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'DiffusionCommitEditController' => 'DiffusionController',
'DiffusionCommitEditEngine' => 'PhabricatorEditEngine',
@ -6574,7 +6567,6 @@ phutil_register_library_map(array(
'PHUIListItemView' => 'AphrontTagView',
'PHUIListView' => 'AphrontTagView',
'PHUIListViewTestCase' => 'PhabricatorTestCase',
'PHUIMainMenuView' => 'AphrontView',
'PHUIObjectBoxView' => 'AphrontTagView',
'PHUIObjectItemListExample' => 'PhabricatorUIExample',
'PHUIObjectItemListView' => 'AphrontTagView',
@ -6678,7 +6670,7 @@ phutil_register_library_map(array(
'PhabricatorAccessLogConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorAccessibilitySetting' => 'PhabricatorSelectSetting',
'PhabricatorAccountSettingsPanel' => 'PhabricatorEditEngineSettingsPanel',
'PhabricatorActionListView' => 'AphrontView',
'PhabricatorActionListView' => 'AphrontTagView',
'PhabricatorActionView' => 'AphrontView',
'PhabricatorActivitySettingsPanel' => 'PhabricatorSettingsPanel',
'PhabricatorAdministratorsPolicyRule' => 'PhabricatorPolicyRule',
@ -7612,7 +7604,6 @@ phutil_register_library_map(array(
'PhabricatorEditEngineConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorEditEngineConfigurationViewController' => 'PhabricatorEditEngineController',
'PhabricatorEditEngineController' => 'PhabricatorApplicationTransactionController',
'PhabricatorEditEngineCreateQuickActions' => 'PhabricatorQuickActions',
'PhabricatorEditEngineDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorEditEngineExtension' => 'Phobject',
'PhabricatorEditEngineExtensionModule' => 'PhabricatorConfigModule',
@ -7692,10 +7683,8 @@ phutil_register_library_map(array(
'PhabricatorFactSpec' => 'Phobject',
'PhabricatorFactUpdateIterator' => 'PhutilBufferedIterator',
'PhabricatorFavoritesApplication' => 'PhabricatorApplication',
'PhabricatorFavoritesConstants' => 'PhabricatorFavoritesController',
'PhabricatorFavoritesController' => 'PhabricatorController',
'PhabricatorFavoritesMainController' => 'PhabricatorFavoritesController',
'PhabricatorFavoritesManageProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorFavoritesMenuItemController' => 'PhabricatorFavoritesController',
'PhabricatorFavoritesProfileMenuEngine' => 'PhabricatorProfileMenuEngine',
'PhabricatorFaxContentSource' => 'PhabricatorContentSource',
@ -7886,7 +7875,6 @@ phutil_register_library_map(array(
'PhabricatorHelpDocumentationController' => 'PhabricatorHelpController',
'PhabricatorHelpEditorProtocolController' => 'PhabricatorHelpController',
'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController',
'PhabricatorHelpMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension',
'PhabricatorHeraldApplication' => 'PhabricatorApplication',
'PhabricatorHeraldContentSource' => 'PhabricatorContentSource',
'PhabricatorHighSecurityRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler',
@ -7899,7 +7887,6 @@ phutil_register_library_map(array(
'PhabricatorHomeMenuItemController' => 'PhabricatorHomeController',
'PhabricatorHomePreferencesSettingsPanel' => 'PhabricatorSettingsPanel',
'PhabricatorHomeProfileMenuEngine' => 'PhabricatorProfileMenuEngine',
'PhabricatorHomeQuickCreateController' => 'PhabricatorHomeController',
'PhabricatorHovercardEngineExtension' => 'Phobject',
'PhabricatorHovercardEngineExtensionModule' => 'PhabricatorConfigModule',
'PhabricatorIDsSearchEngineExtension' => 'PhabricatorSearchEngineExtension',
@ -8093,7 +8080,6 @@ phutil_register_library_map(array(
'PhabricatorModularTransactionType' => 'Phobject',
'PhabricatorMonospacedFontSetting' => 'PhabricatorStringSetting',
'PhabricatorMonospacedTextareasSetting' => 'PhabricatorSelectSetting',
'PhabricatorMotivatorProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorMultiColumnUIExample' => 'PhabricatorUIExample',
'PhabricatorMultiFactorSettingsPanel' => 'PhabricatorSettingsPanel',
'PhabricatorMultimeterApplication' => 'PhabricatorApplication',
@ -8449,7 +8435,6 @@ phutil_register_library_map(array(
'PhabricatorPeopleLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController',
'PhabricatorPeopleMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension',
'PhabricatorPeopleManageProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorPeopleNewController' => 'PhabricatorPeopleController',
'PhabricatorPeopleNoOwnerDatasource' => 'PhabricatorTypeaheadDatasource',
@ -8575,7 +8560,6 @@ phutil_register_library_map(array(
),
'PhabricatorPolicyType' => 'PhabricatorPolicyConstants',
'PhabricatorPonderApplication' => 'PhabricatorApplication',
'PhabricatorProfileMenuCollapsedSetting' => 'PhabricatorInternalSetting',
'PhabricatorProfileMenuEditEngine' => 'PhabricatorEditEngine',
'PhabricatorProfileMenuEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorProfileMenuEngine' => 'Phobject',
@ -8749,7 +8733,6 @@ phutil_register_library_map(array(
'Phobject',
'Iterator',
),
'PhabricatorQuickActions' => 'Phobject',
'PhabricatorRateLimitRequestExceptionHandler' => 'PhabricatorRequestExceptionHandler',
'PhabricatorRecaptchaConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorRecipientHasBadgeEdgeType' => 'PhabricatorEdgeType',
@ -8796,6 +8779,7 @@ phutil_register_library_map(array(
'PhabricatorApplicationTransactionInterface',
'PhabricatorFulltextInterface',
'PhabricatorConduitResultInterface',
'PhabricatorDraftInterface',
),
'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
@ -9015,7 +8999,6 @@ phutil_register_library_map(array(
'PhabricatorSettingsListController' => 'PhabricatorController',
'PhabricatorSettingsLogsPanelGroup' => 'PhabricatorSettingsPanelGroup',
'PhabricatorSettingsMainController' => 'PhabricatorController',
'PhabricatorSettingsMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension',
'PhabricatorSettingsPanel' => 'Phobject',
'PhabricatorSettingsPanelGroup' => 'Phobject',
'PhabricatorSettingsTimezoneController' => 'PhabricatorController',

View file

@ -75,7 +75,7 @@ final class AuditQueryConduitAPIMethod extends AuditConduitAPIMethod {
PhabricatorAuditCommitStatusConstants::CONCERN_RAISED,
),
self::AUDIT_LEGACYSTATUS_ACCEPTED => array(
PhabricatorAuditCommitStatusConstants::CONCERN_ACCEPTED,
PhabricatorAuditCommitStatusConstants::FULLY_AUDITED,
),
self::AUDIT_LEGACYSTATUS_PARTIAL => array(
PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED,

View file

@ -14,7 +14,8 @@ final class PhabricatorCommitSearchEngine
public function newQuery() {
return id(new DiffusionCommitQuery())
->needAuditRequests(true)
->needCommitData(true);
->needCommitData(true)
->needDrafts(true);
}
protected function newResultBuckets() {
@ -140,7 +141,8 @@ final class PhabricatorCommitSearchEngine
$bucket = $this->getResultBucket($query);
$template = id(new PhabricatorAuditListView())
->setViewer($viewer);
->setViewer($viewer)
->setShowDrafts(true);
$views = array();
if ($bucket) {

View file

@ -4,6 +4,7 @@ final class PhabricatorAuditListView extends AphrontView {
private $commits;
private $header;
private $showDrafts;
private $noDataString;
private $highlightedAudits;
@ -25,6 +26,15 @@ final class PhabricatorAuditListView extends AphrontView {
return $this->header;
}
public function setShowDrafts($show_drafts) {
$this->showDrafts = $show_drafts;
return $this;
}
public function getShowDrafts() {
return $this->showDrafts;
}
/**
* These commits should have both commit data and audit requests attached.
*/
@ -73,7 +83,31 @@ final class PhabricatorAuditListView extends AphrontView {
$viewer = $this->getViewer();
$rowc = array();
$handles = $viewer->loadHandles(mpull($this->commits, 'getPHID'));
$phids = array();
foreach ($this->getCommits() as $commit) {
$phids[] = $commit->getPHID();
foreach ($commit->getAudits() as $audit) {
$phids[] = $audit->getAuditorPHID();
}
$author_phid = $commit->getAuthorPHID();
if ($author_phid) {
$phids[] = $author_phid;
}
}
$handles = $viewer->loadHandles($phids);
$show_drafts = $this->getShowDrafts();
$draft_icon = id(new PHUIIconView())
->setIcon('fa-comment yellow')
->addSigil('has-tooltip')
->setMetadata(
array(
'tip' => pht('Unsubmitted Comments'),
));
$list = new PHUIObjectItemListView();
foreach ($this->commits as $commit) {
@ -86,15 +120,6 @@ final class PhabricatorAuditListView extends AphrontView {
$commit_desc = $this->getCommitDescription($commit_phid);
$committed = phabricator_datetime($commit->getEpoch(), $viewer);
$audits = mpull($commit->getAudits(), null, 'getAuditorPHID');
$auditors = array();
$reasons = array();
foreach ($audits as $audit) {
$auditor_phid = $audit->getAuditorPHID();
$auditors[$auditor_phid] = $viewer->renderHandle($auditor_phid);
}
$auditors = phutil_implode_html(', ', $auditors);
$status = $commit->getAuditStatus();
$status_text =
@ -106,7 +131,7 @@ final class PhabricatorAuditListView extends AphrontView {
$author_phid = $commit->getAuthorPHID();
if ($author_phid) {
$author_name = $viewer->renderHandle($author_phid);
$author_name = $handles[$author_phid]->renderLink();
} else {
$author_name = $commit->getCommitData()->getAuthorName();
}
@ -115,14 +140,26 @@ final class PhabricatorAuditListView extends AphrontView {
->setObjectName($commit_name)
->setHeader($commit_desc)
->setHref($commit_link)
->addAttribute(pht('Author: %s', $author_name))
->addAttribute($reasons)
->addByline(pht('Author: %s', $author_name))
->addIcon('none', $committed);
if (!empty($auditors)) {
$item->addByLine(pht('Auditors: %s', $auditors));
if ($show_drafts) {
if ($commit->getHasDraft($viewer)) {
$item->addAttribute($draft_icon);
}
}
$audits = $commit->getAudits();
$auditor_phids = mpull($audits, 'getAuditorPHID');
if ($auditor_phids) {
$auditor_list = $handles->newSublist($auditor_phids)
->renderList()
->setAsInline(true);
} else {
$auditor_list = phutil_tag('em', array(), pht('None'));
}
$item->addAttribute(pht('Auditors: %s', $auditor_list));
if ($status_color) {
$item->setStatusIcon($status_icon.' '.$status_color, $status_text);
}

View file

@ -54,6 +54,8 @@ final class PhabricatorAuthRegisterController
}
}
$errors = array();
$user = new PhabricatorUser();
$default_username = $account->getUsername();
@ -65,23 +67,37 @@ final class PhabricatorAuthRegisterController
$default_email = $invite->getEmailAddress();
}
if (!PhabricatorUserEmail::isValidAddress($default_email)) {
$default_email = null;
if ($default_email !== null) {
if (!PhabricatorUserEmail::isValidAddress($default_email)) {
$errors[] = pht(
'The email address associated with this external account ("%s") is '.
'not a valid email address and can not be used to register a '.
'Phabricator account. Choose a different, valid address.',
phutil_tag('strong', array(), $default_email));
$default_email = null;
}
}
if ($default_email !== null) {
// We should bypass policy here becase e.g. limiting an application use
// to a subset of users should not allow the others to overwrite
// configured application emails
// configured application emails.
$application_email = id(new PhabricatorMetaMTAApplicationEmailQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withAddresses(array($default_email))
->executeOne();
if ($application_email) {
$errors[] = pht(
'The email address associated with this account ("%s") is '.
'already in use by an application and can not be used to '.
'register a new Phabricator account. Choose a different, valid '.
'address.',
phutil_tag('strong', array(), $default_email));
$default_email = null;
}
}
$show_existing = null;
if ($default_email !== null) {
// If the account source provided an email, but it's not allowed by
// the configuration, roadblock the user. Previously, we let the user
@ -105,9 +121,6 @@ final class PhabricatorAuthRegisterController
// If the account source provided an email, but another account already
// has that email, just pretend we didn't get an email.
// TODO: See T3472.
if ($default_email !== null) {
$same_email = id(new PhabricatorUserEmail())->loadOneWhere(
'address = %s',
@ -118,12 +131,57 @@ final class PhabricatorAuthRegisterController
// invite means that the address is nonprimary and unverified and
// we're OK to steal it.
} else {
$show_existing = $default_email;
$default_email = null;
}
}
}
}
if ($show_existing !== null) {
if (!$request->getInt('phase')) {
return $this->newDialog()
->setTitle(pht('Email Address Already in Use'))
->addHiddenInput('phase', 1)
->appendParagraph(
pht(
'You are creating a new Phabricator account linked to an '.
'existing external account from outside Phabricator.'))
->appendParagraph(
pht(
'The email address ("%s") associated with the external account '.
'is already in use by an existing Phabricator account. Multiple '.
'Phabricator accounts may not have the same email address, so '.
'you can not use this email address to register a new '.
'Phabricator account.',
phutil_tag('strong', array(), $show_existing)))
->appendParagraph(
pht(
'If you want to register a new account, continue with this '.
'registration workflow and choose a new, unique email address '.
'for the new account.'))
->appendParagraph(
pht(
'If you want to link an existing Phabricator account to this '.
'external account, do not continue. Instead: log in to your '.
'existing account, then go to "Settings" and link the account '.
'in the "External Accounts" panel.'))
->appendParagraph(
pht(
'If you continue, you will create a new account. You will not '.
'be able to link this external account to an existing account.'))
->addCancelButton('/auth/login/', pht('Cancel'))
->addSubmitButton(pht('Create New Account'));
} else {
$errors[] = pht(
'The external account you are registering with has an email address '.
'that is already in use ("%s") by an existing Phabricator account. '.
'Choose a new, valid email address to register a new Phabricator '.
'account.',
phutil_tag('strong', array(), $show_existing));
}
}
$profile = id(new PhabricatorRegistrationProfile())
->setDefaultUsername($default_username)
->setDefaultEmail($default_email)
@ -167,8 +225,6 @@ final class PhabricatorAuthRegisterController
$value_email = $default_email;
$value_password = null;
$errors = array();
$require_real_name = PhabricatorEnv::getEnvConfig('user.require-real-name');
$e_username = strlen($value_username) ? null : true;
@ -193,7 +249,14 @@ final class PhabricatorAuthRegisterController
$e_username = null;
}
if (($request->isFormPost() || !$can_edit_anything) && !$from_invite) {
$try_register =
($request->isFormPost() || !$can_edit_anything) &&
!$from_invite &&
($request->getInt('phase') != 1);
if ($try_register) {
$errors = array();
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
if ($must_set_password && !$skip_captcha) {
@ -402,7 +465,8 @@ final class PhabricatorAuthRegisterController
}
$form = id(new AphrontFormView())
->setUser($request->getUser());
->setUser($request->getUser())
->addHiddenInput('phase', 2);
if (!$is_default) {
$form->appendChild(

View file

@ -13,9 +13,7 @@ final class PhabricatorAuthMainMenuBarExtension
$viewer = $this->getViewer();
if ($viewer->isLoggedIn()) {
return array(
$this->buildLogoutMenu(),
);
return array();
}
$controller = $this->getController();
@ -30,25 +28,6 @@ final class PhabricatorAuthMainMenuBarExtension
);
}
private function buildLogoutMenu() {
$controller = $this->getController();
$is_selected = ($controller instanceof PhabricatorLogoutController);
$bar_item = id(new PHUIListItemView())
->addClass('core-menu-item')
->setName(pht('Log Out'))
->setIcon('fa-sign-out')
->setWorkflow(true)
->setHref('/logout/')
->setSelected($is_selected)
->setAural(pht('Log Out'));
return id(new PHUIMainMenuView())
->setOrder(900)
->setMenuBarItem($bar_item);
}
private function buildLoginMenu() {
$controller = $this->getController();
@ -58,16 +37,12 @@ final class PhabricatorAuthMainMenuBarExtension
$uri->setQueryParam('next', $path);
}
$bar_item = id(new PHUIListItemView())
->addClass('core-menu-item')
->setName(pht('Log In'))
->setIcon('fa-sign-in')
return id(new PHUIButtonView())
->setTag('a')
->setText(pht('Log In'))
->setHref($uri)
->setAural(pht('Log In'));
return id(new PHUIMainMenuView())
->setOrder(900)
->setMenuBarItem($bar_item);
->setNoCSS(true)
->addClass('phabricator-core-login-button');
}
}

View file

@ -172,41 +172,40 @@ abstract class PhabricatorApplication
$articles = $this->getHelpDocumentationArticles($viewer);
if ($articles) {
$items[] = id(new PHUIListItemView())
->setType(PHUIListItemView::TYPE_LABEL)
->setName(pht('%s Documentation', $this->getName()));
foreach ($articles as $article) {
$item = id(new PHUIListItemView())
$item = id(new PhabricatorActionView())
->setName($article['name'])
->setIcon('fa-book')
->setHref($article['href'])
->addSigil('help-item')
->setOpenInNewWindow(true);
$items[] = $item;
}
}
$command_specs = $this->getMailCommandObjects();
if ($command_specs) {
$items[] = id(new PHUIListItemView())
->setType(PHUIListItemView::TYPE_LABEL)
->setName(pht('Email Help'));
foreach ($command_specs as $key => $spec) {
$object = $spec['object'];
$class = get_class($this);
$href = '/applications/mailcommands/'.$class.'/'.$key.'/';
$item = id(new PHUIListItemView())
$item = id(new PhabricatorActionView())
->setName($spec['name'])
->setIcon('fa-envelope-o')
->setHref($href)
->addSigil('help-item')
->setOpenInNewWindow(true);
$items[] = $item;
}
}
return $items;
if ($items) {
$divider = id(new PhabricatorActionView())
->addSigil('help-item')
->setType(PhabricatorActionView::TYPE_DIVIDER);
array_unshift($items, $divider);
}
return array_values($items);
}
public function getHelpDocumentationArticles(PhabricatorUser $viewer) {

View file

@ -29,7 +29,7 @@ final class CelerityDefaultPostprocessor
"Arial, sans-serif",
// Drop Shadow
'dropshadow' => '0 1px 6px rgba(0, 0, 0, .25)',
'dropshadow' => '0 2px 12px rgba(0, 0, 0, .20)',
'whitetextshadow' => '0 1px 0 rgba(255, 255, 255, 1)',
// Anchors

View file

@ -142,9 +142,11 @@ final class DifferentialGetCommitMessageConduitAPIMethod
private function loadCustomFieldStorage(
PhabricatorUser $viewer,
DifferentialRevision $revision) {
$custom_field_list = PhabricatorCustomField::getObjectFields(
$revision,
DifferentialCustomField::ROLE_COMMITMESSAGE);
PhabricatorCustomField::ROLE_STORAGE);
$custom_field_list
->setViewer($viewer)
->readFieldsFromStorage($revision);

View file

@ -36,10 +36,6 @@ final class DifferentialAuditorsField
return true;
}
public function shouldAppearInCommitMessage() {
return true;
}
public function shouldAppearInConduitTransactions() {
return true;
}

View file

@ -91,10 +91,6 @@ final class DifferentialBlameRevisionField
$xaction->renderHandleLink($object_phid));
}
public function shouldAppearInCommitMessage() {
return true;
}
public function shouldAppearInConduitDictionary() {
return true;
}

View file

@ -156,15 +156,6 @@ abstract class DifferentialCoreCustomField
return $this->value;
}
public function readValueFromCommitMessage($value) {
$this->setValue($value);
return $this;
}
public function renderCommitMessageValue(array $handles) {
return $this->getValue();
}
public function getConduitDictionaryValue() {
return $this->getValue();
}

View file

@ -7,9 +7,6 @@
abstract class DifferentialCustomField
extends PhabricatorCustomField {
const ROLE_COMMITMESSAGE = 'differential:commitmessage';
const ROLE_COMMITMESSAGEEDIT = 'differential:commitmessageedit';
/**
* TODO: It would be nice to remove this, but a lot of different code is
* bound together by it. Until everything is modernized, retaining the old
@ -25,18 +22,6 @@ abstract class DifferentialCustomField
return $this->getFieldKeyForConduit();
}
public function shouldEnableForRole($role) {
switch ($role) {
case self::ROLE_COMMITMESSAGE:
return $this->shouldAppearInCommitMessage();
case self::ROLE_COMMITMESSAGEEDIT:
return $this->shouldAppearInCommitMessage() &&
$this->shouldAllowEditInCommitMessage();
}
return parent::shouldEnableForRole($role);
}
protected function parseObjectList(
$value,
array $types,
@ -97,39 +82,6 @@ abstract class DifferentialCustomField
/* -( Integration with Commit Messages )----------------------------------- */
/**
* @task commitmessage
*/
public function shouldAppearInCommitMessage() {
if ($this->getProxy()) {
return $this->getProxy()->shouldAppearInCommitMessage();
}
return false;
}
/**
* @task commitmessage
*/
public function shouldAppearInCommitMessageTemplate() {
if ($this->getProxy()) {
return $this->getProxy()->shouldAppearInCommitMessageTemplate();
}
return false;
}
/**
* @task commitmessage
*/
public function shouldAllowEditInCommitMessage() {
if ($this->getProxy()) {
return $this->getProxy()->shouldAllowEditInCommitMessage();
}
return true;
}
/**
* @task commitmessage
*/
@ -141,95 +93,6 @@ abstract class DifferentialCustomField
}
/**
* @task commitmessage
*/
public function getCommitMessageLabels() {
if ($this->getProxy()) {
return $this->getProxy()->getCommitMessageLabels();
}
return array($this->renderCommitMessageLabel());
}
/**
* @task commitmessage
*/
public function parseValueFromCommitMessage($value) {
if ($this->getProxy()) {
return $this->getProxy()->parseValueFromCommitMessage($value);
}
return $value;
}
/**
* @task commitmessage
*/
public function readValueFromCommitMessage($value) {
if ($this->getProxy()) {
$this->getProxy()->readValueFromCommitMessage($value);
return $this;
}
return $this;
}
/**
* @task commitmessage
*/
public function shouldOverwriteWhenCommitMessageIsEdited() {
if ($this->getProxy()) {
return $this->getProxy()->shouldOverwriteWhenCommitMessageIsEdited();
}
return false;
}
/**
* @task commitmessage
*/
public function getRequiredHandlePHIDsForCommitMessage() {
if ($this->getProxy()) {
return $this->getProxy()->getRequiredHandlePHIDsForCommitMessage();
}
return array();
}
/**
* @task commitmessage
*/
public function renderCommitMessageLabel() {
if ($this->getProxy()) {
return $this->getProxy()->renderCommitMessageLabel();
}
return $this->getFieldName();
}
/**
* @task commitmessage
*/
public function renderCommitMessageValue(array $handles) {
if ($this->getProxy()) {
return $this->getProxy()->renderCommitMessageValue($handles);
}
throw new PhabricatorCustomFieldImplementationIncompleteException($this);
}
/**
* @task commitmessage
*/
public function validateCommitMessageValue($value) {
if ($this->getProxy()) {
return $this->getProxy()->validateCommitMessageValue($value);
}
return;
}
/* -( Integration with Diff Properties )----------------------------------- */

View file

@ -270,39 +270,6 @@ final class DifferentialJIRAIssuesField
$editor->save();
}
public function shouldAppearInCommitMessage() {
return true;
}
public function shouldAppearInCommitMessageTemplate() {
return true;
}
public function getCommitMessageLabels() {
return array(
'JIRA',
'JIRA Issues',
'JIRA Issue',
);
}
public function parseValueFromCommitMessage($value) {
return preg_split('/[\s,]+/', $value, $limit = -1, PREG_SPLIT_NO_EMPTY);
}
public function readValueFromCommitMessage($value) {
$this->setValue($value);
return $this;
}
public function renderCommitMessageValue(array $handles) {
$value = $this->getValue();
if (!$value) {
return null;
}
return implode(', ', $value);
}
public function shouldAppearInConduitDictionary() {
return true;
}

View file

@ -130,14 +130,6 @@ final class DifferentialRevertPlanField
return array($xaction->getNewValue());
}
public function shouldAppearInCommitMessage() {
return true;
}
public function renderCommitMessageValue(array $handles) {
return $this->getValue();
}
public function shouldAppearInConduitDictionary() {
return true;
}

View file

@ -45,7 +45,7 @@ abstract class DifferentialCommitMessageCustomField
protected function getCustomFieldOrder($key) {
$field_list = PhabricatorCustomField::getObjectFields(
new DifferentialRevision(),
DifferentialCustomField::ROLE_COMMITMESSAGE);
PhabricatorCustomField::ROLE_DEFAULT);
$fields = $field_list->getFields();

View file

@ -473,34 +473,9 @@ final class DifferentialRevisionQuery
}
if ($this->needDrafts) {
$viewer_phid = $viewer->getPHID();
$draft_type = PhabricatorObjectHasDraftEdgeType::EDGECONST;
if (!$viewer_phid) {
// Viewers without a valid PHID can never have drafts.
foreach ($revisions as $revision) {
$revision->attachHasDraft($viewer, false);
}
} else {
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($revisions, 'getPHID'))
->withEdgeTypes(
array(
$draft_type,
))
->withDestinationPHIDs(array($viewer_phid));
$edge_query->execute();
foreach ($revisions as $revision) {
$has_draft = (bool)$edge_query->getDestinationPHIDs(
array(
$revision->getPHID(),
));
$revision->attachHasDraft($viewer, $has_draft);
}
}
PhabricatorDraftEngine::attachDrafts(
$viewer,
$revisions);
}
return $revisions;

View file

@ -50,7 +50,7 @@ final class DifferentialRevisionAcceptTransaction
public function generateOldValue($object) {
$actor = $this->getActor();
return $this->isViewerAcceptingReviewer($object, $actor);
return $this->isViewerFullyAccepted($object, $actor);
}
public function applyExternalEffects($object, $value) {
@ -79,7 +79,7 @@ final class DifferentialRevisionAcceptTransaction
}
}
if ($this->isViewerAcceptingReviewer($object, $viewer)) {
if ($this->isViewerFullyAccepted($object, $viewer)) {
throw new Exception(
pht(
'You can not accept this revision because you have already '.

View file

@ -46,7 +46,7 @@ final class DifferentialRevisionRejectTransaction
public function generateOldValue($object) {
$actor = $this->getActor();
return $this->isViewerRejectingReviewer($object, $actor);
return $this->isViewerFullyRejected($object, $actor);
}
public function applyExternalEffects($object, $value) {
@ -72,7 +72,7 @@ final class DifferentialRevisionRejectTransaction
'not own.'));
}
if ($this->isViewerRejectingReviewer($object, $viewer)) {
if ($this->isViewerFullyRejected($object, $viewer)) {
throw new Exception(
pht(
'You can not request changes to this revision because you have '.

View file

@ -13,10 +13,10 @@ abstract class DifferentialRevisionReviewTransaction
return ($this->getViewerReviewerStatus($revision, $viewer) !== null);
}
protected function isViewerAcceptingReviewer(
protected function isViewerFullyAccepted(
DifferentialRevision $revision,
PhabricatorUser $viewer) {
return $this->isViewerReviewerStatusAmong(
return $this->isViewerReviewerStatusFullyAmong(
$revision,
$viewer,
array(
@ -24,10 +24,10 @@ abstract class DifferentialRevisionReviewTransaction
));
}
protected function isViewerRejectingReviewer(
protected function isViewerFullyRejected(
DifferentialRevision $revision,
PhabricatorUser $viewer) {
return $this->isViewerReviewerStatusAmong(
return $this->isViewerReviewerStatusFullyAmong(
$revision,
$viewer,
array(
@ -54,18 +54,34 @@ abstract class DifferentialRevisionReviewTransaction
return null;
}
protected function isViewerReviewerStatusAmong(
protected function isViewerReviewerStatusFullyAmong(
DifferentialRevision $revision,
PhabricatorUser $viewer,
array $status_list) {
// If the user themselves is not a reviewer, the reviews they have
// authority over can not all be in any set of states since their own
// personal review has no state.
$status = $this->getViewerReviewerStatus($revision, $viewer);
if ($status === null) {
return false;
}
// Otherwise, check that all reviews they have authority over are in
// the desired set of states.
$status_map = array_fuse($status_list);
return isset($status_map[$status]);
foreach ($revision->getReviewerStatus() as $reviewer) {
if (!$reviewer->hasAuthority($viewer)) {
continue;
}
$status = $reviewer->getStatus();
if (!isset($status_map[$status])) {
return false;
}
}
return true;
}
protected function applyReviewerEffect(

View file

@ -20,6 +20,10 @@ final class DiffusionRepositoryEditEngine
return false;
}
public function isDefaultQuickCreateEngine() {
return true;
}
public function getEngineName() {
return pht('Repositories');
}

View file

@ -0,0 +1,18 @@
<?php
final class DiffusionCommitDraftEngine
extends PhabricatorDraftEngine {
protected function hasCustomDraftContent() {
$viewer = $this->getViewer();
$commit = $this->getObject();
$inlines = PhabricatorAuditInlineComment::loadDraftComments(
$viewer,
$commit->getPHID(),
$raw = true);
return (bool)$inlines;
}
}

View file

@ -0,0 +1,41 @@
<?php
final class DiffusionCommitAuditorsHeraldField
extends DiffusionCommitHeraldField {
const FIELDCONST = 'diffusion.commit.auditors';
public function getHeraldFieldName() {
return pht('Auditors');
}
public function getHeraldFieldValue($object) {
$viewer = PhabricatorUser::getOmnipotentUser();
$commit = id(new DiffusionCommitQuery())
->setViewer($viewer)
->withPHIDs(array($object->getPHID()))
->needAuditRequests(true)
->executeOne();
$audits = $commit->getAudits();
$phids = array();
foreach ($audits as $audit) {
if ($audit->isActiveAudit()) {
$phids[] = $audit->getAuditorPHID();
}
}
return $phids;
}
protected function getHeraldFieldStandardType() {
return self::STANDARD_PHID_LIST;
}
protected function getDatasource() {
return new DiffusionAuditorDatasource();
}
}

View file

@ -22,6 +22,7 @@ final class DiffusionCommitQuery
private $importing;
private $needCommitData;
private $needDrafts;
public function withIDs(array $ids) {
$this->ids = $ids;
@ -98,6 +99,11 @@ final class DiffusionCommitQuery
return $this;
}
public function needDrafts($need) {
$this->needDrafts = $need;
return $this;
}
public function needAuditRequests($need) {
$this->needAuditRequests = $need;
return $this;
@ -239,6 +245,8 @@ final class DiffusionCommitQuery
}
protected function didFilterPage(array $commits) {
$viewer = $this->getViewer();
if ($this->needCommitData) {
$data = id(new PhabricatorRepositoryCommitData())->loadAllWhere(
'commitID in (%Ld)',
@ -268,6 +276,12 @@ final class DiffusionCommitQuery
}
}
if ($this->needDrafts) {
PhabricatorDraftEngine::attachDrafts(
$viewer,
$commits);
}
return $commits;
}

View file

@ -187,6 +187,19 @@ final class DiffusionHistoryTableView extends DiffusionView {
'type' => $history->getFileType(),
));
$status = $commit->getAuditStatus();
$icon = PhabricatorAuditCommitStatusConstants::getStatusIcon($status);
$color = PhabricatorAuditCommitStatusConstants::getStatusColor($status);
$name = PhabricatorAuditCommitStatusConstants::getStatusName($status);
$audit_view = id(new PHUIIconView())
->setIcon($icon, $color)
->addSigil('has-tooltip')
->setMetadata(
array(
'tip' => $name,
));
$rows[] = array(
$graph ? $graph[$ii++] : null,
$browse,
@ -194,6 +207,7 @@ final class DiffusionHistoryTableView extends DiffusionView {
$drequest->getRepository(),
$history->getCommitIdentifier()),
$build,
$audit_view,
($commit ?
self::linkRevision(idx($this->revisions, $commit->getPHID())) :
null),
@ -211,7 +225,8 @@ final class DiffusionHistoryTableView extends DiffusionView {
pht('Commit'),
null,
null,
pht('Author/Committer'),
null,
pht('Author'),
pht('Details'),
pht('Committed'),
));
@ -221,6 +236,7 @@ final class DiffusionHistoryTableView extends DiffusionView {
'nudgeright',
'',
'icon',
'icon',
'',
'',
'wide',
@ -232,6 +248,7 @@ final class DiffusionHistoryTableView extends DiffusionView {
true,
true,
$has_any_build,
true,
$show_revisions,
));
$view->setDeviceVisibility(
@ -241,6 +258,7 @@ final class DiffusionHistoryTableView extends DiffusionView {
true,
true,
true,
true,
false,
true,
false,

View file

@ -15,7 +15,7 @@ final class PhabricatorFavoritesApplication extends PhabricatorApplication {
}
public function getIcon() {
return 'fa-star-o';
return 'fa-star';
}
public function getRoutes() {
@ -32,8 +32,82 @@ final class PhabricatorFavoritesApplication extends PhabricatorApplication {
return false;
}
public function getApplicationOrder() {
return 9;
public function buildMainMenuExtraNodes(
PhabricatorUser $viewer,
PhabricatorController $controller = null) {
$dropdown = $this->renderFavoritesDropdown($viewer);
if (!$dropdown) {
return null;
}
return id(new PHUIButtonView())
->setTag('a')
->setHref('#')
->setIcon('fa-star')
->addClass('phabricator-core-user-menu')
->setNoCSS(true)
->setDropdown(true)
->setDropdownMenu($dropdown);
}
private function renderFavoritesDropdown(PhabricatorUser $viewer) {
$application = __CLASS__;
$applications = id(new PhabricatorApplicationQuery())
->setViewer($viewer)
->withClasses(array($application))
->withInstalled(true)
->execute();
$favorites = head($applications);
if (!$favorites) {
return null;
}
$menu_engine = id(new PhabricatorFavoritesProfileMenuEngine())
->setViewer($viewer)
->setProfileObject($favorites);
if ($viewer->getPHID()) {
$menu_engine
->setCustomPHID($viewer->getPHID())
->setMenuType(PhabricatorProfileMenuEngine::MENU_COMBINED);
} else {
$menu_engine
->setMenuType(PhabricatorProfileMenuEngine::MENU_GLOBAL);
}
$filter_view = $menu_engine->buildNavigation();
$menu_view = $filter_view->getMenu();
$item_views = $menu_view->getItems();
$view = id(new PhabricatorActionListView())
->setViewer($viewer);
foreach ($item_views as $item) {
$type = null;
if (!strlen($item->getName())) {
$type = PhabricatorActionView::TYPE_DIVIDER;
}
$action = id(new PhabricatorActionView())
->setName($item->getName())
->setHref($item->getHref())
->setType($type);
$view->addAction($action);
}
// Build out edit interface
if ($viewer->isLoggedIn()) {
$view->addAction(
id(new PhabricatorActionView())
->setType(PhabricatorActionView::TYPE_DIVIDER));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Favorites'))
->setHref('/favorites/'));
}
return $view;
}
}

View file

@ -1,11 +0,0 @@
<?php
final class PhabricatorFavoritesConstants
extends PhabricatorFavoritesController {
const ITEM_TASK = 'favorites.task';
const ITEM_PROJECT = 'favorites.project';
const ITEM_REPOSITORY = 'favorites.repository';
const ITEM_MANAGE = 'favorites.manage';
}

View file

@ -10,6 +10,11 @@ final class PhabricatorFavoritesMainController
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
if (!$viewer->getIsAdmin()) {
$uri = '/favorites/personal/item/configure/';
return id(new AphrontRedirectResponse())->setURI($uri);
}
$menu = id(new PHUIObjectItemListView())
->setUser($viewer);

View file

@ -7,8 +7,10 @@ final class PhabricatorFavoritesMenuItemController
$viewer = $this->getViewer();
$type = $request->getURIData('type');
$custom_phid = null;
$menu = PhabricatorProfileMenuEngine::MENU_GLOBAL;
if ($type == 'personal') {
$custom_phid = $viewer->getPHID();
$menu = PhabricatorProfileMenuEngine::MENU_PERSONAL;
}
$application = 'PhabricatorFavoritesApplication';
@ -21,7 +23,9 @@ final class PhabricatorFavoritesMenuItemController
$engine = id(new PhabricatorFavoritesProfileMenuEngine())
->setProfileObject($favorites)
->setCustomPHID($custom_phid)
->setController($this);
->setController($this)
->setMenuType($menu)
->setShowNavigation(false);
return $engine->buildResponse();
}

View file

@ -20,50 +20,28 @@ final class PhabricatorFavoritesProfileMenuEngine
protected function getBuiltinProfileItems($object) {
$items = array();
$custom_phid = $this->getCustomPHID();
$viewer = $this->getViewer();
// Built-in Global Defaults
if (!$custom_phid) {
$create_task = array(
'name' => null,
'formKey' =>
id(new ManiphestEditEngine())->getProfileMenuItemDefault(),
);
$engines = PhabricatorEditEngine::getAllEditEngines();
$engines = msortv($engines, 'getQuickCreateOrderVector');
$create_project = array(
'name' => null,
'formKey' =>
id(new PhabricatorProjectEditEngine())->getProfileMenuItemDefault(),
);
foreach ($engines as $engine) {
foreach ($engine->getDefaultQuickCreateFormKeys() as $form_key) {
$form_hash = PhabricatorHash::digestForIndex($form_key);
$builtin_key = "editengine.form({$form_hash})";
$create_repository = array(
'name' => null,
'formKey' =>
id(new DiffusionRepositoryEditEngine())->getProfileMenuItemDefault(),
);
$properties = array(
'name' => null,
'formKey' => $form_key,
);
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_TASK)
->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY)
->setMenuItemProperties($create_task);
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_PROJECT)
->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY)
->setMenuItemProperties($create_project);
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_REPOSITORY)
->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY)
->setMenuItemProperties($create_repository);
$items[] = $this->newItem()
->setBuiltinKey($builtin_key)
->setMenuItemKey(PhabricatorEditEngineProfileMenuItem::MENUITEMKEY)
->setMenuItemProperties($properties);
}
}
// Single Manage Item, switches URI based on admin/user
$items[] = $this->newItem()
->setBuiltinKey(PhabricatorFavoritesConstants::ITEM_MANAGE)
->setMenuItemKey(
PhabricatorFavoritesManageProfileMenuItem::MENUITEMKEY);
return $items;
}

View file

@ -1,72 +0,0 @@
<?php
final class PhabricatorFavoritesManageProfileMenuItem
extends PhabricatorProfileMenuItem {
const MENUITEMKEY = 'favorites.manage';
public function getMenuItemTypeName() {
return pht('Manage Favorites');
}
private function getDefaultName() {
return pht('Manage');
}
public function canHideMenuItem(
PhabricatorProfileMenuItemConfiguration $config) {
return false;
}
public function canMakeDefault(
PhabricatorProfileMenuItemConfiguration $config) {
return false;
}
public function getDisplayName(
PhabricatorProfileMenuItemConfiguration $config) {
$name = $config->getMenuItemProperty('name');
if (strlen($name)) {
return $name;
}
return $this->getDefaultName();
}
public function buildEditEngineFields(
PhabricatorProfileMenuItemConfiguration $config) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setPlaceholder($this->getDefaultName())
->setValue($config->getMenuItemProperty('name')),
);
}
protected function newNavigationMenuItems(
PhabricatorProfileMenuItemConfiguration $config) {
$viewer = $this->getViewer();
if ($viewer->isLoggedIn()) {
$admin = $viewer->getIsAdmin();
$name = $this->getDisplayName($config);
$icon = 'fa-pencil';
$href = '/favorites/personal/item/configure/';
if ($admin) {
$href = '/favorites/';
}
$item = $this->newItem()
->setHref($href)
->setName($name)
->setIcon($icon);
}
return array(
$item,
);
}
}

View file

@ -31,7 +31,6 @@ final class PhabricatorHelpDocumentationController
$list->addItem(
id(new PHUIObjectItemView())
->setHeader($item->getName())
->setWorkflow($item->getWorkflow())
->setHref($item->getHref()));
}

View file

@ -1,70 +0,0 @@
<?php
final class PhabricatorHelpMainMenuBarExtension
extends PhabricatorMainMenuBarExtension {
const MAINMENUBARKEY = 'help';
public function isExtensionEnabledForViewer(PhabricatorUser $viewer) {
return true;
}
public function buildMainMenus() {
$application = $this->getApplication();
if (!$application) {
return array();
}
$viewer = $this->getViewer();
$help_links = $application->getHelpMenuItems($viewer);
if (!$help_links) {
return array();
}
$help_id = celerity_generate_unique_node_id();
Javelin::initBehavior(
'aphlict-dropdown',
array(
'bubbleID' => $help_id,
'dropdownID' => 'phabricator-help-menu',
'local' => true,
'desktop' => true,
'right' => true,
));
$help_name = pht('%s Help', $application->getName());
$help_item = id(new PHUIListItemView())
->setIcon('fa-book')
->addClass('core-menu-item')
->setID($help_id)
->setName($help_name)
->setHref('/help/documentation/'.get_class($application).'/')
->setAural($help_name);
$view = new PHUIListView();
foreach ($help_links as $help_link) {
$view->addMenuItem($help_link);
}
$dropdown_menu = phutil_tag(
'div',
array(
'id' => 'phabricator-help-menu',
'class' => 'phabricator-main-menu-dropdown phui-list-sidenav',
'style' => 'display: none',
),
$view);
$help_menu = id(new PHUIMainMenuView())
->setOrder(200)
->setMenuBarItem($help_item)
->appendChild($dropdown_menu);
return array(
$help_menu,
);
}
}

View file

@ -2,7 +2,6 @@
final class PhabricatorHomeApplication extends PhabricatorApplication {
private $quickItems;
const DASHBOARD_DEFAULT = 'dashboard:default';
public function getBaseURI() {
@ -26,7 +25,6 @@ final class PhabricatorHomeApplication extends PhabricatorApplication {
'/' => 'PhabricatorHomeMainController',
'/(?P<only>home)/' => 'PhabricatorHomeMainController',
'/home/' => array(
'create/' => 'PhabricatorHomeQuickCreateController',
'menu/' => array(
'' => 'PhabricatorHomeMenuController',
'(?P<type>global|personal)/item/' => $this->getProfileMenuRouting(
@ -44,73 +42,114 @@ final class PhabricatorHomeApplication extends PhabricatorApplication {
return 9;
}
public function buildMainMenuItems(
PhabricatorUser $user,
PhabricatorController $controller = null) {
$quick_items = $this->getQuickActionItems($user);
if (!$quick_items) {
return array();
}
$items = array();
$create_id = celerity_generate_unique_node_id();
Javelin::initBehavior(
'aphlict-dropdown',
array(
'bubbleID' => $create_id,
'dropdownID' => 'phabricator-quick-create-menu',
'local' => true,
'desktop' => true,
'right' => true,
));
$item = id(new PHUIListItemView())
->setName(pht('Quick Actions'))
->setIcon('fa-plus')
->addClass('core-menu-item')
->setHref('/home/create/')
->addSigil('quick-create-menu')
->setID($create_id)
->setAural(pht('Quick Actions'))
->setOrder(300);
$items[] = $item;
return $items;
}
public function buildMainMenuExtraNodes(
PhabricatorUser $viewer,
PhabricatorController $controller = null) {
$items = $this->getQuickActionItems($viewer);
$view = null;
if ($items) {
$view = new PHUIListView();
foreach ($items as $item) {
$view->addMenuItem($item);
}
return phutil_tag(
'div',
array(
'id' => 'phabricator-quick-create-menu',
'class' => 'phabricator-main-menu-dropdown phui-list-sidenav',
'style' => 'display: none',
),
$view);
if (!$viewer->isLoggedIn()) {
return;
}
$image = $viewer->getProfileImageURI();
$profile_image = id(new PHUIIconView())
->setImage($image)
->setHeadSize(PHUIIconView::HEAD_SMALL);
if ($controller) {
$application = $controller->getCurrentApplication();
} else {
$application = null;
}
$dropdown_menu = $this->renderUserDropdown($viewer, $application);
$menu_id = celerity_generate_unique_node_id();
Javelin::initBehavior(
'user-menu',
array(
'menuID' => $menu_id,
'menu' => $dropdown_menu->getDropdownMenuMetadata(),
));
return id(new PHUIButtonView())
->setID($menu_id)
->setTag('a')
->setHref('/p/'.$viewer->getUsername().'/')
->setIcon($profile_image)
->addClass('phabricator-core-user-menu')
->setHasCaret(true)
->setNoCSS(true);
}
private function renderUserDropdown(
PhabricatorUser $viewer,
$application) {
$person_to_show = id(new PHUIObjectItemView())
->setObjectName($viewer->getRealName())
->setSubHead($viewer->getUsername())
->setImageURI($viewer->getProfileImageURI());
$user_view = id(new PHUIObjectItemListView())
->setViewer($viewer)
->setFlush(true)
->setSimple(true)
->addItem($person_to_show)
->addClass('phabricator-core-user-profile-object');
$view = id(new PhabricatorActionListView())
->setViewer($viewer);
// User Menu
$view->addAction(
id(new PhabricatorActionView())
->appendChild($user_view));
$view->addAction(
id(new PhabricatorActionView())
->setType(PhabricatorActionView::TYPE_DIVIDER));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Profile'))
->setHref('/p/'.$viewer->getUsername().'/'));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Settings'))
->setHref('/settings/user/'.$viewer->getUsername().'/'));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Manage'))
->setHref('/people/manage/'.$viewer->getID().'/'));
// Help Menus
if ($application) {
$help_links = $application->getHelpMenuItems($viewer);
if ($help_links) {
foreach ($help_links as $link) {
$view->addAction($link);
}
}
}
// Logout Menu
$view->addAction(
id(new PhabricatorActionView())
->addSigil('logout-item')
->setType(PhabricatorActionView::TYPE_DIVIDER));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Log Out %s', $viewer->getUsername()))
->addSigil('logout-item')
->setHref('/logout/')
->setColor(PhabricatorActionView::RED)
->setWorkflow(true));
return $view;
}
private function getQuickActionItems(PhabricatorUser $viewer) {
if ($this->quickItems === null) {
$items = PhabricatorQuickActions::loadMenuItemsForUser($viewer);
$this->quickItems = $items;
}
return $this->quickItems;
}
}

View file

@ -1,47 +0,0 @@
<?php
final class PhabricatorHomeQuickCreateController
extends PhabricatorHomeController {
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$items = PhabricatorQuickActions::loadMenuItemsForUser($viewer);
$list = id(new PHUIObjectItemListView())
->setUser($viewer);
foreach ($items as $item) {
$list->addItem(
id(new PHUIObjectItemView())
->setHeader($item->getName())
->setWorkflow($item->getWorkflow())
->setHref($item->getHref()));
}
$title = pht('Quick Create');
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Quick Create'));
$crumbs->setBorder(true);
$box = id(new PHUIObjectBoxView())
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($list);
$header = id(new PHUIHeaderView())
->setHeader($title)
->setHeaderIcon('fa-plus-square');
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter($box);
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
->appendChild($view);
}
}

View file

@ -21,6 +21,10 @@ final class ManiphestEditEngine
return 'PhabricatorManiphestApplication';
}
public function isDefaultQuickCreateEngine() {
return true;
}
protected function newEditableObject() {
return ManiphestTask::initializeNewTask($this->getViewer());
}

View file

@ -45,11 +45,6 @@ final class PhabricatorPeopleProfileManageController
$nav = $this->getProfileMenu();
$nav->selectFilter(PhabricatorPeopleProfileMenuEngine::ITEM_MANAGE);
$timeline = $this->buildTransactionTimeline(
$user,
new PhabricatorPeopleTransactionQuery());
$timeline->setShouldTerminate(true);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Manage'));
$crumbs->setBorder(true);
@ -57,11 +52,7 @@ final class PhabricatorPeopleProfileManageController
$manage = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
->addPropertySection(pht('Details'), $properties)
->setMainColumn(
array(
$timeline,
));
->addPropertySection(pht('Details'), $properties);
return $this->newPage()
->setTitle(

View file

@ -1,41 +0,0 @@
<?php
final class PhabricatorPeopleMainMenuBarExtension
extends PhabricatorMainMenuBarExtension {
const MAINMENUBARKEY = 'people';
public function buildMainMenus() {
$viewer = $this->getViewer();
$image = $viewer->getProfileImageURI();
$bar_item = id(new PHUIListItemView())
->setName($viewer->getUsername())
->setHref('/p/'.$viewer->getUsername().'/')
->addClass('core-menu-item')
->setAural(pht('Profile'));
$classes = array(
'phabricator-core-menu-icon',
'phabricator-core-menu-profile-image',
);
$bar_item->appendChild(
phutil_tag(
'span',
array(
'class' => implode(' ', $classes),
'style' => 'background-image: url('.$image.')',
),
''));
$profile_menu = id(new PHUIMainMenuView())
->setOrder(100)
->setMenuBarItem($bar_item);
return array(
$profile_menu,
);
}
}

View file

@ -11,7 +11,7 @@ final class PhabricatorPhameApplication extends PhabricatorApplication {
}
public function getIcon() {
return 'fa-star';
return 'fa-feed';
}
public function getShortDescription() {

View file

@ -26,6 +26,10 @@ final class PhabricatorProjectEditEngine
return $this->milestoneProject;
}
public function isDefaultQuickCreateEngine() {
return true;
}
public function getEngineName() {
return pht('Projects');
}

View file

@ -49,6 +49,19 @@ final class PhabricatorRepositoryAuditRequest
return $this->assertAttached($this->commit);
}
public function isActiveAudit() {
switch ($this->getAuditStatus()) {
case PhabricatorAuditStatusConstants::NONE:
case PhabricatorAuditStatusConstants::AUDIT_NOT_REQUIRED:
case PhabricatorAuditStatusConstants::RESIGNED:
case PhabricatorAuditStatusConstants::CLOSED:
case PhabricatorAuditStatusConstants::CC:
return false;
}
return true;
}
public function isInteresting() {
switch ($this->getAuditStatus()) {
case PhabricatorAuditStatusConstants::NONE:

View file

@ -14,7 +14,8 @@ final class PhabricatorRepositoryCommit
PhabricatorCustomFieldInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorFulltextInterface,
PhabricatorConduitResultInterface {
PhabricatorConduitResultInterface,
PhabricatorDraftInterface {
protected $repositoryID;
protected $phid;
@ -39,6 +40,7 @@ final class PhabricatorRepositoryCommit
private $audits = self::ATTACHABLE;
private $repository = self::ATTACHABLE;
private $customFields = self::ATTACHABLE;
private $drafts = array();
public function attachRepository(PhabricatorRepository $repository) {
$this->repository = $repository;
@ -342,6 +344,7 @@ final class PhabricatorRepositoryCommit
return nonempty($parsed->getDisplayName(), $parsed->getAddress());
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
@ -603,4 +606,20 @@ final class PhabricatorRepositoryCommit
return array();
}
/* -( PhabricatorDraftInterface )------------------------------------------ */
public function newDraftEngine() {
return new DiffusionCommitDraftEngine();
}
public function getHasDraft(PhabricatorUser $viewer) {
return $this->assertAttachedKey($this->drafts, $viewer->getCacheFragment());
}
public function attachHasDraft(PhabricatorUser $viewer, $has_draft) {
$this->drafts[$viewer->getCacheFragment()] = $has_draft;
return $this;
}
}

View file

@ -109,6 +109,7 @@ final class PhabricatorProfileMenuEditEngine
}
protected function getObjectEditTitleText($object) {
$object->willBuildNavigationItems(array($object));
return pht('Edit Menu Item: %s', $object->getDisplayName());
}
@ -148,4 +149,47 @@ final class PhabricatorProfileMenuEditEngine
return $fields;
}
protected function getValidationExceptionShortMessage(
PhabricatorApplicationTransactionValidationException $ex,
PhabricatorEditField $field) {
// Menu item properties all have the same transaction type, so we need
// to make sure errors about a specific property (like the URI for a
// link) are only applied to the field for that particular property. If
// we don't do this, the red error text like "Required" will display
// next to every field.
$property_type =
PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY;
$xaction_type = $field->getTransactionType();
if ($xaction_type == $property_type) {
$field_key = $field->getKey();
foreach ($ex->getErrors() as $error) {
if ($error->getType() !== $xaction_type) {
continue;
}
$xaction = $error->getTransaction();
if (!$xaction) {
continue;
}
$xaction_setting = $xaction->getMetadataValue('property.key');
if ($xaction_setting != $field_key) {
continue;
}
$short_message = $error->getShortMessage();
if ($short_message !== null) {
return $short_message;
}
}
return null;
}
return parent::getValidationExceptionShortMessage($ex, $field);
}
}

View file

@ -87,4 +87,39 @@ final class PhabricatorProfileMenuEditor
return parent::applyCustomExternalTransaction($object, $xaction);
}
protected function validateTransaction(
PhabricatorLiskDAO $object,
$type,
array $xactions) {
$errors = parent::validateTransaction($object, $type, $xactions);
$actor = $this->getActor();
$menu_item = $object->getMenuItem();
$menu_item->setViewer($actor);
switch ($type) {
case PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY:
$key_map = array();
foreach ($xactions as $xaction) {
$xaction_key = $xaction->getMetadataValue('property.key');
$old = $this->getCustomTransactionOldValue($object, $xaction);
$new = $xaction->getNewValue();
$key_map[$xaction_key][] = array(
'xaction' => $xaction,
'old' => $old,
'new' => $new,
);
}
foreach ($object->validateTransactions($key_map) as $error) {
$errors[] = $error;
}
break;
}
return $errors;
}
}

View file

@ -6,9 +6,16 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
private $profileObject;
private $customPHID;
private $items;
private $menuType = self::MENU_GLOBAL;
private $defaultItem;
private $controller;
private $navigation;
private $showNavigation = true;
const MENU_GLOBAL = 'global';
const MENU_PERSONAL = 'personal';
const MENU_COMBINED = 'menu';
const ITEM_CUSTOM_DIVIDER = 'engine.divider';
public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
@ -57,10 +64,35 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
return $this->defaultItem;
}
abstract protected function getItemURI($path);
public function setMenuType($type) {
$this->menuType = $type;
return $this;
}
private function getMenuType() {
return $this->menuType;
}
public function setShowNavigation($show) {
$this->showNavigation = $show;
return $this;
}
public function getShowNavigation() {
return $this->showNavigation;
}
abstract protected function getItemURI($path);
abstract protected function isMenuEngineConfigurable();
abstract protected function getBuiltinProfileItems($object);
protected function getBuiltinCustomProfileItems(
$object,
$custom_phid) {
return array();
}
public function buildResponse() {
$controller = $this->getController();
@ -130,6 +162,14 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
$navigation->selectFilter('item.configure');
$crumbs = $controller->buildApplicationCrumbsForEditEngine();
switch ($this->getMenuType()) {
case 'personal':
$crumbs->addTextCrumb(pht('Personal'));
break;
case 'global':
$crumbs->addTextCrumb(pht('Global'));
break;
}
switch ($item_action) {
case 'view':
@ -177,11 +217,15 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
$crumbs->setBorder(true);
return $controller->newPage()
$page = $controller->newPage()
->setTitle(pht('Configure Menu'))
->setNavigation($navigation)
->setCrumbs($crumbs)
->appendChild($content);
if ($this->getShowNavigation()) {
$page->setNavigation($navigation);
}
return $page;
}
public function buildNavigation() {
@ -194,6 +238,7 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
->setBaseURI(new PhutilURI($this->getItemURI('')));
$menu_items = $this->getItems();
$filtered_items = array();
foreach ($menu_items as $menu_item) {
if ($menu_item->isDisabled()) {
@ -239,11 +284,6 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
}
}
$more_items = $this->newAutomaticMenuItems($nav);
foreach ($more_items as $item) {
$nav->addMenuItem($item);
}
$nav->selectFilter(null);
$this->navigation = $nav;
@ -264,19 +304,25 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
$items = $this->loadBuiltinProfileItems();
if ($this->getCustomPHID()) {
$stored_items = id(new PhabricatorProfileMenuItemConfigurationQuery())
->setViewer($viewer)
->withProfilePHIDs(array($object->getPHID()))
->withCustomPHIDs(array($this->getCustomPHID()))
->execute();
} else {
$stored_items = id(new PhabricatorProfileMenuItemConfigurationQuery())
->setViewer($viewer)
->withProfilePHIDs(array($object->getPHID()))
->execute();
$query = id(new PhabricatorProfileMenuItemConfigurationQuery())
->setViewer($viewer)
->withProfilePHIDs(array($object->getPHID()));
$menu_type = $this->getMenuType();
switch ($menu_type) {
case self::MENU_GLOBAL:
$query->withCustomPHIDs(array(), true);
break;
case self::MENU_PERSONAL:
$query->withCustomPHIDs(array($this->getCustomPHID()), false);
break;
case self::MENU_COMBINED:
$query->withCustomPHIDs(array($this->getCustomPHID()), true);
break;
}
$stored_items = $query->execute();
foreach ($stored_items as $stored_item) {
$impl = $stored_item->getMenuItem();
$impl->setViewer($viewer);
@ -305,12 +351,7 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
}
}
$items = msort($items, 'getSortKey');
// Normalize keys since callers shouldn't rely on this array being
// partially keyed.
$items = array_values($items);
$items = $this->arrangeItems($items);
// Make sure exactly one valid item is marked as default.
$default = null;
@ -343,7 +384,26 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
private function loadBuiltinProfileItems() {
$object = $this->getProfileObject();
$builtins = $this->getBuiltinProfileItems($object);
$menu_type = $this->getMenuType();
switch ($menu_type) {
case self::MENU_GLOBAL:
$builtins = $this->getBuiltinProfileItems($object);
break;
case self::MENU_PERSONAL:
$builtins = $this->getBuiltinCustomProfileItems(
$object,
$this->getCustomPHID());
break;
case self::MENU_COMBINED:
$builtins = array();
$builtins[] = $this->getBuiltinCustomProfileItems(
$object,
$this->getCustomPHID());
$builtins[] = $this->getBuiltinProfileItems($object);
$builtins = array_mergev($builtins);
break;
}
$items = PhabricatorProfileMenuItem::getAllMenuItems();
$viewer = $this->getViewer();
@ -410,73 +470,6 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
}
}
private function newAutomaticMenuItems(AphrontSideNavFilterView $nav) {
$items = array();
// NOTE: We're adding a spacer item for the fixed footer, so that if the
// menu taller than the page content you can still scroll down the page far
// enough to access the last item without the content being obscured by the
// fixed items.
$items[] = id(new PHUIListItemView())
->setHideInApplicationMenu(true)
->addClass('phui-profile-menu-spacer');
$collapse_id = celerity_generate_unique_node_id();
$viewer = $this->getViewer();
$collapse_key = PhabricatorProfileMenuCollapsedSetting::SETTINGKEY;
$is_collapsed = $viewer->getUserSetting($collapse_key);
if ($is_collapsed) {
$nav->addClass('phui-profile-menu-collapsed');
} else {
$nav->addClass('phui-profile-menu-expanded');
}
if ($viewer->isLoggedIn()) {
$settings_uri = '/settings/adjust/?key='.$collapse_key;
} else {
$settings_uri = null;
}
Javelin::initBehavior(
'phui-profile-menu',
array(
'menuID' => $nav->getMainID(),
'collapseID' => $collapse_id,
'isCollapsed' => (bool)$is_collapsed,
'settingsURI' => $settings_uri,
));
$collapse_icon = id(new PHUIIconCircleView())
->addClass('phui-list-item-icon')
->addClass('phui-profile-menu-visible-when-expanded')
->setIcon('fa-chevron-left');
$expand_icon = id(new PHUIIconCircleView())
->addClass('phui-list-item-icon')
->addClass('phui-profile-menu-visible-when-collapsed')
->addSigil('has-tooltip')
->setMetadata(
array(
'tip' => pht('Expand'),
'align' => 'E',
))
->setIcon('fa-chevron-right');
$items[] = id(new PHUIListItemView())
->setName('Collapse')
->addIcon($collapse_icon)
->addIcon($expand_icon)
->setID($collapse_id)
->addClass('phui-profile-menu-footer')
->addClass('phui-profile-menu-footer-1')
->setHideInApplicationMenu(true)
->setHref('#');
return $items;
}
public function getConfigureURI() {
return $this->getItemURI('configure/');
}
@ -558,10 +551,22 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
$viewer = $this->getViewer();
$object = $this->getProfileObject();
PhabricatorPolicyFilter::requireCapability(
$viewer,
$object,
PhabricatorPolicyCapability::CAN_EDIT);
$filtered_groups = mgroup($items, 'getMenuItemKey');
foreach ($filtered_groups as $group) {
$first_item = head($group);
$first_item->willBuildNavigationItems($group);
}
// Users only need to be able to edit the object which this menu appears
// on if they're editing global menu items. For example, users do not need
// to be able to edit the Favorites application to add new items to the
// Favorites menu.
if (!$this->getCustomPHID()) {
PhabricatorPolicyFilter::requireCapability(
$viewer,
$object,
PhabricatorPolicyCapability::CAN_EDIT);
}
$list_id = celerity_generate_unique_node_id();
@ -573,7 +578,8 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
));
$list = id(new PHUIObjectItemListView())
->setID($list_id);
->setID($list_id)
->setNoDataString(pht('This menu currently has no items.'));
foreach ($items as $item) {
$id = $item->getID();
@ -710,11 +716,11 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
->setName($doc_name));
$header = id(new PHUIHeaderView())
->setHeader(pht('Profile Menu Items'))
->setHeader(pht('Menu Items'))
->setHeaderIcon('fa-list');
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Navigation'))
->setHeaderText(pht('Current Menu Items'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setObjectList($list);
@ -1022,4 +1028,40 @@ abstract class PhabricatorProfileMenuEngine extends Phobject {
return $this;
}
private function arrangeItems(array $items) {
// Sort the items.
$items = msortv($items, 'getSortVector');
// If we have some global items and some custom items and are in "combined"
// mode, put a hard-coded divider item between them.
if ($this->getMenuType() == self::MENU_COMBINED) {
$list = array();
$seen_custom = false;
$seen_global = false;
foreach ($items as $item) {
if ($item->getCustomPHID()) {
$seen_custom = true;
} else {
if ($seen_custom && !$seen_global) {
$list[] = $this->newItem()
->setBuiltinKey(self::ITEM_CUSTOM_DIVIDER)
->setMenuItemKey(PhabricatorDividerProfileMenuItem::MENUITEMKEY)
->attachMenuItem(
new PhabricatorDividerProfileMenuItem());
}
$seen_global = true;
}
$list[] = $item;
}
$items = $list;
}
// Normalize keys since callers shouldn't rely on this array being
// partially keyed.
$items = array_values($items);
return $items;
}
}

View file

@ -5,6 +5,8 @@ final class PhabricatorApplicationProfileMenuItem
const MENUITEMKEY = 'application';
const FIELD_APPLICATION = 'application';
public function getMenuItemTypeIcon() {
return 'fa-globe';
}
@ -19,30 +21,45 @@ final class PhabricatorApplicationProfileMenuItem
public function getDisplayName(
PhabricatorProfileMenuItemConfiguration $config) {
$app = $this->getApplication($config);
if ($app) {
return $app->getName();
} else {
return pht('(Uninstalled Application)');
$application = $this->getApplication($config);
if (!$application) {
return pht('(Restricted/Invalid Application)');
}
return $app->getName();
$name = $this->getName($config);
if (strlen($name)) {
return $name;
}
return $application->getName();
}
public function buildEditEngineFields(
PhabricatorProfileMenuItemConfiguration $config) {
return array(
id(new PhabricatorDatasourceEditField())
->setKey('application')
->setKey(self::FIELD_APPLICATION)
->setLabel(pht('Application'))
->setDatasource(new PhabricatorApplicationDatasource())
->setIsRequired(true)
->setSingleValue($config->getMenuItemProperty('application')),
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setValue($this->getName($config)),
);
}
private function getName(
PhabricatorProfileMenuItemConfiguration $config) {
return $config->getMenuItemProperty('name');
}
private function getApplication(
PhabricatorProfileMenuItemConfiguration $config) {
$viewer = $this->getViewer();
$phid = $config->getMenuItemProperty('application');
$app = id(new PhabricatorApplicationQuery())
->setViewer($viewer)
->withPHIDs(array($phid))
@ -68,7 +85,7 @@ final class PhabricatorApplicationProfileMenuItem
$item = $this->newItem()
->setHref($app->getApplicationURI())
->setName($app->getName())
->setName($this->getDisplayName($config))
->setIcon($app->getIcon());
return array(
@ -76,4 +93,49 @@ final class PhabricatorApplicationProfileMenuItem
);
}
public function validateTransactions(
PhabricatorProfileMenuItemConfiguration $config,
$field_key,
$value,
array $xactions) {
$viewer = $this->getViewer();
$errors = array();
if ($field_key == self::FIELD_APPLICATION) {
if ($this->isEmptyTransaction($value, $xactions)) {
$errors[] = $this->newRequiredError(
pht('You must choose an application.'),
$field_key);
}
foreach ($xactions as $xaction) {
$new = $xaction['new'];
if (!$new) {
continue;
}
if ($new === $value) {
continue;
}
$applications = id(new PhabricatorApplicationQuery())
->setViewer($viewer)
->withPHIDs(array($new))
->execute();
if (!$applications) {
$errors[] = $this->newInvalidError(
pht(
'Application "%s" is not a valid application which you have '.
'permission to see.',
$new),
$xaction['xaction']);
}
}
}
return $errors;
}
}

View file

@ -5,6 +5,8 @@ final class PhabricatorDashboardProfileMenuItem
const MENUITEMKEY = 'dashboard';
const FIELD_DASHBOARD = 'dashboardPHID';
private $dashboard;
public function getMenuItemTypeIcon() {
@ -70,15 +72,16 @@ final class PhabricatorDashboardProfileMenuItem
public function buildEditEngineFields(
PhabricatorProfileMenuItemConfiguration $config) {
return array(
id(new PhabricatorDatasourceEditField())
->setKey(self::FIELD_DASHBOARD)
->setLabel(pht('Dashboard'))
->setIsRequired(true)
->setDatasource(new PhabricatorDashboardDatasource())
->setSingleValue($config->getMenuItemProperty('dashboardPHID')),
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setValue($this->getName($config)),
id(new PhabricatorDatasourceEditField())
->setKey('dashboardPHID')
->setLabel(pht('Dashboard'))
->setDatasource(new PhabricatorDashboardDatasource())
->setSingleValue($config->getMenuItemProperty('dashboardPHID')),
);
}
@ -109,4 +112,49 @@ final class PhabricatorDashboardProfileMenuItem
);
}
public function validateTransactions(
PhabricatorProfileMenuItemConfiguration $config,
$field_key,
$value,
array $xactions) {
$viewer = $this->getViewer();
$errors = array();
if ($field_key == self::FIELD_DASHBOARD) {
if ($this->isEmptyTransaction($value, $xactions)) {
$errors[] = $this->newRequiredError(
pht('You must choose a dashboard.'),
$field_key);
}
foreach ($xactions as $xaction) {
$new = $xaction['new'];
if (!$new) {
continue;
}
if ($new === $value) {
continue;
}
$dashboards = id(new PhabricatorDashboardQuery())
->setViewer($viewer)
->withPHIDs(array($new))
->execute();
if (!$dashboards) {
$errors[] = $this->newInvalidError(
pht(
'Dashboard "%s" is not a valid dashboard which you have '.
'permission to see.',
$new),
$xaction['xaction']);
}
}
}
return $errors;
}
}

View file

@ -5,6 +5,8 @@ final class PhabricatorEditEngineProfileMenuItem
const MENUITEMKEY = 'editengine';
const FIELD_FORM = 'formKey';
private $form;
public function getMenuItemTypeIcon() {
@ -12,7 +14,7 @@ final class PhabricatorEditEngineProfileMenuItem
}
public function getMenuItemTypeName() {
return pht('Forms');
return pht('Form');
}
public function canAddToObject($object) {
@ -51,7 +53,8 @@ final class PhabricatorEditEngineProfileMenuItem
foreach ($items as $item) {
$key = $item->getMenuItemProperty('formKey');
list($engine_key, $form_key) = explode('/', $key);
list($engine_key, $form_key) = PhabricatorEditEngine::splitFullKey($key);
if (is_numeric($form_key)) {
$form = idx($form_ids, $form_key, null);
$item->getMenuItem()->attachForm($form);
@ -78,15 +81,16 @@ final class PhabricatorEditEngineProfileMenuItem
public function buildEditEngineFields(
PhabricatorProfileMenuItemConfiguration $config) {
return array(
id(new PhabricatorDatasourceEditField())
->setKey(self::FIELD_FORM)
->setLabel(pht('Form'))
->setIsRequired(true)
->setDatasource(new PhabricatorEditEngineDatasource())
->setSingleValue($config->getMenuItemProperty('formKey')),
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setValue($this->getName($config)),
id(new PhabricatorDatasourceEditField())
->setKey('formKey')
->setLabel(pht('Form'))
->setDatasource(new PhabricatorEditEngineDatasource())
->setSingleValue($config->getMenuItemProperty('formKey')),
);
}
@ -119,4 +123,53 @@ final class PhabricatorEditEngineProfileMenuItem
);
}
public function validateTransactions(
PhabricatorProfileMenuItemConfiguration $config,
$field_key,
$value,
array $xactions) {
$viewer = $this->getViewer();
$errors = array();
if ($field_key == self::FIELD_FORM) {
if ($this->isEmptyTransaction($value, $xactions)) {
$errors[] = $this->newRequiredError(
pht('You must choose a form.'),
$field_key);
}
foreach ($xactions as $xaction) {
$new = $xaction['new'];
if (!$new) {
continue;
}
if ($new === $value) {
continue;
}
list($engine_key, $form_key) = PhabricatorEditEngine::splitFullKey(
$new);
$forms = id(new PhabricatorEditEngineConfigurationQuery())
->setViewer($viewer)
->withEngineKeys(array($engine_key))
->withIdentifiers(array($form_key))
->execute();
if (!$forms) {
$errors[] = $this->newInvalidError(
pht(
'Form "%s" is not a valid form which you have permission to '.
'see.',
$new),
$xaction['xaction']);
}
}
}
return $errors;
}
}

View file

@ -5,6 +5,9 @@ final class PhabricatorLinkProfileMenuItem
const MENUITEMKEY = 'link';
const FIELD_URI = 'uri';
const FIELD_NAME = 'name';
public function getMenuItemTypeIcon() {
return 'fa-link';
}
@ -26,12 +29,12 @@ final class PhabricatorLinkProfileMenuItem
PhabricatorProfileMenuItemConfiguration $config) {
return array(
id(new PhabricatorTextEditField())
->setKey('name')
->setKey(self::FIELD_NAME)
->setLabel(pht('Name'))
->setIsRequired(true)
->setValue($this->getLinkName($config)),
id(new PhabricatorTextEditField())
->setKey('uri')
->setKey(self::FIELD_URI)
->setLabel(pht('URI'))
->setIsRequired(true)
->setValue($this->getLinkURI($config)),
@ -91,4 +94,53 @@ final class PhabricatorLinkProfileMenuItem
);
}
public function validateTransactions(
PhabricatorProfileMenuItemConfiguration $config,
$field_key,
$value,
array $xactions) {
$viewer = $this->getViewer();
$errors = array();
if ($field_key == self::FIELD_NAME) {
if ($this->isEmptyTransaction($value, $xactions)) {
$errors[] = $this->newRequiredError(
pht('You must choose a link name.'),
$field_key);
}
}
if ($field_key == self::FIELD_URI) {
if ($this->isEmptyTransaction($value, $xactions)) {
$errors[] = $this->newRequiredError(
pht('You must choose a URI to link to.'),
$field_key);
}
foreach ($xactions as $xaction) {
$new = $xaction['new'];
if (!$new) {
continue;
}
if ($new === $value) {
continue;
}
if (!$this->isValidLinkURI($new)) {
$errors[] = $this->newInvalidError(
pht(
'URI "%s" is not a valid link URI. It should be a full, valid '.
'URI beginning with a protocol like "%s".',
$new,
'https://'),
$xaction['xaction']);
}
}
}
return $errors;
}
}

View file

@ -1,164 +0,0 @@
<?php
final class PhabricatorMotivatorProfileMenuItem
extends PhabricatorProfileMenuItem {
const MENUITEMKEY = 'motivator';
public function getMenuItemTypeIcon() {
return 'fa-coffee';
}
public function getMenuItemTypeName() {
return pht('Motivator');
}
public function canAddToObject($object) {
return true;
}
public function getDisplayName(
PhabricatorProfileMenuItemConfiguration $config) {
$options = $this->getOptions();
$name = idx($options, $config->getMenuItemProperty('source'));
if ($name !== null) {
return pht('Motivator: %s', $name);
} else {
return pht('Motivator');
}
}
public function buildEditEngineFields(
PhabricatorProfileMenuItemConfiguration $config) {
return array(
id(new PhabricatorInstructionsEditField())
->setValue(
pht(
'Motivate your team with inspirational quotes from great minds. '.
'This menu item shows a new quote every day.')),
id(new PhabricatorSelectEditField())
->setKey('source')
->setLabel(pht('Source'))
->setOptions($this->getOptions()),
);
}
private function getOptions() {
return array(
'catfacts' => pht('Cat Facts'),
);
}
protected function newNavigationMenuItems(
PhabricatorProfileMenuItemConfiguration $config) {
$source = $config->getMenuItemProperty('source');
switch ($source) {
case 'catfacts':
default:
$facts = $this->getCatFacts();
break;
}
$fact = $this->selectFact($facts);
switch ($source) {
case 'catfacts':
default:
$fact = array(
id(new PHUIIconView())->setIcon('fa-paw'),
' ',
$fact,
);
break;
}
$fact = phutil_tag(
'div',
array(
'class' => 'phui-motivator',
),
$fact);
$item = $this->newItem()
->appendChild($fact);
return array(
$item,
);
}
private function getCatFacts() {
return array(
pht('Cats purr when they are happy, upset, or asleep.'),
pht('The first cats evolved on the savanah about 8,000 years ago.'),
pht(
'Cats have a tail, two feet, between one and three ears, and two '.
'other feet.'),
pht('Cats use their keen sense of smell to avoid feeling empathy.'),
pht('The first cats evolved in swamps about 65 years ago.'),
pht(
'You can tell how warm a cat is by examining the coloration: cooler '.
'areas are darker.'),
pht(
'Cat tails are flexible because they contain thousands of tiny '.
'bones.'),
pht(
'A cattail is a wetland plant with an appearance that resembles '.
'the tail of a cat.'),
pht(
'Cats must eat a diet rich in fish to replace the tiny bones in '.
'their tails.'),
pht('Cats are stealthy predators and nearly invisible to radar.'),
pht(
'Cats use a special type of magnetism to help them land on their '.
'feet.'),
pht(
'A cat can run seven times faster than a human, but only for a '.
'short distance.'),
pht(
'The largest recorded cat was nearly 11 inches long from nose to '.
'tail.'),
pht(
'Not all cats can retract their claws, but most of them can.'),
pht(
'In the wild, cats and racoons sometimes hunt together in packs.'),
pht(
'The Spanish word for cat is "cato". The biggest cat is called '.
'"el cato".'),
pht(
'The Japanese word for cat is "kome", which is also the word for '.
'rice. Japanese cats love to eat rice, so the two are synonymous.'),
pht('Cats have five pointy ends.'),
pht('cat -A can find mice hiding in files.'),
pht('A cat\'s visual, olfactory, and auditory senses, '.
'Contribute to their hunting skills and natural defenses.'),
pht(
'Cats with high self-esteem seek out high perches '.
'to launch their attacks. Watch out!'),
pht('Cats prefer vanilla ice cream.'),
pht('Taco cat spelled backwards is taco cat.'),
pht(
'Cats will often bring you their prey because they feel sorry '.
'for your inability to hunt.'),
pht('Cats spend most of their time plotting to kill their owner.'),
);
}
private function selectFact(array $facts) {
// This is a simple pseudorandom number generator that avoids touching
// srand(), because it would seed it to a highly predictable value. It
// selects a new fact every day.
$seed = ((int)date('Y') * 366) + (int)date('z');
for ($ii = 0; $ii < 32; $ii++) {
$seed = ((1664525 * $seed) + 1013904223) % (1 << 31);
}
return $facts[$seed % count($facts)];
}
}

View file

@ -70,4 +70,41 @@ abstract class PhabricatorProfileMenuItem extends Phobject {
return new PHUIListItemView();
}
public function valdateTransactions(
PhabricatorProfileMenuItemConfiguration $config,
$field_key,
$value,
array $xactions) {
return array();
}
final protected function isEmptyTransaction($value, array $xactions) {
$result = $value;
foreach ($xactions as $xaction) {
$result = $xaction['new'];
}
return !strlen($result);
}
final protected function newError($title, $message, $xaction = null) {
return new PhabricatorApplicationTransactionValidationError(
PhabricatorProfileMenuItemConfigurationTransaction::TYPE_PROPERTY,
$title,
$message,
$xaction);
}
final protected function newRequiredError($message, $type) {
$xaction = id(new PhabricatorProfileMenuItemConfigurationTransaction())
->setMetadataValue('property.key', $type);
return $this->newError(pht('Required'), $message, $xaction)
->setIsMissingFieldError(true);
}
final protected function newInvalidError($message, $xaction = null) {
return $this->newError(pht('Invalid'), $message, $xaction);
}
}

View file

@ -4,6 +4,7 @@ final class PhabricatorProjectProfileMenuItem
extends PhabricatorProfileMenuItem {
const MENUITEMKEY = 'project';
const FIELD_PROJECT = 'project';
private $project;
@ -71,15 +72,16 @@ final class PhabricatorProjectProfileMenuItem
public function buildEditEngineFields(
PhabricatorProfileMenuItemConfiguration $config) {
return array(
id(new PhabricatorDatasourceEditField())
->setKey(self::FIELD_PROJECT)
->setLabel(pht('Project'))
->setIsRequired(true)
->setDatasource(new PhabricatorProjectDatasource())
->setSingleValue($config->getMenuItemProperty('project')),
id(new PhabricatorTextEditField())
->setKey('name')
->setLabel(pht('Name'))
->setValue($this->getName($config)),
id(new PhabricatorDatasourceEditField())
->setKey('project')
->setLabel(pht('Project'))
->setDatasource(new PhabricatorProjectDatasource())
->setSingleValue($config->getMenuItemProperty('project')),
);
}
@ -110,4 +112,49 @@ final class PhabricatorProjectProfileMenuItem
);
}
public function validateTransactions(
PhabricatorProfileMenuItemConfiguration $config,
$field_key,
$value,
array $xactions) {
$viewer = $this->getViewer();
$errors = array();
if ($field_key == self::FIELD_PROJECT) {
if ($this->isEmptyTransaction($value, $xactions)) {
$errors[] = $this->newRequiredError(
pht('You must choose a project.'),
$field_key);
}
foreach ($xactions as $xaction) {
$new = $xaction['new'];
if (!$new) {
continue;
}
if ($new === $value) {
continue;
}
$projects = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->withPHIDs(array($new))
->execute();
if (!$projects) {
$errors[] = $this->newInvalidError(
pht(
'Project "%s" is not a valid project which you have '.
'permission to see.',
$new),
$xaction['xaction']);
}
}
}
return $errors;
}
}

View file

@ -7,6 +7,7 @@ final class PhabricatorProfileMenuItemConfigurationQuery
private $phids;
private $profilePHIDs;
private $customPHIDs;
private $includeGlobal;
public function withIDs(array $ids) {
$this->ids = $ids;
@ -23,8 +24,9 @@ final class PhabricatorProfileMenuItemConfigurationQuery
return $this;
}
public function withCustomPHIDs(array $phids) {
public function withCustomPHIDs(array $phids, $include_global = false) {
$this->customPHIDs = $phids;
$this->includeGlobal = $include_global;
return $this;
}
@ -61,10 +63,21 @@ final class PhabricatorProfileMenuItemConfigurationQuery
}
if ($this->customPHIDs !== null) {
$where[] = qsprintf(
$conn,
'customPHID IN (%Ls)',
$this->customPHIDs);
if ($this->customPHIDs && $this->includeGlobal) {
$where[] = qsprintf(
$conn,
'customPHID IN (%Ls) OR customPHID IS NULL',
$this->customPHIDs);
} else if ($this->customPHIDs) {
$where[] = qsprintf(
$conn,
'customPHID IN (%Ls)',
$this->customPHIDs);
} else {
$where[] = qsprintf(
$conn,
'customPHID IS NULL');
}
}
return $where;

View file

@ -126,18 +126,52 @@ final class PhabricatorProfileMenuItemConfiguration
return $this->getMenuItem()->willBuildNavigationItems($items);
}
public function getSortKey() {
$order = $this->getMenuItemOrder();
if ($order === null) {
$order = 'Z';
} else {
$order = sprintf('%020d', $order);
public function validateTransactions(array $map) {
$item = $this->getMenuItem();
$fields = $item->buildEditEngineFields($this);
$errors = array();
foreach ($fields as $field) {
$field_key = $field->getKey();
$xactions = idx($map, $field_key, array());
$value = $this->getMenuItemProperty($field_key);
$field_errors = $item->validateTransactions(
$this,
$field_key,
$value,
$xactions);
foreach ($field_errors as $error) {
$errors[] = $error;
}
}
return sprintf(
'~%s%020d',
$order,
$this->getID());
return $errors;
}
public function getSortVector() {
// Sort custom items above global items.
if ($this->getCustomPHID()) {
$is_global = 0;
} else {
$is_global = 1;
}
// Sort items with an explicit order above items without an explicit order,
// so any newly created builtins go to the bottom.
$order = $this->getMenuItemOrder();
if ($order !== null) {
$has_order = 0;
} else {
$has_order = 1;
}
return id(new PhutilSortVector())
->addInt($is_global)
->addInt($has_order)
->addInt((int)$order)
->addInt((int)$this->getID());
}
public function isDisabled() {
@ -179,6 +213,21 @@ final class PhabricatorProfileMenuItemConfiguration
public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
// If this is an item with a custom PHID (like a personal menu item),
// we only require that the user can edit the corresponding custom
// object (usually their own user profile), not the object that the
// menu appears on (which may be an Application like Favorites or Home).
if ($capability == PhabricatorPolicyCapability::CAN_EDIT) {
if ($this->getCustomPHID()) {
return array(
array(
$this->getCustomPHID(),
$capability,
),
);
}
}
return array(
array(
$this->getProfileObject(),

View file

@ -1,29 +0,0 @@
<?php
final class PhabricatorSettingsMainMenuBarExtension
extends PhabricatorMainMenuBarExtension {
const MAINMENUBARKEY = 'settings';
public function buildMainMenus() {
$controller = $this->getController();
$is_selected = ($controller instanceof PhabricatorSettingsMainController);
$bar_item = id(new PHUIListItemView())
->setName(pht('Settings'))
->setIcon('fa-wrench')
->addClass('core-menu-item')
->setSelected($is_selected)
->setHref('/settings/')
->setAural(pht('Settings'));
$settings_menu = id(new PHUIMainMenuView())
->setMenuBarItem($bar_item)
->setOrder(400);
return array(
$settings_menu,
);
}
}

View file

@ -1,46 +0,0 @@
<?php
final class PhabricatorEditEngineCreateQuickActions
extends PhabricatorQuickActions {
const QUICKACTIONSKEY = 'editengine.create';
public function getQuickMenuItems() {
$viewer = $this->getViewer();
$engines = PhabricatorEditEngine::getAllEditEngines();
foreach ($engines as $key => $engine) {
if (!$engine->hasQuickCreateActions()) {
unset($engines[$key]);
}
}
if (!$engines) {
return array();
}
$engine_keys = array_keys($engines);
$configs = id(new PhabricatorEditEngineConfigurationQuery())
->setViewer($viewer)
->withEngineKeys($engine_keys)
->withIsDefault(true)
->withIsDisabled(false)
->execute();
$configs = msort($configs, 'getCreateSortKey');
$configs = mgroup($configs, 'getEngineKey');
$items = array();
foreach ($engines as $key => $engine) {
$engine_configs = idx($configs, $key, array());
$engine_items = $engine->newQuickCreateActions($engine_configs);
foreach ($engine_items as $engine_item) {
$items[] = $engine_item;
}
}
return $items;
}
}

View file

@ -1,54 +0,0 @@
<?php
abstract class PhabricatorQuickActions extends Phobject {
private $viewer;
public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;
}
public function getViewer() {
return $this->viewer;
}
public function isEnabled() {
return true;
}
abstract public function getQuickMenuItems();
final public function getQuickActionsKey() {
return $this->getPhobjectClassConstant('QUICKACTIONSKEY');
}
public static function getAllQuickActions() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getQuickActionsKey')
->execute();
}
public static function loadMenuItemsForUser(PhabricatorUser $viewer) {
$actions = self::getAllQuickActions();
foreach ($actions as $key => $action) {
$action->setViewer($viewer);
if (!$action->isEnabled()) {
unset($actions[$key]);
continue;
}
}
$items = array();
foreach ($actions as $key => $action) {
foreach ($action->getQuickMenuItems() as $item) {
$items[] = $item;
}
}
return $items;
}
}

View file

@ -1,12 +0,0 @@
<?php
final class PhabricatorProfileMenuCollapsedSetting
extends PhabricatorInternalSetting {
const SETTINGKEY = 'profile-menu.collapsed';
public function getSettingName() {
return pht('Profile Menu Collapsed');
}
}

View file

@ -95,4 +95,41 @@ abstract class PhabricatorDraftEngine
$editor->save();
}
final public static function attachDrafts(
PhabricatorUser $viewer,
array $objects) {
assert_instances_of($objects, 'PhabricatorDraftInterface');
$viewer_phid = $viewer->getPHID();
if (!$viewer_phid) {
// Viewers without a valid PHID can never have drafts.
foreach ($objects as $object) {
$object->attachHasDraft($viewer, false);
}
return;
} else {
$draft_type = PhabricatorObjectHasDraftEdgeType::EDGECONST;
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($objects, 'getPHID'))
->withEdgeTypes(
array(
$draft_type,
))
->withDestinationPHIDs(array($viewer_phid));
$edge_query->execute();
foreach ($objects as $object) {
$has_draft = (bool)$edge_query->getDestinationPHIDs(
array(
$object->getPHID(),
));
$object->attachHasDraft($viewer, $has_draft);
}
}
}
}

View file

@ -4,4 +4,25 @@ interface PhabricatorDraftInterface {
public function newDraftEngine();
public function getHasDraft(PhabricatorUser $viewer);
public function attachHasDraft(PhabricatorUser $viewer, $has_draft);
}
/* -( PhabricatorDraftInterface )------------------------------------------ */
/*
public function newDraftEngine() {
return new <...>DraftEngine();
}
public function getHasDraft(PhabricatorUser $viewer) {
return $this->assertAttachedKey($this->drafts, $viewer->getCacheFragment());
}
public function attachHasDraft(PhabricatorUser $viewer, $has_draft) {
$this->drafts[$viewer->getCacheFragment()] = $has_draft;
return $this;
}
*/

View file

@ -77,6 +77,33 @@ abstract class PhabricatorEditEngine
return true;
}
public function isDefaultQuickCreateEngine() {
return false;
}
public function getDefaultQuickCreateFormKeys() {
$keys = array();
if ($this->isDefaultQuickCreateEngine()) {
$keys[] = self::EDITENGINECONFIG_DEFAULT;
}
foreach ($keys as $idx => $key) {
$keys[$idx] = $this->getEngineKey().'/'.$key;
}
return $keys;
}
public static function splitFullKey($full_key) {
return explode('/', $full_key, 2);
}
public function getQuickCreateOrderVector() {
return id(new PhutilSortVector())
->addString($this->getObjectCreateShortText());
}
/**
* Force the engine to edit a particular object.
*/
@ -107,10 +134,6 @@ abstract class PhabricatorEditEngine
return $this->hideHeader;
}
public function getProfileMenuItemDefault() {
return $this->getEngineKey().'/'.self::EDITENGINECONFIG_DEFAULT;
}
/* -( Managing Fields )---------------------------------------------------- */
@ -283,14 +306,6 @@ abstract class PhabricatorEditEngine
}
/**
* @task text
*/
protected function getQuickCreateMenuHeaderText() {
return $this->getObjectCreateShortText();
}
/**
* Return a human-readable header describing what this engine is used to do,
* like "Configure Maniphest Task Forms".
@ -2100,50 +2115,6 @@ abstract class PhabricatorEditEngine
return $application->getIcon();
}
public function hasQuickCreateActions() {
if (!$this->isEngineConfigurable()) {
return false;
}
return true;
}
public function newQuickCreateActions(array $configs) {
$items = array();
if (!$configs) {
return array();
}
// If the viewer is logged in and can't create objects, don't show the
// menu item. If they're logged out, we assume they could create objects
// if they logged in, so we show the item as a hint about how to
// accomplish the action.
if ($this->getViewer()->isLoggedIn()) {
if (!$this->hasCreateCapability()) {
return array();
}
}
if (count($configs) == 1) {
$config = head($configs);
$items[] = $this->newQuickCreateAction($config);
} else {
$group_name = $this->getQuickCreateMenuHeaderText();
$items[] = id(new PHUIListItemView())
->setType(PHUIListItemView::TYPE_LABEL)
->setName($group_name);
foreach ($configs as $config) {
$items[] = $this->newQuickCreateAction($config)
->setIndented(true);
}
}
return $items;
}
private function loadUsableConfigurationsForCreate() {
$viewer = $this->getViewer();
@ -2159,20 +2130,6 @@ abstract class PhabricatorEditEngine
return $configs;
}
private function newQuickCreateAction(
PhabricatorEditEngineConfiguration $config) {
$item_name = $config->getName();
$item_icon = $config->getIcon();
$form_key = $config->getIdentifier();
$item_uri = $this->getEditURI(null, "form/{$form_key}/");
return id(new PHUIListItemView())
->setName($item_name)
->setIcon($item_icon)
->setHref($item_uri);
}
protected function getValidationExceptionShortMessage(
PhabricatorApplicationTransactionValidationException $ex,
PhabricatorEditField $field) {

View file

@ -50,7 +50,6 @@ final class PHUIDiffGraphView extends Phobject {
$thread_count = $pos;
for ($n = 0; $n < $thread_count; $n++) {
if (empty($threads[$n])) {
$line .= ' ';
continue;
@ -60,7 +59,7 @@ final class PHUIDiffGraphView extends Phobject {
if ($found) {
$line .= ' ';
$joins[] = $n;
unset($threads[$n]);
$threads[$n] = false;
} else {
$line .= 'o';
$found = true;
@ -114,6 +113,7 @@ final class PHUIDiffGraphView extends Phobject {
if ($thread_commit == $parent) {
$found = true;
$splits[] = $idx;
break;
}
}

View file

@ -270,7 +270,7 @@ final class PHUIDiffInlineCommentDetailView
),
'sigil' => 'differential-inline-preview-jump',
),
pht('Not Visible'));
pht('View'));
$action_buttons[] = id(new PHUIButtonView())
->setTag('a')

View file

@ -45,10 +45,10 @@ final class PHUIDiffGraphViewTestCase extends PhabricatorTestCase {
'^',
'|^',
'o ',
'|^',
'||^',
'o ',
'x',
'| ^',
'| |^',
'o ',
'x ',
);
$this->assertGraph($picture, $graph, pht('Reverse Tree'));
@ -71,7 +71,30 @@ final class PHUIDiffGraphViewTestCase extends PhabricatorTestCase {
'x ',
);
$this->assertGraph($picture, $graph, pht('Reverse Tree'));
$this->assertGraph($picture, $graph, pht('Terminated Tree'));
}
public function testThreeWayGraphJoin() {
$nodes = array(
'A' => array('D', 'C', 'B'),
'B' => array('D'),
'C' => array('B', 'E', 'F'),
'D' => array(),
'E' => array(),
'F' => array(),
);
$graph = $this->newGraph($nodes);
$picture = array(
'^',
'||o',
'|o|',
'x| ||',
' | x|',
' | x',
);
$this->assertGraph($picture, $graph, pht('Three-Way Tree'));
}
private function newGraph(array $nodes) {

View file

@ -1,10 +1,9 @@
<?php
final class PhabricatorActionListView extends AphrontView {
final class PhabricatorActionListView extends AphrontTagView {
private $actions = array();
private $object;
private $id = null;
public function setObject(PhabricatorLiskDAO $object) {
$this->object = $object;
@ -16,16 +15,19 @@ final class PhabricatorActionListView extends AphrontView {
return $this;
}
public function setID($id) {
$this->id = $id;
return $this;
protected function getTagName() {
return 'ul';
}
public function getID() {
return $this->id;
protected function getTagAttributes() {
$classes = array();
$classes[] = 'phabricator-action-list-view';
return array(
'class' => implode(' ', $classes),
);
}
public function render() {
protected function getTagContent() {
$viewer = $this->getViewer();
$event = new PhabricatorEvent(
@ -55,13 +57,7 @@ final class PhabricatorActionListView extends AphrontView {
}
}
return phutil_tag(
'ul',
array(
'class' => 'phabricator-action-list-view',
'id' => $this->id,
),
$items);
return $items;
}
public function getDropdownMenuMetadata() {

View file

@ -18,6 +18,13 @@ final class PhabricatorActionView extends AphrontView {
private $hidden;
private $depth;
private $id;
private $order;
private $color;
private $type;
const TYPE_DIVIDER = 'type-divider';
const TYPE_LABEL = 'label';
const RED = 'action-item-red';
public function setSelected($selected) {
$this->selected = $selected;
@ -51,6 +58,11 @@ final class PhabricatorActionView extends AphrontView {
return $this;
}
public function setColor($color) {
$this->color = $color;
return $this;
}
public function addSigil($sigil) {
$this->sigils[] = $sigil;
return $this;
@ -114,6 +126,24 @@ final class PhabricatorActionView extends AphrontView {
return $this->id;
}
public function setOrder($order) {
$this->order = $order;
return $this;
}
public function getOrder() {
return $this->order;
}
public function setType($type) {
$this->type = $type;
return $this;
}
public function getType() {
return $this->type;
}
public function setSubmenu(array $submenu) {
$this->submenu = $submenu;
@ -173,22 +203,26 @@ final class PhabricatorActionView extends AphrontView {
->setIcon($this->icon.$color);
}
$sigils = array();
if ($this->workflow) {
$sigils[] = 'workflow';
}
if ($this->download) {
$sigils[] = 'download';
}
if ($this->submenu) {
$sigils[] = 'keep-open';
}
if ($this->sigils) {
$sigils = array_merge($sigils, $this->sigils);
}
$sigils = $sigils ? implode(' ', $sigils) : null;
if ($this->href) {
$sigils = array();
if ($this->workflow) {
$sigils[] = 'workflow';
}
if ($this->download) {
$sigils[] = 'download';
}
if ($this->sigils) {
$sigils = array_merge($sigils, $this->sigils);
}
$sigils = $sigils ? implode(' ', $sigils) : null;
if ($this->renderAsForm) {
if (!$this->hasViewer()) {
throw new Exception(
@ -244,12 +278,13 @@ final class PhabricatorActionView extends AphrontView {
array($icon, $this->name, $caret));
}
} else {
$item = phutil_tag(
$item = javelin_tag(
'span',
array(
'class' => 'phabricator-action-view-item',
'sigil' => $sigils,
),
array($icon, $this->name));
array($icon, $this->name, $this->renderChildren()));
}
$classes = array();
@ -275,6 +310,18 @@ final class PhabricatorActionView extends AphrontView {
$classes[] = 'phabricator-action-view-href';
}
if ($this->icon) {
$classes[] = 'action-has-icon';
}
if ($this->color) {
$classes[] = $this->color;
}
if ($this->type) {
$classes[] = 'phabricator-action-view-'.$this->type;
}
$style = array();
if ($this->hidden) {

View file

@ -767,23 +767,6 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView
->setViewer($viewer);
$dropdown_query->execute();
$rendered_dropdowns = array();
$applications = array(
'PhabricatorHelpApplication',
);
foreach ($applications as $application_class) {
if (!PhabricatorApplication::isClassInstalledForViewer(
$application_class,
$viewer)) {
continue;
}
$application = PhabricatorApplication::getByClass($application_class);
$rendered_dropdowns[$application_class] =
$application->buildMainMenuExtraNodes(
$viewer,
$controller);
}
$hisec_warning_config = $this->getHighSecurityWarningConfig();
$console_config = null;
@ -799,6 +782,7 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView
$application_class = null;
$application_search_icon = null;
$application_help = null;
$controller = $this->getController();
if ($controller) {
$application = $controller->getCurrentApplication();
@ -807,6 +791,16 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView
if ($application->getApplicationSearchDocumentTypes()) {
$application_search_icon = $application->getIcon();
}
$help_items = $application->getHelpMenuItems($viewer);
if ($help_items) {
$help_list = id(new PhabricatorActionListView())
->setViewer($viewer);
foreach ($help_items as $help_item) {
$help_list->addAction($help_item);
}
$application_help = $help_list->getDropdownMenuMetadata();
}
}
}
@ -818,11 +812,11 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView
$dropdown_query->getConpherenceData(),
),
'globalDragAndDrop' => $upload_enabled,
'aphlictDropdowns' => $rendered_dropdowns,
'hisecWarningConfig' => $hisec_warning_config,
'consoleConfig' => $console_config,
'applicationClass' => $application_class,
'applicationSearchIcon' => $application_search_icon,
'helpItems' => $application_help,
) + $this->buildAphlictListenConfigData();
}

View file

@ -99,8 +99,10 @@ final class PhabricatorMainMenuSearchView extends AphrontView {
'id' => $button_id,
'class' => 'phui-icon-view phui-font-fa fa-search',
),
$search_text),
$selector,
array(
$selector,
$search_text,
)),
$primary_input,
$target,
)));
@ -118,7 +120,7 @@ final class PhabricatorMainMenuSearchView extends AphrontView {
$items[] = array(
'icon' => 'fa-globe',
'name' => pht('Search All Documents'),
'name' => pht('All Documents'),
'value' => 'all',
);
@ -134,7 +136,7 @@ final class PhabricatorMainMenuSearchView extends AphrontView {
$items[] = array(
'icon' => $application_icon,
'name' => pht('Search Current Application'),
'name' => pht('Current Application'),
'value' => PhabricatorSearchController::SCOPE_CURRENT_APPLICATION,
);

View file

@ -52,10 +52,10 @@ final class PhabricatorMainMenuView extends AphrontView {
$alerts[] = $menu;
}
$menu_bar = array_merge($menu_bar, $dropdowns);
$app_button = $this->renderApplicationMenuButton($header_id);
$app_button = $this->renderApplicationMenuButton();
$search_button = $this->renderSearchMenuButton($header_id);
} else {
$app_button = $this->renderApplicationMenuButton($header_id);
$app_button = $this->renderApplicationMenuButton();
if (PhabricatorEnv::getEnvConfig('policy.allow-public')) {
$search_button = $this->renderSearchMenuButton($header_id);
}
@ -82,27 +82,17 @@ final class PhabricatorMainMenuView extends AphrontView {
phutil_implode_html(' ', $aural));
}
// Build out Header Menus
$applications = PhabricatorApplication::getAllInstalledApplications();
$menus = array();
$controller = $this->getController();
foreach ($applications as $application) {
$app_actions = $application->buildMainMenuItems(
$viewer,
$controller);
$app_extra = $application->buildMainMenuExtraNodes(
$viewer,
$controller);
foreach ($app_actions as $action) {
$menus[] = id(new PHUIMainMenuView())
->setMenuBarItem($action)
->setOrder($action->getOrder());
}
if ($app_extra !== null) {
$menus[] = id(new PHUIMainMenuView())
->appendChild($app_extra);
$menus[] = $app_extra;
}
}
@ -126,26 +116,17 @@ final class PhabricatorMainMenuView extends AphrontView {
}
}
// Builds out "login" button
foreach ($extensions as $extension) {
foreach ($extension->buildMainMenus() as $menu) {
$menus[] = $menu;
}
}
$menus = msort($menus, 'getOrder');
$bar_items = array();
foreach ($menus as $menu) {
$menu_bar[] = $menu;
$item = $menu->getMenuBarItem();
if ($item === null) {
continue;
}
$bar_items[] = $item;
}
$application_menu = $this->renderApplicationMenu($bar_items);
$classes = array();
$classes[] = 'phabricator-main-menu';
$classes[] = 'phabricator-main-menu-background';
@ -162,7 +143,6 @@ final class PhabricatorMainMenuView extends AphrontView {
$this->renderPhabricatorLogo(),
$alerts,
$aural,
$application_menu,
$search_menu,
$menu_bar,
));
@ -218,53 +198,37 @@ final class PhabricatorMainMenuView extends AphrontView {
return $result;
}
public function renderApplicationMenuButton($header_id) {
$button_id = celerity_generate_unique_node_id();
return javelin_tag(
'a',
array(
'class' => 'phabricator-main-menu-expand-button '.
'phabricator-expand-search-menu',
'sigil' => 'jx-toggle-class',
'meta' => array(
'map' => array(
$header_id => 'phabricator-application-menu-expanded',
$button_id => 'menu-icon-selected',
),
),
),
phutil_tag(
'span',
array(
'class' => 'phabricator-menu-button-icon phui-icon-view '.
'phui-font-fa fa-bars',
'id' => $button_id,
),
''));
public function renderApplicationMenuButton() {
$dropdown = $this->renderApplicationMenu();
if (!$dropdown) {
return null;
}
return id(new PHUIButtonView())
->setTag('a')
->setHref('#')
->setIcon('fa-bars')
->addClass('phabricator-core-user-menu')
->addClass('phabricator-core-user-mobile-menu')
->setNoCSS(true)
->setDropdownMenu($dropdown);
}
private function renderApplicationMenu(array $bar_items) {
private function renderApplicationMenu() {
$viewer = $this->getViewer();
$view = $this->getApplicationMenu();
if (!$view) {
$view = new PHUIListView();
}
$view->addClass('phabricator-dark-menu');
$view->addClass('phabricator-application-menu');
if ($bar_items) {
$view->addMenuItem(
id(new PHUIListItemView())
->setType(PHUIListItemView::TYPE_LABEL)
->setName(pht('Actions')));
foreach ($bar_items as $bar_item) {
$view->addMenuItem($bar_item);
if ($view) {
$items = $view->getItems();
$view = id(new PhabricatorActionListView())
->setViewer($viewer);
foreach ($items as $item) {
$view->addAction(
id(new PhabricatorActionView())
->setName($item->getName())
->setHref($item->getHref())
->setType($item->getType()));
}
}
return $view;
}
@ -296,7 +260,6 @@ final class PhabricatorMainMenuView extends AphrontView {
private function renderPhabricatorSearchMenu() {
$view = new PHUIListView();
$view->addClass('phabricator-dark-menu');
$view->addClass('phabricator-search-menu');
$search = $this->renderSearch();

View file

@ -27,6 +27,8 @@ final class PHUIButtonView extends AphrontTagView {
private $disabled;
private $name;
private $tooltip;
private $noCSS;
private $hasCaret;
public function setName($name) {
$this->name = $name;
@ -87,6 +89,20 @@ final class PHUIButtonView extends AphrontTagView {
return $this;
}
public function setNoCSS($no_css) {
$this->noCSS = $no_css;
return $this;
}
public function setHasCaret($has_caret) {
$this->hasCaret = $has_caret;
return $this;
}
public function getHasCaret() {
return $this->hasCaret;
}
public function setIcon($icon, $first = true) {
if (!($icon instanceof PHUIIconView)) {
$icon = id(new PHUIIconView())
@ -164,6 +180,10 @@ final class PHUIButtonView extends AphrontTagView {
);
}
if ($this->noCSS) {
$classes = array();
}
return array(
'class' => $classes,
'href' => $this->href,
@ -191,7 +211,7 @@ final class PHUIButtonView extends AphrontTagView {
}
$caret = null;
if ($this->dropdown) {
if ($this->dropdown || $this->getHasCaret()) {
$caret = phutil_tag('span', array('class' => 'caret'), '');
}

View file

@ -202,7 +202,7 @@ final class PHUIListItemView extends AphrontTagView {
}
return array(
'class' => $classes,
'class' => implode(' ', $classes),
);
}

View file

@ -1,31 +0,0 @@
<?php
final class PHUIMainMenuView extends AphrontView {
private $menuItem;
private $extraContent = array();
private $order;
public function setMenuBarItem(PHUIListItemView $menu_item) {
$this->menuItem = $menu_item;
return $this;
}
public function getMenuBarItem() {
return $this->menuItem;
}
public function setOrder($order) {
$this->order = $order;
return $this;
}
public function getOrder() {
return $this->order;
}
public function render() {
return $this->renderChildren();
}
}

View file

@ -606,8 +606,8 @@ final class PHUITimelineEventView extends AphrontView {
$items[] = id(new PhabricatorActionView())
->setIcon('fa-quote-left')
->setName(pht('Quote Comment'))
->setHref('#')
->setName(pht('Quote'))
->addSigil('transaction-quote')
->setMetadata(
array(
@ -619,9 +619,9 @@ final class PHUITimelineEventView extends AphrontView {
if ($this->getIsNormalComment()) {
$items[] = id(new PhabricatorActionView())
->setIcon('fa-cutlery')
->setIcon('fa-code')
->setHref('/transactions/raw/'.$xaction_phid.'/')
->setName(pht('View Raw'))
->setName(pht('View Remarkup'))
->addSigil('transaction-raw')
->setMetadata(
array(
@ -646,19 +646,6 @@ final class PHUITimelineEventView extends AphrontView {
}
}
if ($this->getIsRemovable()) {
$items[] = id(new PhabricatorActionView())
->setIcon('fa-times')
->setHref('/transactions/remove/'.$xaction_phid.'/')
->setName(pht('Remove Comment'))
->addSigil('transaction-remove')
->setMetadata(
array(
'anchor' => $anchor,
));
}
if ($this->getIsEdited()) {
$items[] = id(new PhabricatorActionView())
->setIcon('fa-list')
@ -667,6 +654,23 @@ final class PHUITimelineEventView extends AphrontView {
->setWorkflow(true);
}
if ($this->getIsRemovable()) {
$items[] = id(new PhabricatorActionView())
->setType(PhabricatorActionView::TYPE_DIVIDER);
$items[] = id(new PhabricatorActionView())
->setIcon('fa-trash-o')
->setHref('/transactions/remove/'.$xaction_phid.'/')
->setName(pht('Remove Comment'))
->setColor(PhabricatorActionView::RED)
->addSigil('transaction-remove')
->setMetadata(
array(
'anchor' => $anchor,
));
}
return $items;
}

View file

@ -63,7 +63,7 @@
}
.device-phone .phabricator-wordmark {
max-width: 112px; /* iPhone 5 limitation */
display: none;
}
.phabricator-wordmark {
@ -119,7 +119,7 @@
*/
.device-desktop .phabricator-main-menu-search {
width: 220px;
width: 298px;
}
.device .phabricator-main-menu-search {
@ -130,7 +130,7 @@
padding: 8px 0;
position: relative;
height: 24px;
margin: 0 8px;
margin: 0 8px 0 0;
}
.phabricator-main-menu-search-target {
@ -150,6 +150,7 @@
.device .phabricator-main-menu-search-container {
padding: 4px 0;
margin: 0 4px;
}
.phabricator-main-menu .phabricator-main-menu-search input {
@ -169,9 +170,9 @@
border-style: solid;
background-color: #fff;
height: 28px;
padding: 3px 30px 3px 6px;
padding: 3px 28px 3px 52px;
float: left;
width: 205px;
width: 280px;
}
.device .phabricator-main-menu-search input {
@ -196,7 +197,7 @@
.phabricator-main-menu-search button {
color: {$bluetext};
position: absolute;
background: {$greybackground};
background: transparent;
border: none;
outline: none;
box-shadow: none;
@ -204,7 +205,7 @@
min-width: 0;
height: 24px;
width: 28px;
top: 10px;
top: 9px;
right: -6px;
margin: 0 8px 0 0;
padding: 0;
@ -214,20 +215,22 @@
.phabricator-main-menu-search button.phabricator-main-menu-search-dropdown {
position: absolute;
right: auto;
left: -45px;
width: 40px;
background: transparent;
left: 12px;
width: 46px;
background: {$greybackground};
z-index: 1;
}
.device-desktop .phabricator-main-menu-search
button.phabricator-main-menu-search-dropdown {
height: 28px;
top: 8px;
height: 24px;
top: 10px;
border-radius: 3px;
}
.device-desktop .phabricator-main-menu-search
button.phabricator-main-menu-search-dropdown:hover .phui-icon-view {
color: #fff;
color: {$sky};
}
.device .phabricator-main-menu-search
@ -236,34 +239,24 @@
background: {$greybackground};
}
button.phabricator-main-menu-search-dropdown .caret:before {
button.phabricator-main-menu-search-dropdown .caret:before,
a.phabricator-core-user-menu .caret:before {
content: "\f107";
font-family: FontAwesome;
color: {$hoverwhite};
}
.phabricator-main-menu-search button.phabricator-main-menu-search-dropdown
.phui-icon-view {
color: {$hoverwhite};
color: {$bluetext};
font-size: 15px;
top: 6px;
top: 4px;
left: 8px;
}
.device
.phabricator-main-menu-search button.phabricator-main-menu-search-dropdown
.phui-icon-view {
color: {$bluetext};
}
.device button.phabricator-main-menu-search-dropdown .caret:before {
color: {$bluetext};
}
.phabricator-main-menu-search-dropdown .caret {
position: absolute;
right: 15px;
top: 5px;
right: 18px;
top: 2px;
border: none;
margin-top: 1px;
}
@ -284,7 +277,7 @@ button.phabricator-main-menu-search-dropdown .caret:before {
word-wrap: break-word;
overflow-y: auto;
box-shadow: {$dropshadow};
border: 1px solid {$blueborder};
border: 1px solid {$lightgreyborder};
border-radius: 3px;
margin-left: 40px;
}
@ -339,12 +332,6 @@ button.phabricator-main-menu-search-dropdown .caret:before {
font-size: {$normalfontsize};
}
.device .phabricator-dark-menu .phui-list-item-type-link
.phabricator-main-search-typeahead-result {
line-height: 18px;
}
/* - Alert ---------------------------------------------------------------------
@ -442,36 +429,6 @@ button.phabricator-main-menu-search-dropdown .caret:before {
display: block;
}
/* - Dark Menu -----------------------------------------------------------------
Styles shared between the "core" menu (left button on mobile) and
"application" menu (right button on mobile). These styles give the menu a
white-on-black appearance.
*/
.device .phabricator-dark-menu,
.device .phabricator-dark-menu a.phui-list-item-href {
color: {$darkbluetext};
-webkit-font-smoothing: antialiased;
}
.device .phabricator-dark-menu .phui-list-item-type-label {
text-transform: uppercase;
font-size: {$normalfontsize};
background-color: #fff;
padding: 6px 0 6px 12px;
display: block;
font-weight: bold;
color: #000;
}
.device .phabricator-dark-menu .phui-list-item-href {
background-color: #fff;
padding: 4px 0 4px 20px;
display: block;
}
/* - Core Menu -----------------------------------------------------------------
@ -479,10 +436,6 @@ button.phabricator-main-menu-search-dropdown .caret:before {
*/
.phabricator-core-menu-profile-image {
background-size: 28px 28px;
}
.device .phabricator-search-menu {
display: none;
}
@ -500,12 +453,7 @@ button.phabricator-main-menu-search-dropdown .caret:before {
border: 1px solid {$lightblueborder};
border-radius: 3px;
box-shadow: {$dropshadow};
}
.device .phabricator-dark-menu .phui-list-item-type-link {
min-height: 24px;
line-height: 20px;
background: #fff;
background: {$page.background};
}
.device-desktop .phabricator-application-menu {
@ -531,12 +479,6 @@ button.phabricator-main-menu-search-dropdown .caret:before {
vertical-align: middle;
}
.device .phabricator-dark-menu.phabricator-application-menu
.phui-list-item-icon.phui-font-fa,
.device .phabricator-dark-menu .phabricator-core-menu-icon {
display: none;
}
.device .phabricator-application-menu .phui-list-item-icon.phui-font-fa {
margin: 4px 12px 4px 0;
}
@ -606,29 +548,108 @@ button.phabricator-main-menu-search-dropdown .caret:before {
padding-left: 12px;
}
/* - User Menu -----------------------------------------------------------------
/* - Application Menu ----------------------------------------------------------
Styles unique to the application menu (right button on mobile).
Styles unique to the user profile menu.
*/
.device .phabricator-application-menu-expanded .phabricator-application-menu {
display: block;
position: absolute;
border: 1px solid {$blueborder};
border-radius: 3px;
box-shadow: {$dropshadow};
top: 42px;
right: 8px;
width: 240px;
.phabricator-core-user-menu {
float: right;
display: inline-block;
padding: 9px 24px 0 8px;
height: 35px;
position: relative;
}
.device .phabricator-application-menu,
.device-desktop .phabricator-dark-menu .phui-list-item-type-label {
.phabricator-core-user-mobile-menu {
display: none;
}
.phabricator-core-user-menu span.phui-icon-view.phuihead-small {
height: 24px;
width: 24px;
background-size: 24px;
border-radius: 3px;
display: inline-block;
margin: 1px 0 0 0;
}
.phabricator-core-user-menu .phui-icon-view {
color: {$hoverwhite};
font-size: 18px;
margin: 4px 0 0 0;
}
.phabricator-core-user-menu .caret {
position: absolute;
right: 17px;
top: 13px;
border: none;
margin: 1px;
color: {$hoverwhite};
}
.phabricator-core-login-button {
float: right;
display: inline-block;
padding: 4px 12px;
border-radius: 3px;
margin: 8px 6px 4px;
border: 1px solid {$hoverwhite};
color: {$hoverwhite};
}
.device-desktop .phabricator-core-login-button:hover {
border: 1px solid #fff;
color: #fff;
}
.device-desktop .phabricator-core-user-menu:hover .caret,
.device-desktop .phabricator-core-user-menu:hover .phui-icon-view {
color: #fff;
}
.device .phabricator-core-user-menu .caret {
display: none;
}
.device .phabricator-core-user-mobile-menu {
display: block;
}
.device .phabricator-core-user-menu {
padding: 9px 8px 0 8px;
}
.device .phabricator-core-user-menu .phui-icon-view {
font-size: 20px;
margin: 3px 0 0 0;
}
ul.phabricator-core-user-profile-object .phui-oi-objname {
font-size: {$biggestfontsize};
}
ul.phabricator-core-user-profile-object li.phui-oi,
ul.phabricator-core-user-profile-object .phui-oi-name,
ul.phabricator-core-user-profile-object .phui-oi-content,
ul.phabricator-core-user-profile-object .phui-oi-subhead {
padding: 0;
margin: 0;
}
ul.phabricator-core-user-profile-object.phui-oi-list-simple .phui-oi-image {
height: 36px;
width: 36px;
}
ul.phabricator-core-user-profile-object.phui-oi-list-simple
.phui-oi-content-box {
margin-left: 44px;
}
/* - Print ---------------------------------------------------------------------
*/

View file

@ -8,7 +8,7 @@
word-wrap: break-word;
overflow-y: auto;
box-shadow: {$dropshadow};
border: 1px solid {$blueborder};
border: 1px solid {$lightgreyborder};
border-radius: 3px;
}

View file

@ -11,6 +11,7 @@
/* When an action list view appears inside a dropdown menu, don't hide it
by default. */
display: block;
padding: 0;
}
.device .phabricator-action-list-view.phabricator-action-list-toggle,
@ -18,7 +19,7 @@
.phabricator-action-list-view.phabricator-action-list-toggle {
display: block;
width: 200px;
border: 1px solid {$lightblueborder};
border: 1px solid {$lightgreyborder};
border-radius: 3px;
position: absolute;
right: 16px;
@ -58,18 +59,49 @@
.phabricator-action-view button.phabricator-action-view-item,
.phabricator-action-view-item {
padding: 4px 4px 4px 28px;
padding: 4px 8px 6px 8px;
display: block;
text-decoration: none;
color: {$darkbluetext};
}
.phabricator-action-view-label .phabricator-action-view-item {
font-size: {$normalfontsize};
.action-has-icon button.phabricator-action-view-item,
.action-has-icon .phabricator-action-view-item {
padding: 4px 4px 4px 28px;
}
.device-desktop .phabricator-action-view-href:hover
.phabricator-action-view-item {
text-decoration: none;
background: rgba({$alphablue}, .08);
color: {$sky};
border-radius: 3px;
}
.device-desktop .phabricator-action-view-href:hover
.phabricator-action-view-icon {
color: {$sky};
}
.device-desktop .phabricator-action-view-href.action-item-red:hover
.phabricator-action-view-item {
background-color: {$sh-redbackground};
color: {$sh-redtext};
}
.device-desktop .phabricator-action-view-href.action-item-red:hover
.phabricator-action-view-icon {
color: {$red};
}
.phabricator-action-view-label .phabricator-action-view-item,
.phabricator-action-view-type-label .phabricator-action-view-item {
font-size: {$smallerfontsize};
font-weight: bold;
color: {$bluetext};
padding: 4px 8px 6px 8px;
display: block;
text-transform: uppercase;
-webkit-font-smoothing: antialiased;
}
@ -87,37 +119,23 @@
width: 14px;
height: 14px;
position: absolute;
top: 8px;
top: 7px;
left: 8px;
text-align: center;
}
.device-desktop .phabricator-action-view:hover .phabricator-action-view-item {
text-decoration: none;
background-color: {$sky};
color: #fff;
}
.device-desktop .phabricator-action-view:hover .phabricator-action-view-icon {
color: #fff;
}
.phabricator-action-view-disabled .phabricator-action-view-item,
.phabricator-action-view-disabled button.phabricator-action-view-item {
color: {$lightgreytext};
}
.phabricator-action-view-selected {
border-left: 3px solid {$sky};
background: {$hoverblue};
background: {$sh-violetbackground};
border-radius: 3px;
}
.phabricator-action-view-selected .phabricator-action-view-item {
padding-left: 25px;
}
.phabricator-action-view-selected .phabricator-action-view-icon {
left: 6px;
.phabricator-action-view-selected:hover a {
text-decoration: none;
}
.phabricator-action-view button[disabled] {
@ -135,3 +153,8 @@
background-color: {$greybackground};
color: {$lightgreytext};
}
.phabricator-action-view-type-divider {
margin-top: 8px;
border-top: 1px solid {$thinblueborder};
}

View file

@ -198,12 +198,12 @@ button.link:hover {
.phuix-dropdown-menu {
position: absolute;
width: 240px;
width: 200px;
background: #fff;
margin-top: -1px;
padding: 5px 0;
padding: 12px;
box-shadow: {$dropshadow};
border: 1px solid {$blueborder};
border: 1px solid {$lightgreyborder};
border-radius: 3px;
margin-bottom: 16px;
}

View file

@ -80,7 +80,7 @@ a.button.phui-document-toc {
.phui-document-view-pro .phui-document-toc-list {
margin: 8px;
border: 1px solid {$blueborder};
border: 1px solid {$lightgreyborder};
border-radius: 3px;
box-shadow: {$dropshadow};
width: 200px;

View file

@ -460,8 +460,7 @@ body .phui-form-view .remarkup-assist-textarea.aphront-textarea-drag-and-drop {
.fancy-datepicker-core {
background-color: white;
border: 1px solid {$lightblueborder};
border-bottom: 1px solid {$blueborder};
border: 1px solid {$lightgreyborder};
box-shadow: {$dropshadow};
border-radius: 3px;
}

View file

@ -2,7 +2,7 @@
* @provides phui-profile-menu-css
*/
.device-desktop .phui-profile-menu-collapsed .phabricator-nav-local {
.device-desktop .phui-profile-menu .phabricator-nav-local {
width: {$menu.profile.width.collapsed};
max-width: {$menu.profile.width.collapsed};
}
@ -58,8 +58,7 @@
background-size: 100%;
}
.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu
.phui-list-item-href {
.phui-profile-menu .phabricator-side-menu .phui-list-item-href {
text-align: center;
padding: 42px 4px 14px;
line-height: 14px;
@ -67,19 +66,17 @@
font-size: {$smallerfontsize};
}
.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu
.phui-list-item-name {
.phui-profile-menu .phabricator-side-menu .phui-list-item-name {
display: block;
overflow: hidden;
text-overflow: ellipsis;
}
.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu
.phui-list-item-icon,
.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu
.phui-list-item-href .phui-list-item-icon {
top: 14px;
left: 32px;
.phui-profile-menu .phabricator-side-menu .phui-list-item-icon,
.phui-profile-menu .phabricator-side-menu .phui-list-item-href
.phui-list-item-icon {
top: 14px;
left: 32px;
}
.phui-profile-menu .phabricator-side-menu
@ -131,14 +128,12 @@
padding: 16px;
}
.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu
.phui-profile-menu-error {
.phui-profile-menu .phabricator-side-menu .phui-profile-menu-error {
padding: 16px 8px;
overflow: hidden;
text-overflow: ellipsis;
}
.phui-profile-menu .phabricator-side-menu .phui-list-item-disabled
.phui-list-item-href,
.phui-profile-menu .phui-list-sidenav .phui-list-item-disabled
@ -153,150 +148,15 @@
padding: 8px 12px 16px;
}
.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu
.phui-profile-segment-bar {
.phui-profile-menu .phabricator-side-menu .phui-profile-segment-bar {
padding: 8px 8px 16px;
}
.phui-profile-menu .phabricator-side-menu .phui-profile-menu-spacer {
box-sizing: border-box;
height: {$menu.profile.item.height};
}
.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu
.phui-profile-menu-footer
.phui-list-item-name {
display: none;
}
.phui-profile-menu .phui-profile-menu-expanded
.phui-profile-menu-visible-when-collapsed,
.phui-profile-menu .phui-profile-menu-collapsed
.phui-profile-menu-visible-when-expanded {
display: none;
}
.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu
.phui-profile-menu-footer .phui-list-item-href {
padding: 20px 0 24px;
}
.phui-profile-menu .phabricator-side-menu .phui-profile-menu-footer
.phui-list-item-href:hover {
background: transparent;
}
.phui-profile-menu .phui-profile-menu-collapsed .phabricator-side-menu
.phui-profile-menu-footer .phui-list-item-href .phui-list-item-icon {
top: 8px;
}
.phui-profile-menu .phui-profile-menu-footer .phui-icon-circle {
border-color: {$darkbluetext};
}
.phui-profile-menu .phui-profile-menu-footer .phui-icon-circle .phui-icon-view {
color: {$darkbluetext};
}
.phui-profile-menu .phui-profile-menu-footer
.phui-icon-circle.phui-list-item-icon {
font-size: 12px;
}
.phui-profile-menu .phabricator-side-menu .phui-profile-menu-footer-1 {
bottom: 0;
position: fixed;
}
.phui-profile-menu .phui-profile-menu-footer-1 {
width: {$menu.profile.width};
}
.phui-profile-menu .phui-profile-menu-collapsed .phui-profile-menu-footer-1 {
width: {$menu.profile.width.collapsed};
}
.phui-profile-menu .phabricator-side-menu
.phui-list-item-selected.phui-profile-menu-footer .phui-list-item-href {
background: transparent;
}
.phui-profile-menu .phui-profile-menu-collapsing
.phabricator-nav-local {
animation: profile-menu-collapse 0.2s;
}
.phui-profile-menu .phui-profile-menu-expanding
.phabricator-nav-local {
animation: profile-menu-expand 0.2s;
}
.phui-profile-menu .phui-profile-menu-collapsing
.phabricator-side-menu .phui-list-item-href {
animation: profile-menu-blink 0.2s;
}
.phui-profile-menu .phui-profile-menu-expanding
.phabricator-side-menu .phui-list-item-href {
animation: profile-menu-blink 0.2s;
}
@keyframes profile-menu-blink {
0% {
opacity: 1.0;
}
25% {
opacity: 0.0;
}
75% {
opacity: 0.0;
}
100% {
opacity: 1.0;
}
}
@keyframes profile-menu-collapse {
0% {
width: {$menu.profile.width};
max-width: {$menu.profile.width};
}
33% {
width: {$menu.profile.width};
max-width: {$menu.profile.width};
}
66% {
width: {$menu.profile.width.collapsed};
max-width: {$menu.profile.width.collapsed};
}
100% {
width: {$menu.profile.width.collapsed};
max-width: {$menu.profile.width.collapsed};
}
}
@keyframes profile-menu-expand {
0% {
width: {$menu.profile.width.collapsed};
max-width: {$menu.profile.width.collapsed};
}
33% {
width: {$menu.profile.width.collapsed};
max-width: {$menu.profile.width.collapsed};
}
66% {
width: {$menu.profile.width};
max-width: {$menu.profile.width};
}
100% {
width: {$menu.profile.width};
max-width: {$menu.profile.width};
}
}
!print .phui-profile-menu .phabricator-side-menu {
display: none;
}

View file

@ -159,24 +159,6 @@
padding: 0 12px;
}
.phabricator-action-view button.phabricator-action-view-item,
.phabricator-action-view-item {
padding: 5px 4px 5px 28px;
}
.device-desktop .phui-two-column-properties .phabricator-action-view-href:hover
.phabricator-action-view-item {
text-decoration: none;
background-color: rgba({$alphablue}, .08);
color: {$sky};
border-radius: 3px;
}
.device-desktop .phui-two-column-properties .phabricator-action-view-href:hover
.phabricator-action-view-icon {
color: {$sky};
}
.phui-two-column-view .phui-property-list-section-header,
.phui-two-column-view .phui-property-list-text-content {
margin: 0 16px;
@ -199,6 +181,10 @@
padding: 12px;
}
.phui-two-column-view .phui-oi-empty .phui-info-view {
margin: 0;
}
.phui-two-column-view .phui-side-column .phui-oi-empty
.phui-info-view {
margin-bottom: 0;

View file

@ -32,11 +32,6 @@
}
.device-desktop .project-board-wrapper .phui-workboard-view-shadow {
left: {$menu.profile.width};
}
.device-desktop .phui-profile-menu-collapsed .project-board-wrapper
.phui-workboard-view-shadow {
left: {$menu.profile.width.collapsed};
}

View file

@ -91,24 +91,6 @@ JX.behavior('aphlict-dropdown', function(config, statics) {
null,
function (e) {
var data = e.getData();
if (config.local && config.applicationClass) {
var local_dropdowns = data.newResponse.aphlictDropdowns;
if (local_dropdowns[config.applicationClass]) {
JX.DOM.replace(
dropdown,
JX.$H(local_dropdowns[config.applicationClass]));
dropdown = JX.$(config.dropdownID);
if (dropdown.childNodes.length === 0) {
JX.DOM.hide(bubble);
} else {
JX.DOM.show(bubble);
}
} else {
JX.DOM.hide(bubble);
}
return;
}
if (!data.fromServer) {
return;
}

View file

@ -34,13 +34,6 @@ JX.behavior('project-boards', function(config, statics) {
data.menu = new JX.PHUIXDropdownMenu(button);
data.menu.setContent(list);
data.menu.open();
JX.DOM.listen(list, 'click', 'tag:a', function(e) {
if (!e.isNormalClick()) {
return;
}
data.menu.close();
});
});
JX.Stratcom.listen(

View file

@ -126,7 +126,7 @@ JX.behavior('comment-actions', function(config) {
}
function force_preview() {
if (!config.shouldPreview) {
if (!config.showPreview) {
return;
}

View file

@ -0,0 +1,57 @@
/**
* @provides javelin-behavior-user-menu
* @requires javelin-behavior
*/
JX.behavior('user-menu', function(config) {
var node = JX.$(config.menuID);
var list = JX.$H(config.menu.items).getFragment().firstChild;
var menu = new JX.PHUIXDropdownMenu(node);
menu.listen('open', function() {
menu.setContent(list);
});
// When the user navigates to a new page, we may need to update the links
// to documentation in the menu.
JX.Stratcom.listen('quicksand-redraw', null, function(e) {
var data = e.getData();
var new_help = data.newResponse.helpItems;
var nodes;
if (new_help) {
nodes = JX.$H(new_help.items).getFragment().firstChild.children;
} else {
nodes = [];
}
var ii;
var tail = [];
for (ii = list.children.length - 1; ii >= 0; ii--) {
var node = list.children[ii];
// Remove any old help items.
if (JX.Stratcom.hasSigil(node.firstChild, 'help-item')) {
JX.DOM.remove(node);
}
// Place the logout items aside, if any exist.
if (JX.Stratcom.hasSigil(node.firstChild, 'logout-item')) {
JX.DOM.remove(node);
tail.push(node);
}
}
while (nodes.length) {
list.appendChild(nodes[0]);
}
tail.reverse();
for (ii = 0; ii < tail.length; ii++) {
list.appendChild(tail[ii]);
}
});
});

View file

@ -42,18 +42,6 @@ JX.behavior('phui-dropdown-menu', function() {
});
data.menu.open();
JX.DOM.listen(list, 'click', 'tag:a', function(e) {
if (!e.isNormalClick()) {
return;
}
if (JX.Stratcom.pass()) {
return;
}
data.menu.close();
});
});
});

View file

@ -1,53 +0,0 @@
/**
* @provides javelin-behavior-phui-profile-menu
* @requires javelin-behavior
* javelin-stratcom
* javelin-dom
*/
JX.behavior('phui-profile-menu', function(config) {
// NOTE: This behavior is not initialized in the rendering pipeline for the
// menu, so it can get initialized when we build but do not render a menu
// (for example, when a page like the panel edit page only has items in
// the mobile/application menu, and does not show the profile menu). For now,
// just bail if we can't find the menu.
try {
var menu_node = JX.$(config.menuID);
} catch (ex) {
return;
}
var collapse_node = JX.$(config.collapseID);
var is_collapsed = config.isCollapsed;
JX.DOM.listen(collapse_node, 'click', null, function(e) {
is_collapsed = !is_collapsed;
JX.DOM.alterClass(menu_node, 'phui-profile-menu-collapsing', is_collapsed);
JX.DOM.alterClass(menu_node, 'phui-profile-menu-expanding', !is_collapsed);
var duration = 0.2;
setTimeout(function() {
JX.DOM.alterClass(menu_node, 'phui-profile-menu-collapsed', is_collapsed);
JX.DOM.alterClass(menu_node, 'phui-profile-menu-expanded', !is_collapsed);
}, (duration / 2) * 1000);
setTimeout(function() {
JX.DOM.alterClass(menu_node, 'phui-profile-menu-collapsing', false);
JX.DOM.alterClass(menu_node, 'phui-profile-menu-expanding', false);
}, duration * 1000);
if (config.settingsURI) {
new JX.Request(config.settingsURI)
.setData({value: (is_collapsed ? 1 : 0)})
.send();
}
e.kill();
});
});

View file

@ -77,16 +77,27 @@ JX.install('PHUIXActionView', {
getNode: function() {
if (!this._node) {
var attr = {
className: 'phabricator-action-view'
};
var classes = ['phabricator-action-view'];
if (this._href || this._handler) {
classes.push('phabricator-action-view-href');
}
if (this._icon) {
classes.push('action-has-icon');
}
var content = [
this._buildIconNode(),
this._buildNameNode()
];
var attr = {
className: classes.join(' ')
};
this._node = JX.$N('li', attr, content);
JX.Stratcom.addSigil(this._node, 'phuix-action-view');
}
return this._node;

View file

@ -40,6 +40,12 @@ JX.install('PHUIXDropdownMenu', {
JX.Stratcom.listen('phuix.dropdown.open', null, JX.bind(this, this.close));
JX.Stratcom.listen('keydown', null, JX.bind(this, this._onkey));
JX.DOM.listen(
this._getMenuNode(),
'click',
'tag:a',
JX.bind(this, this._onlink));
},
events: ['open', 'close'],
@ -112,6 +118,28 @@ JX.install('PHUIXDropdownMenu', {
e.prevent();
},
_onlink: function(e) {
if (!e.isNormalClick()) {
return;
}
// If this action was built dynamically with PHUIXActionView, don't
// do anything by default. The caller is repsonsible for installing a
// handler if they want to react to clicks.
if (e.getNode('phuix-action-view')) {
return;
}
// If this item opens a submenu, we don't want to close the current
// menu. One submenu is "Edit Related Objects..." on mobile.
var link = e.getNode('tag:a');
if (JX.Stratcom.hasSigil(link, 'keep-open')) {
return;
}
this.close();
},
_onanyclick : function(e) {
if (!this._open) {
return;