diff options
-rw-r--r-- | .htaccess | 1 | ||||
-rw-r--r-- | Bugzilla/Template.pm | 5 | ||||
-rw-r--r-- | skins/standard/global.css | 18 | ||||
-rw-r--r-- | skins/standard/mobile.css | 66 | ||||
-rw-r--r-- | template/en/default/account/auth/login.html.tmpl | 95 | ||||
-rw-r--r-- | template/en/default/global/header.html.tmpl | 8 | ||||
-rw-r--r-- | template/en/default/mfa/totp/verify.html.tmpl | 24 |
7 files changed, 157 insertions, 60 deletions
@@ -91,3 +91,4 @@ RewriteRule ^rest/(.*)$ rest.cgi/$1 [NE] RewriteRule ^(?:latest|1\.2|1\.3)/(.*)$ extensions/BzAPI/bin/rest.cgi/$1 [NE] RewriteRule ^bzapi/(.*)$ extensions/BzAPI/bin/rest.cgi/$1 [NE] RewriteRule ^data/assets/ZeroClipboard.swf(.*)$ extensions/BugModal/web/ZeroClipboard/ZeroClipboard.swf$1 [NE] +RewriteRule ^login$ index.cgi?GoAheadAndLogIn=1 [NE] diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm index bc0d77084..b03698477 100644 --- a/Bugzilla/Template.pm +++ b/Bugzilla/Template.pm @@ -1117,6 +1117,11 @@ sub create { return \@optional; }, 'default_authorizer' => sub { return Bugzilla::Auth->new() }, + + # It is almost always better to do mobile feature detection, client side in js. + # However, we need to set the meta[name=viewport] server-side or the behavior is + # not as predictable. It is possible other parts of the frontend may use this feature too. + 'is_mobile_browser' => sub { return Bugzilla->cgi->user_agent =~ /Mobi/ }, }, }; # Use a per-process provider to cache compiled templates in memory across diff --git a/skins/standard/global.css b/skins/standard/global.css index 81736f052..3790539e6 100644 --- a/skins/standard/global.css +++ b/skins/standard/global.css @@ -724,3 +724,21 @@ input.required, select.required, span.required_explanation { background-repeat: no-repeat !important; background-position: right 8px center !important; } + +#login .field-login, #login .field-password { + line-height: 32px; + display: block; + padding-top: 2px; + padding-bottom: 2px; +} + +#login .field-login label, #login .field-password label { + clear: left; + width: 7em; + display: inline-block; + font-weight: bold; +} + +#login .field-restrict, #login .field-remember { + margin-left: 7em; +} diff --git a/skins/standard/mobile.css b/skins/standard/mobile.css new file mode 100644 index 000000000..61179e93d --- /dev/null +++ b/skins/standard/mobile.css @@ -0,0 +1,66 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This Source Code Form is "Incompatible With Secondary Licenses", as + * defined by the Mozilla Public License, v. 2.0. + */ + +@media +only screen and (max-device-width : 720px) { + #header, #footer { + display: none; + } + .cookie-notify { + display: none; + } + + #login .field-login label, #login .field-password label { + display: block; + } + + #login .field-login, #login .field-password { + line-height: auto; + padding-top: 0px; + padding-bottom: 0px; + } + + #login .field-restrict, #login .field-remember { + margin-left: 0px; + } + #login .field-submit { + padding-top: 4px; + } + + h1 { + font-size: 1.5em; + } + + .verify-totp input[type="text"] { + font-size: 28px; + } + + .verify-totp input[type="submit"] { + font-size: 1em; + } +} + +@media +only screen and (-webkit-min-device-pixel-ratio: 2), +only screen and (min--moz-device-pixel-ratio: 2), +only screen and (-o-min-device-pixel-ratio: 2/1), +only screen and (min-device-pixel-ratio: 2), +only screen and (min-resolution: 192dpi), +only screen and (min-resolution: 2dppx) { + #privacy_policy { + font-size: small; + } + + body { + font-size: medium; + } + + label.checkbox-note { + font-size: small; + } +} diff --git a/template/en/default/account/auth/login.html.tmpl b/template/en/default/account/auth/login.html.tmpl index 922a55bd4..33aeaeaea 100644 --- a/template/en/default/account/auth/login.html.tmpl +++ b/template/en/default/account/auth/login.html.tmpl @@ -30,8 +30,9 @@ [% PROCESS global/variables.none.tmpl %] [% PROCESS global/header.html.tmpl - title = "Log in to $terms.Bugzilla", - onload = "document.forms['login'].Bugzilla_login.focus()" + title = "Log in to $terms.Bugzilla", + onload = "document.forms['login'].Bugzilla_login.focus()" + allow_mobile = 1 %] [% USE Bugzilla %] @@ -40,59 +41,55 @@ I need an email address and password to continue. </p> -<form name="login" action="[% target FILTER html %]" method="POST" -[%- IF Bugzilla.cgi.param("data") %] enctype="multipart/form-data"[% END %]> - <table> - <tr> - <th align="right"><label for="Bugzilla_login">Email Address:</label></th> - <td> - <input size="35" id="Bugzilla_login" name="Bugzilla_login" - [%- ' type="email"' UNLESS Param('emailsuffix') %]> - [% Param('emailsuffix') FILTER html %] - </td> - </tr> - <tr> - <th align="right"><label for="Bugzilla_password">Password:</label></th> - <td> - <input type="password" size="35" id="Bugzilla_password" name="Bugzilla_password"> - </td> - </tr> +<div id="login" class="login-form"> + <form name="login" action="[% target FILTER html %]" method="POST" + [%- IF Bugzilla.cgi.param("data") %] enctype="multipart/form-data"[% END %]> + <div class="field-login"> + <label for="Bugzilla_login">Email Address:</label> + <input id="Bugzilla_login" name="Bugzilla_login" + [%- ' type="email"' UNLESS Param('emailsuffix') %]> + [% Param('emailsuffix') FILTER html %] + </div> + + <div class="field-password"> + <label for="Bugzilla_password">Password:</label> + <input type="password" id="Bugzilla_password" name="Bugzilla_password"> + </div> [% IF Param('rememberlogin') == 'defaulton' || - Param('rememberlogin') == 'defaultoff' %] - <tr> - <th> </th> - <td> - <input type="checkbox" id="Bugzilla_remember" name="Bugzilla_remember" value="on" - [%+ "checked" IF Param('rememberlogin') == "defaulton" %]> - <label for="Bugzilla_remember">Remember my email address</label> - </td> - </tr> + Param('rememberlogin') == 'defaultoff' %] + <div class="field-remember"> + <input type="checkbox" id="Bugzilla_remember" name="Bugzilla_remember" value="on" + [%+ "checked" IF Param('rememberlogin') == "defaulton" %]> + <label for="Bugzilla_remember" class="checkbox-note"> + Remember my email address + </label> + </div> [% END %] - <tr> - <th> </th> - <td> - <input type="checkbox" id="Bugzilla_restrictlogin" name="Bugzilla_restrictlogin" - checked="checked"> - <label for="Bugzilla_restrictlogin">Restrict this session to this IP address - (using this option improves security)</label> - </td> - </tr> - </table> + [% PROCESS "global/hidden-fields.html.tmpl" + exclude="^Bugzilla_(login|password|restrictlogin)$" %] - [% PROCESS "global/hidden-fields.html.tmpl" - exclude="^Bugzilla_(login|password|restrictlogin)$" %] + <div class="field-restrict"> + <input type="checkbox" id="Bugzilla_restrictlogin" name="Bugzilla_restrictlogin" + checked="checked"> + <label for="Bugzilla_restrictlogin" class="checkbox-note"> + Restrict this session to this IP address + (using this option improves security)</label> + </div> - <input type="hidden" name="Bugzilla_login_token" - value="[% get_login_request_token() FILTER html %]"> - <input type="submit" name="GoAheadAndLogIn" value="Log in" id="log_in"> + <div class="field-submit"> + <input type="hidden" name="Bugzilla_login_token" + value="[% get_login_request_token() FILTER html %]"> + <input type="submit" name="GoAheadAndLogIn" value="Log in" id="log_in"> + </div> - <p> - (Note: you should make sure cookies are enabled for this site. - Otherwise, you will be required to log in frequently.) - </p> -</form> + <p class="cookie-notify"> + (Note: you should make sure cookies are enabled for this site. + Otherwise, you will be required to log in frequently.) + </p> + </form> +</div> [% Hook.process('additional_methods') %] @@ -117,7 +114,7 @@ If you have an account, but have forgotten your password, enter your email address below and submit a request to change your password.<br> - <input size="35" name="loginname"> + <input name="loginname"> <input type="hidden" id="token" name="token" value="[% issue_hash_token(['reqpw']) FILTER html %]"> <input type="submit" id="request" value="Reset Password"> </form> diff --git a/template/en/default/global/header.html.tmpl b/template/en/default/global/header.html.tmpl index 3f70b9453..23634ed43 100644 --- a/template/en/default/global/header.html.tmpl +++ b/template/en/default/global/header.html.tmpl @@ -37,6 +37,7 @@ # atomlink: Atom link URL, May contain HTML # generate_api_token: generate a token which can be used to make authenticated webservice calls # no_body: if true the body element will not be generated + # allow_mobile: allow special CSS and viewport for detected mobile useragents #%] [% IF message %] @@ -103,6 +104,10 @@ [%# Add our required jQuery plugins %] [% jquery.push("cookie", "devbridgeAutocomplete") %] +[% IF allow_mobile && is_mobile_browser %] + [% style_urls.push("skins/standard/mobile.css") %] +[% END %] + [%# We should be able to set the default value of the header variable # to the value of the title variable using the DEFAULT directive, # but that doesn't work if a caller sets header to the empty string @@ -260,6 +265,9 @@ [%# Required for the 'Autodiscovery' feature in Firefox 2 and IE 7. %] <link rel="search" type="application/opensearchdescription+xml" title="[% terms.BugzillaTitle %]" href="./search_plugin.cgi"> + [% IF allow_mobile && is_mobile_browser %] + <meta name="viewport" content="width=device-width, initial-scale=1"> + [% END %] [% Hook.process("additional_header") %] </head> diff --git a/template/en/default/mfa/totp/verify.html.tmpl b/template/en/default/mfa/totp/verify.html.tmpl index ad75dc6bc..7314d909a 100644 --- a/template/en/default/mfa/totp/verify.html.tmpl +++ b/template/en/default/mfa/totp/verify.html.tmpl @@ -8,6 +8,7 @@ [% INCLUDE global/header.html.tmpl title = "Account Verification" + allow_mobile = 1 %] <h1>Account Verification</h1> @@ -16,16 +17,17 @@ <b>[% reason FILTER html %]</b> requires verification.<br> Please enter your verification code from your TOTP application: </p> - -<form method="POST" action="[% postback.action FILTER none %]"> - [% FOREACH field IN postback.fields.keys %] - <input type="hidden" name="[% field FILTER html %]" value="[% postback.fields.item(field) FILTER html %]"> - [% END %] - <input type="text" name="code" id="code" - placeholder="123456" maxlength="9" pattern="\d{6,9}" size="10" - autocomplete="off" required autofocus><br> - <br> - <input type="submit" value="Submit"> -</form> +<div class="verify-totp"> + <form method="POST" action="[% postback.action FILTER none %]"> + [% FOREACH field IN postback.fields.keys %] + <input type="hidden" name="[% field FILTER html %]" value="[% postback.fields.item(field) FILTER html %]"> + [% END %] + <input type="text" name="code" id="code" + placeholder="123456" maxlength="9" pattern="\d{6,9}" size="10" + autocomplete="off" required autofocus><br> + <br> + <input type="submit" value="Submit"> + </form> +</div> [% INCLUDE global/footer.html.tmpl %] |