diff --git a/resources/builtin/projects/v3/book.png b/resources/builtin/projects/v3/book.png new file mode 100644 index 0000000000..eceb0bfb4d Binary files /dev/null and b/resources/builtin/projects/v3/book.png differ diff --git a/resources/builtin/projects/v3/clipboard.png b/resources/builtin/projects/v3/clipboard.png new file mode 100644 index 0000000000..60e2acd4f4 Binary files /dev/null and b/resources/builtin/projects/v3/clipboard.png differ diff --git a/resources/builtin/projects/v3/lightbulb.png b/resources/builtin/projects/v3/lightbulb.png new file mode 100644 index 0000000000..1aba0d32f3 Binary files /dev/null and b/resources/builtin/projects/v3/lightbulb.png differ diff --git a/resources/builtin/projects/v3/marker.png b/resources/builtin/projects/v3/marker.png new file mode 100644 index 0000000000..c2c753a006 Binary files /dev/null and b/resources/builtin/projects/v3/marker.png differ diff --git a/resources/builtin/projects/v3/piechart.png b/resources/builtin/projects/v3/piechart.png new file mode 100644 index 0000000000..4c707ed6ff Binary files /dev/null and b/resources/builtin/projects/v3/piechart.png differ diff --git a/resources/builtin/projects/v3/robot.png b/resources/builtin/projects/v3/robot.png new file mode 100644 index 0000000000..317544f2dd Binary files /dev/null and b/resources/builtin/projects/v3/robot.png differ diff --git a/resources/builtin/projects/v3/rocket.png b/resources/builtin/projects/v3/rocket.png new file mode 100644 index 0000000000..f5a758ff81 Binary files /dev/null and b/resources/builtin/projects/v3/rocket.png differ diff --git a/resources/builtin/projects/v3/sitemap.png b/resources/builtin/projects/v3/sitemap.png new file mode 100644 index 0000000000..8ee6e232b4 Binary files /dev/null and b/resources/builtin/projects/v3/sitemap.png differ diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 6a3b8778e6..b418ffcdb4 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,12 +9,12 @@ return array( 'names' => array( 'conpherence.pkg.css' => 'ff161f2d', 'conpherence.pkg.js' => 'b5b51108', - 'core.pkg.css' => '37dd219b', + 'core.pkg.css' => '7ae9e755', 'core.pkg.js' => '5d80e0db', 'darkconsole.pkg.js' => '1f9a31bc', - 'differential.pkg.css' => '4ec4a37a', - 'differential.pkg.js' => 'd4ab0e81', - 'diffusion.pkg.css' => 'b93d9b8c', + 'differential.pkg.css' => 'b00f573e', + 'differential.pkg.js' => '1d80ecc6', + 'diffusion.pkg.css' => 'a2d17c7d', 'diffusion.pkg.js' => '6134c5a1', 'favicon.ico' => '30672e08', 'maniphest.pkg.css' => '4845691a', @@ -64,18 +64,18 @@ return array( 'rsrc/css/application/dashboard/dashboard.css' => 'fe5b1869', 'rsrc/css/application/diff/inline-comment-summary.css' => '51efda3a', 'rsrc/css/application/differential/add-comment.css' => 'c47f8c40', - 'rsrc/css/application/differential/changeset-view.css' => 'b5e6be7f', + 'rsrc/css/application/differential/changeset-view.css' => '3cef17bd', 'rsrc/css/application/differential/core.css' => '5b7b8ff4', 'rsrc/css/application/differential/phui-inline-comment.css' => 'ffd1a542', 'rsrc/css/application/differential/revision-comment.css' => '14b8565a', 'rsrc/css/application/differential/revision-history.css' => '0e8eb855', 'rsrc/css/application/differential/revision-list.css' => 'f3c47d33', 'rsrc/css/application/differential/table-of-contents.css' => 'ae4b7a55', - 'rsrc/css/application/diffusion/diffusion-history.css' => '4540f568', - 'rsrc/css/application/diffusion/diffusion-icons.css' => 'a6a1e2ba', + 'rsrc/css/application/diffusion/diffusion-icons.css' => '0c15255e', 'rsrc/css/application/diffusion/diffusion-readme.css' => '419dd5b6', 'rsrc/css/application/diffusion/diffusion-repository.css' => 'ee6f20ec', 'rsrc/css/application/diffusion/diffusion-source.css' => '750add59', + 'rsrc/css/application/diffusion/diffusion.css' => '8d01932f', 'rsrc/css/application/feed/feed.css' => 'ecd4ec57', 'rsrc/css/application/files/global-drag-and-drop.css' => '5c1b47c2', 'rsrc/css/application/flag/flag.css' => 'bba8f811', @@ -161,11 +161,12 @@ return array( 'rsrc/css/phui/phui-header-view.css' => 'e7de7ee2', 'rsrc/css/phui/phui-hovercard.css' => 'f0592bcf', 'rsrc/css/phui/phui-icon-set-selector.css' => '87db8fee', - 'rsrc/css/phui/phui-icon.css' => '4c46b6ba', + 'rsrc/css/phui/phui-icon.css' => '5c4a5de6', 'rsrc/css/phui/phui-image-mask.css' => 'a8498f9c', 'rsrc/css/phui/phui-info-panel.css' => '27ea50a1', 'rsrc/css/phui/phui-info-view.css' => '6e217679', 'rsrc/css/phui/phui-invisible-character-view.css' => '6993d9f0', + 'rsrc/css/phui/phui-left-right.css' => 'f60c67e7', 'rsrc/css/phui/phui-lightbox.css' => '0a035e40', 'rsrc/css/phui/phui-list.css' => 'dcafb463', 'rsrc/css/phui/phui-object-box.css' => '9cff003c', @@ -397,7 +398,7 @@ return array( 'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '453c5375', 'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => 'd4eecc63', 'rsrc/js/application/diff/DiffChangeset.js' => '99abf4cd', - 'rsrc/js/application/diff/DiffChangesetList.js' => '79de07c6', + 'rsrc/js/application/diff/DiffChangesetList.js' => 'cb1570cb', 'rsrc/js/application/diff/DiffInline.js' => '1bfa31c7', 'rsrc/js/application/diff/behavior-preview-link.js' => '051c7832', 'rsrc/js/application/differential/behavior-comment-preview.js' => '51c5ad07', @@ -563,15 +564,15 @@ return array( 'conpherence-thread-manager' => '4d863052', 'conpherence-transaction-css' => '85129c68', 'd3' => 'a11a5ff2', - 'differential-changeset-view-css' => 'b5e6be7f', + 'differential-changeset-view-css' => '3cef17bd', 'differential-core-view-css' => '5b7b8ff4', 'differential-revision-add-comment-css' => 'c47f8c40', 'differential-revision-comment-css' => '14b8565a', 'differential-revision-history-css' => '0e8eb855', 'differential-revision-list-css' => 'f3c47d33', 'differential-table-of-contents-css' => 'ae4b7a55', - 'diffusion-history-css' => '4540f568', - 'diffusion-icons-css' => 'a6a1e2ba', + 'diffusion-css' => '8d01932f', + 'diffusion-icons-css' => '0c15255e', 'diffusion-readme-css' => '419dd5b6', 'diffusion-repository-css' => 'ee6f20ec', 'diffusion-source-css' => '750add59', @@ -777,7 +778,7 @@ return array( 'phabricator-darkmessage' => 'c48cccdd', 'phabricator-dashboard-css' => 'fe5b1869', 'phabricator-diff-changeset' => '99abf4cd', - 'phabricator-diff-changeset-list' => '79de07c6', + 'phabricator-diff-changeset-list' => 'cb1570cb', 'phabricator-diff-inline' => '1bfa31c7', 'phabricator-drag-and-drop-file-upload' => '58dea2fa', 'phabricator-draggable-list' => 'bea6e7f4', @@ -849,12 +850,13 @@ return array( 'phui-hovercard' => '1bd28176', 'phui-hovercard-view-css' => 'f0592bcf', 'phui-icon-set-selector-css' => '87db8fee', - 'phui-icon-view-css' => '4c46b6ba', + 'phui-icon-view-css' => '5c4a5de6', 'phui-image-mask-css' => 'a8498f9c', 'phui-info-panel-css' => '27ea50a1', 'phui-info-view-css' => '6e217679', 'phui-inline-comment-view-css' => 'ffd1a542', 'phui-invisible-character-view-css' => '6993d9f0', + 'phui-left-right-css' => 'f60c67e7', 'phui-lightbox-css' => '0a035e40', 'phui-list-view-css' => 'dcafb463', 'phui-object-box-css' => '9cff003c', @@ -1144,6 +1146,9 @@ return array( 'javelin-util', 'javelin-uri', ), + '3cef17bd' => array( + 'phui-inline-comment-view-css', + ), '3dbf94d5' => array( 'javelin-behavior', 'javelin-dom', @@ -1478,10 +1483,6 @@ return array( 'javelin-behavior', 'javelin-quicksand', ), - '79de07c6' => array( - 'javelin-install', - 'phuix-button-view', - ), '7a68dda3' => array( 'owners-path-editor', 'javelin-behavior', @@ -1813,9 +1814,6 @@ return array( 'javelin-dom', 'javelin-util', ), - 'b5e6be7f' => array( - 'phui-inline-comment-view-css', - ), 'b6993408' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1959,6 +1957,10 @@ return array( 'cae95e89' => array( 'syntax-default-css', ), + 'cb1570cb' => array( + 'javelin-install', + 'phuix-button-view', + ), 'ccf1cbf8' => array( 'javelin-install', 'javelin-dom', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 095759a351..1e3ed214fa 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -619,6 +619,7 @@ phutil_register_library_map(array( 'DiffusionCachedResolveRefsQuery' => 'applications/diffusion/query/DiffusionCachedResolveRefsQuery.php', 'DiffusionChangeController' => 'applications/diffusion/controller/DiffusionChangeController.php', 'DiffusionChangeHeraldFieldGroup' => 'applications/diffusion/herald/DiffusionChangeHeraldFieldGroup.php', + 'DiffusionCloneController' => 'applications/diffusion/controller/DiffusionCloneController.php', 'DiffusionCloneURIView' => 'applications/diffusion/view/DiffusionCloneURIView.php', 'DiffusionCommandEngine' => 'applications/diffusion/protocol/DiffusionCommandEngine.php', 'DiffusionCommandEngineTestCase' => 'applications/diffusion/protocol/__tests__/DiffusionCommandEngineTestCase.php', @@ -1773,6 +1774,8 @@ phutil_register_library_map(array( 'PHUIInfoView' => 'view/form/PHUIInfoView.php', 'PHUIInvisibleCharacterTestCase' => 'view/phui/__tests__/PHUIInvisibleCharacterTestCase.php', 'PHUIInvisibleCharacterView' => 'view/phui/PHUIInvisibleCharacterView.php', + 'PHUILeftRightExample' => 'applications/uiexample/examples/PHUILeftRightExample.php', + 'PHUILeftRightView' => 'view/phui/PHUILeftRightView.php', 'PHUIListExample' => 'applications/uiexample/examples/PHUIListExample.php', 'PHUIListItemView' => 'view/phui/PHUIListItemView.php', 'PHUIListView' => 'view/phui/PHUIListView.php', @@ -3612,6 +3615,7 @@ phutil_register_library_map(array( 'PhabricatorProjectBoardManageController' => 'applications/project/controller/PhabricatorProjectBoardManageController.php', 'PhabricatorProjectBoardReorderController' => 'applications/project/controller/PhabricatorProjectBoardReorderController.php', 'PhabricatorProjectBoardViewController' => 'applications/project/controller/PhabricatorProjectBoardViewController.php', + 'PhabricatorProjectBuiltinsExample' => 'applications/uiexample/examples/PhabricatorProjectBuiltinsExample.php', 'PhabricatorProjectCardView' => 'applications/project/view/PhabricatorProjectCardView.php', 'PhabricatorProjectColorTransaction' => 'applications/project/xaction/PhabricatorProjectColorTransaction.php', 'PhabricatorProjectColorsConfigType' => 'applications/project/config/PhabricatorProjectColorsConfigType.php', @@ -5607,6 +5611,7 @@ phutil_register_library_map(array( 'DiffusionCachedResolveRefsQuery' => 'DiffusionLowLevelQuery', 'DiffusionChangeController' => 'DiffusionController', 'DiffusionChangeHeraldFieldGroup' => 'HeraldFieldGroup', + 'DiffusionCloneController' => 'DiffusionController', 'DiffusionCloneURIView' => 'AphrontView', 'DiffusionCommandEngine' => 'Phobject', 'DiffusionCommandEngineTestCase' => 'PhabricatorTestCase', @@ -6926,6 +6931,8 @@ phutil_register_library_map(array( 'PHUIInfoView' => 'AphrontTagView', 'PHUIInvisibleCharacterTestCase' => 'PhabricatorTestCase', 'PHUIInvisibleCharacterView' => 'AphrontView', + 'PHUILeftRightExample' => 'PhabricatorUIExample', + 'PHUILeftRightView' => 'AphrontTagView', 'PHUIListExample' => 'PhabricatorUIExample', 'PHUIListItemView' => 'AphrontTagView', 'PHUIListView' => 'AphrontTagView', @@ -9063,6 +9070,7 @@ phutil_register_library_map(array( 'PhabricatorProjectBoardManageController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardReorderController' => 'PhabricatorProjectBoardController', 'PhabricatorProjectBoardViewController' => 'PhabricatorProjectBoardController', + 'PhabricatorProjectBuiltinsExample' => 'PhabricatorUIExample', 'PhabricatorProjectCardView' => 'AphrontTagView', 'PhabricatorProjectColorTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectColorsConfigType' => 'PhabricatorJSONConfigType', diff --git a/src/applications/differential/constants/DifferentialChangeType.php b/src/applications/differential/constants/DifferentialChangeType.php index 7ee3c89b65..fd0bcf81bb 100644 --- a/src/applications/differential/constants/DifferentialChangeType.php +++ b/src/applications/differential/constants/DifferentialChangeType.php @@ -71,7 +71,7 @@ final class DifferentialChangeType extends Phobject { self::FILE_TEXT => 'fa-file-text-o', self::FILE_IMAGE => 'fa-file-image-o', self::FILE_BINARY => 'fa-file', - self::FILE_DIRECTORY => 'fa-folder-open', + self::FILE_DIRECTORY => 'fa-folder', self::FILE_SYMLINK => 'fa-link', self::FILE_DELETED => 'fa-file', self::FILE_NORMAL => 'fa-file-text-o', @@ -83,14 +83,14 @@ final class DifferentialChangeType extends Phobject { public static function getIconColorForFileType($type) { static $icons = array( - self::FILE_TEXT => 'black', - self::FILE_IMAGE => 'black', + self::FILE_TEXT => 'bluetext', + self::FILE_IMAGE => 'bluetext', self::FILE_BINARY => 'green', - self::FILE_DIRECTORY => 'blue', - self::FILE_SYMLINK => 'blue', + self::FILE_DIRECTORY => 'bluetext', + self::FILE_SYMLINK => 'bluetext', self::FILE_DELETED => 'red', - self::FILE_NORMAL => 'black', - self::FILE_SUBMODULE => 'blue', + self::FILE_NORMAL => 'bluetext', + self::FILE_SUBMODULE => 'bluetext', ); return idx($icons, $type, 'black'); diff --git a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php index dc1b120138..b00fcce77f 100644 --- a/src/applications/diffusion/application/PhabricatorDiffusionApplication.php +++ b/src/applications/diffusion/application/PhabricatorDiffusionApplication.php @@ -55,6 +55,7 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication { '' => 'DiffusionRepositoryController', 'repository/(?P.*)' => 'DiffusionRepositoryController', 'change/(?P.*)' => 'DiffusionChangeController', + 'clone/' => 'DiffusionCloneController', 'history/(?P.*)' => 'DiffusionHistoryController', 'graph/(?P.*)' => 'DiffusionGraphController', 'browse/(?P.*)' => 'DiffusionBrowseController', diff --git a/src/applications/diffusion/controller/DiffusionCloneController.php b/src/applications/diffusion/controller/DiffusionCloneController.php new file mode 100644 index 0000000000..8bc4faa1a2 --- /dev/null +++ b/src/applications/diffusion/controller/DiffusionCloneController.php @@ -0,0 +1,122 @@ +getViewer(); + $response = $this->loadDiffusionContext(); + if ($response) { + return $response; + } + + $drequest = $this->getDiffusionRequest(); + $repository = $drequest->getRepository(); + + $view = id(new PHUIPropertyListView()) + ->setUser($viewer); + + $display_never = PhabricatorRepositoryURI::DISPLAY_NEVER; + $warning = null; + + $uris = $repository->getURIs(); + foreach ($uris as $uri) { + if ($uri->getIsDisabled()) { + continue; + } + + if ($uri->getEffectiveDisplayType() == $display_never) { + continue; + } + + if ($repository->isSVN()) { + $label = phutil_tag_div('diffusion-clone-label', pht('Checkout')); + } else { + $label = phutil_tag_div('diffusion-clone-label', pht('Clone')); + } + + $view->addProperty( + $label, + $this->renderCloneURI($repository, $uri)); + } + + if (!$view->hasAnyProperties()) { + $view = id(new PHUIInfoView()) + ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) + ->appendChild(pht('Repository has no URIs set.')); + } + + $info = null; + + // Try to load alternatives. This may fail for repositories which have not + // cloned yet. If it does, just ignore it and continue. + try { + $alternatives = $drequest->getRefAlternatives(); + } catch (ConduitClientException $ex) { + $alternatives = array(); + } + + if ($alternatives) { + $message = array( + pht( + 'The ref "%s" is ambiguous in this repository.', + $drequest->getBranch()), + ' ', + phutil_tag( + 'a', + array( + 'href' => $drequest->generateURI( + array( + 'action' => 'refs', + )), + ), + pht('View Alternatives')), + ); + + $messages = array($message); + + $warning = id(new PHUIInfoView()) + ->setSeverity(PHUIInfoView::SEVERITY_WARNING) + ->setErrors(array($message)); + } + + $cancel_uri = $drequest->generateURI( + array( + 'action' => 'branch', + 'path' => '/', + )); + + return $this->newDialog() + ->setTitle(pht('Clone Repository')) + ->setWidth(AphrontDialogView::WIDTH_FORM) + ->addCancelButton($cancel_uri, pht('Close')) + ->appendChild(array($view, $warning)); + } + + private function renderCloneURI( + PhabricatorRepository $repository, + PhabricatorRepositoryURI $uri) { + + if ($repository->isSVN()) { + $display = csprintf( + 'svn checkout %R %R', + (string)$uri->getDisplayURI(), + $repository->getCloneName()); + } else { + $display = csprintf('%R', (string)$uri->getDisplayURI()); + } + + $display = (string)$display; + $viewer = $this->getViewer(); + + return id(new DiffusionCloneURIView()) + ->setViewer($viewer) + ->setRepository($repository) + ->setRepositoryURI($uri) + ->setDisplayURI($display); + } + +} diff --git a/src/applications/diffusion/controller/DiffusionLastModifiedController.php b/src/applications/diffusion/controller/DiffusionLastModifiedController.php index faf9457c15..945f8a58b5 100644 --- a/src/applications/diffusion/controller/DiffusionLastModifiedController.php +++ b/src/applications/diffusion/controller/DiffusionLastModifiedController.php @@ -132,7 +132,11 @@ final class DiffusionLastModifiedController extends DiffusionController { } } - $details = AphrontTableView::renderSingleDisplayLine($data->getSummary()); + $details = DiffusionView::linkDetail( + $drequest->getRepository(), + $commit->getCommitIdentifier(), + $data->getSummary()); + $details = AphrontTableView::renderSingleDisplayLine($details); } else { $author = ''; $details = ''; diff --git a/src/applications/diffusion/controller/DiffusionRepositoryController.php b/src/applications/diffusion/controller/DiffusionRepositoryController.php index d8451db2db..6def808cff 100644 --- a/src/applications/diffusion/controller/DiffusionRepositoryController.php +++ b/src/applications/diffusion/controller/DiffusionRepositoryController.php @@ -17,6 +17,8 @@ final class DiffusionRepositoryController extends DiffusionController { return $response; } + require_celerity_resource('diffusion-css'); + $viewer = $this->getViewer(); $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); @@ -25,11 +27,12 @@ final class DiffusionRepositoryController extends DiffusionController { $crumbs->setBorder(true); $header = $this->buildHeaderView($repository); - $curtain = $this->buildCurtain($repository); - $property_table = $this->buildPropertiesTable($repository); + $actions = $this->buildActionList($repository); $description = $this->buildDescriptionView($repository); $locate_file = $this->buildLocateFile(); + $header->setActionList($actions); + // Before we do any work, make sure we're looking at a some content: we're // on a valid branch, and the repository is not empty. $page_has_content = false; @@ -86,16 +89,41 @@ final class DiffusionRepositoryController extends DiffusionController { $tabs = $this->buildTabsView('home'); + $clone_uri = $drequest->generateURI( + array( + 'action' => 'clone', + )); + + if ($repository->isSVN()) { + $clone_text = pht('Checkout'); + } else { + $clone_text = pht('Clone'); + } + + $clone_button = id(new PHUIButtonView()) + ->setTag('a') + ->setText($clone_text) + ->setColor(PHUIButtonView::GREEN) + ->setIcon('fa-download') + ->setWorkflow(true) + ->setHref($clone_uri); + + $bar = id(new PHUILeftRightView()) + ->setLeft($locate_file) + ->setRight($clone_button) + ->addClass('diffusion-action-bar'); + $view = id(new PHUITwoColumnView()) ->setHeader($header) - ->setCurtain($curtain) - ->setTabs($tabs) - ->setMainColumn(array( - $property_table, + ->setFooter(array( + $bar, $description, - $locate_file, - )) - ->setFooter($content); + $content, + )); + + if ($page_has_content) { + $view->setTabs($tabs); + } return $this->newPage() ->setTitle( @@ -236,7 +264,8 @@ final class DiffusionRepositoryController extends DiffusionController { ->setPolicyObject($repository) ->setProfileHeader(true) ->setImage($repository->getProfileImageURI()) - ->setImageEditURL('/diffusion/picture/'.$repository->getID().'/'); + ->setImageEditURL('/diffusion/picture/'.$repository->getID().'/') + ->addClass('diffusion-profile-header'); if (!$repository->isTracked()) { $header->setStatus('fa-ban', 'dark', pht('Inactive')); @@ -254,13 +283,15 @@ final class DiffusionRepositoryController extends DiffusionController { return $header; } - private function buildCurtain(PhabricatorRepository $repository) { + private function buildActionList(PhabricatorRepository $repository) { $viewer = $this->getViewer(); $edit_uri = $repository->getPathURI('manage/'); - $curtain = $this->newCurtainView($repository); + $action_view = id(new PhabricatorActionListView()) + ->setUser($viewer) + ->setObject($repository); - $curtain->addAction( + $action_view->addAction( id(new PhabricatorActionView()) ->setName(pht('Manage Repository')) ->setIcon('fa-cogs') @@ -270,14 +301,14 @@ final class DiffusionRepositoryController extends DiffusionController { $push_uri = $this->getApplicationURI( 'pushlog/?repositories='.$repository->getMonogram()); - $curtain->addAction( + $action_view->addAction( id(new PhabricatorActionView()) ->setName(pht('View Push Logs')) ->setIcon('fa-list-alt') ->setHref($push_uri)); } - return $curtain; + return $action_view; } private function buildDescriptionView(PhabricatorRepository $repository) { @@ -290,94 +321,12 @@ final class DiffusionRepositoryController extends DiffusionController { $description = new PHUIRemarkupView($viewer, $description); $view->addTextContent($description); return id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Description')) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->appendChild($view); + ->appendChild($view) + ->addClass('diffusion-profile-description'); } return null; } - private function buildPropertiesTable(PhabricatorRepository $repository) { - $viewer = $this->getViewer(); - - $view = id(new PHUIPropertyListView()) - ->setUser($viewer); - - $display_never = PhabricatorRepositoryURI::DISPLAY_NEVER; - - $uris = $repository->getURIs(); - foreach ($uris as $uri) { - if ($uri->getIsDisabled()) { - continue; - } - - if ($uri->getEffectiveDisplayType() == $display_never) { - continue; - } - - if ($repository->isSVN()) { - $label = phutil_tag_div('diffusion-clone-label', pht('Checkout')); - } else { - $label = phutil_tag_div('diffusion-clone-label', pht('Clone')); - } - - $view->addProperty( - $label, - $this->renderCloneURI($repository, $uri)); - } - - if (!$view->hasAnyProperties()) { - $view = id(new PHUIInfoView()) - ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) - ->appendChild(pht('Repository has no URIs set.')); - } - - $box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Details')) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->appendChild($view); - - $info = null; - $drequest = $this->getDiffusionRequest(); - - // Try to load alternatives. This may fail for repositories which have not - // cloned yet. If it does, just ignore it and continue. - try { - $alternatives = $drequest->getRefAlternatives(); - } catch (ConduitClientException $ex) { - $alternatives = array(); - } - - if ($alternatives) { - $message = array( - pht( - 'The ref "%s" is ambiguous in this repository.', - $drequest->getBranch()), - ' ', - phutil_tag( - 'a', - array( - 'href' => $drequest->generateURI( - array( - 'action' => 'refs', - )), - ), - pht('View Alternatives')), - ); - - $messages = array($message); - - $info = id(new PHUIInfoView()) - ->setSeverity(PHUIInfoView::SEVERITY_WARNING) - ->setErrors(array($message)); - - $box->setInfoView($info); - } - - - return $box; - } - private function buildHistoryTable( $history_results, $history, @@ -432,7 +381,7 @@ final class DiffusionRepositoryController extends DiffusionController { $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); - $locate_panel = null; + $form_box = null; if ($repository->canUsePathTree()) { Javelin::initBehavior( 'diffusion-locate-file', @@ -455,15 +404,12 @@ final class DiffusionRepositoryController extends DiffusionController { id(new AphrontFormTypeaheadControl()) ->setHardpointID('locate-control') ->setID('locate-input') - ->setLabel(pht('Locate File'))); + ->setPlaceholder(pht('Locate File'))); $form_box = id(new PHUIBoxView()) - ->appendChild($form->buildLayoutView()); - $locate_panel = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Locate File')) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->appendChild($form_box); + ->appendChild($form->buildLayoutView()) + ->addClass('diffusion-profile-locate'); } - return $locate_panel; + return $form_box; } private function buildBrowseTable( @@ -502,52 +448,13 @@ final class DiffusionRepositoryController extends DiffusionController { } $browse_uri = $drequest->generateURI(array('action' => 'browse')); - - $browse_panel = id(new PHUIObjectBoxView()) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY); - $header = id(new PHUIHeaderView()) - ->setHeader($repository->getName()); - - $button = id(new PHUIButtonView()) - ->setText(pht('Browse')) - ->setTag('a') - ->setIcon('fa-code') - ->setHref($browse_uri); - - $header->addActionLink($button); - $browse_panel->setHeader($header); - $browse_panel->setTable($browse_table); - $pager->setURI($browse_uri, 'offset'); - if ($pager->willShowPagingControls()) { - $browse_panel->setPager($pager); - } - - return $browse_panel; - } - - private function renderCloneURI( - PhabricatorRepository $repository, - PhabricatorRepositoryURI $uri) { - - if ($repository->isSVN()) { - $display = csprintf( - 'svn checkout %R %R', - (string)$uri->getDisplayURI(), - $repository->getCloneName()); - } else { - $display = csprintf('%R', (string)$uri->getDisplayURI()); - } - - $display = (string)$display; - $viewer = $this->getViewer(); - - return id(new DiffusionCloneURIView()) - ->setViewer($viewer) - ->setRepository($repository) - ->setRepositoryURI($uri) - ->setDisplayURI($display); + return id(new PHUIObjectBoxView()) + ->setHeaderText($repository->getName()) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) + ->setTable($browse_table) + ->setPager($pager); } private function getTagLimit() { diff --git a/src/applications/diffusion/protocol/DiffusionMercurialWireProtocol.php b/src/applications/diffusion/protocol/DiffusionMercurialWireProtocol.php index 11e864e74e..32a73867e5 100644 --- a/src/applications/diffusion/protocol/DiffusionMercurialWireProtocol.php +++ b/src/applications/diffusion/protocol/DiffusionMercurialWireProtocol.php @@ -105,14 +105,14 @@ final class DiffusionMercurialWireProtocol extends Phobject { * disallow the client from knowing we speak bundle2 by removing it * from the capabilities listing. * - * The format of the capabilties string is: "a space separated list + * The format of the capabilities string is: "a space separated list * of strings representing what commands the server supports" * @link https://www.mercurial-scm.org/wiki/CommandServer#Protocol * * @param string $capabilities - The string of capabilities to * strip the bundle2 capability from. This is expected to be * the space-separated list of strings resulting from the - * querying the 'capabilties' command. + * querying the 'capabilities' command. * * @return string The resulting space-separated list of capabilities * which no longer contains the 'bundle2' capability. This is meant diff --git a/src/applications/diffusion/view/DiffusionBranchListView.php b/src/applications/diffusion/view/DiffusionBranchListView.php index 8d1df82dc9..1a9df42e05 100644 --- a/src/applications/diffusion/view/DiffusionBranchListView.php +++ b/src/applications/diffusion/view/DiffusionBranchListView.php @@ -23,7 +23,7 @@ final class DiffusionBranchListView extends DiffusionView { $repository = $drequest->getRepository(); $commits = $this->commits; $viewer = $this->getUser(); - require_celerity_resource('diffusion-history-css'); + require_celerity_resource('diffusion-css'); $buildables = $this->loadBuildables($commits); $have_builds = false; diff --git a/src/applications/diffusion/view/DiffusionBrowseTableView.php b/src/applications/diffusion/view/DiffusionBrowseTableView.php index ffc5ce61ed..48729d0669 100644 --- a/src/applications/diffusion/view/DiffusionBrowseTableView.php +++ b/src/applications/diffusion/view/DiffusionBrowseTableView.php @@ -20,6 +20,7 @@ final class DiffusionBrowseTableView extends DiffusionView { public function render() { $request = $this->getDiffusionRequest(); $repository = $request->getRepository(); + require_celerity_resource('diffusion-css'); $base_path = trim($request->getPath(), '/'); if ($base_path) { @@ -74,7 +75,6 @@ final class DiffusionBrowseTableView extends DiffusionView { $dict = array( 'lint' => celerity_generate_unique_node_id(), - 'commit' => celerity_generate_unique_node_id(), 'date' => celerity_generate_unique_node_id(), 'author' => celerity_generate_unique_node_id(), 'details' => celerity_generate_unique_node_id(), @@ -86,13 +86,13 @@ final class DiffusionBrowseTableView extends DiffusionView { } $rows[] = array( - $history_link, $browse_link, idx($dict, 'lint'), - $dict['commit'], $dict['details'], $dict['date'], + $history_link, ); + } if ($need_pull) { @@ -113,27 +113,16 @@ final class DiffusionBrowseTableView extends DiffusionView { $lint = $request->getLint(); $view = new AphrontTableView($rows); - $view->setHeaders( - array( - null, - pht('Path'), - ($lint ? $lint : pht('Lint')), - pht('Modified'), - pht('Details'), - pht('Committed'), - )); $view->setColumnClasses( array( - 'nudgeright', '', '', - '', - 'wide', + 'wide commit-detail', 'right', + 'right narrow', )); $view->setColumnVisibility( array( - true, true, $show_lint, true, @@ -144,15 +133,14 @@ final class DiffusionBrowseTableView extends DiffusionView { $view->setDeviceVisibility( array( true, - true, - false, false, true, false, + false, )); - return $view->render(); + return phutil_tag_div('diffusion-browse-table', $view->render()); } } diff --git a/src/applications/diffusion/view/DiffusionCommitListView.php b/src/applications/diffusion/view/DiffusionCommitListView.php index 4d4bcc1020..d4f20d0014 100644 --- a/src/applications/diffusion/view/DiffusionCommitListView.php +++ b/src/applications/diffusion/view/DiffusionCommitListView.php @@ -73,7 +73,7 @@ final class DiffusionCommitListView extends AphrontView { } public function render() { - require_celerity_resource('diffusion-history-css'); + require_celerity_resource('diffusion-css'); return $this->buildList(); } diff --git a/src/applications/diffusion/view/DiffusionHistoryListView.php b/src/applications/diffusion/view/DiffusionHistoryListView.php index 9dfa46cbef..8f9301c53a 100644 --- a/src/applications/diffusion/view/DiffusionHistoryListView.php +++ b/src/applications/diffusion/view/DiffusionHistoryListView.php @@ -7,7 +7,7 @@ final class DiffusionHistoryListView extends DiffusionHistoryView { $viewer = $this->getUser(); $repository = $drequest->getRepository(); - require_celerity_resource('diffusion-history-css'); + require_celerity_resource('diffusion-css'); Javelin::initBehavior('phabricator-tooltips'); $buildables = $this->loadBuildables( diff --git a/src/applications/diffusion/view/DiffusionTagListView.php b/src/applications/diffusion/view/DiffusionTagListView.php index f9030581e3..abab9003c3 100644 --- a/src/applications/diffusion/view/DiffusionTagListView.php +++ b/src/applications/diffusion/view/DiffusionTagListView.php @@ -29,7 +29,7 @@ final class DiffusionTagListView extends DiffusionView { $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); $viewer = $this->getViewer(); - require_celerity_resource('diffusion-history-css'); + require_celerity_resource('diffusion-css'); $buildables = $this->loadBuildables($this->commits); diff --git a/src/applications/diffusion/view/DiffusionView.php b/src/applications/diffusion/view/DiffusionView.php index d058dc5cec..eb43e49f3c 100644 --- a/src/applications/diffusion/view/DiffusionView.php +++ b/src/applications/diffusion/view/DiffusionView.php @@ -156,6 +156,19 @@ abstract class DiffusionView extends AphrontView { $commit_name); } + final public static function linkDetail( + PhabricatorRepository $repository, + $commit, + $detail) { + + return phutil_tag( + 'a', + array( + 'href' => $repository->getCommitURI($commit), + ), + $detail); + } + final public static function linkRevision($id) { if (!$id) { return null; diff --git a/src/applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php b/src/applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php index 4eb5d9d825..ac51e30386 100644 --- a/src/applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php +++ b/src/applications/files/builtin/PhabricatorFilesOnDiskBuiltinFile.php @@ -56,4 +56,20 @@ final class PhabricatorFilesOnDiskBuiltinFile return $map; } + public function getProjectBuiltinFiles() { + $root = dirname(phutil_get_library_root('phabricator')); + $root = $root.'/resources/builtin/projects/'; + + $map = array(); + $list = id(new FileFinder($root)) + ->withType('f') + ->withFollowSymlinks(true) + ->find(); + + foreach ($list as $file) { + $map[$file] = $root.$file; + } + return $map; + } + } diff --git a/src/applications/policy/controller/PhabricatorPolicyExplainController.php b/src/applications/policy/controller/PhabricatorPolicyExplainController.php index da4103765b..fc508cfa3a 100644 --- a/src/applications/policy/controller/PhabricatorPolicyExplainController.php +++ b/src/applications/policy/controller/PhabricatorPolicyExplainController.php @@ -253,7 +253,7 @@ final class PhabricatorPolicyExplainController ->appendParagraph( pht( 'To access this object, users must have first have access '. - 'capabilties on these other objects:')) + 'capabilities on these other objects:')) ->appendList($items); } diff --git a/src/applications/project/config/PhabricatorProjectConfigOptions.php b/src/applications/project/config/PhabricatorProjectConfigOptions.php index 36b6f09d86..c61faa64fb 100644 --- a/src/applications/project/config/PhabricatorProjectConfigOptions.php +++ b/src/applications/project/config/PhabricatorProjectConfigOptions.php @@ -34,6 +34,8 @@ a dictionary, which may contain these keys: - `key` //Required string.// Internal key identifying the icon. - `name` //Required string.// Human-readable icon name. - `icon` //Required string.// Specifies which actual icon image to use. + - `image` //Optional string.// Selects a default image. Select an image from + `resources/builtins/projects/`. - `default` //Optional bool.// Selects a default icon. Exactly one icon must be selected as the default. - `disabled` //Optional bool.// If true, this icon will no longer be diff --git a/src/applications/project/controller/PhabricatorProjectEditPictureController.php b/src/applications/project/controller/PhabricatorProjectEditPictureController.php index d6b8a73896..97b7fe1792 100644 --- a/src/applications/project/controller/PhabricatorProjectEditPictureController.php +++ b/src/applications/project/controller/PhabricatorProjectEditPictureController.php @@ -98,7 +98,10 @@ final class PhabricatorProjectEditPictureController $form = id(new PHUIFormLayoutView()) ->setUser($viewer); - $default_image = PhabricatorFile::loadBuiltin($viewer, 'project.png'); + $builtin = PhabricatorProjectIconSet::getIconImage( + $project->getIcon()); + $default_image = PhabricatorFile::loadBuiltin($this->getViewer(), + 'projects/'.$builtin); $images = array(); @@ -122,8 +125,10 @@ final class PhabricatorProjectEditPictureController } $builtins = array( + 'projects/v3/book.png', 'projects/v3/bug.png', 'projects/v3/calendar.png', + 'projects/v3/clipboard.png', 'projects/v3/cloud.png', 'projects/v3/creditcard.png', 'projects/v3/database.png', @@ -131,12 +136,18 @@ final class PhabricatorProjectEditPictureController 'projects/v3/experimental.png', 'projects/v3/flag.png', 'projects/v3/folder.png', + 'projects/v3/lightbulb.png', 'projects/v3/lock.png', 'projects/v3/mail.png', + 'projects/v3/marker.png', 'projects/v3/mobile.png', 'projects/v3/organization.png', 'projects/v3/people.png', + 'projects/v3/piechart.png', + 'projects/v3/robot.png', + 'projects/v3/rocket.png', 'projects/v3/servers.png', + 'projects/v3/sitemap.png', 'projects/v3/tag.png', 'projects/v3/trash.png', 'projects/v3/truck.png', diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php index 393c4569f6..7702b74bd6 100644 --- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php +++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php @@ -296,10 +296,6 @@ final class PhabricatorProjectTransactionEditor } } - if ($this->getIsNewObject()) { - $this->setDefaultProfilePicture($object); - } - // TODO: We should dump an informational transaction onto the parent // project to show that we created the sub-thing. @@ -457,34 +453,6 @@ final class PhabricatorProjectTransactionEditor return $results; } - private function setDefaultProfilePicture(PhabricatorProject $project) { - if ($project->isMilestone()) { - return; - } - - $compose_color = $project->getDisplayIconComposeColor(); - $compose_icon = $project->getDisplayIconComposeIcon(); - - $builtin = id(new PhabricatorFilesComposeIconBuiltinFile()) - ->setColor($compose_color) - ->setIcon($compose_icon); - - $data = $builtin->loadBuiltinFileData(); - - $file = PhabricatorFile::newFromFileData( - $data, - array( - 'name' => $builtin->getBuiltinDisplayName(), - 'profile' => true, - 'canCDN' => true, - )); - - $project - ->setProfileImagePHID($file->getPHID()) - ->save(); - } - - protected function shouldApplyHeraldRules( PhabricatorLiskDAO $object, array $xactions) { diff --git a/src/applications/project/icon/PhabricatorProjectIconSet.php b/src/applications/project/icon/PhabricatorProjectIconSet.php index 2283026598..b128a35cad 100644 --- a/src/applications/project/icon/PhabricatorProjectIconSet.php +++ b/src/applications/project/icon/PhabricatorProjectIconSet.php @@ -18,87 +18,104 @@ final class PhabricatorProjectIconSet 'icon' => 'fa-briefcase', 'name' => pht('Project'), 'default' => true, + 'image' => 'v3/briefcase.png', ), array( 'key' => 'tag', 'icon' => 'fa-tags', 'name' => pht('Tag'), + 'image' => 'v3/tag.png', ), array( 'key' => 'policy', 'icon' => 'fa-lock', 'name' => pht('Policy'), + 'image' => 'v3/lock.png', ), array( 'key' => 'group', 'icon' => 'fa-users', 'name' => pht('Group'), + 'image' => 'v3/people.png', ), array( 'key' => 'folder', 'icon' => 'fa-folder', 'name' => pht('Folder'), + 'image' => 'v3/folder.png', ), array( 'key' => 'timeline', 'icon' => 'fa-calendar', 'name' => pht('Timeline'), + 'image' => 'v3/calendar.png', ), array( 'key' => 'goal', 'icon' => 'fa-flag-checkered', 'name' => pht('Goal'), + 'image' => 'v3/flag.png', ), array( 'key' => 'release', 'icon' => 'fa-truck', 'name' => pht('Release'), + 'image' => 'v3/truck.png', ), array( 'key' => 'bugs', 'icon' => 'fa-bug', 'name' => pht('Bugs'), + 'image' => 'v3/bug.png', ), array( 'key' => 'cleanup', 'icon' => 'fa-trash-o', 'name' => pht('Cleanup'), + 'image' => 'v3/trash.png', ), array( 'key' => 'umbrella', 'icon' => 'fa-umbrella', 'name' => pht('Umbrella'), + 'image' => 'v3/umbrella.png', ), array( 'key' => 'communication', 'icon' => 'fa-envelope', 'name' => pht('Communication'), + 'image' => 'v3/mail.png', ), array( 'key' => 'organization', 'icon' => 'fa-building', 'name' => pht('Organization'), + 'image' => 'v3/organization.png', ), array( 'key' => 'infrastructure', 'icon' => 'fa-cloud', 'name' => pht('Infrastructure'), + 'image' => 'v3/cloud.png', ), array( 'key' => 'account', 'icon' => 'fa-credit-card', 'name' => pht('Account'), + 'image' => 'v3/creditcard.png', ), array( 'key' => 'experimental', 'icon' => 'fa-flask', 'name' => pht('Experimental'), + 'image' => 'v3/experimental.png', ), array( 'key' => 'milestone', 'icon' => 'fa-map-marker', 'name' => pht('Milestone'), 'special' => self::SPECIAL_MILESTONE, + 'image' => 'v3/marker.png', ), ); } @@ -149,6 +166,11 @@ final class PhabricatorProjectIconSet return idx($spec, 'name', null); } + public static function getIconImage($key) { + $spec = self::getIconSpec($key); + return idx($spec, 'image', 'v3/briefcase.png'); + } + private static function getIconSpec($key) { $icons = self::getIconSpecifications(); foreach ($icons as $icon) { @@ -190,6 +212,7 @@ final class PhabricatorProjectIconSet 'key' => 'string', 'name' => 'string', 'icon' => 'string', + 'image' => 'optional string', 'special' => 'optional string', 'disabled' => 'optional bool', 'default' => 'optional bool', @@ -239,6 +262,26 @@ final class PhabricatorProjectIconSet $is_disabled = idx($value, 'disabled'); + $image = idx($value, 'image'); + if ($image !== null) { + $builtin = idx($value, 'image'); + $builtin_map = id(new PhabricatorFilesOnDiskBuiltinFile()) + ->getProjectBuiltinFiles(); + $builtin_map = array_flip($builtin_map); + + $root = dirname(phutil_get_library_root('phabricator')); + $image = $root.'/resources/builtin/projects/'.$builtin; + + if (!array_key_exists($image, $builtin_map)) { + throw new Exception( + pht( + 'The project image ("%s") specified for ("%s") '. + 'was not found in the folder "resources/builtin/projects/".', + $builtin, + $key)); + } + } + if (idx($value, 'default')) { if ($default === null) { if ($is_disabled) { diff --git a/src/applications/project/query/PhabricatorProjectQuery.php b/src/applications/project/query/PhabricatorProjectQuery.php index 44055b7260..780f072678 100644 --- a/src/applications/project/query/PhabricatorProjectQuery.php +++ b/src/applications/project/query/PhabricatorProjectQuery.php @@ -358,8 +358,6 @@ final class PhabricatorProjectQuery protected function didFilterPage(array $projects) { if ($this->needImages) { - $default = null; - $file_phids = mpull($projects, 'getProfileImagePHID'); $file_phids = array_filter($file_phids); if ($file_phids) { @@ -376,12 +374,10 @@ final class PhabricatorProjectQuery foreach ($projects as $project) { $file = idx($files, $project->getProfileImagePHID()); if (!$file) { - if (!$default) { - $default = PhabricatorFile::loadBuiltin( - $this->getViewer(), - 'project.png'); - } - $file = $default; + $builtin = PhabricatorProjectIconSet::getIconImage( + $project->getIcon()); + $file = PhabricatorFile::loadBuiltin($this->getViewer(), + 'projects/'.$builtin); } $project->attachProfileImageFile($file); } diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php index f8a434e42b..eb6608eb57 100644 --- a/src/applications/repository/storage/PhabricatorRepository.php +++ b/src/applications/repository/storage/PhabricatorRepository.php @@ -700,6 +700,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO switch ($action) { case 'history': case 'graph': + case 'clone': case 'browse': case 'change': case 'lastmodified': @@ -818,6 +819,9 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO // it came from a URI. $uri = rawurldecode("{$path}{$commit}"); break; + case 'clone': + $uri = $this->getPathURI("/{$action}/"); + break; } if ($action == 'rendering-ref') { diff --git a/src/applications/uiexample/examples/PHUILeftRightExample.php b/src/applications/uiexample/examples/PHUILeftRightExample.php new file mode 100644 index 0000000000..46d96ddc38 --- /dev/null +++ b/src/applications/uiexample/examples/PHUILeftRightExample.php @@ -0,0 +1,72 @@ +getRequest(); + $user = $request->getUser(); + + $text = pht('This is a sample of some text.'); + $button = id(new PHUIButtonView()) + ->setTag('a') + ->setText(pht('Actions')) + ->setIcon('fa-bars'); + + $content1 = id(new PHUILeftRightView()) + ->setLeft($text) + ->setRight($button) + ->setVerticalAlign(PHUILeftRightView::ALIGN_TOP); + + $content2 = id(new PHUILeftRightView()) + ->setLeft($text) + ->setRight($button) + ->setVerticalAlign(PHUILeftRightView::ALIGN_MIDDLE); + + $content3 = id(new PHUILeftRightView()) + ->setLeft($text) + ->setRight($button) + ->setVerticalAlign(PHUILeftRightView::ALIGN_BOTTOM); + + + $head2 = id(new PHUIHeaderView()) + ->setHeader('Align Top') + ->addClass('ml'); + + $head3 = id(new PHUIHeaderView()) + ->setHeader(pht('Align Middle')) + ->addClass('ml'); + + $head4 = id(new PHUIHeaderView()) + ->setHeader(pht('Align Bottom')) + ->addClass('ml'); + + $wrap2 = id(new PHUIBoxView()) + ->appendChild($content1) + ->addMargin(PHUI::MARGIN_LARGE); + + $wrap3 = id(new PHUIBoxView()) + ->appendChild($content2) + ->addMargin(PHUI::MARGIN_LARGE); + + $wrap4 = id(new PHUIBoxView()) + ->appendChild($content3) + ->addMargin(PHUI::MARGIN_LARGE); + + return array( + $head2, + $wrap2, + $head3, + $wrap3, + $head4, + $wrap4, + ); + } +} diff --git a/src/applications/uiexample/examples/PhabricatorProjectBuiltinsExample.php b/src/applications/uiexample/examples/PhabricatorProjectBuiltinsExample.php new file mode 100644 index 0000000000..2cc89b56d5 --- /dev/null +++ b/src/applications/uiexample/examples/PhabricatorProjectBuiltinsExample.php @@ -0,0 +1,71 @@ +getRequest()->getUser(); + + $root = dirname(phutil_get_library_root('phabricator')); + $root = $root.'/resources/builtin/projects/v3/'; + + Javelin::initBehavior('phabricator-tooltips', array()); + + $map = array(); + $builtin_map = id(new FileFinder($root)) + ->withType('f') + ->withFollowSymlinks(true) + ->find(); + + $images = array(); + foreach ($builtin_map as $image) { + $file = PhabricatorFile::loadBuiltin($viewer, 'projects/v3/'.$image); + $images[$file->getPHID()] = array( + 'uri' => $file->getBestURI(), + 'tip' => 'v3/'.$image, + ); + } + + $buttons = array(); + foreach ($images as $phid => $spec) { + $button = javelin_tag( + 'img', + array( + 'height' => 100, + 'width' => 100, + 'src' => $spec['uri'], + 'style' => 'float: left; padding: 4px;', + 'sigil' => 'has-tooltip', + 'meta' => array( + 'tip' => $spec['tip'], + 'size' => 300, + ), + )); + + $buttons[] = $button; + } + + $wrap1 = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Images')) + ->appendChild($buttons) + ->addClass('grouped'); + + return phutil_tag( + 'div', + array(), + array( + $wrap1, + )); + } +} diff --git a/src/docs/user/support.diviner b/src/docs/user/support.diviner index 18de79a9a1..9dc06b15a3 100644 --- a/src/docs/user/support.diviner +++ b/src/docs/user/support.diviner @@ -30,19 +30,13 @@ Reporting Bugs ============== The upstream will accept **reproducible** bug reports in modern, first-party -production code running in reasonable environments. +production code running in reasonable environments. Before submitting a bug +report you **must update** to the latest version of Phabricator. This reduces +support costs on the upstream, please be mindful. To report bugs, see @{article:Contributing Bug Reports}. -Requesting Features -=================== - -The upstream accepts feature requests which **describe problems** you would -like Phabricator to be able to solve. - -To request features, see @{article:Contributing Feature Requests}. - Contributing ============ @@ -64,8 +58,8 @@ See [[ https://secure.phabricator.com/w/consulting/ | Consulting ]] for details. Helping individual installs navigate unique setup problems takes our time away from developing Phabricator, so we can not offer this service for free. -You may be able to get free help with these issues from the community. See -below for details. +You may be able to get free help with these issues from the +[[ https://phurl.io/u/discourse | community ]]. See below for details. Hosting @@ -82,42 +76,12 @@ endlessly to make installation a perplexing nightmare that none other than ourselves can hope to navigate. -Prioritization -============== +Phabricator Community +===================== -The upstream offers prioritization, a service which allows you to control -our roadmap and get features you're interested in built sooner at reasonable -rates. See -[[ https://secure.phabricator.com/w/prioritization/ | Prioritization ]] for -details. - - -Consulting -========== - -The upstream offers general-purpose consulting services. See -[[ https://secure.phabricator.com/w/consulting/ | Consulting ]] for details. - - -Community -========= - -These resources are not provided by the upstream. They are not official support -channels and you may not receive support here, or you may receive help which is -misleading or wrong. - -You may be able to get answers to questions on sites like -[[ http://stackoverflow.com | Stack Overflow ]], -[[ https://www.quora.com | Quora ]], -[[ https://jelly.co | Jelly ]], or -[[ https://twitter.com | Twitter ]]. The upstream occasionally participates on -these sites but these are not official support channels and you should not -expect to receive a response. - -There is a -[[ https://secure.phabricator.com/conpherence/1336/ | General Chat ]] -Conpherence room on this install, and you can ask questions in -[[ https://secure.phabricator.com/ponder/ | Ponder ]]. These -are not upstream support channels and you may not receive a response to -questions, but someone in the community may be able to point you in the right -direction. +We provide hosting for a +[[ https://phurl.io/u/discourse | Discussion Forum ]] +where admins and users help and answer questions from other community members. +Upstream developers may occasionally participate, but this is mostly +a user to user community. If you run into general problems, but are not +interested in paid support, this is the main place to find help. diff --git a/src/view/form/control/AphrontFormTypeaheadControl.php b/src/view/form/control/AphrontFormTypeaheadControl.php index e4bee7c1ca..1e859ee132 100644 --- a/src/view/form/control/AphrontFormTypeaheadControl.php +++ b/src/view/form/control/AphrontFormTypeaheadControl.php @@ -3,6 +3,7 @@ final class AphrontFormTypeaheadControl extends AphrontFormControl { private $hardpointID; + private $placeholder; public function setHardpointID($hardpoint_id) { $this->hardpointID = $hardpoint_id; @@ -13,6 +14,11 @@ final class AphrontFormTypeaheadControl extends AphrontFormControl { return $this->hardpointID; } + public function setPlaceholder($placeholder) { + $this->placeholder = $placeholder; + return $this; + } + protected function getCustomControlClass() { return 'aphront-form-control-typeahead'; } @@ -30,6 +36,7 @@ final class AphrontFormTypeaheadControl extends AphrontFormControl { 'type' => 'text', 'name' => $this->getName(), 'value' => $this->getValue(), + 'placeholder' => $this->placeholder, 'disabled' => $this->getDisabled() ? 'disabled' : null, 'autocomplete' => 'off', 'id' => $this->getID(), diff --git a/src/view/phui/PHUILeftRightView.php b/src/view/phui/PHUILeftRightView.php new file mode 100644 index 0000000000..c3873c4899 --- /dev/null +++ b/src/view/phui/PHUILeftRightView.php @@ -0,0 +1,51 @@ +left = $left; + return $this; + } + + public function setRight($right) { + $this->right = $right; + return $this; + } + + public function setVerticalAlign($align) { + $this->verticalAlign = $align; + return $this; + } + + protected function getTagAttributes() { + require_celerity_resource('phui-left-right-css'); + + $classes = array(); + $classes[] = 'phui-left-right-view'; + + if ($this->verticalAlign) { + $classes[] = 'phui-lr-view-'.$this->verticalAlign; + } + + return array('class' => implode(' ', $classes)); + } + + protected function getTagName() { + return 'div'; + } + + protected function getTagContent() { + $left = phutil_tag_div('phui-left-view', $this->left); + $right = phutil_tag_div('phui-right-view', $this->right); + + return phutil_tag_div('phui-lr-container', array($left, $right)); + } +} diff --git a/src/view/phui/PHUIObjectBoxView.php b/src/view/phui/PHUIObjectBoxView.php index 26044ef3a0..0089e8e26e 100644 --- a/src/view/phui/PHUIObjectBoxView.php +++ b/src/view/phui/PHUIObjectBoxView.php @@ -302,7 +302,9 @@ final class PHUIObjectBoxView extends AphrontTagView { $pager = null; if ($this->pager) { - $pager = phutil_tag_div('phui-object-box-pager', $this->pager); + if ($this->pager->willShowPagingControls()) { + $pager = phutil_tag_div('phui-object-box-pager', $this->pager); + } } $content = array( diff --git a/webroot/rsrc/css/application/differential/changeset-view.css b/webroot/rsrc/css/application/differential/changeset-view.css index bf532d0eb3..98c8f099ba 100644 --- a/webroot/rsrc/css/application/differential/changeset-view.css +++ b/webroot/rsrc/css/application/differential/changeset-view.css @@ -402,10 +402,6 @@ tr.differential-inline-loading { line-height: 28px; } -.diff-banner .phui-icon-view { - margin-right: 4px; -} - .diff-banner-path { color: {$greytext}; } diff --git a/webroot/rsrc/css/application/diffusion/diffusion-icons.css b/webroot/rsrc/css/application/diffusion/diffusion-icons.css index 8edc034975..072db01660 100644 --- a/webroot/rsrc/css/application/diffusion/diffusion-icons.css +++ b/webroot/rsrc/css/application/diffusion/diffusion-icons.css @@ -20,6 +20,7 @@ input.diffusion-clone-uri { .diffusion-browse-name { margin-left: 8px; + letter-spacing: 0.02em; } .diffusion-link-icon + .diffusion-link-icon { diff --git a/webroot/rsrc/css/application/diffusion/diffusion-history.css b/webroot/rsrc/css/application/diffusion/diffusion.css similarity index 67% rename from webroot/rsrc/css/application/diffusion/diffusion-history.css rename to webroot/rsrc/css/application/diffusion/diffusion.css index f4a51f7b56..3d81cd5c62 100644 --- a/webroot/rsrc/css/application/diffusion/diffusion-history.css +++ b/webroot/rsrc/css/application/diffusion/diffusion.css @@ -1,7 +1,48 @@ /** - * @provides diffusion-history-css + * @provides diffusion-css */ +/* - Home Styles ------------------------------------------------------------*/ + +.diffusion-profile-header.phui-profile-header .phui-header-col3 { + vertical-align: middle; +} + +.diffusion-profile-header .phui-header-action-links a.button { + display: block; +} + +.diffusion-action-bar { + margin-bottom: 16px; +} + +.diffusion-profile-locate .phui-form-view { + margin: 0; + padding: 0; +} + +.diffusion-profile-locate .phui-form-view .aphront-form-control { + padding: 0; +} + +.diffusion-profile-locate .phui-form-view .aphront-form-input { + margin: 0; + width: 480px; +} + +.device .diffusion-profile-locate .phui-form-view .aphront-form-input { + margin: 0; + width: 100%; +} + +.diffusion-profile-description.phui-object-box { + padding: 0; +} + +.device-phone .diffusion-profile-description.phui-object-box { + padding: 0; +} + /* - List Styles ------------------------------------------------------------*/ .diffusion-history-list .phui-oi-link { @@ -48,6 +89,16 @@ margin-right: 4px; } +/* - Browse Styles ----------------------------------------------------------*/ + +.diffusion-browse-table .commit-detail { + padding-left: 32px; +} + +.diffusion-browse-table .commit-detail a { + color: {$darkbluetext}; +} + /* - Phone Style ------------------------------------------------------------*/ .device-phone.diffusion-history-view .phui-two-column-view diff --git a/webroot/rsrc/css/phui/phui-icon.css b/webroot/rsrc/css/phui/phui-icon.css index 5fd7fd97bc..acc7818765 100644 --- a/webroot/rsrc/css/phui/phui-icon.css +++ b/webroot/rsrc/css/phui/phui-icon.css @@ -45,6 +45,10 @@ img.phui-image-disabled { filter: grayscale(100%); } +.phui-icon-view.bluetext { + color: {$bluetext}; +} + /* - Icon in a Circle ------------------------------------------------------- */ .phui-icon-circle { diff --git a/webroot/rsrc/css/phui/phui-left-right.css b/webroot/rsrc/css/phui/phui-left-right.css new file mode 100644 index 0000000000..2d260758b4 --- /dev/null +++ b/webroot/rsrc/css/phui/phui-left-right.css @@ -0,0 +1,32 @@ +/** + * @provides phui-left-right-css + */ + +.phui-left-right-view { + display: table; + width: 100%; +} + +.phui-lr-container { + display: table-row; +} + +.phui-left-view { + display: table-cell; + text-align: left; +} + +.phui-right-view { + display: table-cell; + text-align: right; +} + +.phui-lr-view-top .phui-left-view, +.phui-lr-view-top .phui-right-view { + vertical-align: top; +} + +.phui-lr-view-bottom .phui-left-view, +.phui-lr-view-bottom .phui-right-view { + vertical-align: bottom; +} diff --git a/webroot/rsrc/js/application/diff/DiffChangesetList.js b/webroot/rsrc/js/application/diff/DiffChangesetList.js index 808527876c..89a18a9a8b 100644 --- a/webroot/rsrc/js/application/diff/DiffChangesetList.js +++ b/webroot/rsrc/js/application/diff/DiffChangesetList.js @@ -1610,7 +1610,7 @@ JX.install('DiffChangesetList', { _getMenuButton: function() { if (!this._menuButton) { var button = new JX.PHUIXButtonView() - .setIcon('fa-gear') + .setIcon('fa-bars') .setButtonType(JX.PHUIXButtonView.BUTTONTYPE_SIMPLE); var dropdown = new JX.PHUIXDropdownMenu(button.getNode()); @@ -1659,7 +1659,7 @@ JX.install('DiffChangesetList', { list.addItem( new JX.PHUIXActionView() - .setIcon('fa-link') + .setIcon('fa-external-link') .setName(pht('List Inline Comments')) .setHref(this.getInlineListURI())); }