Edit questions impl (bug 569288)

This commit is contained in:
Ricky Rosario 2010-07-21 11:52:32 -04:00
Родитель 6eba591e2d
Коммит f0a7b4b73c
6 изменённых файлов: 180 добавлений и 0 удалений

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

@ -239,6 +239,11 @@
<div class="content">
{{ answer.content_parsed|safe }}
</div>
{% if answer.updated_by %}
<p class="edited">
{{ _('Modified <time>{datetime}</time> by {name}')|fe(name=answer.updated_by.username, datetime=datetimeformat(answer.updated, format='longdatetime')) }}
</p>
{% endif %}
{% if not question.is_locked %}
<div class="reply">
<a href="#question-reply">{{ _('Reply to this post') }}</a>
@ -281,6 +286,11 @@
<input type="submit" value="{{ _('Report this post') }}" />
</form>
{% endif %}
{% if user.has_perm('questions.change_answer') %}
<a class="edit" href="{{ url('questions.edit_answer', question.id, answer.id) }}">
{{ _('Edit this post') }}
</a>
{% endif %}
{% if user.has_perm('questions.delete_answer') %}
<a class="delete" href="{{ url('questions.delete_answer', question.id, answer.id) }}">
{{ _('Delete this post') }}

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

@ -0,0 +1,51 @@
{# vim: set ts=2 et sts=2 sw=2: #}
{% extends "questions/base.html" %}
{% from "layout/errorlist.html" import errorlist %}
{# L10n: {t} is the title of the question. #}
{% set title = _('Editing an answer | {t} | Firefox Support Forum')|f(t=answer.question.title) %}
{% block content %}
<div class="edit-answer">
<h2>{{ _('Edit an answer') }}</h2>
<ul class="info">
<li>
<label>{{ _('Created by:') }}</label>
{{ answer.creator }}
</li>
<li>
<label>{{ _('Created:') }}</label>
{{ datetimeformat(answer.created, format='longdatetime') }}
</li>
{% if answer.updated_by %}
<li>
<label>{{ _('Last updated by:') }}</label>
{{ answer.updated_by }}
</li>
<li>
<label>{{ _('Last updated:') }}</label>
{{ datetimeformat(answer.updated, format='longdatetime') }}
</li>
{% endif %}
<li>
<label>{{ _('Question:') }}</label>
{{ answer.question.title }}
</li>
</ul>
<form action="{{ url('questions.edit_answer', answer.question.id, answer.id) }}" method="post">
{{ csrf() }}
{{ errorlist(form) }}
<div class="form-widget{% if form.content.errors %} invalid{% endif %}">
<div class="forum-editor">
<div class="forum-editor-tools"></div>
{{ form.content|safe }}
</div>
</div>
<div class="form-widget submit">
<a href="{{ url('questions.answers', answer.question.id) }}">{{ _('Cancel') }}</a>
<input type="submit" class="btn g-btn" value="{{ _('Update answer') }}" />
</div>
</form>
</div>
{% endblock %}

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

@ -288,6 +288,56 @@ class AnswersTemplateTestCase(TestCaseBase):
args=[self.question.id, answer.id])
eq_(0, Answer.objects.filter(pk=self.question.id).count())
def test_edit_answer_without_permission(self):
"""Editing an answer without permissions redirects to login.
The edit link shouldn't show up on the Answers page."""
response = get(self.client, 'questions.answers',
args=[self.question.id])
doc = pq(response.content)
eq_(0, len(doc('ol.answers a.edit')))
answer = self.question.last_answer
response = get(self.client, 'questions.edit_answer',
args=[self.question.id, answer.id])
redirect = response.redirect_chain[0]
eq_(302, redirect[1])
eq_('http://testserver/tiki-login.php?next=/en-US/' +
'questions/1/edit/1',
redirect[0])
content = 'New content for answer'
response = post(self.client, 'questions.edit_answer',
{'content': content},
args=[self.question.id, answer.id])
redirect = response.redirect_chain[0]
eq_(302, redirect[1])
eq_('http://testserver/tiki-login.php?next=/en-US/' +
'questions/1/edit/1',
redirect[0])
def test_edit_answer_with_permissions(self):
"""Editing an answer with permissions.
The edit link should show up on the Answers page."""
self.client.login(username='admin', password='testpass')
response = get(self.client, 'questions.answers',
args=[self.question.id])
doc = pq(response.content)
eq_(1, len(doc('ol.answers a.edit')))
answer = self.question.last_answer
response = get(self.client, 'questions.edit_answer',
args=[self.question.id, answer.id])
eq_(200, response.status_code)
content = 'New content for answer'
response = post(self.client, 'questions.edit_answer',
{'content': content},
args=[self.question.id, answer.id])
eq_(content, Answer.objects.get(pk=answer.id).content)
def test_lock_question_without_permissions(self):
"""Trying to lock a question without permission redirects to login."""
q = self.question

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

@ -12,6 +12,8 @@ urlpatterns = patterns('questions.views',
name='questions.lock'),
url(r'^/(?P<question_id>\d+)/delete/(?P<answer_id>\d+)$',
'delete_answer', name='questions.delete_answer'),
url(r'^/(?P<question_id>\d+)/edit/(?P<answer_id>\d+)$', 'edit_answer',
name='questions.edit_answer'),
url(r'^/(?P<question_id>\d+)/solution/(?P<answer_id>\d+)$', 'solution',
name='questions.solution'),
url(r'^/feed$', QuestionsFeed(), name='questions.feed'),

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

@ -373,6 +373,31 @@ def lock_question(request, question_id):
return HttpResponseRedirect(question.get_absolute_url())
@login_required
@permission_required('questions.change_answer')
def edit_answer(request, question_id, answer_id):
"""Edit an answer."""
answer = get_object_or_404(Answer, pk=answer_id, question=question_id)
if request.method == 'GET':
form = AnswerForm({'content': answer.content})
return jingo.render(request, 'questions/edit_answer.html',
{'form': form, 'answer': answer})
form = AnswerForm(request.POST)
if form.is_valid():
log.warning('User %s is editing answer with id=%s' %
(request.user, answer.id))
answer.content = form.cleaned_data['content']
answer.updated_by = request.user
answer.save()
return HttpResponseRedirect(answer.get_absolute_url())
return jingo.render(request, 'questions/edit_answer.html',
{'form': form, 'answer': answer})
def _answers_data(request, question_id, form=None):
"""Return a map of the minimal info necessary to draw an answers page."""

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

@ -814,6 +814,7 @@ ol.answers span.author {
font-size: 14px;
}
ol.answers p.edited,
ol.answers p.posted {
color: #898378;
font-size: 12px;
@ -821,6 +822,10 @@ ol.answers p.posted {
margin: 0 0 5px 15px;
}
ol.answers p.edited {
font-size: 11px;
}
ol.answers div.content {
margin: 0;
}
@ -869,6 +874,7 @@ ol.answers form.report {
margin: 15px 0 0;
}
ol.answers a.edit,
ol.answers a.delete {
background: transparent url(../img/forums/delete.png) no-repeat left center;
clear: left;
@ -878,6 +884,10 @@ ol.answers a.delete {
padding: 0 0 0 23px;
}
ol.answers a.edit {
background: transparent url(../img/forums/edit.png) no-repeat left center;
}
/* reply to question */
#question-reply {
font-size: 14px;
@ -902,6 +912,7 @@ ol.answers a.delete {
padding: 0;
}
div.edit-answer textarea,
#question-reply textarea {
border: solid 1px #87C4DC;
border-radius: 8px;
@ -1194,3 +1205,34 @@ div.to-delete div.content ul,
div.to-delete div.content ol {
margin: 0 0 0 1.5em;
}
/*
* Edit answer
*/
div.edit-answer {
font-size: 14px;
padding: 0 0 0 30px;
}
div.edit-answer ul.info {
list-style: none;
margin: 10px 0 0;
}
div.edit-answer ul.info li {
padding: 2px 0;
}
div.edit-answer ul.info label {
font-weight: bold;
float: left;
width: 150px;
}
div.edit-answer div.forum-editor {
padding-left: 0;
}
div.edit-answer input.btn {
margin-left: 1em;
}