diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -70,6 +70,7 @@ 'rsrc/css/application/feed/feed.css' => 'ecd4ec57', 'rsrc/css/application/files/global-drag-and-drop.css' => '5c1b47c2', 'rsrc/css/application/flag/flag.css' => '5337623f', + 'rsrc/css/application/guides/guides.css' => '1d5414e5', 'rsrc/css/application/harbormaster/harbormaster.css' => 'f491c9f4', 'rsrc/css/application/herald/herald-test.css' => 'a52e323e', 'rsrc/css/application/herald/herald.css' => 'dc31f6e9', @@ -127,7 +128,7 @@ 'rsrc/css/phui/phui-box.css' => '5c8387cf', 'rsrc/css/phui/phui-button.css' => '4a5fbe3d', 'rsrc/css/phui/phui-chart.css' => '6bf6f78e', - 'rsrc/css/phui/phui-cms.css' => '33064557', + 'rsrc/css/phui/phui-cms.css' => 'be43c8a8', 'rsrc/css/phui/phui-crumbs-view.css' => '9dac418c', 'rsrc/css/phui/phui-curtain-view.css' => '7148ae25', 'rsrc/css/phui/phui-document-pro.css' => 'dc3d46ed', @@ -573,6 +574,7 @@ 'font-fontawesome' => '2b7ebbcc', 'font-lato' => 'c7ccd872', 'global-drag-and-drop-css' => '5c1b47c2', + 'guides-app-css' => '1d5414e5', 'harbormaster-css' => 'f491c9f4', 'herald-css' => 'dc31f6e9', 'herald-rule-editor' => 'd6a7e717', @@ -833,7 +835,7 @@ 'phui-calendar-list-css' => 'fcc9fb41', 'phui-calendar-month-css' => '8e10e92c', 'phui-chart-css' => '6bf6f78e', - 'phui-cms-css' => '33064557', + 'phui-cms-css' => 'be43c8a8', 'phui-crumbs-view-css' => '9dac418c', 'phui-curtain-view-css' => '7148ae25', 'phui-document-summary-view-css' => '9ca48bdf', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2633,6 +2633,8 @@ 'PhabricatorGuideApplication' => 'applications/guides/application/PhabricatorGuideApplication.php', 'PhabricatorGuideController' => 'applications/guides/controller/PhabricatorGuideController.php', 'PhabricatorGuideInstallController' => 'applications/guides/controller/PhabricatorGuideInstallController.php', + 'PhabricatorGuideItemView' => 'applications/guides/view/PhabricatorGuideItemView.php', + 'PhabricatorGuideListView' => 'applications/guides/view/PhabricatorGuideListView.php', 'PhabricatorGuideQuickStartController' => 'applications/guides/controller/PhabricatorGuideQuickStartController.php', 'PhabricatorGuideWelcomeController' => 'applications/guides/controller/PhabricatorGuideWelcomeController.php', 'PhabricatorHTTPParameterTypeTableView' => 'applications/config/view/PhabricatorHTTPParameterTypeTableView.php', @@ -7439,6 +7441,8 @@ 'PhabricatorGuideApplication' => 'PhabricatorApplication', 'PhabricatorGuideController' => 'PhabricatorController', 'PhabricatorGuideInstallController' => 'PhabricatorGuideController', + 'PhabricatorGuideItemView' => 'Phobject', + 'PhabricatorGuideListView' => 'AphrontView', 'PhabricatorGuideQuickStartController' => 'PhabricatorGuideController', 'PhabricatorGuideWelcomeController' => 'PhabricatorGuideController', 'PhabricatorHTTPParameterTypeTableView' => 'AphrontView', diff --git a/src/applications/guides/controller/PhabricatorGuideInstallController.php b/src/applications/guides/controller/PhabricatorGuideInstallController.php --- a/src/applications/guides/controller/PhabricatorGuideInstallController.php +++ b/src/applications/guides/controller/PhabricatorGuideInstallController.php @@ -8,6 +8,7 @@ } public function handleRequest(AphrontRequest $request) { + require_celerity_resource('guides-app-css'); $viewer = $request->getViewer(); $title = pht('Installation Guide'); @@ -22,7 +23,7 @@ $crumbs = $this->buildApplicationCrumbs() ->addTextCrumb(pht('Installation')); - $content = null; + $content = $this->getGuideContent($viewer); $view = id(new PHUICMSView()) ->setCrumbs($crumbs) @@ -37,10 +38,159 @@ } - private function getGuideContent() { + private function getGuideContent($viewer) { + $guide_items = new PhabricatorGuideListView(); - $guide = null; + $title = pht('Resolve Setup Issues'); + $issues_resolved = !PhabricatorSetupCheck::getOpenSetupIssueKeys(); + $href = PhabricatorEnv::getURI('/config/issue/'); + if ($issues_resolved) { + $icon = 'fa-check'; + $icon_bg = 'bg-green'; + $skip = null; + $description = pht( + "You've resolved (or ignored) all outstanding setup issues."); + } else { + $icon = 'fa-warning'; + $icon_bg = 'bg-red'; + $skip = '#'; + $description = + pht('You have some unresolved setup issues to take care of.'); + } - return $guide; + $item = id(new PhabricatorGuideItemView()) + ->setTitle($title) + ->setHref($href) + ->setIcon($icon) + ->setIconBackground($icon_bg) + ->setSkipHref($skip) + ->setDescription($description); + $guide_items->addItem($item); + + $configs = id(new PhabricatorAuthProviderConfigQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->execute(); + + $title = pht('Login and Registration'); + $href = PhabricatorEnv::getURI('/auth/'); + $have_auth = (bool)$configs; + if ($have_auth) { + $icon = 'fa-check'; + $icon_bg = 'bg-green'; + $skip = null; + $description = pht( + "You've configured at least one authentication provider."); + } else { + $icon = 'fa-key'; + $icon_bg = 'bg-sky'; + $skip = '#'; + $description = pht( + 'Authentication providers allow users to register accounts and '. + 'log in to Phabricator.'); + } + + $item = id(new PhabricatorGuideItemView()) + ->setTitle($title) + ->setHref($href) + ->setIcon($icon) + ->setIconBackground($icon_bg) + ->setSkipHref($skip) + ->setDescription($description); + $guide_items->addItem($item); + + + $title = pht('Configure Phabricator'); + $href = PhabricatorEnv::getURI('/config/'); + + // Just load any config value at all; if one exists the install has figured + // out how to configure things. + $have_config = (bool)id(new PhabricatorConfigEntry())->loadAllWhere( + '1 = 1 LIMIT 1'); + + if ($have_config) { + $icon = 'fa-check'; + $icon_bg = 'bg-green'; + $skip = null; + $description = pht( + "You've configured at least one setting from the web interface."); + } else { + $icon = 'fa-sliders'; + $icon_bg = 'bg-sky'; + $skip = '#'; + $description = pht( + 'Learn how to configure mail and other options in Phabricator.'); + } + + $item = id(new PhabricatorGuideItemView()) + ->setTitle($title) + ->setHref($href) + ->setIcon($icon) + ->setIconBackground($icon_bg) + ->setSkipHref($skip) + ->setDescription($description); + $guide_items->addItem($item); + + + $title = pht('User Account Settings'); + $href = PhabricatorEnv::getURI('/settings/'); + $preferences = id(new PhabricatorUserPreferencesQuery()) + ->setViewer($viewer) + ->withUsers(array($viewer)) + ->executeOne(); + + $have_settings = ($preferences && $preferences->getPreferences()); + if ($have_settings) { + $icon = 'fa-check'; + $icon_bg = 'bg-green'; + $skip = null; + $description = pht( + "You've adjusted at least one setting on your account."); + } else { + $icon = 'fa-wrench'; + $icon_bg = 'bg-sky'; + $skip = '#'; + $description = pht( + 'Configure account settings for all users, or just yourself'); + } + + $item = id(new PhabricatorGuideItemView()) + ->setTitle($title) + ->setHref($href) + ->setIcon($icon) + ->setIconBackground($icon_bg) + ->setSkipHref($skip) + ->setDescription($description); + $guide_items->addItem($item); + + + $title = pht('Notification Server'); + $href = PhabricatorEnv::getURI('/config/notifications/'); + // TODO: Wire up a notifications check + $have_notifications = false; + if ($have_notifications) { + $icon = 'fa-check'; + $icon_bg = 'bg-green'; + $skip = null; + $description = pht( + "You've set up a real-time notification server."); + } else { + $icon = 'fa-bell'; + $icon_bg = 'bg-sky'; + $skip = '#'; + $description = pht( + 'Phabricator can deliver notifications in real-time with WebSockets.'); + } + + $item = id(new PhabricatorGuideItemView()) + ->setTitle($title) + ->setHref($href) + ->setIcon($icon) + ->setIconBackground($icon_bg) + ->setSkipHref($skip) + ->setDescription($description); + + $guide_items->addItem($item); + + return $guide_items; } } diff --git a/src/applications/guides/controller/PhabricatorGuideQuickStartController.php b/src/applications/guides/controller/PhabricatorGuideQuickStartController.php --- a/src/applications/guides/controller/PhabricatorGuideQuickStartController.php +++ b/src/applications/guides/controller/PhabricatorGuideQuickStartController.php @@ -8,6 +8,7 @@ } public function handleRequest(AphrontRequest $request) { + require_celerity_resource('guides-app-css'); $viewer = $request->getViewer(); $title = pht('Quick Start Guide'); @@ -22,7 +23,7 @@ $crumbs = $this->buildApplicationCrumbs() ->addTextCrumb(pht('Quick Start')); - $content = null; + $content = $this->getGuideContent($viewer); $view = id(new PHUICMSView()) ->setCrumbs($crumbs) @@ -37,10 +38,173 @@ } - private function getGuideContent() { + private function getGuideContent($viewer) { + $guide_items = new PhabricatorGuideListView(); - $guide = null; + $title = pht('Configure Applications'); + $apps_check = true; + $href = PhabricatorEnv::getURI('/applications/'); + if ($apps_check) { + $icon = 'fa-check'; + $icon_bg = 'bg-green'; + $skip = null; + $description = pht( + "You've uninstalled any unneeded applications for now."); + } else { + $icon = 'fa-globe'; + $icon_bg = 'bg-sky'; + $skip = '#'; + $description = + pht('Use all our applications, or uninstall the ones you don\'t want.'); + } - return $guide; + $item = id(new PhabricatorGuideItemView()) + ->setTitle($title) + ->setHref($href) + ->setIcon($icon) + ->setIconBackground($icon_bg) + ->setSkipHref($skip) + ->setDescription($description); + $guide_items->addItem($item); + + + $title = pht('Invite Collaborators'); + $people_check = true; + $href = PhabricatorEnv::getURI('/people/invite/'); + if ($people_check) { + $icon = 'fa-check'; + $icon_bg = 'bg-green'; + $skip = null; + $description = pht( + 'You will not be alone on this journey.'); + } else { + $icon = 'fa-group'; + $icon_bg = 'bg-sky'; + $skip = '#'; + $description = + pht('Invite the rest of your team to get started on Phabricator.'); + } + + $item = id(new PhabricatorGuideItemView()) + ->setTitle($title) + ->setHref($href) + ->setIcon($icon) + ->setIconBackground($icon_bg) + ->setSkipHref($skip) + ->setDescription($description); + $guide_items->addItem($item); + + + $title = pht('Create a Repository'); + $repository_check = true; + $href = PhabricatorEnv::getURI('/diffusion/'); + if ($repository_check) { + $icon = 'fa-check'; + $icon_bg = 'bg-green'; + $skip = null; + $description = pht( + "You've created at least one repository."); + } else { + $icon = 'fa-code'; + $icon_bg = 'bg-sky'; + $skip = '#'; + $description = + pht('If you are here for code review, let\'s set up your first '. + 'repository.'); + } + + $item = id(new PhabricatorGuideItemView()) + ->setTitle($title) + ->setHref($href) + ->setIcon($icon) + ->setIconBackground($icon_bg) + ->setSkipHref($skip) + ->setDescription($description); + $guide_items->addItem($item); + + + $title = pht('Create a Project'); + $project_check = true; + $href = PhabricatorEnv::getURI('/project/'); + if ($project_check) { + $icon = 'fa-check'; + $icon_bg = 'bg-green'; + $skip = null; + $description = pht( + "You've created at least one project."); + } else { + $icon = 'fa-briefcase'; + $icon_bg = 'bg-sky'; + $skip = '#'; + $description = + pht('Project tags define everything. Create them for teams, tags, '. + 'or actual projects.'); + } + + $item = id(new PhabricatorGuideItemView()) + ->setTitle($title) + ->setHref($href) + ->setIcon($icon) + ->setIconBackground($icon_bg) + ->setSkipHref($skip) + ->setDescription($description); + $guide_items->addItem($item); + + + $title = pht('Build a Dashboard'); + $dashboard_check = true; + $href = PhabricatorEnv::getURI('/dashboard/'); + if ($dashboard_check) { + $icon = 'fa-check'; + $icon_bg = 'bg-green'; + $skip = null; + $description = pht( + "You've created at least one dashboard."); + } else { + $icon = 'fa-dashboard'; + $icon_bg = 'bg-sky'; + $skip = '#'; + $description = + pht('Customize the default homepage layout and items.'); + } + + $item = id(new PhabricatorGuideItemView()) + ->setTitle($title) + ->setHref($href) + ->setIcon($icon) + ->setIconBackground($icon_bg) + ->setSkipHref($skip) + ->setDescription($description); + $guide_items->addItem($item); + + + $title = pht('Personalize your Install'); + $ui_check = true; + $href = PhabricatorEnv::getURI('/config/group/ui/'); + if ($dashboard_check) { + $icon = 'fa-check'; + $icon_bg = 'bg-green'; + $skip = null; + $description = pht( + 'It looks amazing, good work. Home Sweet Home.'); + } else { + $icon = 'fa-home'; + $icon_bg = 'bg-sky'; + $skip = '#'; + $description = + pht('Change the name and add your company logo, just to give it a '. + 'little extra polish.'); + } + + $item = id(new PhabricatorGuideItemView()) + ->setTitle($title) + ->setHref($href) + ->setIcon($icon) + ->setIconBackground($icon_bg) + ->setSkipHref($skip) + ->setDescription($description); + $guide_items->addItem($item); + + return $guide_items; } } diff --git a/src/applications/guides/controller/PhabricatorGuideWelcomeController.php b/src/applications/guides/controller/PhabricatorGuideWelcomeController.php --- a/src/applications/guides/controller/PhabricatorGuideWelcomeController.php +++ b/src/applications/guides/controller/PhabricatorGuideWelcomeController.php @@ -8,6 +8,7 @@ } public function handleRequest(AphrontRequest $request) { + require_celerity_resource('guides-app-css'); $viewer = $request->getViewer(); $title = pht('Welcome to Phabricator'); @@ -22,7 +23,8 @@ $crumbs = $this->buildApplicationCrumbs() ->addTextCrumb(pht('Welcome')); - $content = null; + $content = id(new PHUIDocumentViewPro()) + ->appendChild($this->getGuideContent($viewer)); $view = id(new PHUICMSView()) ->setCrumbs($crumbs) @@ -37,10 +39,15 @@ } - private function getGuideContent() { + private function getGuideContent($viewer) { - $guide = null; + $content = pht( + 'You have successfully installed Phabricator. These next guides will '. + 'take you through configuration and new user orientation. '. + 'These steps are optional, and you can go through them in any order. '. + 'If you want to get back to this guide later on, you can find it in '. + 'the **Config** application under **Welcome Guide**.'); - return $guide; + return new PHUIRemarkupView($viewer, $content); } } diff --git a/src/applications/guides/view/PhabricatorGuideItemView.php b/src/applications/guides/view/PhabricatorGuideItemView.php new file mode 100644 --- /dev/null +++ b/src/applications/guides/view/PhabricatorGuideItemView.php @@ -0,0 +1,67 @@ +title = $title; + return $this; + } + + public function setDescription($description) { + $this->description = $description; + return $this; + } + + public function setHref($href) { + $this->href = $href; + return $this; + } + + public function setIcon($icon) { + $this->icon = $icon; + return $this; + } + + public function setIconBackground($background) { + $this->iconBackground = $background; + return $this; + } + + public function setSkipHref($href) { + $this->skipHref = $href; + return $this; + } + + public function getTitle() { + return $this->title; + } + + public function getDescription() { + return $this->description; + } + + public function getHref() { + return $this->href; + } + + public function getIcon() { + return $this->icon; + } + + public function getIconBackground() { + return $this->iconBackground; + } + + public function getSkipHref() { + return $this->skipHref; + } + + +} diff --git a/src/applications/guides/view/PhabricatorGuideListView.php b/src/applications/guides/view/PhabricatorGuideListView.php new file mode 100644 --- /dev/null +++ b/src/applications/guides/view/PhabricatorGuideListView.php @@ -0,0 +1,45 @@ +items[] = $item; + return $this; + } + + public function render() { + require_celerity_resource('guides-app-css'); + + $list = id(new PHUIObjectItemListView()) + ->addClass('guides-app'); + + foreach ($this->items as $item) { + $icon = id(new PHUIIconView()) + ->setIcon($item->getIcon()) + ->setBackground($item->getIconBackground()); + + $list_item = id(new PHUIObjectItemView()) + ->setHeader($item->getTitle()) + ->setHref($item->getHref()) + ->setImageIcon($icon) + ->addAttribute($item->getDescription()); + + $skip_href = $item->getSkipHref(); + if ($skip_href) { + $skip = id(new PHUIButtonView()) + ->setText(pht('Skip')) + ->setTag('a') + ->setHref($skip_href) + ->setColor(PHUIButtonView::GREY); + $list_item->setLaunchButton($skip); + } + $list->addItem($list_item); + } + + return $list; + + } + +} diff --git a/webroot/rsrc/css/application/guides/guides.css b/webroot/rsrc/css/application/guides/guides.css new file mode 100644 --- /dev/null +++ b/webroot/rsrc/css/application/guides/guides.css @@ -0,0 +1,34 @@ +/** + * @provides guides-app-css + */ + +.guides-app ul.phui-object-item-list-view { + margin: 0; + padding: 20px; +} + +.guides-app .phui-object-item-no-bar .phui-object-item-frame { + border: 0; +} + +.guides-app .phui-object-item-image-icon { + margin: 8px 2px 12px; +} + +.guides-app a.phui-object-item-link { + color: #000; + font-size: {$biggestfontsize}; +} + +.guides-app .phui-object-item-name { + padding-top: 6px; +} + +.guides-app .phui-object-item-launch-button a.button { + font-size: {$normalfontsize}; + padding: 3px 12px 4px; +} + +.device-desktop .guides-app .phui-object-item { + margin-bottom: 8px; +} diff --git a/webroot/rsrc/css/phui/phui-cms.css b/webroot/rsrc/css/phui/phui-cms.css --- a/webroot/rsrc/css/phui/phui-cms.css +++ b/webroot/rsrc/css/phui/phui-cms.css @@ -35,13 +35,14 @@ border: none; } -.phui-cms-view .phui-profile-header { +.phui-cms-view .phui-cms-page-content .phui-profile-header { padding: 32px 20px; border-bottom: 1px solid {$thinblueborder}; } .phui-cms-view .phui-document-view.phui-document-view-pro { width: auto; - padding: 32px 20px; + max-width: inherit; + padding: 0 20px; margin: 0; }