Implemented questions template (bug 565367)

This commit is contained in:
Ricky Rosario 2010-05-24 16:44:28 -04:00
Родитель e291839071
Коммит 8eb19c64b4
22 изменённых файлов: 662 добавлений и 31 удалений

Просмотреть файл

@ -0,0 +1,5 @@
# The number of answers per page.
ANSWERS_PER_PAGE = 20
# The number of questions per page.
QUESTIONS_PER_PAGE = 20

Просмотреть файл

@ -1,15 +1,13 @@
{# vim: set ts=2 et sts=2 sw=2: #}
{% extends "common/base.html" %}
{% extends "questions/base.html" %}
{# L10n: {q} is the title of the question. {f} is the name of the question forum. #}
{% set title = _('{q} | {f} | Questions')|f(q=question.title, f=forum.name) %}
{% set crumbs = [(url('questions.question_forums'), _('Questions')),
(url('questions.questions', forum_slug=forum.slug), forum.name),
(None, question.title)] %}
{% set classes = 'answers' %}
{% block content %}
<h2>{{ question.title }}</h2>
{% if answers %}
{% if answers.object_list %}
<ol class="answers">
{% for answer in answers.object_list %}
<li id="answer-{{ answer.id }}">

Просмотреть файл

@ -0,0 +1,88 @@
{# vim: set ts=2 et sts=2 sw=2: #}
{% extends "layout/base.html" %}
{% set styles = ('questions',) %}
{% set scripts = ('questions',) %}
{% block content_area %}
<div id="main-hdr">
<hgroup>
<h1><a href="{{ url('questions.questions', forum_slug=forum.slug) }}">{{ _('Firefox Support Forum') }}</a></h1>
<h2>{{ _('The Official Community-Driven Support Web Site for Firefox') }}</h2>
</hgroup>
<div id="support-search" role="search">
<form action="#{# TODO #}" method="get">
<div class="wrap">
<input type="text" class="text" name="q" placeholder="{{ _('Search Mozilla Support') }}" required="required" />
</div>
<noscript>
<input type="submit" class="submit" value="{{ _('Search') }}" />
</noscript>
</form>
</div>
<div id="greeting">
{% if user.is_authenticated() %}
{{ _('Welcome, <span class="user">{user}</span>.')|fe(user=user) }}
<nav>
<a href="{{ profile_url(user) }}">{{ _('Profile') }}</a>
&bull;
<a href="{{ settings.LOGOUT_URL }}">{{ _('Sign Out') }}</a>
</nav>
{% else %}
<p>
{% trans login_url=settings.LOGIN_URL, register_url=settings.REGISTER_URL %}
Want to contribute? <a href="{{ login_url }}">Sign In</a> or <a href="{{ register_url }}">Register</a>
{% endtrans %}
{% endif %}
</div>
</div>
{% block filter %}
{% endblock %}
<div id="main-content">
{% block content %}
{% endblock %}
</div>
<div id="main-sd">
{% block side %}
<div class="sd-module" id="ask-question">
<h3>{{ _("Can't Find an Answer?") }}</h3>
<p>{{ _('Post your question to the support forum. The Firefox community is here to help!') }}</p>
<div class="ask-question">
<a href="{{ url('questions.new_question', forum_slug=forum.slug) }}">
<span class="q">?</span>
{{ _('Ask a Question') }}
</a>
</div>
</div>
<div class="sd-module" id="top-contributors">
<h3>{{ _('Top Contributors') }}</h3>
<h4>{{ _('Most Solutions this Week') }}</h4>
<ol>
{# TODO #}
<li>Lorem Ipsum</li>
<li>Dolor sit Amet</li>
<li>Consectetur Adipisicing</li>
<li>Sed do Eiusmod</li>
<li>Tempor Incididunt</li>
<li>Labore Dolore</li>
<li>Magna Aliqua</li>
<li>Enim Minim</li>
<li>Veniam Nostrud</li>
<li>Exercitation Ullamco</li>
</ol>
</div>
{% endblock %}
</div>
{% endblock %}
{% block breadcrumbs %}
{% endblock %}
{% block sidebar %}
{% endblock %}

Просмотреть файл

@ -1,22 +1,152 @@
{# vim: set ts=2 et sts=2 sw=2: #}
{% extends "common/base.html" %}
{% extends "questions/base.html" %}
{% set title = _('{f} | Questions')|f(f=forum.name) %}
{% set crumbs = [(url('questions.question_forums'), _('Questions')),
(None, forum.name)] %}
{% set classes = 'questions' %}
{% block filter %}
<div id="filter">
<label>{{ _('Posts:') }}</label>
<ul>
{% if user.is_authenticated() %}
<li>
<a href="#{# TODO #}">{{ _('My Contributions') }}</a>
</li>
{% endif %}
<li>
<a href="#{# TODO #}">{{ _('Most Recent') }}</a>
</li>
<li class="active {# TODO: conditional logic #}">
<a href="#{# TODO #}">{{ _('Most Requested') }}</a>
</li>
<li>
<a href="#{# TODO #}">{{ _('Unsolved') }}</a>
</li>
<li>
<a href="#{# TODO #}">{{ _('Solved') }}</a>
</li>
<li>
<a href="#{# TODO #}">{{ _('No Replies') }}</a>
</li>
</ul>
</div>
{% endblock %}
{% block content %}
<h2>{{ forum.name }}</h2>
{% if threads %}
<ul>
{% for question in questions %}
<li><a href="{{ url('questions.answers', forum_slug=forum.slug, question_id=question.id) }}">{{ question.title }}</a><br/>
Answers: {{ question.answers }} | Last answer by {{ question.last_answer.creator.username }}</li>
{% if questions.object_list %}
<ol class="questions">
{% for question in questions.object_list %}
<li>
<div class="people just-one {# possible classes are: just-one (==1), less-ten (<10), more-ten (>=10) #}">
{% trans %}{# TODO #}<strong>1 person</strong> <span>has this problem</span>{% endtrans %}
</div>
<div class="title">
<h2><a href="{{ url('questions.answers', forum_slug=forum.slug, question_id=question.id) }}">{{ question.title }}</a></h2>
</div>
<div class="asked-by">
{% trans creator=question.creator%}Asked by <span class="user">{{ creator }}</span>{% endtrans %}
<time>{{ datetimeformat(question.created, format='longdatetime') }}</time>
</div>
<p>{{ question.content|striptags()|truncate(170) }}</p>
<div class="meta">
<span>{# TODO #}Firefox Mobile 1.0</span>
&bull;
<span>{# TODO #}Mac OS X 10.6</span>
&bull;
<span>{{ _('Tagged') }} {# TODO #}lorem, ipsum, dolor, sit amet</span>
</div>
</li>
{% endfor %}
</ul>
{# Some extra static questions with different variations #}
<li>
<div class="people less-ten">
{% trans %}{# TODO #}<strong>9 people</strong> <span>have this problem</span>{% endtrans %}
</div>
<div class="title">
<h2><a href="#">Lorem ipsum dolor sit amet, conectetur adipisicing elit, sed do eiusmod tempor</a></h2>
<span class="badge replies">12 replies</span>
</div>
<div class="asked-by">
Asked by <span class="user">Noob</span>
<time>today at 10:41am</time>
</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation...</p>
<div class="meta">
<span>Firefox Mobile 1.0</span>
&bull;
<span>Mac OS X 10.6</span>
&bull;
<span>{{ _('Tagged') }} lorem, ipsum, dolor, sit amet</span>
</div>
</li>
<li>
<div class="people more-ten">
{% trans %}{# TODO #}<strong>25 people</strong> <span>have this problem</span>{% endtrans %}
</div>
<div class="title">
<h2><a href="#">Lorem ipsum dolor sit amet, conectetur adipisicing elit, sed do eiusmod tempor</a></h2>
<span class="badge solutions">3 solutions</span>
</div>
<div class="asked-by">
Asked by <span class="user">Noob</span>
<time>today at 10:41am</time>
</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation...</p>
<div class="meta">
<span>Firefox Mobile 1.0</span>
&bull;
<span>Mac OS X 10.6</span>
&bull;
<span>{{ _('Tagged') }} lorem, ipsum, dolor, sit amet</span>
</div>
</li>
<li>
<div class="people more-ten">
{% trans %}{# TODO #}<strong>35 people</strong> <span>have this problem</span>{% endtrans %}
</div>
<div class="title">
<h2><a href="#">Lorem ipsum dolor sit amet, conectetur adipisicing elit, sed do eiusmod tempor</a></h2>
<span class="badge solved">solved</span>
</div>
<div class="asked-by">
Asked by <span class="user">Noob</span>
<time>today at 10:41am</time>
</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation...</p>
<div class="meta">
<span>Firefox Mobile 1.0</span>
&bull;
<span>Mac OS X 10.6</span>
&bull;
<span>{{ _('Tagged') }} lorem, ipsum, dolor, sit amet</span>
</div>
</li>
<li>
<div class="people more-ten">
{% trans %}{# TODO #}<strong>35 people</strong> <span>have this problem</span>{% endtrans %}
</div>
<div class="title">
<h2><a href="#">Lorem ipsum dolor sit amet, conectetur adipisicing elit, sed do eiusmod tempor</a></h2>
<span class="badge contributed">contributed</span>
</div>
<div class="asked-by">
Asked by <span class="user">Noob</span>
<time>today at 10:41am</time>
</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation...</p>
<div class="meta">
<span>Firefox Mobile 1.0</span>
&bull;
<span>Mac OS X 10.6</span>
&bull;
<span>{{ _('Tagged') }} lorem, ipsum, dolor, sit amet</span>
</div>
</li>
</ol>
{{ questions|paginator }}
{% else %}
{# Not localized because it's not worth localizers time. #}
<p>There are no questions. Maybe you should ask some!</p>
{% endif %}
{% endblock %}

Просмотреть файл

@ -4,6 +4,7 @@ import jingo
from sumo.utils import paginate
from .models import QuestionForum, Question
import questions as constants
def question_forums(request):
@ -20,7 +21,8 @@ def questions(request, forum_slug):
forum = get_object_or_404(QuestionForum, slug=forum_slug)
questions_ = paginate(forum.question_set.all())
questions_ = paginate(request, forum.questions.all(),
per_page=constants.QUESTIONS_PER_PAGE)
return jingo.render(request, 'questions/questions.html',
{'forum': forum, 'questions': questions_})
@ -32,7 +34,8 @@ def answers(request, forum_slug, question_id):
forum = get_object_or_404(QuestionForum, slug=forum_slug)
question = get_object_or_404(Question, pk=question_id)
answers_ = paginate(question.answer_set.all())
answers_ = paginate(request, question.answers.all(),
per_page=constants.ANSWERS_PER_PAGE)
return jingo.render(request, 'questions/answers.html',
{'forum': forum, 'question': question,

Просмотреть файл

@ -368,6 +368,7 @@ h2 {
----------------------------------*/
#content {
clear:both;
width: 920px;
margin: auto;
text-align: left;

348
media/css/questions.css Normal file
Просмотреть файл

@ -0,0 +1,348 @@
/*
* Questions forums CSS
*/
/* base style overrides */
body {
background: #fff url(../img/background-feature.jpg) repeat-x center -65px;
}
/* main header */
#main-hdr {
height: 200px;
}
#main-hdr hgroup {
float: left;
padding: 45px 0 0 25px;
width: 600px;
}
#main-hdr h1 {
color: #fff;
font-size: 46px;
line-height: 46px;
}
#main-hdr h1 a {
color: #fff;
}
#main-hdr h2 {
color: #4B4741;
font-size: 18px;
margin: .5em 0 0;
}
#support-search, #greeting {
float: right;
padding: 0 20px 0 0;
width: 260px;
}
#support-search {
padding-top: 50px;
}
#support-search div.wrap {
background: #fff url(../img/questions/icon.search.gif) no-repeat 6px 3px;
border: solid 1px #87c4dc;
border-radius: 15px;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
float:left;
padding:0 10px 0 30px;
}
#support-search input.text {
border: none;
font-size: 14px;
padding: 4px 0;
width: 225px;
}
#greeting {
color: #807970;
font-family: Verdana;
font-size: 12px;
margin: 20px 0 0;
text-align: right;
}
#greeting span.user {
color: #4B4740;
}
#greeting nav a:first-child {
padding: 0 0 0 5px;
}
/* Questions filter */
#filter {
font-size: 14px;
height: 30px;
margin: 0 0 10px;
padding: 0 0 0 25px;
}
#filter label {
color: #898378;
float: left;
padding: 4px 0;
}
#filter ul {
float: left;
list-style: none;
padding: 0 0 0 5px;
}
#filter li {
float: left;
list-style: none;
}
#filter li a {
float:left;
padding: 4px 10px;
}
#filter li a:hover {
text-decoration: underline;
}
#filter li.active a {
background: #009ac3;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
color: #fff;
}
/* main content layout */
#main-content {
float: left;
width: 640px;
}
#main-sd {
float: right;
width: 235px;
}
/* questions list */
ol.questions {
border-top: solid 2px #edece9;
color: #898378;
list-style: none;
margin: 0 0 0 10px;
}
ol.questions li {
border-bottom: solid 2px #edece9;
list-style: none;
padding: 15px 15px 18px;
}
ol.questions div.people {
float: right;
text-align: right;
width: 150px;
}
ol.questions div.people strong {
display: block;
float: right;
padding: 5px 0 5px 50px;
}
div.people.just-one strong {
background: transparent url(../img/questions/icon.one.gif) no-repeat 27px 6px;
}
div.people.less-ten strong {
background: transparent url(../img/questions/icon.lessten.gif) no-repeat 25px 6px;
}
div.people.more-ten strong {
background: transparent url(../img/questions/icon.tenmore.gif) no-repeat 0 6px;
}
ol.questions div.people span {
clear: right;
display: block;
}
ol.questions div.title h2 {
font-size: 17px;
display: inline;
line-height: 25px;
}
ol.questions span.badge {
border-radius: 4px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
display: inline-block;
font-family: Verdana;
font-size: 12px;
margin: 0 0 0 10px;
padding: 3px 7px 3px 25px;
}
ol.questions span.badge.replies {
background: #eaf4f8 url(../img/questions/icon.replies.gif) no-repeat 5px center;
color: #0489B6;
}
ol.questions span.badge.solutions {
background: #fff0cb url(../img/questions/icon.solutions.gif) no-repeat 5px center;
color: #926E2D;
text-transform: uppercase;
}
ol.questions span.badge.solved {
background: #d3e8ca url(../img/questions/icon.solved.gif) no-repeat 5px center;
color: #377300;
text-transform: uppercase;
}
ol.questions span.badge.contributed {
background: #eaf4f8 url(../img/questions/icon.contributed.gif) no-repeat 5px center;
color: #0489B6;
}
ol.questions div.asked-by {
font-size: 14px;
margin: 7px 0;
}
ol.questions div.asked-by span.user {
color: #4B4740;
}
ol.questions p {
margin: 3px 0 0;
}
ol.questions div.meta {
margin: 10px 0 0;
}
/* questions pagination */
ol.pagination {
font-family: Verdana;
margin: 1.5em auto 0;
padding: 0 0 0 25px;
}
ol.pagination li {
float: left;
padding: 0 2px;
}
ol.pagination li[rel="prev"] {
padding-left: 0;
}
ol.pagination li a {
float: left;
padding: 4px 8px;
}
ol.pagination li a:hover {
text-decoration: underline;
}
ol.pagination li[rel="prev"] a {
padding-left: 0;
}
ol.pagination li.selected a {
background: #0489B6;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
color: #fff;
cursor: default;
}
ol.pagination li.selected a:hover {
text-decoration:none;
}
/* side modules */
div.sd-module {
background:transparent url(../img/questions/bkg.askquestion.gif) no-repeat;
padding: 15px;
}
div.sd-module h3 {
color: #4B4740;
font-size: 20px;
}
div.sd-module h4 {
color: #4B4740;
font-size: 14px;
font-weight: normal;
margin: 5px 0 0;
}
div.sd-module p {
color: #898378;
font-size: 14px;
margin: 20px 0 0;
}
/* ask a question */
#ask-question div.ask-question {
margin: 15px 0 0;
}
#ask-question div.ask-question a {
background: #F6D600;
background: -moz-linear-gradient(top, #FDF9D8, #F6D600);
background: -webkit-gradient(linear, left top, left bottom, from(#FDF9D8), to(#F6D600));
border: solid 1px #DA7C2F;
border-radius: 6px;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
box-shadow: 2px 4px 5px #aaa;
-moz-box-shadow: 2px 4px 5px #aaa;
-webkit-box-shadow: 2px 4px 5px #aaa;
color: #D13E05;
display: block;
font-family: Verdana;
font-size: 12px;
font-weight: bold;
padding: 10px;
text-shadow: #fff 0 1px 0;
width: 180px;
}
#ask-question div.ask-question a span.q{
background: #fff;
border: solid 1px #DA7C2F;
border-radius: 15px;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
margin: 0 5px 0 0;
padding: 3px 7px 3px 8px;
}
/* top contributors */
#top-contributors {
margin: 30px 0 0;
}
#top-contributors ol {
color: #898378;
font-size: 14px;
margin: 10px 0 0 22px;
}
#top-contributors li {
margin: 0 0 5px;
}

Двоичные данные
media/img/questions/bkg.askquestion.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 13 KiB

Двоичные данные
media/img/questions/icon.contributed.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 544 B

Двоичные данные
media/img/questions/icon.lessten.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.0 KiB

Двоичные данные
media/img/questions/icon.one.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 994 B

Двоичные данные
media/img/questions/icon.replies.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1021 B

Двоичные данные
media/img/questions/icon.search.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 172 B

Двоичные данные
media/img/questions/icon.solutions.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 594 B

Двоичные данные
media/img/questions/icon.solved.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 345 B

Двоичные данные
media/img/questions/icon.tenmore.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.3 KiB

Просмотреть файл

Просмотреть файл

13
media/js/libs/modernizr-1.1.min.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

33
media/js/questions.js Normal file
Просмотреть файл

@ -0,0 +1,33 @@
/*
* questions.js
* Scripts for the questions app.
*/
(function($){
function init() {
initSearch();
}
/*
* Initialize the search widget
*/
function initSearch() {
var $input = $('#support-search input[name="q"]');
// check for html5 placeholder support and fallback to js solution
if (!Modernizr.input.placeholder) {
$input.autoFillHelpText($input.attr('placeholder'));
}
// submit the form on Enter
$input.keyup(function(ev) {
if(ev.keyCode === 13 && $input.val()) {
$('#support-search form').submit();
}
});
}
$(document).ready(init);
}(jQuery));

Просмотреть файл

@ -23,12 +23,12 @@ MANAGERS = ADMINS
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'kitsune', # Or path to database file if using sqlite3.
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used with sqlite3.
'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'kitsune', # Or path to database file if using sqlite3.
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used with sqlite3.
'OPTIONS': {'init_command': 'SET storage_engine=InnoDB'},
}
}
@ -137,7 +137,7 @@ MIDDLEWARE_CLASSES = (
# Auth
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'sumo.backends.SessionBackend', # TODO: Replace with Kitsune auth.
'sumo.backends.SessionBackend', # TODO: Replace with Kitsune auth.
)
ROOT_URLCONF = '%s.urls' % ROOT_PACKAGE
@ -180,11 +180,12 @@ if DEBUG:
TEST_RUNNER = 'test_utils.runner.RadicalTestSuiteRunner'
def JINJA_CONFIG():
import jinja2
from django.conf import settings
from caching.base import cache
config = {'extensions': ['tower.template.i18n', 'caching.ext.cache',],
config = {'extensions': ['tower.template.i18n', 'caching.ext.cache', ],
'finalize': lambda x: x if x is not None else ''}
if 'memcached' in cache.scheme and not settings.DEBUG:
# We're passing the _cache object directly to jinja because
@ -230,6 +231,9 @@ MINIFY_BUNDLES = {
'forums': (
'css/forums.css',
),
'questions': (
'css/questions.css',
),
'search': (
'css/search.css',
),
@ -239,12 +243,16 @@ MINIFY_BUNDLES = {
},
'js': {
'common': (
'js/jquery.min.js',
'js/libs/jquery.min.js',
'js/libs/modernizr-1.1.min.js',
'js/menu.js',
'js/main.js',
),
'questions': (
'js/questions.js',
),
'search': (
'js/jqueryui.min.js',
'js/libs/jqueryui.min.js',
'js/search.js',
),
'forums': (
@ -277,8 +285,8 @@ SPHINX_CONFIG_PATH = path('configs/sphinx/sphinx.conf')
#
# Sphinx results tweaking
SEARCH_FORUM_MIN_AGE = 7 # age before which decay doesn't apply, in days
SEARCH_FORUM_HALF_LIFE = 14 # controls the decay rate, in days
SEARCH_FORUM_MIN_AGE = 7 # age before which decay doesn't apply, in days
SEARCH_FORUM_HALF_LIFE = 14 # controls the decay rate, in days
SEARCH_MAX_RESULTS = 1000
SEARCH_RESULTS_PER_PAGE = 10

Просмотреть файл

@ -39,11 +39,15 @@
<div id="content">
{% block sidebar %}
<div id="sidebar">
{% include 'layout/sidebar.html' %}
</div>
{% endblock %}
{% block breadcrumbs %}
{{ breadcrumbs(crumbs) }}
{% endblock %}
<div id="main" role="main">
{% block content_area %}