diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 7d846e4cec..9296082d99 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,7 +7,7 @@ */ return array( 'names' => array( - 'core.pkg.css' => '90c46327', + 'core.pkg.css' => '340c5b75', 'core.pkg.js' => 'b562c3db', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '3fb7f532', @@ -24,7 +24,7 @@ return array( 'rsrc/css/aphront/multi-column.css' => 'fd18389d', 'rsrc/css/aphront/notification.css' => '3f6c89c9', 'rsrc/css/aphront/panel-view.css' => '8427b78d', - 'rsrc/css/aphront/phabricator-nav-view.css' => '09f3d0db', + 'rsrc/css/aphront/phabricator-nav-view.css' => 'b29426e9', 'rsrc/css/aphront/table-view.css' => '832656fd', 'rsrc/css/aphront/tokenizer.css' => '056da01b', 'rsrc/css/aphront/tooltip.css' => '1a07aea8', @@ -32,7 +32,7 @@ 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' => 'b623169f', + 'rsrc/css/application/base/main-menu-view.css' => '3b0d39f7', 'rsrc/css/application/base/notification-menu.css' => 'f31c0bde', 'rsrc/css/application/base/phabricator-application-launch-view.css' => '95351601', 'rsrc/css/application/base/phui-theme.css' => '027ba77e', @@ -41,7 +41,7 @@ return array( 'rsrc/css/application/conduit/conduit-api.css' => '7bc725c4', 'rsrc/css/application/config/config-options.css' => '0ede4c9b', 'rsrc/css/application/config/config-template.css' => '8e6c6fcd', - 'rsrc/css/application/config/config-welcome.css' => '6abd79be', + 'rsrc/css/application/config/config-welcome.css' => '035aa483', 'rsrc/css/application/config/setup-issue.css' => 'db7e9c40', 'rsrc/css/application/config/unhandled-exception.css' => '4c96257a', 'rsrc/css/application/conpherence/durable-column.css' => '86396117', @@ -131,7 +131,7 @@ return array( 'rsrc/css/phui/phui-curtain-view.css' => '7148ae25', 'rsrc/css/phui/phui-document-pro.css' => 'dc3d46ed', 'rsrc/css/phui/phui-document-summary.css' => '9ca48bdf', - 'rsrc/css/phui/phui-document.css' => '715aedfb', + 'rsrc/css/phui/phui-document.css' => 'c32e8dec', 'rsrc/css/phui/phui-feed-story.css' => 'aa49845d', 'rsrc/css/phui/phui-fontkit.css' => '9cda225e', 'rsrc/css/phui/phui-form-view.css' => 'fab0a10f', @@ -163,7 +163,6 @@ return array( 'rsrc/css/phui/workboards/phui-workcard.css' => '0c62d7c5', 'rsrc/css/phui/workboards/phui-workpanel.css' => '92197373', 'rsrc/css/sprite-login.css' => '60e8560e', - 'rsrc/css/sprite-menu.css' => '9dd65b92', 'rsrc/css/sprite-tokens.css' => '9cdfd599', 'rsrc/css/syntax/syntax-default.css' => '9923583c', 'rsrc/externals/d3/d3.min.js' => 'a11a5ff2', @@ -320,6 +319,7 @@ return array( 'rsrc/image/icon/tango/upload.png' => '7bbb7984', 'rsrc/image/icon/unsubscribe.png' => '25725013', 'rsrc/image/lightblue-header.png' => '5c168b6d', + 'rsrc/image/logo/light-eye.png' => '1a576ddd', 'rsrc/image/main_texture.png' => '29a2c5ad', 'rsrc/image/menu_texture.png' => '5a17580d', 'rsrc/image/people/harding.png' => '45aa614e', @@ -343,8 +343,6 @@ return array( 'rsrc/image/resize.png' => 'fd476de4', 'rsrc/image/sprite-login-X2.png' => 'e3991e37', 'rsrc/image/sprite-login.png' => '03d5af29', - 'rsrc/image/sprite-menu-X2.png' => 'cfd8fca5', - 'rsrc/image/sprite-menu.png' => 'd7a99faa', 'rsrc/image/sprite-tokens-X2.png' => '804a5232', 'rsrc/image/sprite-tokens.png' => 'b41d03da', 'rsrc/image/texture/card-gradient.png' => '815f26e8', @@ -548,7 +546,7 @@ return array( 'changeset-view-manager' => 'a2828756', 'conduit-api-css' => '7bc725c4', 'config-options-css' => '0ede4c9b', - 'config-welcome-css' => '6abd79be', + 'config-welcome-css' => '035aa483', 'conpherence-durable-column-view' => '86396117', 'conpherence-menu-css' => 'f99fee4c', 'conpherence-message-pane-css' => '5897d3ac', @@ -785,8 +783,8 @@ return array( 'phabricator-flag-css' => '5337623f', 'phabricator-keyboard-shortcut' => '1ae869f2', 'phabricator-keyboard-shortcut-manager' => '4a021c10', - 'phabricator-main-menu-view' => 'b623169f', - 'phabricator-nav-view-css' => '09f3d0db', + 'phabricator-main-menu-view' => '3b0d39f7', + 'phabricator-nav-view-css' => 'b29426e9', 'phabricator-notification' => 'ccf1cbf8', 'phabricator-notification-css' => '3f6c89c9', 'phabricator-notification-menu-css' => 'f31c0bde', @@ -837,7 +835,7 @@ return array( 'phui-crumbs-view-css' => '9dac418c', 'phui-curtain-view-css' => '7148ae25', 'phui-document-summary-view-css' => '9ca48bdf', - 'phui-document-view-css' => '715aedfb', + 'phui-document-view-css' => 'c32e8dec', 'phui-document-view-pro-css' => 'dc3d46ed', 'phui-feed-story-css' => 'aa49845d', 'phui-font-icon-base-css' => '6449bce8', @@ -891,7 +889,6 @@ return array( 'releeph-request-typeahead-css' => '667a48ae', 'setup-issue-css' => 'db7e9c40', 'sprite-login-css' => '60e8560e', - 'sprite-menu-css' => '9dd65b92', 'sprite-tokens-css' => '9cdfd599', 'syntax-default-css' => '9923583c', 'syntax-highlighting-css' => '769d3498', @@ -1165,6 +1162,9 @@ return array( 'javelin-dom', 'javelin-magical-init', ), + '3b0d39f7' => array( + 'phui-theme-css', + ), '3cb0b2fc' => array( 'javelin-behavior', 'javelin-dom', @@ -1844,9 +1844,6 @@ return array( 'javelin-dom', 'javelin-util', ), - 'b623169f' => array( - 'phui-theme-css', - ), 'b6993408' => array( 'javelin-behavior', 'javelin-stratcom', @@ -2246,7 +2243,6 @@ return array( 'aphront-tooltip-css', 'phabricator-flag-css', 'phui-info-view-css', - 'sprite-menu-css', 'phabricator-main-menu-view', 'phabricator-notification-css', 'phabricator-notification-menu-css', diff --git a/resources/celerity/packages.php b/resources/celerity/packages.php index 103d395f79..66015f6263 100644 --- a/resources/celerity/packages.php +++ b/resources/celerity/packages.php @@ -104,7 +104,6 @@ return array( 'aphront-tooltip-css', 'phabricator-flag-css', 'phui-info-view-css', - 'sprite-menu-css', 'phabricator-main-menu-view', 'phabricator-notification-css', diff --git a/resources/sprite/manifest/menu.json b/resources/sprite/manifest/menu.json deleted file mode 100644 index 68fe112276..0000000000 --- a/resources/sprite/manifest/menu.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "version": 1, - "sprites": { - "dark-eye": { - "name": "dark-eye", - "rule": ".dark-eye", - "hash": "c8112e52666fa1cb509ebb2cdf3a3df5" - }, - "dark-logo": { - "name": "dark-logo", - "rule": ".dark-logo", - "hash": "e3425da87e8f6737d8db0063d064cd7d" - }, - "light-eye": { - "name": "light-eye", - "rule": ".light-eye", - "hash": "5b6bf7c8c10d4f7414d976f6e79ae2ff" - }, - "light-logo": { - "name": "light-logo", - "rule": ".light-logo", - "hash": "bee37c0a86825ec7ded38936b1ba7b65" - } - }, - "scales": [ - 1, - 2 - ], - "header": "\/**\n * @provides sprite-menu-css\n * @generated\n *\/\n\n.sprite-menu {\n background-image: url(\/rsrc\/image\/sprite-menu.png);\n background-repeat: no-repeat;\n}\n\n@media\nonly screen and (min-device-pixel-ratio: 1.5),\nonly screen and (-webkit-min-device-pixel-ratio: 1.5),\nonly screen and (min-resolution: 1.5dppx) {\n .sprite-menu {\n background-image: url(\/rsrc\/image\/sprite-menu-X2.png);\n background-size: {X}px {Y}px;\n }\n}\n", - "type": "standard" -} diff --git a/resources/sprite/menu_1x/dark-eye.png b/resources/sprite/menu_1x/dark-eye.png deleted file mode 100644 index 2e13cbf2a1..0000000000 Binary files a/resources/sprite/menu_1x/dark-eye.png and /dev/null differ diff --git a/resources/sprite/menu_1x/dark-logo.png b/resources/sprite/menu_1x/dark-logo.png deleted file mode 100644 index be96d3c13c..0000000000 Binary files a/resources/sprite/menu_1x/dark-logo.png and /dev/null differ diff --git a/resources/sprite/menu_1x/light-eye.png b/resources/sprite/menu_1x/light-eye.png deleted file mode 100644 index 64e37bcac2..0000000000 Binary files a/resources/sprite/menu_1x/light-eye.png and /dev/null differ diff --git a/resources/sprite/menu_1x/light-logo.png b/resources/sprite/menu_1x/light-logo.png deleted file mode 100644 index 8544d7ad3b..0000000000 Binary files a/resources/sprite/menu_1x/light-logo.png and /dev/null differ diff --git a/resources/sprite/menu_2x/dark-eye.png b/resources/sprite/menu_2x/dark-eye.png deleted file mode 100644 index dd28bf3a8c..0000000000 Binary files a/resources/sprite/menu_2x/dark-eye.png and /dev/null differ diff --git a/resources/sprite/menu_2x/dark-logo.png b/resources/sprite/menu_2x/dark-logo.png deleted file mode 100644 index 0920a8a6ec..0000000000 Binary files a/resources/sprite/menu_2x/dark-logo.png and /dev/null differ diff --git a/resources/sprite/menu_2x/light-eye.png b/resources/sprite/menu_2x/light-eye.png deleted file mode 100644 index 267ba6c1cb..0000000000 Binary files a/resources/sprite/menu_2x/light-eye.png and /dev/null differ diff --git a/resources/sprite/menu_2x/light-logo.png b/resources/sprite/menu_2x/light-logo.png deleted file mode 100644 index a9710c8857..0000000000 Binary files a/resources/sprite/menu_2x/light-logo.png and /dev/null differ diff --git a/resources/sql/autopatches/20160810.commit.01.summarylength.sql b/resources/sql/autopatches/20160810.commit.01.summarylength.sql new file mode 100644 index 0000000000..366f0948cd --- /dev/null +++ b/resources/sql/autopatches/20160810.commit.01.summarylength.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_repository.repository_commit + CHANGE summary summary VARCHAR(255) NOT NULL COLLATE {$COLLATE_TEXT}; diff --git a/scripts/celerity/generate_sprites.php b/scripts/celerity/generate_sprites.php index 61f63d155d..ccdd194b36 100755 --- a/scripts/celerity/generate_sprites.php +++ b/scripts/celerity/generate_sprites.php @@ -27,7 +27,6 @@ $webroot = Filesystem::readablePath($webroot); $generator = new CeleritySpriteGenerator(); $sheets = array( - 'menu' => $generator->buildMenuSheet(), 'tokens' => $generator->buildTokenSheet(), 'login' => $generator->buildLoginSheet(), ); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index c5059723a5..fc75e65838 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1622,9 +1622,7 @@ phutil_register_library_map(array( 'PHUIDiffTableOfContentsItemView' => 'infrastructure/diff/view/PHUIDiffTableOfContentsItemView.php', 'PHUIDiffTableOfContentsListView' => 'infrastructure/diff/view/PHUIDiffTableOfContentsListView.php', 'PHUIDiffTwoUpInlineCommentRowScaffold' => 'infrastructure/diff/view/PHUIDiffTwoUpInlineCommentRowScaffold.php', - 'PHUIDocumentExample' => 'applications/uiexample/examples/PHUIDocumentExample.php', 'PHUIDocumentSummaryView' => 'view/phui/PHUIDocumentSummaryView.php', - 'PHUIDocumentView' => 'view/phui/PHUIDocumentView.php', 'PHUIDocumentViewPro' => 'view/phui/PHUIDocumentViewPro.php', 'PHUIFeedStoryExample' => 'applications/uiexample/examples/PHUIFeedStoryExample.php', 'PHUIFeedStoryView' => 'view/phui/PHUIFeedStoryView.php', @@ -2268,7 +2266,7 @@ phutil_register_library_map(array( 'PhabricatorCustomFieldStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldStorage.php', 'PhabricatorCustomFieldStorageQuery' => 'infrastructure/customfield/query/PhabricatorCustomFieldStorageQuery.php', 'PhabricatorCustomFieldStringIndexStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldStringIndexStorage.php', - 'PhabricatorCustomHeaderConfigType' => 'applications/config/custom/PhabricatorCustomHeaderConfigType.php', + 'PhabricatorCustomLogoConfigType' => 'applications/config/custom/PhabricatorCustomLogoConfigType.php', 'PhabricatorDaemon' => 'infrastructure/daemon/PhabricatorDaemon.php', 'PhabricatorDaemonBulkJobController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobController.php', 'PhabricatorDaemonBulkJobListController' => 'applications/daemon/controller/PhabricatorDaemonBulkJobListController.php', @@ -3383,6 +3381,7 @@ phutil_register_library_map(array( 'PhabricatorRepositoryCommitPHIDType' => 'applications/repository/phid/PhabricatorRepositoryCommitPHIDType.php', 'PhabricatorRepositoryCommitParserWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitParserWorker.php', 'PhabricatorRepositoryCommitRef' => 'applications/repository/engine/PhabricatorRepositoryCommitRef.php', + 'PhabricatorRepositoryCommitTestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryCommitTestCase.php', 'PhabricatorRepositoryConfigOptions' => 'applications/repository/config/PhabricatorRepositoryConfigOptions.php', 'PhabricatorRepositoryDAO' => 'applications/repository/storage/PhabricatorRepositoryDAO.php', 'PhabricatorRepositoryDiscoveryEngine' => 'applications/repository/engine/PhabricatorRepositoryDiscoveryEngine.php', @@ -6270,9 +6269,7 @@ phutil_register_library_map(array( 'PHUIDiffTableOfContentsItemView' => 'AphrontView', 'PHUIDiffTableOfContentsListView' => 'AphrontView', 'PHUIDiffTwoUpInlineCommentRowScaffold' => 'PHUIDiffInlineCommentRowScaffold', - 'PHUIDocumentExample' => 'PhabricatorUIExample', 'PHUIDocumentSummaryView' => 'AphrontTagView', - 'PHUIDocumentView' => 'AphrontTagView', 'PHUIDocumentViewPro' => 'AphrontTagView', 'PHUIFeedStoryExample' => 'PhabricatorUIExample', 'PHUIFeedStoryView' => 'AphrontView', @@ -7014,7 +7011,7 @@ phutil_register_library_map(array( 'PhabricatorCustomFieldStorage' => 'PhabricatorLiskDAO', 'PhabricatorCustomFieldStorageQuery' => 'Phobject', 'PhabricatorCustomFieldStringIndexStorage' => 'PhabricatorCustomFieldIndexStorage', - 'PhabricatorCustomHeaderConfigType' => 'PhabricatorConfigOptionType', + 'PhabricatorCustomLogoConfigType' => 'PhabricatorConfigOptionType', 'PhabricatorDaemon' => 'PhutilDaemon', 'PhabricatorDaemonBulkJobController' => 'PhabricatorDaemonController', 'PhabricatorDaemonBulkJobListController' => 'PhabricatorDaemonBulkJobController', @@ -8342,6 +8339,7 @@ phutil_register_library_map(array( 'PhabricatorRepositoryCommitPHIDType' => 'PhabricatorPHIDType', 'PhabricatorRepositoryCommitParserWorker' => 'PhabricatorWorker', 'PhabricatorRepositoryCommitRef' => 'Phobject', + 'PhabricatorRepositoryCommitTestCase' => 'PhabricatorTestCase', 'PhabricatorRepositoryConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO', 'PhabricatorRepositoryDiscoveryEngine' => 'PhabricatorRepositoryEngine', diff --git a/src/applications/calendar/application/PhabricatorCalendarApplication.php b/src/applications/calendar/application/PhabricatorCalendarApplication.php index 16e6daf3bf..8dd68c42e0 100644 --- a/src/applications/calendar/application/PhabricatorCalendarApplication.php +++ b/src/applications/calendar/application/PhabricatorCalendarApplication.php @@ -28,6 +28,10 @@ final class PhabricatorCalendarApplication extends PhabricatorApplication { return "\xE2\x8C\xA8"; } + public function getApplicationGroup() { + return self::GROUP_UTILITIES; + } + public function isPrototype() { return true; } diff --git a/src/applications/celerity/CeleritySpriteGenerator.php b/src/applications/celerity/CeleritySpriteGenerator.php index 0dba6c346f..8c09bbc59f 100644 --- a/src/applications/celerity/CeleritySpriteGenerator.php +++ b/src/applications/celerity/CeleritySpriteGenerator.php @@ -2,58 +2,6 @@ final class CeleritySpriteGenerator extends Phobject { - public function buildMenuSheet() { - $sprites = array(); - - $colors = array( - 'dark', - 'light', - ); - - $sources = array(); - foreach ($colors as $color) { - $sources[$color.'-logo'] = array( - 'x' => 96, - 'y' => 40, - 'css' => '.'.$color.'-logo', - ); - $sources[$color.'-eye'] = array( - 'x' => 40, - 'y' => 40, - 'css' => '.'.$color.'-eye', - ); - } - - $scales = array( - '1x' => 1, - '2x' => 2, - ); - - $template = new PhutilSprite(); - foreach ($sources as $name => $spec) { - $sprite = id(clone $template) - ->setName($name) - ->setSourceSize($spec['x'], $spec['y']) - ->setTargetCSS($spec['css']); - - foreach ($scales as $scale_name => $scale) { - $path = 'menu_'.$scale_name.'/'.$name.'.png'; - $path = $this->getPath($path); - - $sprite->setSourceFile($path, $scale); - } - $sprites[] = $sprite; - } - - $sheet = $this->buildSheet('menu', true); - $sheet->setScales($scales); - foreach ($sprites as $sprite) { - $sheet->addSprite($sprite); - } - - return $sheet; - } - public function buildTokenSheet() { $icons = $this->getDirectoryList('tokens_1x'); $scales = array( diff --git a/src/applications/config/check/PhabricatorExtraConfigSetupCheck.php b/src/applications/config/check/PhabricatorExtraConfigSetupCheck.php index 1e2eaa5680..6547f9ca96 100644 --- a/src/applications/config/check/PhabricatorExtraConfigSetupCheck.php +++ b/src/applications/config/check/PhabricatorExtraConfigSetupCheck.php @@ -328,6 +328,10 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck { 'metamta.re-prefix' => $global_settings_reason, 'metamta.vary-subjects' => $global_settings_reason, + + 'ui.custom-header' => pht( + 'This option has been replaced with `ui.logo`, which provides more '. + 'flexible configuration options.'), ); return $ancient_config; diff --git a/src/applications/config/controller/PhabricatorConfigClusterRepositoriesController.php b/src/applications/config/controller/PhabricatorConfigClusterRepositoriesController.php index d03d58a954..bea1a0dec6 100644 --- a/src/applications/config/controller/PhabricatorConfigClusterRepositoriesController.php +++ b/src/applications/config/controller/PhabricatorConfigClusterRepositoriesController.php @@ -43,7 +43,6 @@ final class PhabricatorConfigClusterRepositoriesController $all_repositories = id(new PhabricatorRepositoryQuery()) ->setViewer($viewer) - ->withHosted(PhabricatorRepositoryQuery::HOSTED_PHABRICATOR) ->withTypes( array( PhabricatorRepositoryType::REPOSITORY_TYPE_GIT, diff --git a/src/applications/config/controller/PhabricatorConfigEditController.php b/src/applications/config/controller/PhabricatorConfigEditController.php index ab246b56ce..71b4499591 100644 --- a/src/applications/config/controller/PhabricatorConfigEditController.php +++ b/src/applications/config/controller/PhabricatorConfigEditController.php @@ -98,7 +98,8 @@ final class PhabricatorConfigEditController } } - $form = new AphrontFormView(); + $form = id(new AphrontFormView()) + ->setEncType('multipart/form-data'); $error_view = null; if ($errors) { @@ -144,9 +145,9 @@ final class PhabricatorConfigEditController } if ($option->getHidden() || $option->getLocked()) { - $control = null; + $controls = array(); } else { - $control = $this->renderControl( + $controls = $this->renderControls( $option, $display_value, $e_value); @@ -201,9 +202,9 @@ final class PhabricatorConfigEditController } } - $form - ->appendChild($control); - + foreach ($controls as $control) { + $form->appendControl($control); + } if (!$option->getLocked()) { $form->appendChild( @@ -279,23 +280,23 @@ final class PhabricatorConfigEditController $e_value = null; $errors = array(); - $value = $request->getStr('value'); - if (!strlen($value)) { - $value = null; - - $xaction->setNewValue( - array( - 'deleted' => true, - 'value' => null, - )); - - return array($e_value, $errors, $value, $xaction); - } - if ($option->isCustomType()) { $info = $option->getCustomObject()->readRequest($option, $request); list($e_value, $errors, $set_value, $value) = $info; } else { + $value = $request->getStr('value'); + if (!strlen($value)) { + $value = null; + + $xaction->setNewValue( + array( + 'deleted' => true, + 'value' => null, + )); + + return array($e_value, $errors, $value, $xaction); + } + $type = $option->getType(); $set_value = null; @@ -415,13 +416,13 @@ final class PhabricatorConfigEditController } } - private function renderControl( + private function renderControls( PhabricatorConfigOption $option, $display_value, $e_value) { if ($option->isCustomType()) { - $control = $option->getCustomObject()->renderControl( + $controls = $option->getCustomObject()->renderControls( $option, $display_value, $e_value); @@ -487,9 +488,11 @@ final class PhabricatorConfigEditController ->setError($e_value) ->setValue($display_value) ->setName('value'); + + $controls = array($control); } - return $control; + return $controls; } private function renderExamples(PhabricatorConfigOption $option) { diff --git a/src/applications/config/controller/PhabricatorConfigWelcomeController.php b/src/applications/config/controller/PhabricatorConfigWelcomeController.php index a7d29b913b..6825abba8c 100644 --- a/src/applications/config/controller/PhabricatorConfigWelcomeController.php +++ b/src/applications/config/controller/PhabricatorConfigWelcomeController.php @@ -358,7 +358,7 @@ final class PhabricatorConfigWelcomeController $quick_header = new PHUIRemarkupView( $viewer, pht('=Quick Start Guide')); - return id(new PHUIDocumentView()) + $document = id(new PHUIDocumentViewPro()) ->setHeader($header) ->setFluid(true) ->appendChild($setup_header) @@ -367,6 +367,11 @@ final class PhabricatorConfigWelcomeController ->appendChild($explore) ->appendChild($quick_header) ->appendChild($quick); + + return id(new PHUIBoxView()) + ->setBorder(true) + ->appendChild($document) + ->addClass('mlb'); } private function newItem(AphrontRequest $request, $icon, $content) { diff --git a/src/applications/config/custom/PhabricatorConfigOptionType.php b/src/applications/config/custom/PhabricatorConfigOptionType.php index 733229e652..429b080cda 100644 --- a/src/applications/config/custom/PhabricatorConfigOptionType.php +++ b/src/applications/config/custom/PhabricatorConfigOptionType.php @@ -31,6 +31,16 @@ abstract class PhabricatorConfigOptionType extends Phobject { } + public function renderControls( + PhabricatorConfigOption $option, + $display_value, + $e_value) { + + $control = $this->renderControl($option, $display_value, $e_value); + + return array($control); + } + public function renderControl( PhabricatorConfigOption $option, $display_value, diff --git a/src/applications/config/custom/PhabricatorCustomHeaderConfigType.php b/src/applications/config/custom/PhabricatorCustomHeaderConfigType.php deleted file mode 100644 index fee8ba5a4c..0000000000 --- a/src/applications/config/custom/PhabricatorCustomHeaderConfigType.php +++ /dev/null @@ -1,48 +0,0 @@ -setViewer(PhabricatorUser::getOmnipotentUser()) - ->withPHIDs(array($value)) - ->executeOne(); - if (!$file) { - throw new Exception( - pht( - '%s is not a valid file PHID.', - $value)); - } - - $most_open_policy = PhabricatorPolicies::getMostOpenPolicy(); - if ($file->getViewPolicy() != $most_open_policy) { - throw new Exception( - pht( - 'Specified file %s has policy "%s" but should have policy "%s".', - $value, - $file->getViewPolicy(), - $most_open_policy)); - } - - if (!$file->isViewableImage()) { - throw new Exception( - pht( - 'Specified file %s is not a viewable image.', - $value)); - } - } - - public static function getExampleConfig() { - $config = 'PHID-FILE-abcd1234abcd1234abcd'; - return $config; - } - -} diff --git a/src/applications/config/custom/PhabricatorCustomLogoConfigType.php b/src/applications/config/custom/PhabricatorCustomLogoConfigType.php new file mode 100644 index 0000000000..ff29050602 --- /dev/null +++ b/src/applications/config/custom/PhabricatorCustomLogoConfigType.php @@ -0,0 +1,118 @@ + 'optional string|null', + 'wordmarkText' => 'optional string|null', + )); + } + + public function readRequest( + PhabricatorConfigOption $option, + AphrontRequest $request) { + + $viewer = $request->getViewer(); + $view_policy = PhabricatorPolicies::POLICY_PUBLIC; + + if ($request->getBool('removeLogo')) { + $logo_image_phid = null; + } else if ($request->getFileExists('logoImage')) { + $logo_image = PhabricatorFile::newFromPHPUpload( + idx($_FILES, 'logoImage'), + array( + 'name' => 'logo', + 'authorPHID' => $viewer->getPHID(), + 'viewPolicy' => $view_policy, + 'canCDN' => true, + 'isExplicitUpload' => true, + )); + $logo_image_phid = $logo_image->getPHID(); + } else { + $logo_image_phid = self::getLogoImagePHID(); + } + + $wordmark_text = $request->getStr('wordmarkText'); + + $value = array( + 'logoImagePHID' => $logo_image_phid, + 'wordmarkText' => $wordmark_text, + ); + + $errors = array(); + $e_value = null; + + try { + $this->validateOption($option, $value); + } catch (Exception $ex) { + $e_value = pht('Invalid'); + $errors[] = $ex->getMessage(); + $value = array(); + } + + return array($e_value, $errors, $value, phutil_json_encode($value)); + } + + public function renderControls( + PhabricatorConfigOption $option, + $display_value, + $e_value) { + + try { + $value = phutil_json_decode($display_value); + } catch (Exception $ex) { + $value = array(); + } + + $logo_image_phid = idx($value, 'logoImagePHID'); + $wordmark_text = idx($value, 'wordmarkText'); + + $controls = array(); + + // TODO: This should be a PHUIFormFileControl, but that currently only + // works in "workflow" forms. It isn't trivial to convert this form into + // a workflow form, nor is it trivial to make the newer control work + // in non-workflow forms. + $controls[] = id(new AphrontFormFileControl()) + ->setName('logoImage') + ->setLabel(pht('Logo Image')); + + if ($logo_image_phid) { + $controls[] = id(new AphrontFormCheckboxControl()) + ->addCheckbox( + 'removeLogo', + 1, + pht('Remove Custom Logo')); + } + + $controls[] = id(new AphrontFormTextControl()) + ->setName('wordmarkText') + ->setLabel(pht('Wordmark')) + ->setPlaceholder(pht('Phabricator')) + ->setValue($wordmark_text); + + return $controls; + } + + +} diff --git a/src/applications/config/option/PhabricatorUIConfigOptions.php b/src/applications/config/option/PhabricatorUIConfigOptions.php index e73b4ee780..4f93946ce2 100644 --- a/src/applications/config/option/PhabricatorUIConfigOptions.php +++ b/src/applications/config/option/PhabricatorUIConfigOptions.php @@ -20,9 +20,6 @@ final class PhabricatorUIConfigOptions } public function getOptions() { - $custom_header_example = - PhabricatorCustomHeaderConfigType::getExampleConfig(); - $experimental_link = 'https://secure.phabricator.com/T4214'; $options = array( 'blindigo' => 'blindigo', 'red' => 'red', @@ -48,11 +45,24 @@ final class PhabricatorUIConfigOptions ] EOJSON; + $logo_type = 'custom:PhabricatorCustomLogoConfigType'; + return array( $this->newOption('ui.header-color', 'enum', 'blindigo') ->setDescription( pht('Sets the default color scheme of Phabricator.')) ->setEnumOptions($options), + $this->newOption('ui.logo', $logo_type, array()) + ->setSummary( + pht('Customize the logo and wordmark text in the header.')) + ->setDescription( + pht( + "Customize the logo image and text which appears in the main ". + "site header:\n\n". + " - **Logo Image**: Upload a new 80 x 80px image to replace the ". + "Phabricator logo in the site header.\n\n". + " - **Wordmark**: Choose new text to display next to the logo. ". + "By default, the header displays //Phabricator//.\n\n")), $this->newOption('ui.footer-items', 'list', array()) ->setSummary( pht( @@ -69,31 +79,6 @@ EOJSON; " omit this if you just want a piece of text, like a copyright ". " notice.")) ->addExample($example, pht('Basic Example')), - $this->newOption( - 'ui.custom-header', - 'custom:PhabricatorCustomHeaderConfigType', - null) - ->setSummary( - pht('Customize the Phabricator logo.')) - ->setDescription( - pht('You can customize the Phabricator logo by specifying the '. - 'phid for a viewable image you have uploaded to Phabricator '. - 'via the [[ /file/ | Files application]]. This image should '. - 'be:'."\n". - ' - 192px X 80px; while not enforced, images with these '. - 'dimensions will look best across devices.'."\n". - ' - have view policy public if [[ '. - '/config/edit/policy.allow-public | `policy.allow-public`]] '. - 'is true and otherwise view policy user; mismatches in these '. - 'policy settings will result in a broken logo for some users.'. - "\n\n". - 'You should restart Phabricator after updating this value '. - 'to see this change take effect.'. - "\n\n". - 'As this feature is experimental, please read [[ %s | T4214 ]] '. - 'for up to date information.', - $experimental_link)) - ->addExample($custom_header_example, pht('Valid Config')), ); } diff --git a/src/applications/config/schema/PhabricatorConfigSchemaSpec.php b/src/applications/config/schema/PhabricatorConfigSchemaSpec.php index 740402524a..e29795b98b 100644 --- a/src/applications/config/schema/PhabricatorConfigSchemaSpec.php +++ b/src/applications/config/schema/PhabricatorConfigSchemaSpec.php @@ -70,7 +70,12 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject { } $details = $this->getDetailsForDataType($type); - list($column_type, $charset, $collation, $nullable, $auto) = $details; + + $column_type = $details['type']; + $charset = $details['charset']; + $collation = $details['collation']; + $nullable = $details['nullable']; + $auto = $details['auto']; $column = $this->newColumn($name) ->setDataType($type) @@ -182,11 +187,17 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject { ->setName($name); } + public function getMaximumByteLengthForDataType($data_type) { + $info = $this->getDetailsForDataType($data_type); + return idx($info, 'bytes'); + } + private function getDetailsForDataType($data_type) { $column_type = null; $charset = null; $collation = null; $auto = false; + $bytes = null; // If the type ends with "?", make the column nullable. $nullable = false; @@ -211,7 +222,6 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject { 'text255' => true, 'text160' => true, 'text128' => true, - 'text80' => true, 'text64' => true, 'text40' => true, 'text32' => true, @@ -237,6 +247,10 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject { $type = $matches[1]; $size = idx($matches, 2); + if ($size) { + $bytes = $size; + } + switch ($type) { case 'text': if ($is_binary) { @@ -363,7 +377,14 @@ abstract class PhabricatorConfigSchemaSpec extends Phobject { } } - return array($column_type, $charset, $collation, $nullable, $auto); + return array( + 'type' => $column_type, + 'charset' => $charset, + 'collation' => $collation, + 'nullable' => $nullable, + 'auto' => $auto, + 'bytes' => $bytes, + ); } } diff --git a/src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php b/src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php index 026558f1b8..6fa0bac9e8 100644 --- a/src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php +++ b/src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php @@ -598,7 +598,7 @@ final class DiffusionRepositoryClusterEngine extends Phobject { ->setArgv($argv) ->setSudoAsDaemon(true) ->setCredentialPHID($repository->getCredentialPHID()) - ->setURI($repository->getRemoteURI()) + ->setURI($repository->getRemoteURIObject()) ->newFuture(); $future->setCWD($local_path); diff --git a/src/applications/feed/application/PhabricatorFeedApplication.php b/src/applications/feed/application/PhabricatorFeedApplication.php index f24ff76fe4..287cf2d387 100644 --- a/src/applications/feed/application/PhabricatorFeedApplication.php +++ b/src/applications/feed/application/PhabricatorFeedApplication.php @@ -18,6 +18,10 @@ final class PhabricatorFeedApplication extends PhabricatorApplication { return 'fa-newspaper-o'; } + public function getApplicationGroup() { + return self::GROUP_UTILITIES; + } + public function canUninstall() { return false; } diff --git a/src/applications/herald/controller/HeraldRuleViewController.php b/src/applications/herald/controller/HeraldRuleViewController.php index 818eb7560f..9e696c23c4 100644 --- a/src/applications/herald/controller/HeraldRuleViewController.php +++ b/src/applications/herald/controller/HeraldRuleViewController.php @@ -2,6 +2,10 @@ final class HeraldRuleViewController extends HeraldController { + public function shouldAllowPublic() { + return true; + } + public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); $id = $request->getURIData('id'); diff --git a/src/applications/herald/controller/HeraldTranscriptController.php b/src/applications/herald/controller/HeraldTranscriptController.php index e15c7ed52c..a9509beb33 100644 --- a/src/applications/herald/controller/HeraldTranscriptController.php +++ b/src/applications/herald/controller/HeraldTranscriptController.php @@ -249,9 +249,13 @@ final class HeraldTranscriptController extends HeraldController { foreach ($rule_xscripts as $rule_xscript) { $rule_id = $rule_xscript->getRuleID(); + $rule_monogram = pht('H%d', $rule_id); + $rule_uri = '/'.$rule_monogram; + $rule_item = id(new PHUIObjectItemView()) - ->setObjectName(pht('H%d', $rule_id)) - ->setHeader($rule_xscript->getRuleName()); + ->setObjectName($rule_monogram) + ->setHeader($rule_xscript->getRuleName()) + ->setHref($rule_uri); if (!$rule_xscript->getResult()) { $rule_item->setDisabled(true); diff --git a/src/applications/herald/storage/HeraldRule.php b/src/applications/herald/storage/HeraldRule.php index 19f9b95507..cf00e046b7 100644 --- a/src/applications/herald/storage/HeraldRule.php +++ b/src/applications/herald/storage/HeraldRule.php @@ -288,39 +288,40 @@ final class HeraldRule extends HeraldDAO } public function getPolicy($capability) { + if ($capability == PhabricatorPolicyCapability::CAN_VIEW) { + return PhabricatorPolicies::getMostOpenPolicy(); + } + if ($this->isGlobalRule()) { - switch ($capability) { - case PhabricatorPolicyCapability::CAN_VIEW: - return PhabricatorPolicies::POLICY_USER; - case PhabricatorPolicyCapability::CAN_EDIT: - $app = 'PhabricatorHeraldApplication'; - $herald = PhabricatorApplication::getByClass($app); - $global = HeraldManageGlobalRulesCapability::CAPABILITY; - return $herald->getPolicy($global); - } + $app = 'PhabricatorHeraldApplication'; + $herald = PhabricatorApplication::getByClass($app); + $global = HeraldManageGlobalRulesCapability::CAPABILITY; + return $herald->getPolicy($global); } else if ($this->isObjectRule()) { return $this->getTriggerObject()->getPolicy($capability); } else { - return PhabricatorPolicies::POLICY_NOONE; + return $this->getAuthorPHID(); } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { - if ($this->isPersonalRule()) { - return ($viewer->getPHID() == $this->getAuthorPHID()); - } else { - return false; - } + return false; } public function describeAutomaticCapability($capability) { - if ($this->isPersonalRule()) { - return pht("A personal rule's owner can always view and edit it."); - } else if ($this->isObjectRule()) { - return pht('Object rules inherit the policies of their objects.'); + if ($capability == PhabricatorPolicyCapability::CAN_VIEW) { + return null; } - return null; + if ($this->isGlobalRule()) { + return pht( + 'Global Herald rules can be edited by users with the "Can Manage '. + 'Global Rules" Herald application permission.'); + } else if ($this->isObjectRule()) { + return pht('Object rules inherit the edit policies of their objects.'); + } else { + return pht('A personal rule can only be edited by its owner.'); + } } diff --git a/src/applications/packages/application/PhabricatorPackagesApplication.php b/src/applications/packages/application/PhabricatorPackagesApplication.php index 7a100e82b8..9de74dddc0 100644 --- a/src/applications/packages/application/PhabricatorPackagesApplication.php +++ b/src/applications/packages/application/PhabricatorPackagesApplication.php @@ -22,6 +22,10 @@ final class PhabricatorPackagesApplication extends PhabricatorApplication { return 'fa-gift'; } + public function getApplicationGroup() { + return self::GROUP_UTILITIES; + } + public function isPrototype() { return true; } diff --git a/src/applications/people/application/PhabricatorPeopleApplication.php b/src/applications/people/application/PhabricatorPeopleApplication.php index adc3d87560..44672edd3c 100644 --- a/src/applications/people/application/PhabricatorPeopleApplication.php +++ b/src/applications/people/application/PhabricatorPeopleApplication.php @@ -30,6 +30,10 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication { return pht('Sort of a social utility.'); } + public function getApplicationGroup() { + return self::GROUP_UTILITIES; + } + public function canUninstall() { return false; } diff --git a/src/applications/phurl/application/PhabricatorPhurlApplication.php b/src/applications/phurl/application/PhabricatorPhurlApplication.php index 763a85173c..59f8f1546f 100644 --- a/src/applications/phurl/application/PhabricatorPhurlApplication.php +++ b/src/applications/phurl/application/PhabricatorPhurlApplication.php @@ -26,6 +26,10 @@ final class PhabricatorPhurlApplication extends PhabricatorApplication { return true; } + public function getApplicationGroup() { + return self::GROUP_UTILITIES; + } + public function getRemarkupRules() { return array( new PhabricatorPhurlRemarkupRule(), diff --git a/src/applications/ponder/application/PhabricatorPonderApplication.php b/src/applications/ponder/application/PhabricatorPonderApplication.php index 616eda10c9..ced8606e99 100644 --- a/src/applications/ponder/application/PhabricatorPonderApplication.php +++ b/src/applications/ponder/application/PhabricatorPonderApplication.php @@ -34,6 +34,10 @@ final class PhabricatorPonderApplication extends PhabricatorApplication { ); } + public function getApplicationGroup() { + return self::GROUP_UTILITIES; + } + public function supportsEmailIntegration() { return true; } diff --git a/src/applications/releeph/application/PhabricatorReleephApplication.php b/src/applications/releeph/application/PhabricatorReleephApplication.php index ab5a12dc80..2590478f1a 100644 --- a/src/applications/releeph/application/PhabricatorReleephApplication.php +++ b/src/applications/releeph/application/PhabricatorReleephApplication.php @@ -18,6 +18,10 @@ final class PhabricatorReleephApplication extends PhabricatorApplication { return 'fa-flag-checkered'; } + public function getApplicationGroup() { + return self::GROUP_UTILITIES; + } + public function isPrototype() { return true; } diff --git a/src/applications/repository/storage/PhabricatorRepositoryCommit.php b/src/applications/repository/storage/PhabricatorRepositoryCommit.php index ae43c67416..f2ae90d9f3 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryCommit.php +++ b/src/applications/repository/storage/PhabricatorRepositoryCommit.php @@ -108,7 +108,7 @@ final class PhabricatorRepositoryCommit 'mailKey' => 'bytes20', 'authorPHID' => 'phid?', 'auditStatus' => 'uint32', - 'summary' => 'text80', + 'summary' => 'text255', 'importStatus' => 'uint32', ), self::CONFIG_KEY_SCHEMA => array( diff --git a/src/applications/repository/storage/PhabricatorRepositoryCommitData.php b/src/applications/repository/storage/PhabricatorRepositoryCommitData.php index 705634895b..3a4c3a75f5 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryCommitData.php +++ b/src/applications/repository/storage/PhabricatorRepositoryCommitData.php @@ -2,12 +2,6 @@ final class PhabricatorRepositoryCommitData extends PhabricatorRepositoryDAO { - /** - * NOTE: We denormalize this into the commit table; make sure the sizes - * match up. - */ - const SUMMARY_MAX_LENGTH = 80; - protected $commitID; protected $authorName = ''; protected $commitMessage = ''; @@ -38,10 +32,14 @@ final class PhabricatorRepositoryCommitData extends PhabricatorRepositoryDAO { } public static function summarizeCommitMessage($message) { + $max_bytes = id(new PhabricatorRepositoryCommit()) + ->getColumnMaximumByteLength('summary'); + $summary = phutil_split_lines($message, $retain_endings = false); $summary = head($summary); $summary = id(new PhutilUTF8StringTruncator()) - ->setMaximumBytes(self::SUMMARY_MAX_LENGTH) + ->setMaximumBytes($max_bytes) + ->setMaximumGlyphs(80) ->truncateString($summary); return $summary; diff --git a/src/applications/repository/storage/__tests__/PhabricatorRepositoryCommitTestCase.php b/src/applications/repository/storage/__tests__/PhabricatorRepositoryCommitTestCase.php new file mode 100644 index 0000000000..d7715564ce --- /dev/null +++ b/src/applications/repository/storage/__tests__/PhabricatorRepositoryCommitTestCase.php @@ -0,0 +1,38 @@ + 0, + 'a' => 1, + str_repeat('a', 81) => 82, + str_repeat('a', 255) => 82, + str_repeat('aa ', 30) => 80, + str_repeat($zhe, 300) => 161, + str_repeat($snowman, 300) => 240, + str_repeat($boar, 300) => 255, + ); + + foreach ($map as $input => $expect) { + $actual = PhabricatorRepositoryCommitData::summarizeCommitMessage( + $input); + $this->assertEqual($expect, strlen($actual)); + } + + } + +} diff --git a/src/applications/uiexample/examples/PHUIDocumentExample.php b/src/applications/uiexample/examples/PHUIDocumentExample.php deleted file mode 100644 index 155489b80b..0000000000 --- a/src/applications/uiexample/examples/PHUIDocumentExample.php +++ /dev/null @@ -1,199 +0,0 @@ -getRequest(); - $user = $request->getUser(); - - $action = id(new PHUIListItemView()) - ->setName(pht('Actions')) - ->setType(PHUIListItemView::TYPE_LABEL); - - $action1 = id(new PHUIListItemView()) - ->setName(pht('Edit Document')) - ->setHref('#') - ->setIcon('fa-edit') - ->setType(PHUIListItemView::TYPE_LINK); - - $action2 = id(new PHUIListItemView()) - ->setName(pht('Move Document')) - ->setHref('#') - ->setIcon('fa-arrows') - ->setType(PHUIListItemView::TYPE_LINK); - - $action3 = id(new PHUIListItemView()) - ->setName(pht('Delete Document')) - ->setHref('#') - ->setIcon('fa-times') - ->setType(PHUIListItemView::TYPE_LINK); - - $action4 = id(new PHUIListItemView()) - ->setName(pht('View History')) - ->setHref('#') - ->setIcon('fa-list') - ->setType(PHUIListItemView::TYPE_LINK); - - $action5 = id(new PHUIListItemView()) - ->setName(pht('Subscribe')) - ->setHref('#') - ->setIcon('fa-plus-circle') - ->setType(PHUIListItemView::TYPE_LINK); - - $divider = id(new PHUIListItemView()) - ->setType(PHUIListItemView::TYPE_DIVIDER); - - $header = id(new PHUIHeaderView()) - ->setHeader(pht('Installation')); - - $label1 = id(new PHUIListItemView()) - ->setName(pht('Getting Started')) - ->setType(PHUIListItemView::TYPE_LABEL); - - $label2 = id(new PHUIListItemView()) - ->setName(pht('Documentation')) - ->setType(PHUIListItemView::TYPE_LABEL); - - $item1 = id(new PHUIListItemView()) - ->setName(pht('Installation')) - ->setHref('#') - ->setType(PHUIListItemView::TYPE_LINK); - - $item2 = id(new PHUIListItemView()) - ->setName(pht('Webserver Config')) - ->setHref('#') - ->setType(PHUIListItemView::TYPE_LINK); - - $item3 = id(new PHUIListItemView()) - ->setName(pht('Adding Users')) - ->setHref('#') - ->setType(PHUIListItemView::TYPE_LINK); - - $item4 = id(new PHUIListItemView()) - ->setName(pht('Debugging')) - ->setHref('#') - ->setType(PHUIListItemView::TYPE_LINK); - - $sidenav = id(new PHUIListView()) - ->setType(PHUIListView::SIDENAV_LIST) - ->addMenuItem($action) - ->addMenuItem($action1) - ->addMenuItem($action2) - ->addMenuItem($action3) - ->addMenuItem($action4) - ->addMenuItem($action5) - ->addMenuItem($divider) - ->addMenuItem($label1) - ->addMenuItem($item1) - ->addMenuItem($item2) - ->addMenuItem($item3) - ->addMenuItem($item4) - ->addMenuItem($label2) - ->addMenuItem($item2) - ->addMenuItem($item3) - ->addMenuItem($item4) - ->addMenuItem($item1); - - $home = id(new PHUIListItemView()) - ->setIcon('fa-home') - ->setHref('#') - ->setType(PHUIListItemView::TYPE_ICON); - - $item1 = id(new PHUIListItemView()) - ->setName(pht('Installation')) - ->setHref('#') - ->setSelected(true) - ->setType(PHUIListItemView::TYPE_LINK); - - $item2 = id(new PHUIListItemView()) - ->setName(pht('Webserver Config')) - ->setHref('#') - ->setType(PHUIListItemView::TYPE_LINK); - - $item3 = id(new PHUIListItemView()) - ->setName(pht('Adding Users')) - ->setHref('#') - ->setType(PHUIListItemView::TYPE_LINK); - - $item4 = id(new PHUIListItemView()) - ->setName(pht('Debugging')) - ->setHref('#') - ->setType(PHUIListItemView::TYPE_LINK); - - $topnav = id(new PHUIListView()) - ->setType(PHUIListView::NAVBAR_LIST) - ->addMenuItem($home) - ->addMenuItem($item1) - ->addMenuItem($item2) - ->addMenuItem($item3) - ->addMenuItem($item4); - - $document = hsprintf( - '

Lorem ipsum dolor sit amet, consectetur adipisicing, '. - 'sed do eiusmod tempor incididunt ut labore et dolore magna '. - 'aliqua. Ut enim ad minim veniam, quis nostrud exercitation '. - 'ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis '. - 'aute irure dolor in reprehenderit in voluptate velit esse cillum '. - 'dolore eu fugiat nulla pariatur. Excepteur sint occaecat '. - 'cupidatat non proident, sunt in culpa qui officia deserunt '. - 'mollit anim id est laborum.

'. - '

Lorem ipsum dolor sit amet, consectetur, '. - 'sed do eiusmod tempor incididunt ut labore et dolore magna '. - 'aliqua. Ut enim ad minim veniam, quis nostrud exercitation '. - 'ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis '. - 'aute irure dolor in reprehenderit in voluptate velit esse cillum '. - 'dolore eu fugiat nulla pariatur. Excepteur sint occaecat '. - 'cupidatat non proident, sunt in culpa qui officia deserunt '. - 'mollit anim id est laborum.

'. - '

Lorem ipsum dolor sit amet, consectetur, '. - 'sed do eiusmod tempor incididunt ut labore et dolore magna '. - 'aliqua. Ut enim ad minim veniam, quis nostrud exercitation '. - 'ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis '. - 'aute irure dolor in reprehenderit in voluptate velit esse cillum '. - 'dolore eu fugiat nulla pariatur. Excepteur sint occaecat '. - 'cupidatat non proident, sunt in culpa qui officia deserunt '. - 'mollit anim id est laborum.

'. - '

Lorem ipsum dolor sit amet, consectetur, '. - 'sed do eiusmod tempor incididunt ut labore et dolore magna '. - 'aliqua. Ut enim ad minim veniam, quis nostrud exercitation '. - 'ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis '. - 'aute irure dolor in reprehenderit in voluptate velit esse cillum '. - 'dolore eu fugiat nulla pariatur. Excepteur sint occaecat '. - 'cupidatat non proident, sunt in culpa qui officia deserunt '. - 'mollit anim id est laborum.

'. - '

Lorem ipsum dolor sit amet, consectetur, '. - 'sed do eiusmod tempor incididunt ut labore et dolore magna '. - 'aliqua. Ut enim ad minim veniam, quis nostrud exercitation '. - 'ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis '. - 'aute irure dolor in reprehenderit in voluptate velit esse cillum '. - 'dolore eu fugiat nulla pariatur. Excepteur sint occaecat '. - 'cupidatat non proident, sunt in culpa qui officia deserunt '. - 'mollit anim id est laborum.

'. - '

Lorem ipsum dolor sit amet, consectetur, '. - 'sed do eiusmod tempor incididunt ut labore et dolore magna '. - 'aliqua. Ut enim ad minim veniam, quis nostrud exercitation '. - 'ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis '. - 'aute irure dolor in reprehenderit in voluptate velit esse cillum '. - 'dolore eu fugiat nulla pariatur. Excepteur sint occaecat '. - 'cupidatat non proident, sunt in culpa qui officia deserunt '. - 'mollit anim id est laborum.

'); - - $content = new PHUIDocumentView(); - $content->setBook(pht('Book or Project Name'), pht('Article')); - $content->setHeader($header); - $content->setFluid(true); - $content->setTopNav($topnav); - $content->setSidenav($sidenav); - $content->appendChild($document); - - return $content; - } -} diff --git a/src/docs/user/userguide/herald.diviner b/src/docs/user/userguide/herald.diviner index be4992cf4d..6c5c6239cb 100644 --- a/src/docs/user/userguide/herald.diviner +++ b/src/docs/user/userguide/herald.diviner @@ -3,96 +3,138 @@ Use Herald to get notified of changes you care about. -= Overview = +Overview +======== -Herald allows you to write processing rules that take effect when objects (such -as Differential revisions and commits) are created or updated. For instance, you -might want to get notified every time someone sends out a revision that affects -some file you're interested in, even if they didn't add you as a reviewer. +Herald allows you to write rules which run automatically when objects (like +tasks or commits) are created or updated. For instance, you might want to get +notified every time someone sends out a revision that affects some file you're +interested in, even if they didn't add you as a reviewer. -Herald is less useful for small organizations (where everyone will generally -know most of what's going on) but the usefulness of the application increases -as an organization scales. Once there is too much activity to keep track of it -all, Herald allows you to filter it down so you're only notified of things you -are interested in. - -= Global and Personal Rules = - -You can create two kinds of Herald rules, //global// and //personal//: - - - **Personal Rules** are rules you own, but they can only affect you. Only - you can edit or delete personal rules, but their actions are limited to - adding you to CC, subscribing you, etc. - - **Global Rules** are rules everyone owns, and they can affect anything. - Anyone can edit or delete a global rule, and they can take any action, - including affecting projects and mailing lists. - -The general idea is to prevent individuals from controlling rules that affect -shared resources, so if a rule needs to be updated it's not a big deal if the -person who created it is on vacation. - -= Rules, Conditions and Actions = - -The best way to think of Herald is as a system similar to the mail rules you can -set up in most email clients, to organize mail based on "To", "Subject", etc. +One way to think about Herald is that it is a lot like the mail rules you can +set up in most email clients to organize mail based on "To", "Subject", etc. Herald works very similarly, but operates on Phabricator objects (like revisions and commits) instead of emails. -Every time an object is created or updated, Herald rules are run on it and -the actions for any matching rules are taken. +For example, you can write a personal rule like this which triggers on tasks: -To create a new Herald rule, choose which type of event you want to act on -(e.g., changes to Differential Revisions, or Commits), and then set a list of -conditions. For example, you might add the condition `Author is alincoln -(Abraham Lincoln)` to keep track of everything alincoln does. Finally, set -a list of actions to take when the conditions match, like adding yourself to the -CC list. +> When [ all of ] these conditions are met: +> [ Title ][ contains ][ quasar ] +> Take these actions [ every time ] this rule matches: +> [ Add me as a subscriber ] -Now you'll automatically be added to CC any time alincoln creates a revision, -and can keep an eye on what he's up to. +This rule will automatically subscribe you to any newly created or updated +tasks that contain "quasar" in the title. -= Available Actions = +Herald rules are often used to: notify users, add reviewers, initiate audits, +classify objects, block commits, enforce CLAs, and run builds. -Herald rules can take a number of actions. Note that some actions are only -available from Global rules, and others only from Personal rules. Additionally, -not every action is available for every object type (for instance, you can not -trigger an audit based on a Differential revision). - - **Add CC**: Add a user or mailing list to the CC list for the object. For - personal rules, you can only add yourself. - - **Remove CC**: Remove a user or mailing list from the CC list for the - object. For personal rules, you can only remove yourself. - - **Send an Email to**: Send one email, but don't subscribe to other updates. - For personal rules, you can only email yourself. - - **Trigger an Audit**: For commits, trigger an audit request for a project - or user. For personal rules, you can only trigger an audit request to - yourself. - - **Mark with flag**: Flag the object for later review. This action is only - available on personal rules. If an object already has a flag, this action - will not add another flag. - - **Do Nothing**: Don't do anything. This can be used to disable a rule - temporarily, or to create a rule for an "Another Herald rule" condition. +Working with Rules +================== -= Testing Rules = +To create new Herald rules, navigate to the {nav Herald} application and select +{nav Create Herald Rule}. -When you've created a rule, use the "Test Console" to test it out. Enter a -revision or commit and Herald will do a dry run against that object, showing -you which rules //would// match had it actually been updated. Dry runs executed -via the test console don't take any actions. +Next, you'll choose an event that you want to write a rule for: for example, +a rule for when commits are discovered or a rule for when tasks are created or +updated. -= Advanced Herald = +After selecting an event, choose the type of rule to create. See "Rule Types" +below for a more detailed discussion. -A few features in Herald are particularly complicated: +Name the rule and provide conditions and actions. When events occur, the rule +will be evaluated automatically. If the conditions pass, the actions will be +taken. - - **matches regexp pair**: for Differential revisions, you can set a condition - like "Any changed file content matches regexp pair...". This allows you to - specify two regexes in JSON format. The first will be used to match the - filename of the changed file; the second will be used to match the content. - For example, if you want to match revisions which add or remove calls to - a "muffinize" function, //but only in JS files//, you can set the value - to `["/\\.js$/", "/muffinize/"]` or similar. - - **Another Herald rule**: you can create Herald rules which depend on other - rules. This can be useful if you need to express a more complicated predicate - than "all" vs "any" allows, or have a common set of conditions which you want - to share between several rules. If a rule is only being used as a group of - conditions, you can set the action to "Do Nothing". +To test rules, use {nav Herald > Test Console}. See "Testing Rules" below +for greater detail. + +To review which rules did or did not trigger for a particular event (and why), +see {nav Herald > Transcripts}. + + +Rule Types +========== + +You can create three kinds of Herald rules: personal rules, object rules, and +global rules. + + - **Personal Rules** are rules owned by an individual. They're often used + to keep people informed about changes they're interested in. + - **Object Rules** are rules associated with an object (like a repository + or project). These are similar to global rules. + - **Global Rules** are apply to all objects. They're often used to block + commits or run builds. + + +Rule Policies +============= + +All Herald rules are always visible to all users. + +The edit policy for a rule depends on what type of rule it is: + + - Personal rules are owned by a particular user, and can only be created or + edited by that user. + - Object rules are associated with a particular object (like a repository), + and can only be created or edited by users who can edit that object. That + is, if you can edit a repository, you can also create object rules for it + and edit existing object rules. + - Global rules are administrative and can only be created or edited by users + with the **Can Manage Global Rules** Herald application permission. + +When rules are about to evaluate, they may first perform some policy tests. + + - Personal rules check if the owning user can see the object which the rule + is about to run on. If the user can not see the object, the rule does not + run. This prevents individuals from writing rules which give them access + to information they don't have permission to see. + - Object and global rules **bypass policies** and always execute. This makes + them very powerful, and is why the **Can Manage Global Rules** policy is + restricted by default. + + +Testing Rules +============= + +When you've created a rule, use the {nav Herald > Test Console} to test it out. + +Enter an object name (like `D123`, `rXYZabcdef`, or `T456`) and Herald will +execute a dry run against that object, showing you which rules //would// match +had it actually been updated. Dry runs executed via the test console don't take +any actions. + + +Advanced Herald +=============== + +A few features in Herald are particularly complicated or unintuitive. + +Condition **matches regexp pair**: Some conditions allow you to select the +operator "matches regexp pair". For example, you can write a rule against +revisions like this one: + +> When [ all of ] these conditions are met: +> [ Changed file content ][ matches regexp pair ][ ... ] + +This condition allows you to specify two regexes in JSON format. The first will +be used to match the filename of the changed file; the second will be used to +match the content. You can use these together to express conditions like +"content in Javascript files". + +For example, if you want to match revisions which add or remove calls to a +"muffinize" function, //but only in JS files//, you can set the value to +`["/\\.js$/", "/muffinize/"]` or similar. This condition is satisfied only +when the filename matches the first expression and the conent matches the +second expression. + +**Another Herald rule**: you can create Herald rules which depend on other +rules. + +This can be useful if you need to express a more complicated condition +than "all" vs "any" allows, or have a common set of conditions which you want +to share between several rules. + +If a rule is only being used as a group of conditions, you can set the action +to "Do Nothing". diff --git a/src/infrastructure/daemon/PhabricatorDaemon.php b/src/infrastructure/daemon/PhabricatorDaemon.php index 349e0f0ffe..f42a59f134 100644 --- a/src/infrastructure/daemon/PhabricatorDaemon.php +++ b/src/infrastructure/daemon/PhabricatorDaemon.php @@ -11,7 +11,7 @@ abstract class PhabricatorDaemon extends PhutilDaemon { } protected function willSleep($duration) { - LiskDAO::closeAllConnections(); + LiskDAO::closeInactiveConnections(60); return; } @@ -34,6 +34,24 @@ abstract class PhabricatorDaemon extends PhutilDaemon { return $command; } + // We may reach this method while already running as the daemon user: for + // example, active and passive synchronization of clustered repositories + // run the same commands through the same code, but as different users. + + // By default, `sudo` won't let you sudo to yourself, so we can get into + // trouble if we're already running as the daemon user unless the host has + // been configured to let the daemon user run commands as itself. + + // Since this is silly and more complicated than doing this check, don't + // use `sudo` if we're already running as the correct user. + if (function_exists('posix_getuid')) { + $uid = posix_getuid(); + $info = posix_getpwuid($uid); + if ($info && $info['name'] == $user) { + return $command; + } + } + // Get the absolute path so we're safe against the caller wiping out // PATH. $sudo = Filesystem::resolveBinary('sudo'); diff --git a/src/infrastructure/storage/lisk/LiskDAO.php b/src/infrastructure/storage/lisk/LiskDAO.php index 88c3e83e74..e795777394 100644 --- a/src/infrastructure/storage/lisk/LiskDAO.php +++ b/src/infrastructure/storage/lisk/LiskDAO.php @@ -1621,10 +1621,55 @@ abstract class LiskDAO extends Phobject { return (bool)self::$transactionIsolationLevel; } - public static function closeAllConnections() { - self::$connections = array(); + /** + * Close any connections with no recent activity. + * + * Long-running processes can use this method to clean up connections which + * have not been used recently. + * + * @param int Close connections with no activity for this many seconds. + * @return void + */ + public static function closeInactiveConnections($idle_window) { + $connections = self::$connections; + + $now = PhabricatorTime::getNow(); + foreach ($connections as $key => $connection) { + $last_active = $connection->getLastActiveEpoch(); + + $idle_duration = ($now - $last_active); + if ($idle_duration <= $idle_window) { + continue; + } + + self::closeConnection($key); + } } + + public static function closeAllConnections() { + $connections = self::$connections; + + foreach ($connections as $key => $connection) { + self::closeConnection($key); + } + } + + private static function closeConnection($key) { + if (empty(self::$connections[$key])) { + throw new Exception( + pht( + 'No database connection with connection key "%s" exists!', + $key)); + } + + $connection = self::$connections[$key]; + unset(self::$connections[$key]); + + $connection->close(); + } + + /* -( Utilities )---------------------------------------------------------- */ @@ -1831,7 +1876,6 @@ abstract class LiskDAO extends Phobject { return $this->getConfigOption(self::CONFIG_BINARY); } - public function getSchemaColumns() { $custom_map = $this->getConfigOption(self::CONFIG_COLUMN_SCHEMA); if (!$custom_map) { @@ -1953,4 +1997,21 @@ abstract class LiskDAO extends Phobject { return $custom_map + $default_map; } + public function getColumnMaximumByteLength($column) { + $map = $this->getSchemaColumns(); + + if (!isset($map[$column])) { + throw new Exception( + pht( + 'Object (of class "%s") does not have a column "%s".', + get_class($this), + $column)); + } + + $data_type = $map[$column]; + + return id(new PhabricatorStorageSchemaSpec()) + ->getMaximumByteLengthForDataType($data_type); + } + } diff --git a/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php b/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php index 99f1bcb864..21fabed8a8 100644 --- a/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php +++ b/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php @@ -122,15 +122,16 @@ abstract class PhabricatorLiskDAO extends LiskDAO { } $replica = PhabricatorDatabaseRef::getReplicaDatabaseRef(); - if (!$replica) { - throw new Exception( - pht('No valid databases are configured!')); + if ($replica) { + $connection = $replica->newApplicationConnection($database); + $connection->setReadOnly(true); + if ($replica->isReachable($connection)) { + return $connection; + } } - $connection = $replica->newApplicationConnection($database); - $connection->setReadOnly(true); - if ($replica->isReachable($connection)) { - return $connection; + if (!$master && !$replica) { + $this->raiseUnconfigured($database); } $this->raiseUnreachable($database); @@ -153,10 +154,18 @@ abstract class PhabricatorLiskDAO extends LiskDAO { $database)); } + private function raiseUnconfigured($database) { + throw new Exception( + pht( + 'Unable to establish a connection to any database host '. + '(while trying "%s"). No masters or replicas are configured.', + $database)); + } + private function raiseUnreachable($database) { throw new PhabricatorClusterStrandedException( pht( - 'Unable to establish a connection to ANY database host '. + 'Unable to establish a connection to any database host '. '(while trying "%s"). All masters and replicas are completely '. 'unreachable.', $database)); diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php index 45f4d2d8e8..84e2ed5489 100644 --- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php +++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php @@ -31,7 +31,7 @@ final class PhabricatorStorageManagementShellWorkflow } return phutil_passthru( - 'mysql --protocol=TCP --default-character-set=utf8 '. + 'mysql --protocol=TCP --default-character-set=utf8mb4 '. '-u %s %C -h %s %C', $api->getUser(), $flag_password, diff --git a/src/view/page/menu/PhabricatorMainMenuView.php b/src/view/page/menu/PhabricatorMainMenuView.php index 25dba1871a..c0ebe680dc 100644 --- a/src/view/page/menu/PhabricatorMainMenuView.php +++ b/src/view/page/menu/PhabricatorMainMenuView.php @@ -297,11 +297,13 @@ final class PhabricatorMainMenuView extends AphrontView { } private function renderPhabricatorLogo() { - $style_logo = null; - $custom_header = PhabricatorEnv::getEnvConfig('ui.custom-header'); + $custom_header = PhabricatorCustomLogoConfigType::getLogoImagePHID(); + + $logo_style = array(); if ($custom_header) { $cache = PhabricatorCaches::getImmutableCache(); - $cache_key_logo = 'ui.custom-header.logo-phid.v1.'.$custom_header; + $cache_key_logo = 'ui.custom-header.logo-phid.v3.'.$custom_header; + $logo_uri = $cache->getKey($cache_key_logo); if (!$logo_uri) { $file = id(new PhabricatorFileQuery()) @@ -313,21 +315,32 @@ final class PhabricatorMainMenuView extends AphrontView { $cache->setKey($cache_key_logo, $logo_uri); } } - if ($logo_uri) { - $style_logo = - 'background-size: 96px 40px; '. - 'background-position: 0px 0px; '. - 'background-image: url('.$logo_uri.');'; - } + + $logo_style[] = 'background-size: 40px 40px;'; + $logo_style[] = 'background-position: 0 0;'; + $logo_style[] = 'background-image: url('.$logo_uri.')'; } - $color = PhabricatorEnv::getEnvConfig('ui.header-color'); - if ($color == 'light') { - $color = 'dark'; - } else { - $color = 'light'; + $logo_node = phutil_tag( + 'span', + array( + 'class' => 'phabricator-main-menu-eye', + 'style' => implode(' ', $logo_style), + )); + + + $wordmark_text = PhabricatorCustomLogoConfigType::getLogoWordmark(); + if (!strlen($wordmark_text)) { + $wordmark_text = pht('Phabricator'); } + $wordmark_node = phutil_tag( + 'span', + array( + 'class' => 'phabricator-wordmark', + ), + $wordmark_text); + return phutil_tag( 'a', array( @@ -341,19 +354,8 @@ final class PhabricatorMainMenuView extends AphrontView { 'aural' => true, ), pht('Home')), - phutil_tag( - 'span', - array( - 'class' => 'sprite-menu phabricator-main-menu-eye '.$color.'-eye', - ), - ''), - phutil_tag( - 'span', - array( - 'class' => 'sprite-menu phabricator-main-menu-logo '.$color.'-logo', - 'style' => $style_logo, - ), - ''), + $logo_node, + $wordmark_node, )); } diff --git a/src/view/phui/PHUIDocumentView.php b/src/view/phui/PHUIDocumentView.php deleted file mode 100644 index 9a076b4b74..0000000000 --- a/src/view/phui/PHUIDocumentView.php +++ /dev/null @@ -1,162 +0,0 @@ -offset = $offset; - return $this; - } - - public function setHeader(PHUIHeaderView $header) { - $header->setTall(true); - $this->header = $header; - return $this; - } - - public function setSideNav(PHUIListView $list, $display = self::NAV_BOTTOM) { - $list->setType(PHUIListView::SIDENAV_LIST); - $this->sidenav = $list; - $this->mobileview = $display; - return $this; - } - - public function setTopNav(PHUIListView $list) { - $list->setType(PHUIListView::NAVBAR_LIST); - $this->topnav = $list; - return $this; - } - - public function setCrumbs(PHUIListView $list) { - $this->crumbs = $list; - return $this; - } - - public function setBook($name, $description) { - $this->bookname = $name; - $this->bookdescription = $description; - return $this; - } - - public function setFluid($fluid) { - $this->fluid = $fluid; - return $this; - } - - protected function getTagAttributes() { - $classes = array(); - - if ($this->offset) { - $classes[] = 'phui-document-offset'; - } - - if ($this->fluid) { - $classes[] = 'phui-document-fluid'; - } - - return array( - 'class' => $classes, - ); - } - - protected function getTagContent() { - require_celerity_resource('phui-document-view-css'); - - $classes = array(); - $classes[] = 'phui-document-view'; - if ($this->offset) { - $classes[] = 'phui-offset-view'; - } - if ($this->sidenav) { - $classes[] = 'phui-sidenav-view'; - } - - $sidenav = null; - if ($this->sidenav) { - $sidenav = phutil_tag( - 'div', - array( - 'class' => 'phui-document-sidenav', - ), - $this->sidenav); - } - - $book = null; - if ($this->bookname) { - $book = pht('%s (%s)', $this->bookname, $this->bookdescription); - } - - $topnav = null; - if ($this->topnav) { - $topnav = phutil_tag( - 'div', - array( - 'class' => 'phui-document-topnav', - ), - $this->topnav); - } - - $crumbs = null; - if ($this->crumbs) { - $crumbs = phutil_tag( - 'div', - array( - 'class' => 'phui-document-crumbs', - ), - $this->bookName); - } - - $main_content = $this->renderChildren(); - - if ($book) { - $this->header->setSubheader($book); - } - $content_inner = phutil_tag( - 'div', - array( - 'class' => 'phui-document-inner', - ), - array( - $this->header, - $topnav, - $main_content, - $crumbs, - )); - - if ($this->mobileview == self::NAV_BOTTOM) { - $order = array($content_inner, $sidenav); - } else { - $order = array($sidenav, $content_inner); - } - - $content = phutil_tag( - 'div', - array( - 'class' => 'phui-document-content', - ), - $order); - - $view = phutil_tag( - 'div', - array( - 'class' => implode(' ', $classes), - ), - $content); - - return $view; - } - -} diff --git a/webroot/rsrc/css/aphront/phabricator-nav-view.css b/webroot/rsrc/css/aphront/phabricator-nav-view.css index 760c2cd372..0846a1a4fe 100644 --- a/webroot/rsrc/css/aphront/phabricator-nav-view.css +++ b/webroot/rsrc/css/aphront/phabricator-nav-view.css @@ -68,6 +68,12 @@ margin-left: 212px; } +.has-drag-nav ul.phui-list-view { + height: 100%; + overflow-y: auto; + overflow-x: hidden; +} + .device-desktop .phui-navigation-shell .has-drag-nav .phabricator-nav-local { width: 205px; padding: 0; diff --git a/webroot/rsrc/css/application/base/main-menu-view.css b/webroot/rsrc/css/application/base/main-menu-view.css index 8be3a97f5e..4ee1372c16 100644 --- a/webroot/rsrc/css/application/base/main-menu-view.css +++ b/webroot/rsrc/css/application/base/main-menu-view.css @@ -41,27 +41,20 @@ } .phabricator-main-menu-brand { - display: inline-block; - width: 148px; height: 44px; float: left; - margin-right: 4px; + margin-right: 6px; padding-left: 6px; } -.phabricator-main-menu-logo { - position: absolute; - width: 96px; - height: 40px; - left: 52px; - top: 2px; -} - .phabricator-main-menu-eye { - position: absolute; + margin: 2px 0; width: 40px; height: 40px; - top: 2px; + float: left; + display: block; + background-image: url(/rsrc/image/logo/light-eye.png); + background-size: 40px 40px; } .device-desktop .phabricator-main-menu-brand:hover { @@ -69,6 +62,21 @@ cursor: hand; } +.device-phone .phabricator-wordmark { + max-width: 112px; /* iPhone 5 limitation */ +} + +.phabricator-wordmark { + float: left; + color: #fff; + font-size: 18px; + margin: 9px 4px 9px 6px; + padding-right: 8px; + max-width: 175px; + overflow: hidden; + white-space: nowrap; +} + /* - Expand/Collapse Button ---------------------------------------------------- On phones, the menu switches to a vertical layout and uses a button to expand diff --git a/webroot/rsrc/css/application/config/config-welcome.css b/webroot/rsrc/css/application/config/config-welcome.css index 8410d00500..748726476e 100644 --- a/webroot/rsrc/css/application/config/config-welcome.css +++ b/webroot/rsrc/css/application/config/config-welcome.css @@ -19,5 +19,10 @@ width: 32px; float: left; text-align: center; - margin-left: 16px; } + +.phui-document-view-pro .phui-document-content .config-welcome-box + .phabricator-remarkup { + margin: 0; + padding: 0; + } diff --git a/webroot/rsrc/css/phui/phui-document.css b/webroot/rsrc/css/phui/phui-document.css index 2b75227c42..87cdc60ddd 100644 --- a/webroot/rsrc/css/phui/phui-document.css +++ b/webroot/rsrc/css/phui/phui-document.css @@ -8,15 +8,6 @@ position: relative; } -.phui-document-view .phui-header-shell { - padding: 16px; - background-color: {$bluebackground}; -} - -.phui-document-content { - border-radius: 3px; -} - .device-desktop .phui-document-view { border: 1px solid {$lightblueborder}; max-width: 960px; @@ -33,44 +24,11 @@ margin: 16px; } -.phui-crumbs-view + .phui-document-fluid .phui-document-view { - margin-top: 0; -} - -.device-desktop .phui-document-view.phui-offset-view { - max-width: 800px; -} - /* Fix so that Phriction Document preview is the same width as the document */ .device-desktop .phui-remarkup-preview .phui-document-view { width: 800px; } -.phui-document-sidenav { - position:absolute; - width: 200px; - text-overflow: ellipsis; - top: 0; - right: 0; -} - -.device-phone .phui-document-sidenav { - position: static; - width: auto; - border-top: 1px solid {$thinblueborder}; - border-bottom: 1px solid {$thinblueborder}; -} - -.device-phone .phui-sidenav-view .phui-document-inner { - margin: 0; -} - -.phui-sidenav-view .phui-document-inner { - margin-right: 200px; - border-right: 1px solid {$thinblueborder}; - background: #fff; -} - .phui-document-content .phui-header-shell { border-top: none; border-bottom: 1px solid {$lightblueborder}; @@ -88,11 +46,6 @@ padding: 8px 0 4px; } -.phui-document-content .phui-property-list-container { - border-bottom: 1px solid {$thinblueborder}; - background-color: {$lightgreybackground}; -} - .legalpad .phui-document-content .phui-property-list-view { border: none; box-shadow: none; @@ -127,18 +80,10 @@ margin: 16px 0; } -.device-desktop .phui-document-offset { - padding-right: 120px; -} - .phui-document-view .phui-info-severity-nodata { background-color: {$lightgreybackground}; } -body .phui-document-view .phui-header-shell.phui-bleed-header { - padding: 0; -} - .phui-document-view .phui-property-list-section-header { padding: 20px 24px 0px; border-top: none; diff --git a/webroot/rsrc/css/sprite-menu.css b/webroot/rsrc/css/sprite-menu.css deleted file mode 100644 index 61e1240b07..0000000000 --- a/webroot/rsrc/css/sprite-menu.css +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @provides sprite-menu-css - * @generated - */ - -.sprite-menu { - background-image: url(/rsrc/image/sprite-menu.png); - background-repeat: no-repeat; -} - -@media -only screen and (min-device-pixel-ratio: 1.5), -only screen and (-webkit-min-device-pixel-ratio: 1.5), -only screen and (min-resolution: 1.5dppx) { - .sprite-menu { - background-image: url(/rsrc/image/sprite-menu-X2.png); - background-size: 97px 123px; - } -} - - -.dark-logo { - background-position: 0px 0px; -} - -.dark-eye { - background-position: 0px -82px; -} - -.light-logo { - background-position: 0px -41px; -} - -.light-eye { - background-position: -41px -82px; -} diff --git a/webroot/rsrc/image/logo/light-eye.png b/webroot/rsrc/image/logo/light-eye.png new file mode 100644 index 0000000000..772dcb0c01 Binary files /dev/null and b/webroot/rsrc/image/logo/light-eye.png differ diff --git a/webroot/rsrc/image/sprite-menu-X2.png b/webroot/rsrc/image/sprite-menu-X2.png deleted file mode 100644 index ea92e0e9cf..0000000000 Binary files a/webroot/rsrc/image/sprite-menu-X2.png and /dev/null differ diff --git a/webroot/rsrc/image/sprite-menu.png b/webroot/rsrc/image/sprite-menu.png deleted file mode 100644 index bdb250c3c1..0000000000 Binary files a/webroot/rsrc/image/sprite-menu.png and /dev/null differ