From 0b3117bb684eec75a4037649764a77215d78ec2e Mon Sep 17 00:00:00 2001 From: Chad Little Date: Sun, 9 Jul 2017 06:40:51 -0700 Subject: [PATCH 01/16] Fix comparison check for SVN in browsing Diffusion Summary: Fixes T12905. Missed setting this variable. Test Plan: Browse an SVN repository. Reviewers: epriestley Subscribers: Korvin Maniphest Tasks: T12905 Differential Revision: https://secure.phabricator.com/D18190 --- .../diffusion/controller/DiffusionBrowseController.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/applications/diffusion/controller/DiffusionBrowseController.php b/src/applications/diffusion/controller/DiffusionBrowseController.php index 3fa9e62948..06c8336f5c 100644 --- a/src/applications/diffusion/controller/DiffusionBrowseController.php +++ b/src/applications/diffusion/controller/DiffusionBrowseController.php @@ -1667,6 +1667,7 @@ final class DiffusionBrowseController extends DiffusionController { $repository = $drequest->getRepository(); $history_uri = $drequest->generateURI(array('action' => 'history')); $behind_head = $drequest->getSymbolicCommit(); + $compare = null; $head_uri = $drequest->generateURI( array( 'commit' => '', @@ -1771,11 +1772,11 @@ final class DiffusionBrowseController extends DiffusionController { } $header = id(new PHUIHeaderView()) - ->setHeader(pht('Recently Open Revisions')) - ->setHeaderIcon('fa-gear'); + ->setHeader(pht('Recently Open Revisions')); $view = id(new DifferentialRevisionListView()) ->setHeader($header) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setRevisions($revisions) ->setUser($viewer); From 0bd1dfd52473306c7e9230a0f5b60191c3cfa176 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Sun, 9 Jul 2017 09:00:02 -0700 Subject: [PATCH 02/16] Add 8 more project images to builtins Summary: More pretty images. Test Plan: Set a robot as image for security project. So pretty. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D18191 --- resources/builtin/projects/v3/book.png | Bin 0 -> 3411 bytes resources/builtin/projects/v3/clipboard.png | Bin 0 -> 4737 bytes resources/builtin/projects/v3/lightbulb.png | Bin 0 -> 6435 bytes resources/builtin/projects/v3/marker.png | Bin 0 -> 8125 bytes resources/builtin/projects/v3/piechart.png | Bin 0 -> 11337 bytes resources/builtin/projects/v3/robot.png | Bin 0 -> 9119 bytes resources/builtin/projects/v3/rocket.png | Bin 0 -> 11037 bytes resources/builtin/projects/v3/sitemap.png | Bin 0 -> 4336 bytes .../PhabricatorProjectEditPictureController.php | 8 ++++++++ 9 files changed, 8 insertions(+) create mode 100644 resources/builtin/projects/v3/book.png create mode 100644 resources/builtin/projects/v3/clipboard.png create mode 100644 resources/builtin/projects/v3/lightbulb.png create mode 100644 resources/builtin/projects/v3/marker.png create mode 100644 resources/builtin/projects/v3/piechart.png create mode 100644 resources/builtin/projects/v3/robot.png create mode 100644 resources/builtin/projects/v3/rocket.png create mode 100644 resources/builtin/projects/v3/sitemap.png diff --git a/resources/builtin/projects/v3/book.png b/resources/builtin/projects/v3/book.png new file mode 100644 index 0000000000000000000000000000000000000000..eceb0bfb4d7c52863963ff876b96c190a04a6cb4 GIT binary patch literal 3411 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 F{0GGBJ@fzo literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/v3/clipboard.png b/resources/builtin/projects/v3/clipboard.png new file mode 100644 index 0000000000000000000000000000000000000000..60e2acd4f43b697e427ee12322cab45ee83a9bf3 GIT binary patch literal 4737 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 BfY1N{ literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/v3/lightbulb.png b/resources/builtin/projects/v3/lightbulb.png new file mode 100644 index 0000000000000000000000000000000000000000..1aba0d32f31aaa735d2d693b6408b991844ea507 GIT binary patch literal 6435 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 literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/v3/piechart.png b/resources/builtin/projects/v3/piechart.png new file mode 100644 index 0000000000000000000000000000000000000000..4c707ed6ffc177b1f5d7b3c4ac6a2039b9fdaacf GIT binary patch literal 11337 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 Rr}^Iy>M$LZ8YLU#{{U8yX8HgC literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/v3/robot.png b/resources/builtin/projects/v3/robot.png new file mode 100644 index 0000000000000000000000000000000000000000..317544f2dd8447e401b6b3df1f78dccf171541ec GIT binary patch literal 9119 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 literal 0 HcmV?d00001 diff --git a/resources/builtin/projects/v3/rocket.png b/resources/builtin/projects/v3/rocket.png new file mode 100644 index 0000000000000000000000000000000000000000..f5a758ff815d8cec16bdca7dee500de4bbde7adc GIT binary patch literal 11037 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

YPya(}dajO4BEY+w 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 Date: Sat, 8 Jul 2017 19:54:23 -0700 Subject: [PATCH 03/16] Simplify Diffusion Browse Table Summary: Cleans up colors, removes commit hash and links the text instead. Also unsure how valuable "lint" column is here, but left it. I'd maybe like to understand that workflow since it just seems like clutter overall. Also Fixes T12905 Test Plan: Review Phabricator, hg, and a few other test repositories locally. Holler if anything here seems bad, but this feels easier to read and use to me. {F5038425} Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Maniphest Tasks: T12905 Differential Revision: https://secure.phabricator.com/D18189 --- resources/celerity/map.php | 16 ++++++------ .../constants/DifferentialChangeType.php | 14 +++++----- .../DiffusionLastModifiedController.php | 6 ++++- .../view/DiffusionBrowseTableView.php | 26 +++++-------------- .../diffusion/view/DiffusionView.php | 13 ++++++++++ .../diffusion/diffusion-history.css | 10 +++++++ .../application/diffusion/diffusion-icons.css | 1 + webroot/rsrc/css/phui/phui-icon.css | 4 +++ 8 files changed, 55 insertions(+), 35 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 6a3b8778e6..939b48a643 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', + 'diffusion.pkg.css' => 'a2d17c7d', 'diffusion.pkg.js' => '6134c5a1', 'favicon.ico' => '30672e08', 'maniphest.pkg.css' => '4845691a', @@ -71,8 +71,8 @@ return array( '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-history.css' => '898ed727', + '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', @@ -161,7 +161,7 @@ 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', @@ -570,8 +570,8 @@ return array( '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-history-css' => '898ed727', + 'diffusion-icons-css' => '0c15255e', 'diffusion-readme-css' => '419dd5b6', 'diffusion-repository-css' => 'ee6f20ec', 'diffusion-source-css' => '750add59', @@ -849,7 +849,7 @@ 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', 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/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/view/DiffusionBrowseTableView.php b/src/applications/diffusion/view/DiffusionBrowseTableView.php index ffc5ce61ed..bd53cf97a1 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-history-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/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/webroot/rsrc/css/application/diffusion/diffusion-history.css b/webroot/rsrc/css/application/diffusion/diffusion-history.css index f4a51f7b56..7339d05ac1 100644 --- a/webroot/rsrc/css/application/diffusion/diffusion-history.css +++ b/webroot/rsrc/css/application/diffusion/diffusion-history.css @@ -48,6 +48,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/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/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 { From 250aaabd6484e2742512dc285434a07f36d70fe2 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Sun, 9 Jul 2017 11:15:46 -0700 Subject: [PATCH 04/16] Choose default project image by icon Summary: Builds out a map for icon->image in Projects, selects the icon's image as the default project image if there is no custom image chosen by the user. Test Plan: Select various icons, see image change. Test choose picture, pick a new image. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D18174 --- .../PhabricatorFilesOnDiskBuiltinFile.php | 16 +++++++ .../PhabricatorProjectConfigOptions.php | 2 + ...habricatorProjectEditPictureController.php | 5 ++- .../PhabricatorProjectTransactionEditor.php | 32 -------------- .../icon/PhabricatorProjectIconSet.php | 42 +++++++++++++++++++ .../project/query/PhabricatorProjectQuery.php | 12 ++---- 6 files changed, 68 insertions(+), 41 deletions(-) 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/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 f8f1d532a9..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(); 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..f487b216f3 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,25 @@ final class PhabricatorProjectIconSet $is_disabled = idx($value, 'disabled'); + if (idx($value, 'image')) { + $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); } From b4aedab955438fec74b1231d53b9c5a925598fb5 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Sun, 9 Jul 2017 12:25:27 -0700 Subject: [PATCH 05/16] Fix sitemap image Summary: Re-export sitemap image. Test Plan: look carefully Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D18192 --- resources/builtin/projects/v3/sitemap.png | Bin 4336 -> 4336 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/resources/builtin/projects/v3/sitemap.png b/resources/builtin/projects/v3/sitemap.png index 1812d13416403fc8899ea75efc84562f314d0c6d..8ee6e232b4885d6575767f75380182fb7d69fff7 100644 GIT binary patch literal 4336 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 XhPe?U1_~UO>H7LQ#@c0?h=~6I4BOMy literal 4336 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 Date: Sun, 9 Jul 2017 18:38:38 -0700 Subject: [PATCH 06/16] Move actions into Diffusion header Summary: This moves actions into the Diffusion main header, removes the locate file box, and widens description and cloning details. Projects are not currently in this layout, but will follow up in another diff. Trying to keep these changes small and iterative. Test Plan: Locate some files, test actions dropdown, repository with and without description. Also tablet, mobile layouts. {F5040026} Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D18193 --- resources/celerity/map.php | 4 +- .../DiffusionRepositoryController.php | 46 ++++++++++--------- .../view/DiffusionBranchListView.php | 2 +- .../view/DiffusionBrowseTableView.php | 2 +- .../view/DiffusionCommitListView.php | 2 +- .../view/DiffusionHistoryListView.php | 2 +- .../diffusion/view/DiffusionTagListView.php | 2 +- .../control/AphrontFormTypeaheadControl.php | 7 +++ .../{diffusion-history.css => diffusion.css} | 39 +++++++++++++++- 9 files changed, 76 insertions(+), 30 deletions(-) rename webroot/rsrc/css/application/diffusion/{diffusion-history.css => diffusion.css} (74%) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 939b48a643..4dc65888b9 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -71,11 +71,11 @@ return array( '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' => '898ed727', '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' => '08991f7e', 'rsrc/css/application/feed/feed.css' => 'ecd4ec57', 'rsrc/css/application/files/global-drag-and-drop.css' => '5c1b47c2', 'rsrc/css/application/flag/flag.css' => 'bba8f811', @@ -570,7 +570,7 @@ return array( 'differential-revision-history-css' => '0e8eb855', 'differential-revision-list-css' => 'f3c47d33', 'differential-table-of-contents-css' => 'ae4b7a55', - 'diffusion-history-css' => '898ed727', + 'diffusion-css' => '08991f7e', 'diffusion-icons-css' => '0c15255e', 'diffusion-readme-css' => '419dd5b6', 'diffusion-repository-css' => 'ee6f20ec', diff --git a/src/applications/diffusion/controller/DiffusionRepositoryController.php b/src/applications/diffusion/controller/DiffusionRepositoryController.php index d8451db2db..1db5716f6c 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,13 @@ 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; @@ -88,14 +92,13 @@ final class DiffusionRepositoryController extends DiffusionController { $view = id(new PHUITwoColumnView()) ->setHeader($header) - ->setCurtain($curtain) ->setTabs($tabs) - ->setMainColumn(array( + ->setFooter(array( + $locate_file, $property_table, $description, - $locate_file, - )) - ->setFooter($content); + $content, + )); return $this->newPage() ->setTitle( @@ -236,7 +239,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 +258,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 +276,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,9 +296,8 @@ 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; } @@ -455,15 +460,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( 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 bd53cf97a1..48729d0669 100644 --- a/src/applications/diffusion/view/DiffusionBrowseTableView.php +++ b/src/applications/diffusion/view/DiffusionBrowseTableView.php @@ -20,7 +20,7 @@ final class DiffusionBrowseTableView extends DiffusionView { public function render() { $request = $this->getDiffusionRequest(); $repository = $request->getRepository(); - require_celerity_resource('diffusion-history-css'); + require_celerity_resource('diffusion-css'); $base_path = trim($request->getPath(), '/'); if ($base_path) { 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/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/webroot/rsrc/css/application/diffusion/diffusion-history.css b/webroot/rsrc/css/application/diffusion/diffusion.css similarity index 74% rename from webroot/rsrc/css/application/diffusion/diffusion-history.css rename to webroot/rsrc/css/application/diffusion/diffusion.css index 7339d05ac1..599f229152 100644 --- a/webroot/rsrc/css/application/diffusion/diffusion-history.css +++ b/webroot/rsrc/css/application/diffusion/diffusion.css @@ -1,7 +1,44 @@ /** - * @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-profile-locate .phui-form-view { + margin: 0 0 16px 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 { From 5f1a359a92de5bcd2372cb60257b5ad1a5bbcca6 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Mon, 10 Jul 2017 11:20:03 -0700 Subject: [PATCH 07/16] Add a UIExamples page for new project image builtins Summary: Adds a page to view all and their path in UIExamples. Test Plan: Review page in UIExamples, hover over image for path. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D18196 --- src/__phutil_library_map__.php | 2 + .../PhabricatorProjectBuiltinsExample.php | 71 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 src/applications/uiexample/examples/PhabricatorProjectBuiltinsExample.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 095759a351..d99eb9e2f1 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -3612,6 +3612,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', @@ -9063,6 +9064,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/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, + )); + } +} From af71c990eee1754fcaf9f9fc0683a55f79c85194 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Mon, 10 Jul 2017 12:01:13 -0700 Subject: [PATCH 08/16] Test 0 and "" cases in Project Icon Config Summary: Better validation for setting a default image in project.icon Test Plan: Test adding `"0"` and `""` as image options in project.icon, see error. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D18197 --- src/applications/project/icon/PhabricatorProjectIconSet.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/applications/project/icon/PhabricatorProjectIconSet.php b/src/applications/project/icon/PhabricatorProjectIconSet.php index f487b216f3..b128a35cad 100644 --- a/src/applications/project/icon/PhabricatorProjectIconSet.php +++ b/src/applications/project/icon/PhabricatorProjectIconSet.php @@ -262,7 +262,8 @@ final class PhabricatorProjectIconSet $is_disabled = idx($value, 'disabled'); - if (idx($value, 'image')) { + $image = idx($value, 'image'); + if ($image !== null) { $builtin = idx($value, 'image'); $builtin_map = id(new PhabricatorFilesOnDiskBuiltinFile()) ->getProjectBuiltinFiles(); From b987b4dd64f54c5bbd8deccc62564589f463ed5b Mon Sep 17 00:00:00 2001 From: Chad Little Date: Mon, 10 Jul 2017 16:01:43 -0700 Subject: [PATCH 09/16] Rudamentary PHUILeftRightView Summary: First pass at providing a skeleton framework for laying out basic items in a left/right view. Will likely add some mobile-responsive options. Test Plan: UIExamples Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D18200 --- resources/celerity/map.php | 2 + src/__phutil_library_map__.php | 4 ++ .../examples/PHUILeftRightExample.php | 72 +++++++++++++++++++ src/view/phui/PHUILeftRightView.php | 51 +++++++++++++ webroot/rsrc/css/phui/phui-left-right.css | 32 +++++++++ 5 files changed, 161 insertions(+) create mode 100644 src/applications/uiexample/examples/PHUILeftRightExample.php create mode 100644 src/view/phui/PHUILeftRightView.php create mode 100644 webroot/rsrc/css/phui/phui-left-right.css diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 4dc65888b9..50200049a5 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -166,6 +166,7 @@ return array( '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', @@ -855,6 +856,7 @@ return array( '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', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index d99eb9e2f1..6d24871583 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1773,6 +1773,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', @@ -6927,6 +6929,8 @@ phutil_register_library_map(array( 'PHUIInfoView' => 'AphrontTagView', 'PHUIInvisibleCharacterTestCase' => 'PhabricatorTestCase', 'PHUIInvisibleCharacterView' => 'AphrontView', + 'PHUILeftRightExample' => 'PhabricatorUIExample', + 'PHUILeftRightView' => 'AphrontTagView', 'PHUIListExample' => 'PhabricatorUIExample', 'PHUIListItemView' => 'AphrontTagView', 'PHUIListView' => 'AphrontTagView', 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/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/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; +} From a6b550ba0394284441ee55d11e276a05eb568ad9 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Mon, 10 Jul 2017 20:20:09 -0700 Subject: [PATCH 10/16] Move Clone Repository to Dialog Summary: This moves the clone details on the Repository Home to a button / dialog. Functionally this is to pull content on the page way up, while giving full space to all the clone options. I think we can build this into some FancyJS if needed, but this seems to clean ui the UI dramatically with little overhead. I don't want to attempt the JS dropdown unless we're sure that's the best path (it exposes the most common URI by default, saving a click). Test Plan: Tested hg, svn, git repositories and the raw URL page. Test close button. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D18203 --- src/__phutil_library_map__.php | 2 + .../PhabricatorDiffusionApplication.php | 1 + .../controller/DiffusionCloneController.php | 122 ++++++++++++++ .../DiffusionRepositoryController.php | 151 +++--------------- .../storage/PhabricatorRepository.php | 4 + 5 files changed, 152 insertions(+), 128 deletions(-) create mode 100644 src/applications/diffusion/controller/DiffusionCloneController.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 6d24871583..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', @@ -5610,6 +5611,7 @@ phutil_register_library_map(array( 'DiffusionCachedResolveRefsQuery' => 'DiffusionLowLevelQuery', 'DiffusionChangeController' => 'DiffusionController', 'DiffusionChangeHeraldFieldGroup' => 'HeraldFieldGroup', + 'DiffusionCloneController' => 'DiffusionController', 'DiffusionCloneURIView' => 'AphrontView', 'DiffusionCommandEngine' => 'Phobject', 'DiffusionCommandEngineTestCase' => 'PhabricatorTestCase', 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/DiffusionRepositoryController.php b/src/applications/diffusion/controller/DiffusionRepositoryController.php index 1db5716f6c..08f77f8c3e 100644 --- a/src/applications/diffusion/controller/DiffusionRepositoryController.php +++ b/src/applications/diffusion/controller/DiffusionRepositoryController.php @@ -27,7 +27,6 @@ final class DiffusionRepositoryController extends DiffusionController { $crumbs->setBorder(true); $header = $this->buildHeaderView($repository); - $property_table = $this->buildPropertiesTable($repository); $actions = $this->buildActionList($repository); $description = $this->buildDescriptionView($repository); $locate_file = $this->buildLocateFile(); @@ -90,12 +89,28 @@ final class DiffusionRepositoryController extends DiffusionController { $tabs = $this->buildTabsView('home'); + $clone_uri = $drequest->generateURI( + array( + 'action' => 'clone', + )); + + $clone_button = id(new PHUIButtonView()) + ->setTag('a') + ->setText('Clone') + ->setColor(PHUIButtonView::GREEN) + ->setIcon('fa-download') + ->setWorkflow(true) + ->setHref($clone_uri); + + $bar = id(new PHUILeftRightView()) + ->setLeft($locate_file) + ->setRight($clone_button); + $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setTabs($tabs) ->setFooter(array( - $locate_file, - $property_table, + $bar, $description, $content, )); @@ -302,87 +317,6 @@ final class DiffusionRepositoryController extends DiffusionController { 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, @@ -504,52 +438,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/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') { From 7408483c2f02d955b07b36c278f21721dfe72e05 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Tue, 11 Jul 2017 14:33:17 -0700 Subject: [PATCH 11/16] Hide Pager border if no pager exists Summary: I guess we have this magical method that tells me if a pager is coming down the render pipe. Huzzah. Test Plan: Test Branches page in Diffusion, see no pager border. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D18202 --- src/view/phui/PHUIObjectBoxView.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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( From db57da0f7472b57e17f53ce604e4c8b0350f0a56 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Tue, 11 Jul 2017 19:46:58 -0700 Subject: [PATCH 12/16] Fix SVN form_box error Summary: Fixes T12915. Test Plan: Test a SVN repository locally, ensure page loads. Reviewers: epriestley Subscribers: Korvin Maniphest Tasks: T12915 Differential Revision: https://secure.phabricator.com/D18207 --- .../diffusion/controller/DiffusionRepositoryController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/diffusion/controller/DiffusionRepositoryController.php b/src/applications/diffusion/controller/DiffusionRepositoryController.php index 08f77f8c3e..a3ea11f7fc 100644 --- a/src/applications/diffusion/controller/DiffusionRepositoryController.php +++ b/src/applications/diffusion/controller/DiffusionRepositoryController.php @@ -371,7 +371,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', From 0c4cff28df73632ba94410cf6ac33418186f9ea6 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Tue, 11 Jul 2017 20:37:06 -0700 Subject: [PATCH 13/16] Clean up NUX a bit on Diffusion Summary: Just some cleanup. Make sure action-bar has consistent space if locate is there or not, hide tabs if repository has no content. Use clone or checkout language depending on SCM. Fixes T12915. Test Plan: Test git, hg, svn blank states. {F5042707} Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Maniphest Tasks: T12915 Differential Revision: https://secure.phabricator.com/D18208 --- resources/celerity/map.php | 4 ++-- .../controller/DiffusionRepositoryController.php | 16 +++++++++++++--- .../rsrc/css/application/diffusion/diffusion.css | 6 +++++- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 50200049a5..96744377e2 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -75,7 +75,7 @@ return array( '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' => '08991f7e', + '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', @@ -571,7 +571,7 @@ return array( 'differential-revision-history-css' => '0e8eb855', 'differential-revision-list-css' => 'f3c47d33', 'differential-table-of-contents-css' => 'ae4b7a55', - 'diffusion-css' => '08991f7e', + 'diffusion-css' => '8d01932f', 'diffusion-icons-css' => '0c15255e', 'diffusion-readme-css' => '419dd5b6', 'diffusion-repository-css' => 'ee6f20ec', diff --git a/src/applications/diffusion/controller/DiffusionRepositoryController.php b/src/applications/diffusion/controller/DiffusionRepositoryController.php index a3ea11f7fc..6def808cff 100644 --- a/src/applications/diffusion/controller/DiffusionRepositoryController.php +++ b/src/applications/diffusion/controller/DiffusionRepositoryController.php @@ -94,9 +94,15 @@ final class DiffusionRepositoryController extends DiffusionController { 'action' => 'clone', )); + if ($repository->isSVN()) { + $clone_text = pht('Checkout'); + } else { + $clone_text = pht('Clone'); + } + $clone_button = id(new PHUIButtonView()) ->setTag('a') - ->setText('Clone') + ->setText($clone_text) ->setColor(PHUIButtonView::GREEN) ->setIcon('fa-download') ->setWorkflow(true) @@ -104,17 +110,21 @@ final class DiffusionRepositoryController extends DiffusionController { $bar = id(new PHUILeftRightView()) ->setLeft($locate_file) - ->setRight($clone_button); + ->setRight($clone_button) + ->addClass('diffusion-action-bar'); $view = id(new PHUITwoColumnView()) ->setHeader($header) - ->setTabs($tabs) ->setFooter(array( $bar, $description, $content, )); + if ($page_has_content) { + $view->setTabs($tabs); + } + return $this->newPage() ->setTitle( array( diff --git a/webroot/rsrc/css/application/diffusion/diffusion.css b/webroot/rsrc/css/application/diffusion/diffusion.css index 599f229152..3d81cd5c62 100644 --- a/webroot/rsrc/css/application/diffusion/diffusion.css +++ b/webroot/rsrc/css/application/diffusion/diffusion.css @@ -12,8 +12,12 @@ display: block; } +.diffusion-action-bar { + margin-bottom: 16px; +} + .diffusion-profile-locate .phui-form-view { - margin: 0 0 16px 0; + margin: 0; padding: 0; } From 565c49ad0ee8e4601301ef675da94ee744a6954e Mon Sep 17 00:00:00 2001 From: Chad Little Date: Wed, 12 Jul 2017 15:21:54 -0700 Subject: [PATCH 14/16] Minor touchup on diff banner Summary: Remove extra icon spacing, swap icons. Test Plan: Review a diff with comments in sandbox. Try dropdown. Follow links Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D18216 --- resources/celerity/map.php | 26 +++++++++---------- .../differential/changeset-view.css | 4 --- .../js/application/diff/DiffChangesetList.js | 4 +-- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 96744377e2..b418ffcdb4 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -12,8 +12,8 @@ return array( 'core.pkg.css' => '7ae9e755', 'core.pkg.js' => '5d80e0db', 'darkconsole.pkg.js' => '1f9a31bc', - 'differential.pkg.css' => '4ec4a37a', - 'differential.pkg.js' => 'd4ab0e81', + 'differential.pkg.css' => 'b00f573e', + 'differential.pkg.js' => '1d80ecc6', 'diffusion.pkg.css' => 'a2d17c7d', 'diffusion.pkg.js' => '6134c5a1', 'favicon.ico' => '30672e08', @@ -64,7 +64,7 @@ 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', @@ -398,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', @@ -564,7 +564,7 @@ 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', @@ -778,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', @@ -1146,6 +1146,9 @@ return array( 'javelin-util', 'javelin-uri', ), + '3cef17bd' => array( + 'phui-inline-comment-view-css', + ), '3dbf94d5' => array( 'javelin-behavior', 'javelin-dom', @@ -1480,10 +1483,6 @@ return array( 'javelin-behavior', 'javelin-quicksand', ), - '79de07c6' => array( - 'javelin-install', - 'phuix-button-view', - ), '7a68dda3' => array( 'owners-path-editor', 'javelin-behavior', @@ -1815,9 +1814,6 @@ return array( 'javelin-dom', 'javelin-util', ), - 'b5e6be7f' => array( - 'phui-inline-comment-view-css', - ), 'b6993408' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1961,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/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/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())); } From b8cd5b0eb89a29d1e1f365818894c02f5c8c5d3d Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 12 Jul 2017 14:47:19 -0700 Subject: [PATCH 15/16] Use a less-esoteric spelling of "capabilities" in several places Summary: This spelling can definitely feel a little overplayed at times, but I still think it's a gold standard in spellings of "capabilities". Test Plan: Felt old and uncool. Reviewers: chad Reviewed By: chad Differential Revision: https://secure.phabricator.com/D18215 --- .../diffusion/protocol/DiffusionMercurialWireProtocol.php | 4 ++-- .../policy/controller/PhabricatorPolicyExplainController.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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/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); } From bddd1da053e86b1b7a78236f4115fa2903720d1f Mon Sep 17 00:00:00 2001 From: Chad Little Date: Thu, 13 Jul 2017 10:36:34 -0700 Subject: [PATCH 16/16] Update Support diviner document Summary: This updates the support document, specifically, scopes down feature requests, updates community links, and other wordsmithing. Unsure where to direct bug reports right now, but we'll have something soon? Test Plan: Read carefully Reviewers: epriestley Reviewed By: epriestley Subscribers: Luke081515.2, Korvin Differential Revision: https://secure.phabricator.com/D18218 --- src/docs/user/support.diviner | 62 ++++++++--------------------------- 1 file changed, 13 insertions(+), 49 deletions(-) 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.