Finishing login/signup forms and interactions. Added 4 features and images. Formatted activity. Needs some love and integration with the reader, but it's almost there.

This commit is contained in:
Samuel Clay 2012-09-12 18:47:37 -07:00
parent f4e3e1328e
commit 11ac02e852
16 changed files with 471 additions and 154 deletions

View file

@ -11,10 +11,10 @@ from utils import log as logging
class LoginForm(forms.Form):
username = forms.CharField(label=_("Username or Email"), max_length=30,
widget=forms.TextInput(attrs={'tabindex': 1}),
widget=forms.TextInput(attrs={'tabindex': 1, 'class': 'NB-input'}),
error_messages={'required': 'Please enter a username.'})
password = forms.CharField(label=_("Password"),
widget=forms.PasswordInput(attrs={'tabindex': 2}),
widget=forms.PasswordInput(attrs={'tabindex': 2, 'class': 'NB-input'}),
required=False)
# error_messages={'required': 'Please enter a password.'})
@ -69,17 +69,17 @@ class LoginForm(forms.Form):
class SignupForm(forms.Form):
username = forms.RegexField(regex=r'^\w+$',
max_length=30,
widget=forms.TextInput(),
widget=forms.TextInput(attrs={'class': 'NB-input'}),
label=_(u'username'),
error_messages={
'required': 'Please enter a username.',
'invalid': "Your username may only contain letters and numbers."
})
email = forms.EmailField(widget=forms.TextInput(attrs=dict(maxlength=75)),
email = forms.EmailField(widget=forms.TextInput(attrs={'maxlength': 75, 'class': 'NB-input'}),
label=_(u'email address'),
required=False)
# error_messages={'required': 'Please enter your email.'})
password = forms.CharField(widget=forms.PasswordInput(),
password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'NB-input'}),
label=_(u'password'),
required=False)
# error_messages={'required': 'Please enter a password.'})

View file

@ -106,7 +106,7 @@ def welcome(request, **kwargs):
social_profile = MSocialProfile.get_user(user.pk)
if request.method == "POST":
if request.POST.get('submit') == 'login':
if request.POST.get('submit').startswith('log'):
login_form = LoginForm(request.POST, prefix='login')
signup_form = SignupForm(prefix='signup')
else:
@ -123,6 +123,7 @@ def welcome(request, **kwargs):
'signup_form' : signup_form,
'statistics' : statistics,
'social_profile' : social_profile,
'post_request' : request.method == 'POST',
}, "reader/welcome.xhtml"
@never_cache

View file

@ -25,9 +25,9 @@
padding: 2px;
margin: 2px 4px 2px;
border: 1px solid #606060;
-moz-box-shadow:2px 2px 0 #D0D0D0;
-webkit-box-shadow:2px 2px 0 #D0D0D0;
box-shadow:2px 2px 0 #D0D0D0;
-moz-box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
-webkit-box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
}
/* ========== */
@ -117,9 +117,9 @@
padding: 2px;
margin: 0px 4px 6px;
border: 1px solid #606060;
-moz-box-shadow:2px 2px 0 #D0D0D0;
-webkit-box-shadow:2px 2px 0 #D0D0D0;
box-shadow:2px 2px 0 #D0D0D0;
-moz-box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
-webkit-box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
}
.NB-modal .NB-modal-field input[type=checkbox] {
@ -205,9 +205,9 @@
text-transform: uppercase;
margin: 2px 4px 2px;
border: 1px solid #606060;
-moz-box-shadow:2px 2px 0 #D0D0D0;
-webkit-box-shadow:2px 2px 0 #D0D0D0;
box-shadow:2px 2px 0 #D0D0D0;
-moz-box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
-webkit-box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
box-shadow:2px 2px 0 rgba(50, 50, 50, 0.15);
border-radius: 4px;
-moz-border-radius: 4px;
cursor: pointer;

View file

@ -4469,6 +4469,9 @@ form.opml_import_form input {
.NB-account .NB-module.NB-module-account .NB-module-account-stats {
min-height: 0;
}
.NB-account .NB-module.NB-module-account .NB-module-stats-counts {
overflow: hidden;
}
.NB-account .NB-module.NB-module-account .NB-module-stats-count {
margin: 0;
}

View file

@ -92,17 +92,20 @@ body.NB-welcome {
width: 500px;
height: 327px;
position: absolute;
bottom: -20px;
bottom: -350px;
right: 0;
border-radius: 2px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.NB-welcome-header-image.NB-active img.NB-1 {
bottom: 0px;
}
.NB-welcome-header-image img.NB-2 {
opacity: 0;
height: 325px;
position: absolute;
bottom: -10px;
bottom: -300px;
right: 0;
border-radius: 2px;
margin-right: 100px;
@ -113,7 +116,7 @@ body.NB-welcome {
opacity: 0;
height: 300px;
position: absolute;
bottom: -10px;
bottom: -300px;
right: 0;
border-radius: 2px;
margin-right: 140px;
@ -122,10 +125,10 @@ body.NB-welcome {
}
.NB-welcome-header-captions {
text-align: center;
margin: 36px auto 0;
margin: 0 auto;
position: absolute;
top: 0;
left: 470px;
left: 420px;
overflow: hidden;
text-shadow: 0 1px 0 rgba(35,35,35,0.35);
padding-left: 64px;
@ -136,9 +139,12 @@ body.NB-welcome {
float: left;
color: #FDC85B;
cursor: pointer;
padding: 0 12px;
padding: 36px 12px 12px;
text-transform: uppercase;
}
.NB-welcome-header-caption.NB-welcome-header-caption-signin {
color: #A5E665;
}
.NB-welcome-header-caption span {
padding: 2px 8px;
border-radius: 4px;
@ -148,6 +154,12 @@ body.NB-welcome {
-o-transition: all 1s ease-in-out;
-ms-transition: all 1s ease-in-out;
}
.NB-welcome-header-caption:hover span {
-webkit-transition: all .25s ease-in-out;
-moz-transition: all .25s ease-in-out;
-o-transition: all .25s ease-in-out;
-ms-transition: all .25s ease-in-out;
}
.NB-welcome-header-caption.NB-active span {
color: #FAA518;
background-color: rgba(235, 235, 235, 0.1);
@ -207,12 +219,217 @@ body.NB-welcome {
color: white;
}
/* ================== */
/* = Login / Signup = */
/* ================== */
.NB-welcome-header-account {
position: absolute;
bottom: -350px;
right: 12px;
width: 400px;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
background-color: rgba(245, 245, 245, 0.4);
padding: 36px 36px 12px;
}
.NB-welcome-header-account.NB-active {
bottom: 0;
}
.NB-welcome-header-account .NB-module-header-login {
width: 142px;
margin: 0 50px 0 0;
padding: 0 4px;
float: left;
text-shadow: 0 1px 0 rgba(35, 35, 35, 0.3);
}
.NB-welcome-header-account .NB-module-header-signup {
width: 142px;
margin: 0;
padding: 0 4px;
float: left;
text-shadow: 0 1px 0 rgba(35, 35, 35, 0.3);
}
.NB-welcome-header-account .NB-login {
padding: 0 4px;
margin: 12px 50px 0 12px;
width: 146px;
float: left;
}
.NB-welcome-header-account .NB-signup {
float: left;
width: 146px;
padding: 0 4px;
margin: 12px 0 0;
height: 206px;
overflow: hidden;
}
.NB-welcome-header-account .NB-import-signup {
float: left;
width: 146px;
padding: 0 0 64px 0;
margin: 0 24px 0 12px;
height: 206px;
overflow: hidden;
}
.NB-welcome-header-account .NB-import-signup-text {
text-align: center;
width: 190px;
}
.NB-welcome-header-account .NB-import-signup-text h3 {
margin-top: 48px;
color: #20843D;
}
.NB-welcome-header-account .NB-import-signup-text p {
color: #636363;
}
.NB-welcome-header-account .NB-signup-orline {
margin: 30px auto 24px;
text-align: center;
font-size: 14px;
line-height: 10px;
color: #F9F9F9;
font-weight: bold;
}
.NB-welcome-header-account .NB-signup-orline-reduced {
margin: 0px auto 0px;
}
.NB-welcome-header-account .NB-signup-orline .NB-signup-orline-or {
padding: 0 4px;
}
.NB-welcome-header-account .NB-signup-optional {
float: right;
text-transform: uppercase;
color: rgba(255, 255, 255, 0.4);
font-weight: bold;
font-size: 9px;
line-height: 17px;
}
.NB-welcome-header-account .NB-signup-hidden {
display: none;
}
.NB-welcome-header-account .NB-import-signup {
height: auto;
}
.NB-welcome-header-account .NB-signup .NB-signup-google {
margin: 12px auto;
display: block;
font-size: 12px;
text-align: center;
}
.NB-welcome-header-account input[type=text],
.NB-welcome-header-account input[type=password] {
border: 1px solid rgba(35, 35, 35, 0.5);
display:block;
font-size:13px;
margin:0 0 12px;
padding:5px;
width:134px;
}
.NB-welcome-header-account input[type=text]:focus,
.NB-welcome-header-account input[type=password]:focus {
border-color: #739BBE;
}
.NB-welcome-header-account input[type=submit] {
outline: none;
width: 146px; /* 174=input-width + 5*2=padding + 2=border */
margin: 4px 5px 0 0;
padding: 4px 10px 5px;
text-shadow: 0 -1px 0 rgba(35, 35, 35, 0.4);
font-weight: bold;
font-size: 12px;
border: 1px solid rgba(35, 35, 35, 0.5);
color: white;
cursor: pointer;
}
.NB-welcome-header-account input[type=hidden] {
display: none;
}
.NB-welcome-header-account label,
.NB-welcome-header-account .NB-account-label {
margin: 0;
color: #FFFFB0;
text-shadow: 0 1px 0 rgba(35, 35, 35, 0.3);
font-size: 12px;
display: block;
text-transform: uppercase;
}
.NB-welcome-header-account .NB-account-label {
font-weight: bold;
}
.NB-welcome-header-account .NB-account-text {
font-size: 13px;
color: #90A0B0;
margin-bottom: 30px;
}
.NB-welcome-header-account .NB-account-text a {
text-decoration: none;
color: #3E4773;
}
.NB-welcome-header-account .NB-account-text a:hover {
color: #0E1763;
}
.NB-welcome-header-account .errorlist {
list-style: none;
font-size: 12px;
color: #AF4D18;
font-weight: bold;
padding: 0;
}
/* ============ */
/* = Features = */
/* ============ */
.NB-welcome-features {
margin: 36px 0;
margin: 48px 0;
overflow: hidden;
}
.NB-welcome-features .NB-feature {
float: left;
width: 204px;
margin: 0 36px 0 0;
text-align: center;
}
.NB-welcome-features img {
width: 200px;
height: 175px;
box-shadow: 0 0 3px rgba(30, 30, 30, 0.3);
}
.NB-welcome-features .NB-feature-caption {
font-weight: bold;
font-size: 24px;
margin: 8px 0 0;
}
.NB-welcome-features .NB-feature-text {
color: #808080;
margin: 8px 0 0;
font-size: 15px;
line-height: 22px;
}
/* ============ */
@ -221,4 +438,30 @@ body.NB-welcome {
.NB-welcome-activity {
overflow: hidden;
}
clear: both;
margin: 48px 0;
padding: 36px 0;
background-color: #F5F5F5;
}
.NB-welcome-activity .NB-module {
width: 50%;
float: left;
}
.NB-welcome-activity .NB-module .NB-module-header {
display: none;
}
.NB-welcome-activity .NB-module .NB-module-stats-counts {
overflow: hidden;
}
.NB-welcome-activity .NB-module-stats .NB-module-content-header-hour {
margin-top: 36px;
}
.NB-welcome-activity .NB-module-stats-count-graph {
margin-left: 4px;
}
.NB-welcome-activity .NB-graph-bar {
width: 4px;
}
.NB-welcome-activity .NB-graph-value {
width: 4px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 720 KiB

After

Width:  |  Height:  |  Size: 718 KiB

View file

@ -203,7 +203,7 @@
this.layout.outerLayout = this.$s.$body.layout({
closable: true,
zIndex: 1,
zIndex: 2,
fxName: "slideOffscreen",
fxSettings: { duration: 560, easing: "easeInOutQuint" },
center__paneSelector: ".right-pane",

View file

@ -1,42 +1,89 @@
NEWSBLUR.Welcome = Backbone.View.extend({
el: 'body',
flags: {},
rotation: 0,
events: {
"click .NB-button-login" : "show_signin_form",
"mouseenter .NB-welcome-header-caption" : "enter_header_caption",
"mouseleave .NB-welcome-header-caption" : "leave_header_caption"
},
initialize: function() {
this.start_rotation();
},
// ==========
// = Header =
// ==========
enter_header_caption: function(e) {
this.flags.on_header_caption = true;
var $caption = $(e.currentTarget);
if ($caption.hasClass('NB-welcome-header-caption-signin')) {
this.show_signin_form();
} else {
var r = parseInt($caption.data('ss'), 10);
this.rotate_screenshots(r);
}
},
leave_header_caption: function(e) {
var $caption = $(e.currentTarget);
console.log(["leave_header_caption", $caption]);
if ($caption.hasClass('NB-welcome-header-caption-signin')) {
} else {
this.flags.on_header_caption = false;
}
},
start_rotation: function() {
if (this.$('.NB-welcome-header-account').hasClass('NB-active')) {
this.show_signin_form();
}
this.$('.NB-welcome-header-image img').eq(0).load(_.bind(function() {
_.delay(_.bind(this.rotate_screenshots, this), 2000);
setInterval(_.bind(this.rotate_screenshots, this), 3000);
}, this));
},
rotate_screenshots: function() {
var r = this.rotation;
var $images = $('.NB-welcome-header-image img');
var $captions = $('.NB-welcome-header-caption');
var $in_img = $images.eq((r+1) % $images.length);
var $out_img = $images.eq(r % $images.length);
var $in_caption = $captions.eq((r+1) % $images.length);
var $out_caption = $captions.eq(r % $images.length);
rotate_screenshots: function(force, callback) {
if (this.flags.on_header_caption && _.isUndefined(force)) {
return;
}
$out_img.css({zIndex: 0}).animate({
var NUM_CAPTIONS = 3;
var r = force ? force - 1 : (this.rotation + 1) % NUM_CAPTIONS;
if (!force) {
this.rotation += 1;
}
var $images = $('.NB-welcome-header-image img').add('.NB-welcome-header-account');
var $captions = $('.NB-welcome-header-caption');
var $in_img = $images.eq(r);
var $out_img = $images.not($in_img);
var $in_caption = $captions.eq(r);
var $out_caption = $captions.not($in_caption);
$out_img.css({zIndex: 0}).stop(true).animate({
bottom: -300,
opacity: 0
}, {easing: 'easeInOutQuart', queue: false, duration: 1400});
$in_img.css({zIndex: 1, bottom: -300}).animate({
}, {easing: 'easeInOutQuart', queue: false, duration: force ? 650 : 1400, complete: callback});
$in_img.css({zIndex: 1}).stop(true).animate({
bottom: 0,
opacity: 1
}, {easing: 'easeInOutQuart', queue: false, duration: 1400});
}, {easing: 'easeInOutQuart', queue: false, duration: force ? 650 : 1400});
$out_caption.removeClass('NB-active');
$in_caption.addClass('NB-active');
this.rotation += 1;
_.delay(_.bind(this.rotate_screenshots, this), 3000);
},
show_signin_form: function() {
this.flags.on_header_caption = true;
this.rotate_screenshots(4, _.bind(function() {
this.$('input[name=login-username]').focus();
}, this));
}
});

View file

@ -22,15 +22,16 @@
<div class="NB-welcome-header">
<div class="NB-inner">
<div class="NB-welcome-header-logo">
<img src="{{ MEDIA_URL }}img/logo_newsblur.png" class="NB-module-logo-image" style="width: 312px; height: 55px;" />
<a href="/"><img src="{{ MEDIA_URL }}img/logo_newsblur.png" class="NB-module-logo-image" style="width: 312px; height: 55px;" /></a>
</div>
<div class="NB-welcome-header-tagline">
Focus on the best stories from<br><b>your friends</b> and <b>favorite blogs</b>
</div>
<div class="NB-welcome-header-captions">
<div class="NB-welcome-header-caption NB-1 NB-active"><span>Web</span></div>
<div class="NB-welcome-header-caption NB-2"><span>iPad &amp; iPhone</span></div>
<div class="NB-welcome-header-caption NB-3"><span>Android</span></div>
<div class="NB-welcome-header-caption NB-1 {% if not post_request %}NB-active{% endif %}" data-ss="1"><span>Web</span></div>
<div class="NB-welcome-header-caption NB-2" data-ss="2"><span>iPad &amp; iPhone</span></div>
<div class="NB-welcome-header-caption NB-3" data-ss="3"><span>Android</span></div>
<div class="NB-welcome-header-caption NB-welcome-header-caption-signin {% if post_request %}NB-active{% endif %}"><span>Sign in</span></div>
</div>
<div class="NB-welcome-header-actions">
<div class="NB-welcome-header-action">
@ -42,81 +43,79 @@
</div>
<div class="NB-welcome-header-action">
<div class="NB-welcome-header-action-subtext">Then</div>
<div class="NB-button NB-button-tryout">
<div class="NB-button NB-button-login">
<img src="{{ MEDIA_URL }}img/reader/32-Power.png" class="NB-welcome-header-action-bolt">
<img src="{{ MEDIA_URL }}img/reader/32-Arrow-Right.png" class="NB-welcome-header-action-arrow">
Sign up or Log in
</div>
</div>
</div>
<div class="NB-welcome-header-image">
<div class="NB-welcome-header-image {% if not post_request %}NB-active{% endif %}">
<img src="{{ MEDIA_URL }}img/welcome/header1.jpg" class="NB-1">
<img src="{{ MEDIA_URL }}img/welcome/header-ios.png" class="NB-2">
<img src="{{ MEDIA_URL }}img/welcome/header-android.png" class="NB-3">
</div>
<div class="NB-account">
<div class="NB-module NB-module-login">
<h5>
<div class="NB-module-header-login">Log in</div>
<div class="NB-module-header-signup">Sign up</div>
</h5>
<div class="NB-login">
{% if login_form.errors %}
{% for field, error in login_form.errors.items %}
{{ error|safe }}
{% endfor %}
{% endif %}
<form method="post" action="{% url login %}">
<div>
{{ login_form.username.label_tag }}
{{ login_form.username }}
</div>
<div>
<div class="NB-signup-optional">
{% if login_form.errors %}
{% for field, error in login_form.errors.items %}
<a href="mailto:password@newsblur.com?subject=Forgot%20Password%20on%20NewsBlur&amp;body=Hello!%20My%20username%20is:%20" class="NB-splash-link">Forgot?</a>
{% endfor %}
{% else %}
Optional
{% endif %}
</div>
{{ login_form.password.label_tag }}
{{ login_form.password }}
</div>
<input name="submit" type="submit" value="log in" />
<input type="hidden" name="next" value="/" />
</form>
</div>
<div class="NB-signup">
<form method="post" action="{% url signup %}">
<div>
{{ signup_form.username.label_tag }}
{{ signup_form.username }}
</div>
<div class="NB-signup-hidden">
<div class="NB-signup-optional">Optional</div>
{{ signup_form.password.label_tag }}
{{ signup_form.password }}
</div>
<div class="NB-signup-hidden">
{{ signup_form.email.label_tag }}
{{ signup_form.email }}
<div class="NB-welcome-header-account {% if post_request %}NB-active{% endif %}">
<div class="NB-account-header">
<div class="NB-module-header-login">Log in</div>
<div class="NB-module-header-signup">Sign up</div>
</div>
<div class="NB-login">
<form method="post" action="{% url login %}">
<div>
{{ login_form.username.label_tag }}
{{ login_form.username }}
</div>
<div>
<div class="NB-signup-optional">
{% if login_form.errors and login_form.errors|length %}
<a href="mailto:password@newsblur.com?subject=Forgot%20Password%20on%20NewsBlur&amp;body=Hello!%20My%20username%20is:%20" class="NB-splash-link">Forgot?</a>
{% else %}
Optional
{% endif %}
</div>
{{ login_form.password.label_tag }}
{{ login_form.password }}
</div>
<input name="submit" type="submit" class="NB-modal-submit-button NB-modal-submit-green" value="log in" />
<input type="hidden" name="next" value="/" />
</form>
{% if login_form.errors %}
{% for field, error in login_form.errors.items %}
{{ error|safe }}
{% endfor %}
{% else %}
<img src="{{ MEDIA_URL }}img/welcome/fleuron.png" style="width: 36px; height: 36px; opacity: .35; margin: 24px auto; display: block">
{% endif %}
</div>
<div class="NB-signup">
<form method="post" action="{% url signup %}">
<div>
{{ signup_form.username.label_tag }}
{{ signup_form.username }}
</div>
<div class="NB-signup-hidden">
<div class="NB-signup-optional">Optional</div>
{{ signup_form.password.label_tag }}
{{ signup_form.password }}
</div>
<div class="NB-signup-hidden">
{{ signup_form.email.label_tag }}
{{ signup_form.email }}
</div>
<input name="submit" type="submit" value="create account" />
<input type="hidden" name="next" value="/" />
</form>
{% if signup_form.errors %}
{% for field, error in signup_form.errors.items %}
{{ error|safe }}
{% endfor %}
{% endif %}
<div class="NB-signup-orline {% if signup_form.errors %}NB-signup-orline-reduced{% endif %}">&mdash; <span class="NB-signup-orline-or">or</span> &mdash;</div>
<a href="{% url google-reader-authorize %}" class="NB-splash-link NB-signup-google">Import from <img src="{{ MEDIA_URL }}img/reader/google-reader-logo.png" width="112" height="24" /></a>
</div>
<input name="submit" type="submit" class="NB-modal-submit-button NB-modal-submit-green" value="create account" />
<input type="hidden" name="next" value="/" />
</form>
{% if signup_form.errors %}
{% for field, error in signup_form.errors.items %}
{{ error|safe }}
{% endfor %}
{% endif %}
<div class="NB-signup-orline {% if signup_form.errors %}NB-signup-orline-reduced{% endif %}">&mdash; <span class="NB-signup-orline-or">or</span> &mdash;</div>
<a href="{% url google-reader-authorize %}" class="NB-splash-link NB-signup-google">Import from Google Reader</a>
</div>
</div>
@ -125,7 +124,26 @@
<div class="NB-welcome-features">
<div class="NB-inner">
<div class="NB-feature">
<img src="{{ MEDIA_URL }}img/welcome/feature_1.png">
<div class="NB-feature-caption">Real-time RSS</div>
<div class="NB-feature-text">Stories are pushed directly to you, so you can read news as it comes in.</div>
</div>
<div class="NB-feature">
<img src="{{ MEDIA_URL }}img/welcome/feature_2.png">
<div class="NB-feature-caption">Original site</div>
<div class="NB-feature-text">Read the content in context, the way it was meant to be seen.</div>
</div>
<div class="NB-feature">
<img src="{{ MEDIA_URL }}img/welcome/feature_3.png">
<div class="NB-feature-caption">Shared stories</div>
<div class="NB-feature-text">Reading news is better with friends. Shares stories on your blurblog.</div>
</div>
<div class="NB-feature">
<img src="{{ MEDIA_URL }}img/welcome/feature_4.png">
<div class="NB-feature-caption">Training</div>
<div class="NB-feature-text">Hide the stories you don't like and highlight the stories you do.</div>
</div>
</div>
</div>

View file

@ -8,58 +8,63 @@
Past day
</h3>
<div class="NB-module-stats-count">
<div class="NB-module-stats-count-number">{{ statistics.premium_users|commify }}</div>
<div class="NB-module-stats-count-description">Premium Users</div>
</div>
<div class="NB-module-stats-count">
<div class="NB-module-stats-count-number">{{ statistics.standard_users|commify }}</div>
<div class="NB-module-stats-count-description">Standard Users</div>
</div>
<div class="NB-module-stats-count">
<div class="NB-module-stats-count-number">{{ statistics.feeds_fetched|commify }}</div>
<div class="NB-module-stats-count-description">Feeds fetched</div>
<div class="NB-module-stats-counts">
<div class="NB-module-stats-count">
<div class="NB-module-stats-count-number">{{ statistics.premium_users|commify }}</div>
<div class="NB-module-stats-count-description">Premium Users</div>
</div>
<div class="NB-module-stats-count">
<div class="NB-module-stats-count-number">{{ statistics.standard_users|commify }}</div>
<div class="NB-module-stats-count-description">Standard Users</div>
</div>
<div class="NB-module-stats-count">
<div class="NB-module-stats-count-number">{{ statistics.feeds_fetched|commify }}</div>
<div class="NB-module-stats-count-description">Feeds fetched</div>
</div>
</div>
<h3 class="NB-module-content-header">
<h3 class="NB-module-content-header NB-module-content-header-hour">
Past day by hour
</h3>
<div class="NB-module-stats-count">
<div class="NB-module-stats-count-graph">
{% for i in statistics.sites_loaded %}<div class="NB-graph-value">
<div class="NB-graph-label">{{ i|commify }}</div>
<div class="NB-graph-bar" style="height:{{ i|format_graph:statistics.max_sites_loaded }}px"></div>
</div>{% endfor %}
</div>
<div class="NB-module-stats-count-number">{{ statistics.total_sites_loaded|commify }}</div>
<div class="NB-module-stats-count-description">Sites loaded</div>
</div>
<div class="NB-module-stats-count">
<div class="NB-module-stats-count-graph">
{% for i in statistics.avg_time_taken %}
<div class="NB-graph-value">
<div class="NB-graph-label">{{ i|floatformat:2 }}</div>
<div class="NB-graph-bar" style="height:{{ i|format_graph:statistics.max_avg_time_taken }}px"></div>
<div class="NB-module-stats-counts">
<div class="NB-module-stats-count">
<div class="NB-module-stats-count-graph">
{% for i in statistics.sites_loaded %}<div class="NB-graph-value">
<div class="NB-graph-label">{{ i|commify }}</div>
<div class="NB-graph-bar" style="height:{{ i|format_graph:statistics.max_sites_loaded }}px"></div>
</div>{% endfor %}
</div>
<div class="NB-module-stats-count-number">{{ statistics.total_sites_loaded|commify }}</div>
<div class="NB-module-stats-count-description">Sites loaded</div>
</div>
{% endfor %}
</div>
<div class="NB-module-stats-count-number">{{ statistics.latest_avg_time_taken|floatformat:2 }} <small>sec</small></div>
<div class="NB-module-stats-count-description">Avg. load time</div>
</div>
<div class="NB-module-stats-count">
<div class="NB-module-stats-count-graph">
{% for i in statistics.stories_shared %}
<div class="NB-graph-value">
<div class="NB-graph-label">{{ i|commify }}</div>
<div class="NB-graph-bar" style="height:{{ i|format_graph:statistics.max_stories_shared }}px"></div>
<div class="NB-module-stats-count">
<div class="NB-module-stats-count-graph">
{% for i in statistics.avg_time_taken %}
<div class="NB-graph-value">
<div class="NB-graph-label">{{ i|floatformat:2 }}</div>
<div class="NB-graph-bar" style="height:{{ i|format_graph:statistics.max_avg_time_taken }}px"></div>
</div>
{% endfor %}
</div>
<div class="NB-module-stats-count-number">{{ statistics.latest_avg_time_taken|floatformat:2 }} <small>sec</small></div>
<div class="NB-module-stats-count-description">Avg. load time</div>
</div>
<div class="NB-module-stats-count">
<div class="NB-module-stats-count-graph">
{% for i in statistics.stories_shared %}
<div class="NB-graph-value">
<div class="NB-graph-label">{{ i|commify }}</div>
<div class="NB-graph-bar" style="height:{{ i|format_graph:statistics.max_stories_shared }}px"></div>
</div>
{% endfor %}
</div>
<div class="NB-module-stats-count-number">{{ statistics.total_stories_shared|commify }}</div>
<div class="NB-module-stats-count-description">
{% if statistics.latest_stories_shared == 1 %}Story{% else %}Stories{% endif %} Shared
</div>
</div>
{% endfor %}
</div>
<div class="NB-module-stats-count-number">{{ statistics.total_stories_shared|commify }}</div>
<div class="NB-module-stats-count-description">
{% if statistics.latest_stories_shared == 1 %}Story{% else %}Stories{% endif %} Shared
</div>
</div>
</div>