From 7cf7f3645293adbc5f4acb27a178899f52a1471c Mon Sep 17 00:00:00 2001 From: epriestley Date: Sun, 16 Jun 2013 16:31:14 -0700 Subject: [PATCH] Restyle username/password login for reduced hideousness Summary: Ref T1536. Error state is a bit gross but we need to sort that out in general. Test Plan: {F46549} {F46550} Reviewers: chad, btrahan Reviewed By: chad CC: aran Maniphest Tasks: T1536 Differential Revision: https://secure.phabricator.com/D6208 --- src/__celerity_resource_map__.php | 90 +++++++++---------- .../response/AphrontDialogResponse.php | 4 + .../PhabricatorAuthProviderPassword.php | 53 +++++------ .../base/controller/PhabricatorController.php | 2 + src/view/AphrontDialogView.php | 59 ++++++++++-- webroot/rsrc/css/aphront/dialog-view.css | 20 ++++- 6 files changed, 143 insertions(+), 85 deletions(-) diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index 16f8136943..4197e90d69 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -796,7 +796,7 @@ celerity_register_resource_map(array( ), 'aphront-dialog-view-css' => array( - 'uri' => '/res/71190d8c/rsrc/css/aphront/dialog-view.css', + 'uri' => '/res/b5811686/rsrc/css/aphront/dialog-view.css', 'type' => 'css', 'requires' => array( @@ -4048,7 +4048,7 @@ celerity_register_resource_map(array( ), array( 'packages' => array( - 'ab82f2c0' => + '1cdd0caf' => array( 'name' => 'core.pkg.css', 'symbols' => @@ -4096,7 +4096,7 @@ celerity_register_resource_map(array( 40 => 'phabricator-property-list-view-css', 41 => 'phabricator-tag-view-css', ), - 'uri' => '/res/pkg/ab82f2c0/core.pkg.css', + 'uri' => '/res/pkg/1cdd0caf/core.pkg.css', 'type' => 'css', ), 'f2ad0683' => @@ -4290,16 +4290,16 @@ celerity_register_resource_map(array( 'reverse' => array( 'aphront-attached-file-view-css' => 'a7ca34a9', - 'aphront-dialog-view-css' => 'ab82f2c0', - 'aphront-error-view-css' => 'ab82f2c0', - 'aphront-form-view-css' => 'ab82f2c0', - 'aphront-list-filter-view-css' => 'ab82f2c0', - 'aphront-pager-view-css' => 'ab82f2c0', - 'aphront-panel-view-css' => 'ab82f2c0', - 'aphront-table-view-css' => 'ab82f2c0', - 'aphront-tokenizer-control-css' => 'ab82f2c0', - 'aphront-tooltip-css' => 'ab82f2c0', - 'aphront-typeahead-control-css' => 'ab82f2c0', + 'aphront-dialog-view-css' => '1cdd0caf', + 'aphront-error-view-css' => '1cdd0caf', + 'aphront-form-view-css' => '1cdd0caf', + 'aphront-list-filter-view-css' => '1cdd0caf', + 'aphront-pager-view-css' => '1cdd0caf', + 'aphront-panel-view-css' => '1cdd0caf', + 'aphront-table-view-css' => '1cdd0caf', + 'aphront-tokenizer-control-css' => '1cdd0caf', + 'aphront-tooltip-css' => '1cdd0caf', + 'aphront-typeahead-control-css' => '1cdd0caf', 'differential-changeset-view-css' => 'dd27a69b', 'differential-core-view-css' => 'dd27a69b', 'differential-inline-comment-editor' => '9488bb69', @@ -4313,7 +4313,7 @@ celerity_register_resource_map(array( 'differential-table-of-contents-css' => 'dd27a69b', 'diffusion-commit-view-css' => 'c8ce2d88', 'diffusion-icons-css' => 'c8ce2d88', - 'global-drag-and-drop-css' => 'ab82f2c0', + 'global-drag-and-drop-css' => '1cdd0caf', 'inline-comment-summary-css' => 'dd27a69b', 'javelin-aphlict' => 'f2ad0683', 'javelin-behavior' => 'a9f14d76', @@ -4387,55 +4387,55 @@ celerity_register_resource_map(array( 'javelin-util' => 'a9f14d76', 'javelin-vector' => 'a9f14d76', 'javelin-workflow' => 'a9f14d76', - 'lightbox-attachment-css' => 'ab82f2c0', + 'lightbox-attachment-css' => '1cdd0caf', 'maniphest-task-summary-css' => 'a7ca34a9', 'maniphest-transaction-detail-css' => 'a7ca34a9', - 'phabricator-action-list-view-css' => 'ab82f2c0', - 'phabricator-application-launch-view-css' => 'ab82f2c0', + 'phabricator-action-list-view-css' => '1cdd0caf', + 'phabricator-application-launch-view-css' => '1cdd0caf', 'phabricator-busy' => 'f2ad0683', 'phabricator-content-source-view-css' => 'dd27a69b', - 'phabricator-core-css' => 'ab82f2c0', - 'phabricator-crumbs-view-css' => 'ab82f2c0', + 'phabricator-core-css' => '1cdd0caf', + 'phabricator-crumbs-view-css' => '1cdd0caf', 'phabricator-drag-and-drop-file-upload' => '9488bb69', 'phabricator-dropdown-menu' => 'f2ad0683', 'phabricator-file-upload' => 'f2ad0683', - 'phabricator-filetree-view-css' => 'ab82f2c0', - 'phabricator-flag-css' => 'ab82f2c0', - 'phabricator-form-view-css' => 'ab82f2c0', - 'phabricator-header-view-css' => 'ab82f2c0', + 'phabricator-filetree-view-css' => '1cdd0caf', + 'phabricator-flag-css' => '1cdd0caf', + 'phabricator-form-view-css' => '1cdd0caf', + 'phabricator-header-view-css' => '1cdd0caf', 'phabricator-hovercard' => 'f2ad0683', - 'phabricator-jump-nav' => 'ab82f2c0', + 'phabricator-jump-nav' => '1cdd0caf', 'phabricator-keyboard-shortcut' => 'f2ad0683', 'phabricator-keyboard-shortcut-manager' => 'f2ad0683', - 'phabricator-main-menu-view' => 'ab82f2c0', + 'phabricator-main-menu-view' => '1cdd0caf', 'phabricator-menu-item' => 'f2ad0683', - 'phabricator-nav-view-css' => 'ab82f2c0', + 'phabricator-nav-view-css' => '1cdd0caf', 'phabricator-notification' => 'f2ad0683', - 'phabricator-notification-css' => 'ab82f2c0', - 'phabricator-notification-menu-css' => 'ab82f2c0', - 'phabricator-object-item-list-view-css' => 'ab82f2c0', + 'phabricator-notification-css' => '1cdd0caf', + 'phabricator-notification-menu-css' => '1cdd0caf', + 'phabricator-object-item-list-view-css' => '1cdd0caf', 'phabricator-object-selector-css' => 'dd27a69b', 'phabricator-phtize' => 'f2ad0683', 'phabricator-prefab' => 'f2ad0683', 'phabricator-project-tag-css' => 'a7ca34a9', - 'phabricator-property-list-view-css' => 'ab82f2c0', - 'phabricator-remarkup-css' => 'ab82f2c0', + 'phabricator-property-list-view-css' => '1cdd0caf', + 'phabricator-remarkup-css' => '1cdd0caf', 'phabricator-shaped-request' => '9488bb69', - 'phabricator-side-menu-view-css' => 'ab82f2c0', - 'phabricator-standard-page-view' => 'ab82f2c0', - 'phabricator-tag-view-css' => 'ab82f2c0', + 'phabricator-side-menu-view-css' => '1cdd0caf', + 'phabricator-standard-page-view' => '1cdd0caf', + 'phabricator-tag-view-css' => '1cdd0caf', 'phabricator-textareautils' => 'f2ad0683', 'phabricator-tooltip' => 'f2ad0683', - 'phabricator-transaction-view-css' => 'ab82f2c0', - 'phabricator-zindex-css' => 'ab82f2c0', - 'phui-button-css' => 'ab82f2c0', - 'phui-form-css' => 'ab82f2c0', - 'phui-icon-view-css' => 'ab82f2c0', - 'phui-spacing-css' => 'ab82f2c0', - 'sprite-apps-large-css' => 'ab82f2c0', - 'sprite-gradient-css' => 'ab82f2c0', - 'sprite-icons-css' => 'ab82f2c0', - 'sprite-menu-css' => 'ab82f2c0', - 'syntax-highlighting-css' => 'ab82f2c0', + 'phabricator-transaction-view-css' => '1cdd0caf', + 'phabricator-zindex-css' => '1cdd0caf', + 'phui-button-css' => '1cdd0caf', + 'phui-form-css' => '1cdd0caf', + 'phui-icon-view-css' => '1cdd0caf', + 'phui-spacing-css' => '1cdd0caf', + 'sprite-apps-large-css' => '1cdd0caf', + 'sprite-gradient-css' => '1cdd0caf', + 'sprite-icons-css' => '1cdd0caf', + 'sprite-menu-css' => '1cdd0caf', + 'syntax-highlighting-css' => '1cdd0caf', ), )); diff --git a/src/aphront/response/AphrontDialogResponse.php b/src/aphront/response/AphrontDialogResponse.php index b19fca9cee..7aa34db8ae 100644 --- a/src/aphront/response/AphrontDialogResponse.php +++ b/src/aphront/response/AphrontDialogResponse.php @@ -12,6 +12,10 @@ final class AphrontDialogResponse extends AphrontResponse { return $this; } + public function getDialog() { + return $this->dialog; + } + public function buildResponseString() { return $this->dialog->render(); } diff --git a/src/applications/auth/provider/PhabricatorAuthProviderPassword.php b/src/applications/auth/provider/PhabricatorAuthProviderPassword.php index b8a6ec5da0..04e0548355 100644 --- a/src/applications/auth/provider/PhabricatorAuthProviderPassword.php +++ b/src/applications/auth/provider/PhabricatorAuthProviderPassword.php @@ -59,17 +59,25 @@ final class PhabricatorAuthProviderPassword $viewer = $request->getUser(); - $submit = id(new AphrontFormSubmitControl()) - ->setValue(pht('Login')); + $dialog = id(new AphrontDialogView()) + ->setSubmitURI($this->getLoginURI()) + ->setUser($viewer) + ->setTitle(pht('Login to Phabricator')) + ->addSubmitButton(pht('Login')); if ($this->shouldAllowRegistration()) { - $submit->addCancelButton( + $dialog->addCancelButton( '/auth/register/', pht('Register New Account')); } - $header = id(new PhabricatorHeaderView()) - ->setHeader(pht('Login to Phabricator')); + $dialog->addFooter( + phutil_tag( + 'a', + array( + 'href' => '/login/email/', + ), + pht('Forgot your password?'))); $v_user = nonempty( $request->getStr('username'), @@ -97,13 +105,16 @@ final class PhabricatorAuthProviderPassword $errors[] = pht('Username or password are incorrect.'); } - $form = id(new AphrontFormView()) - ->setAction($this->getLoginURI()) - ->setUser($viewer) - ->setFlexible(true) + if ($errors) { + $errors = id(new AphrontErrorView())->setErrors($errors); + } + + $form = id(new AphrontFormLayoutView()) + ->setFullWidth(true) + ->appendChild($errors) ->appendChild( id(new AphrontFormTextControl()) - ->setLabel('Username/Email') + ->setLabel('Username or Email') ->setName('username') ->setValue($v_user) ->setError($e_user)) @@ -111,14 +122,7 @@ final class PhabricatorAuthProviderPassword id(new AphrontFormPasswordControl()) ->setLabel('Password') ->setName('password') - ->setError($e_pass) - ->setCaption( - phutil_tag( - 'a', - array( - 'href' => '/login/email/', - ), - pht('Forgot your password?')))); + ->setError($e_pass)); if ($require_captcha) { $form->appendChild( @@ -126,18 +130,9 @@ final class PhabricatorAuthProviderPassword ->setError($e_captcha)); } - $form - ->appendChild($submit); + $dialog->appendChild($form); - if ($errors) { - $errors = id(new AphrontErrorView())->setErrors($errors); - } - - return array( - $errors, - $header, - $form, - ); + return $dialog; } public function processLoginRequest( diff --git a/src/applications/base/controller/PhabricatorController.php b/src/applications/base/controller/PhabricatorController.php index 6b40fbd90d..8d3e8c97cd 100644 --- a/src/applications/base/controller/PhabricatorController.php +++ b/src/applications/base/controller/PhabricatorController.php @@ -228,6 +228,8 @@ abstract class PhabricatorController extends AphrontController { $response->setContent($view->render()); return $response; } else { + $response->getDialog()->setIsStandalone(true); + return id(new AphrontAjaxResponse()) ->setContent(array( 'dialog' => $response->buildResponseString(), diff --git a/src/view/AphrontDialogView.php b/src/view/AphrontDialogView.php index 26042ce3bf..4fa384a205 100644 --- a/src/view/AphrontDialogView.php +++ b/src/view/AphrontDialogView.php @@ -12,6 +12,17 @@ final class AphrontDialogView extends AphrontView { private $renderAsForm = true; private $formID; private $headerColor = PhabricatorActionHeaderView::HEADER_DARK_GREY; + private $footers = array(); + private $isStandalone; + + public function setIsStandalone($is_standalone) { + $this->isStandalone = $is_standalone; + return $this; + } + + public function getIsStandalone() { + return $this->isStandalone; + } private $width = 'default'; const WIDTH_DEFAULT = 'default'; @@ -51,6 +62,11 @@ final class AphrontDialogView extends AphrontView { return $this; } + public function addFooter($footer) { + $this->footers[] = $footer; + return $this; + } + public function addHiddenInput($key, $value) { if (is_array($value)) { foreach ($value as $hidden_key => $hidden_value) { @@ -132,6 +148,10 @@ final class AphrontDialogView extends AphrontView { throw new Exception("Unknown dialog width '{$this->width}'!"); } + if ($this->isStandalone) { + $more .= ' aphront-dialog-view-standalone'; + } + $attributes = array( 'class' => 'aphront-dialog-view '.$more, 'sigil' => 'jx-dialog', @@ -171,21 +191,44 @@ final class AphrontDialogView extends AphrontView { array_merge($hidden_inputs, $buttons))); } - $buttons[] = phutil_tag('div', array('style' => 'clear: both;'), ''); $children = $this->renderChildren(); $header = new PhabricatorActionHeaderView(); $header->setHeaderTitle($this->title); $header->setHeaderColor($this->headerColor); - $content = hsprintf( - '%s%s%s', + $footer = null; + if ($this->footers) { + $footer = phutil_tag( + 'div', + array( + 'class' => 'aphront-dialog-foot', + ), + $this->footers); + } + + $content = array( + phutil_tag( + 'div', + array( + 'class' => 'aphront-dialog-head', + ), + $header), phutil_tag('div', - array('class' => 'aphront-dialog-head'), $header), - phutil_tag('div', - array('class' => 'aphront-dialog-body grouped'), $children), - phutil_tag('div', - array('class' => 'aphront-dialog-tail'), $buttons)); + array( + 'class' => 'aphront-dialog-body grouped', + ), + $children), + phutil_tag( + 'div', + array( + 'class' => 'aphront-dialog-tail grouped', + ), + array( + $buttons, + $footer, + )), + ); if ($this->renderAsForm) { return phabricator_form( diff --git a/webroot/rsrc/css/aphront/dialog-view.css b/webroot/rsrc/css/aphront/dialog-view.css index a2d7f62ee1..0b956831db 100644 --- a/webroot/rsrc/css/aphront/dialog-view.css +++ b/webroot/rsrc/css/aphront/dialog-view.css @@ -4,11 +4,22 @@ .aphront-dialog-view { width: 480px; - margin: auto; + margin: 16px auto; border-radius: 6px; - box-shadow: 0 4px 12px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.5); + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.25), + inset 0 1px 0 rgba(255, 255, 255, 0.5); } +/* The "standalone" dialog (which is delivered over Ajax and appears above + an existing page) has a more pronounced shadow than dialogs do when they + are embedded in a page. */ +.aphront-dialog-view-standalone { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4), + inset 0 1px 0 rgba(255, 255, 255, 0.5); + margin: auto; +} + + .aphront-dialog-head .phabricator-action-header { border-bottom: 1px solid #d4dadf; padding: 5px 15px; @@ -43,7 +54,10 @@ border-top: 1px solid #d4dadf; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; - text-align: right; +} + +.aphront-dialog-foot { + padding: 6px; } .aphront-dialog-tail button,