Working on building out a proper account management page.

master
Nick Sergeant 2013-01-12 12:45:20 -05:00
parent 28cfc79310
commit 6f34a45e35
10 changed files with 359 additions and 335 deletions

0
accounts/forms.py Normal file
View File

View File

@ -0,0 +1,24 @@
{% extends "base.html" %}
{% block page-title %}/ Account - {{ block.super }}{% endblock %}
{% block body-class %}{{ block.super }} static account{% endblock %}
{% block breadcrumb %}
<li><a href="/account/">Account</a></li>
{% endblock %}
{% block content %}
<div class="static-box">
<h2>Account settings</h2>
<ul>
<li><a href="/api/">API</a> key: {{ request.user.api_key.key }}</li>
<li><a href="/api/">API</a> user ID: {{ request.user.id }}</li>
<li><a href="/password/change/">Change password</a></li>
{% if request.user.profile.is_pro %}
<li>Pro since: </li>
<li>GitTip username:</li>
{% endif %}
</ul>
</div>
{% endblock %}

View File

@ -2,12 +2,13 @@
{% load pagination_tags %}
{% block page-title %}Stats {{ block.super }}{% endblock %}
{% block page-title %}/ Stats / Account - {{ block.super }}{% endblock %}
{% block body-class %}{{ block.super }} static stats{% endblock %}
{% block breadcrumb %}
<li><a href="/stats/">Stats</a></li>
<li><a href="/account/">Account</a></li>
<span class="prompt">/</span> <li><a href="/account/stats/">Stats</a></li>
{% endblock %}
{% block content %}

8
accounts/urls.py Normal file
View File

@ -0,0 +1,8 @@
from django.conf.urls.defaults import *
from accounts import views
urlpatterns = patterns('',
url(r'^$', views.account, name='account-detail'),
url(r'^stats/$', views.stats, name='account-stats'),
)

View File

@ -1 +1,22 @@
# Create your views here.
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect
from annoying.decorators import render_to
from snipts.models import Snipt
@login_required
@render_to('account.html')
def account(request):
return {}
@login_required
@render_to('stats.html')
def stats(request):
if not request.user.profile.is_pro:
return HttpResponseRedirect('/pro/')
snipts = Snipt.objects.filter(user=request.user).order_by('-views')
return {
'snipts': snipts
}

View File

@ -1369,13 +1369,116 @@ div.site-notice {
text-decoration: underline;
}
}
body.detail {
div.site-notice {
margin-right: 100px;
}
}
// Pages
body.api {
section.main {
div.inner {
div.sifter {
margin-bottom: 0;
margin-top: 10px;
margin-right: 100px;
a.sifter-logo {
float: left;
img {
height: 30px;
margin: 0;
margin-top: 10px;
}
}
div.right {
float: left;
margin-left: 10px;
padding-top: 10px;
h3 {
margin: 0;
}
p {
margin: 0;
}
}
}
section.snipts {
article.snipt {
div.container {
header {
h1 {
a {
white-space: normal;
}
}
}
section.code {
height: auto;
}
}
}
}
}
aside.api-info {
float: right;
width: 190px;
div.api-inner {
background: rgba(#99D0DA, .3);
font: normal 11px $Helvetica;
margin: 0 0 30px 15px;
padding: 10px;
@include border-radius(8px);
h5 {
margin-bottom: 5px;
margin-top: 0;
}
ul {
margin: 0;
li {
margin: 2px 0;
list-style-type: none;
input {
margin-bottom: 0;
margin-top: 5px;
width: 145px;
}
}
}
}
&.api-creds {
div.api-inner {
margin-bottom: 0;
}
}
&.immediate-help {
margin-top: 20px;
p {
margin: 0;
}
}
}
aside.main {
nav.footer {
float: left;
margin-bottom: 0;
}
}
}
div#disqus_thread {
width: 719px;
}
}
body.blog {
article.snipt {
section.code {
height: auto;
}
}
}
body.detail {
div.right-y {
display: none;
@ -1448,106 +1551,8 @@ body.detail {
div.rochester-made {
width: 840px;
}
}
body.is-pro {
section.main {
div.inner {
section.snipts {
article.snipt {
margin-bottom: 0;
margin-top: 30px;
}
}
}
}
}
body.static {
.static-box {
background: rgba(#FFF, .65);
border: 1px solid #DDDDDD;
margin: 30px;
padding: 20px;
@include border-radius(4px);
div.form-actions {
margin-bottom: 0;
padding-bottom: 0;
@include vertical-gradient(#F5F5F5, #FBFBFB);
a.pull-right {
margin-left: 5px;
}
}
div.alert {
ul {
margin: 0;
li {
list-style-type: none;
}
}
}
div.alert-info {
a {
color: #3A87AD;
text-decoration: underline;
}
}
ul {
margin-bottom: 15px;
margin-top: 15px;
li {
font-size: 13px;
line-height: 18px;
margin: 5px 0;
}
}
h2 {
font-size: 24px;
line-height: 36px;
margin: 0;
}
h3 {
margin-bottom: 20px;
}
p {
line-height: 20px;
margin: 15px 0;
}
}
aside.main {
padding-top: 30px;
nav.footer {
margin-top: 10px;
}
}
div.alert-alone {
margin: 0;
}
form.form-horizontal {
legend + .control-group {
margin-top: 0;
}
div.form-actions {
margin-top: 27px;
}
fieldset {
padding-top: 27px;
legend {
margin: 0;
}
}
}
div#disqus_thread {
margin-left: 20px;
width: 709px;
div#dsq-content {
margin-top: 23px;
}
div.site-notice {
margin-right: 100px;
}
}
body.editing {
@ -1707,133 +1712,80 @@ body.error {
margin-top: 54px;
}
}
body.search {
div.empty-snipts {
margin-top: 20px;
}
div.static-box {
border-left: 0;
margin-left: 0;
margin-right: 30px;
@include multi-border-radius(0px, 4px, 4px, 0px);
form {
margin-bottom: 0;
input.search-query {
width: 564px;
}
button {
padding: 4px 16px 4px;
}
}
}
}
body.api {
body.is-pro {
section.main {
div.inner {
div.sifter {
margin-bottom: 0;
margin-top: 10px;
margin-right: 100px;
a.sifter-logo {
float: left;
img {
height: 30px;
margin: 0;
margin-top: 10px;
}
}
div.right {
float: left;
margin-left: 10px;
padding-top: 10px;
h3 {
margin: 0;
}
p {
margin: 0;
}
}
}
section.snipts {
article.snipt {
div.container {
header {
h1 {
a {
white-space: normal;
}
}
}
section.code {
height: auto;
}
}
}
}
}
aside.api-info {
float: right;
width: 190px;
div.api-inner {
background: rgba(#99D0DA, .3);
font: normal 11px $Helvetica;
margin: 0 0 30px 15px;
padding: 10px;
@include border-radius(8px);
h5 {
margin-bottom: 5px;
margin-top: 0;
}
ul {
margin: 0;
li {
margin: 2px 0;
list-style-type: none;
input {
margin-bottom: 0;
margin-top: 5px;
width: 145px;
}
}
}
}
&.api-creds {
div.api-inner {
margin-bottom: 0;
}
}
&.immediate-help {
margin-top: 20px;
p {
margin: 0;
margin-top: 30px;
}
}
}
aside.main {
nav.footer {
float: left;
margin-bottom: 0;
}
}
}
div#disqus_thread {
width: 719px;
}
}
body.blog {
article.snipt {
section.code {
height: auto;
body.jobs {
section.jobs {
margin: 30px;
h4 {
border-bottom: 1px solid #C0C0C0;
color: #999999;
font-size: 14px;
margin-top: 30px;
padding-bottom: 5px;
padding-left: 10px;
}
ul {
margin: 0;
li {
list-style-type: none;
margin: 10px 0;
a {
background: #FBFBFB;
border: 1px solid #DDDDDD;
color: #333333;
display: block;
padding: 10px;
@include border-radius;
@include box-shadow(0, 1px, 1px, rgba(0, 0, 0, .3));
&:hover {
background: rgba(#FBFBFB, .5);
}
span.left {
float: left;
span {
display: block;
&.job {
color: #3096B4;
font-size: 16px;
font-weight: bold;
margin-bottom: 4px;
}
}
}
span.right {
float: right;
span {
display: block;
text-align: right;
&.location {
color: #999999;
font-size: 16px;
font-weight: bold;
margin-bottom: 4px;
}
}
}
}
}
}
}
}
@ -1956,6 +1908,122 @@ body.pro {
}
}
}
body.search {
div.empty-snipts {
margin-top: 20px;
}
div.static-box {
border-left: 0;
margin-left: 0;
margin-right: 30px;
@include multi-border-radius(0px, 4px, 4px, 0px);
form {
margin-bottom: 0;
input.search-query {
width: 564px;
}
button {
padding: 4px 16px 4px;
}
}
}
}
body.static {
.static-box {
background: rgba(#FFF, .65);
border: 1px solid #DDDDDD;
margin: 30px;
padding: 20px;
@include border-radius(4px);
div.form-actions {
margin-bottom: 0;
padding-bottom: 0;
@include vertical-gradient(#F5F5F5, #FBFBFB);
a.pull-right {
margin-left: 5px;
}
}
div.alert {
ul {
margin: 0;
li {
list-style-type: none;
}
}
}
div.alert-info {
a {
color: #3A87AD;
text-decoration: underline;
}
}
ul {
margin-bottom: 15px;
margin-top: 15px;
li {
font-size: 13px;
line-height: 18px;
margin: 5px 0;
}
}
h2 {
font-size: 24px;
line-height: 36px;
margin: 0;
}
h3 {
margin-bottom: 20px;
}
p {
line-height: 20px;
margin: 15px 0;
}
}
aside.main {
padding-top: 30px;
nav.footer {
margin-top: 10px;
}
}
div.alert-alone {
margin: 0;
}
form.form-horizontal {
legend + .control-group {
margin-top: 0;
}
div.form-actions {
margin-top: 27px;
}
fieldset {
padding-top: 27px;
legend {
margin: 0;
}
}
}
div#disqus_thread {
margin-left: 20px;
width: 709px;
div#dsq-content {
margin-top: 23px;
}
}
}
body.stats {
table {
margin-bottom: 0;
}
}
body.tags {
div.alert {
margin: 30px 30px 10px 30px;
@ -1975,73 +2043,3 @@ body.tags {
padding-top: 30px;
}
}
body.stats {
table {
margin-bottom: 0;
}
}
body.jobs {
section.jobs {
margin: 30px;
h4 {
border-bottom: 1px solid #C0C0C0;
color: #999999;
font-size: 14px;
margin-top: 30px;
padding-bottom: 5px;
padding-left: 10px;
}
ul {
margin: 0;
li {
list-style-type: none;
margin: 10px 0;
a {
background: #FBFBFB;
border: 1px solid #DDDDDD;
color: #333333;
display: block;
padding: 10px;
@include border-radius;
@include box-shadow(0, 1px, 1px, rgba(0, 0, 0, .3));
&:hover {
background: rgba(#FBFBFB, .5);
}
span.left {
float: left;
span {
display: block;
&.job {
color: #3096B4;
font-size: 16px;
font-weight: bold;
margin-bottom: 4px;
}
}
}
span.right {
float: right;
span {
display: block;
text-align: right;
&.location {
color: #999999;
font-size: 16px;
font-weight: bold;
margin-bottom: 4px;
}
}
}
}
}
}
}
}

View File

@ -106,37 +106,31 @@
<li>
<a href="/{{ request.user.username }}/">
<i class="icon-user icon-white"></i>
View profile
Profile
</a>
</li>
{% if request.user.profile.is_pro %}
<li>
<a href="/stats/">
<a href="/account/stats/">
<i class="icon-star icon-white"></i>
View stats
Stats
</a>
</li>
{% endif %}
<li>
<a href="/api/">
<i class="icon-fire icon-white"></i>
Get your API Key
<a href="/account/">
<i class="icon-cog icon-white"></i>
Account
</a>
</li>
{% if not request.user.profile.is_pro %}
<li>
<a href="/pro/">
<i class="icon-star-empty icon-white"></i>
Upgrade to Pro
Go Pro
</a>
</li>
{% endif %}
<li>
<a href="/password/change/">
<i class="icon-wrench icon-white"></i>
Change password
</a>
</li>
{% if request.user.is_superuser %}
<li>
<a href="/admin/">

View File

@ -14,9 +14,10 @@
<p>We're still building our <span class="pro">Pro</span> platform, but it already kicks ass. By becoming a Pro now, you'll also get access to future Pro features the moment they're released.</p>
<h6>Current Pro features:</h6>
<ul>
<li>No advertisements.</li>
<li>Stats on "views" and "favorites" for your snipts.</li>
<li>No ads.</li>
<li>Statistics for "views" and "favorites" of your snipts.</li>
<li>&ldquo;Pro&rdquo; badge throughout the site.</li>
<li>GitTip</li>
<li>Custom domain for your <a href="https://blog.snipt.net/announcing-the-sniptnet-blogging-platform/">Snipt blog</a>. Contact <a href="mailto:support@snipt.net">support@snipt.net</a> to set it up.</li>
</ul>
{% if request.user.profile.is_pro %}

View File

@ -1,5 +1,4 @@
from views import (jobs, lexers, pro_signup,
sitemap, tags, pro_signup_complete, stats)
from views import (lexers, pro_signup, sitemap, tags, pro_signup_complete)
from django.conf.urls.defaults import include, patterns, url
from django.views.generic.simple import direct_to_template
from utils.forms import SniptRegistrationForm
@ -41,8 +40,7 @@ urlpatterns = patterns('',
url(r'^pro/signup/$', pro_signup),
url(r'^pro/signup/complete/$', pro_signup_complete),
#url(r'^jobs/$', jobs),
url(r'^stats/$', stats),
url(r'^account/', include('accounts.urls')),
url(r'^api/public/lexer/$', lexers),

View File

@ -1,16 +1,12 @@
from django.http import HttpResponseRedirect, HttpResponseBadRequest
from django.contrib.auth.decorators import login_required
from annoying.decorators import ajax_request, render_to
from django.template.defaultfilters import striptags
from django.shortcuts import render_to_response
from django.template import RequestContext
from snipts.utils import get_lexers_list
from django.db.models import Count
from django.conf import settings
from snipts.models import Snipt
from taggit.models import Tag
import os, urllib
import stripe
@ -43,10 +39,6 @@ def lexers(request):
return {'objects': objects}
@render_to('jobs.html')
def jobs(request):
return {}
@login_required
@render_to('pro-signup.html')
def pro_signup(request):
@ -92,19 +84,6 @@ def sitemap(request):
context_instance=RequestContext(request),
mimetype='application/xml')
@login_required
@render_to('stats.html')
def stats(request):
if not request.user.profile.is_pro:
return HttpResponseRedirect('/pro/')
snipts = Snipt.objects.filter(user=request.user).order_by('-views')
return {
'snipts': snipts
}
@render_to('tags.html')
def tags(request):