Commit 5a7d79342b098e356e5b6cda9d86764cea3bd8ec
1 parent
df375701
Exists in
master
and in
5 other branches
Adding post edition [Issue: #74]
Showing
8 changed files
with
132 additions
and
57 deletions
Show diff stats
forum/models.py
@@ -41,6 +41,15 @@ class Post(models.Model): | @@ -41,6 +41,15 @@ class Post(models.Model): | ||
41 | def __str__(self): | 41 | def __str__(self): |
42 | return ''.join([self.user.name, " / ", str(self.post_date)]) | 42 | return ''.join([self.user.name, " / ", str(self.post_date)]) |
43 | 43 | ||
44 | + def is_modified(self): | ||
45 | + create = self.post_date.strftime("%Y-%m-%d %H:%M:%S") | ||
46 | + edit = self.modification_date.strftime("%Y-%m-%d %H:%M:%S") | ||
47 | + | ||
48 | + if create != edit: | ||
49 | + return True | ||
50 | + | ||
51 | + return False | ||
52 | + | ||
44 | """ | 53 | """ |
45 | It represents an answer to a forum's post | 54 | It represents an answer to a forum's post |
46 | """ | 55 | """ |
forum/static/js/forum.js
@@ -50,6 +50,54 @@ function showForum(url, forum_id) { | @@ -50,6 +50,54 @@ function showForum(url, forum_id) { | ||
50 | $('#forumModal').modal(); | 50 | $('#forumModal').modal(); |
51 | } | 51 | } |
52 | 52 | ||
53 | +/* | ||
54 | +* | ||
55 | +* Function to load form to edit post | ||
56 | +* | ||
57 | +*/ | ||
58 | +function edit_post(url, post_id) { | ||
59 | + $.ajax({ | ||
60 | + url: url, | ||
61 | + success: function(data) { | ||
62 | + $("#post_"+post_id).find(".post_content").hide(); | ||
63 | + $("#post_"+post_id).find(".post_content").after(data); | ||
64 | + | ||
65 | + var frm = $("#post_"+post_id).find(".edit_post_form"); | ||
66 | + frm.submit(function () { | ||
67 | + $.ajax({ | ||
68 | + type: frm.attr('method'), | ||
69 | + url: frm.attr('action'), | ||
70 | + data: frm.serialize(), | ||
71 | + success: function (data) { | ||
72 | + $("#post_"+post_id).parent().after(data); | ||
73 | + frm.parent().parent().remove(); | ||
74 | + }, | ||
75 | + error: function(data) { | ||
76 | + console.log(frm.serialize()); | ||
77 | + console.log('Error'); | ||
78 | + } | ||
79 | + }); | ||
80 | + return false; | ||
81 | + }); | ||
82 | + } | ||
83 | + }); | ||
84 | +} | ||
85 | + | ||
86 | +/* | ||
87 | +* | ||
88 | +* Function to cancel post edition | ||
89 | +* | ||
90 | +*/ | ||
91 | +function cancelEditPost(post_id) { | ||
92 | + $("#post_"+post_id).find(".post_content").show(); | ||
93 | + $("#post_"+post_id).find(".edit_post_form").remove(); | ||
94 | +} | ||
95 | + | ||
96 | +/* | ||
97 | +* | ||
98 | +* Function to delete a post | ||
99 | +* | ||
100 | +*/ | ||
53 | function delete_post(url, post) { | 101 | function delete_post(url, post) { |
54 | var csrftoken = getCookie('csrftoken'); | 102 | var csrftoken = getCookie('csrftoken'); |
55 | 103 | ||
@@ -74,36 +122,4 @@ function answer(id, url) { | @@ -74,36 +122,4 @@ function answer(id, url) { | ||
74 | }); | 122 | }); |
75 | 123 | ||
76 | $("#post_"+id).find(".answer_post").show(); | 124 | $("#post_"+id).find(".answer_post").show(); |
77 | -} | ||
78 | - | ||
79 | -function showPosts(url, forum) { | ||
80 | - if ($("#collapse" + forum).hasClass('in')) { | ||
81 | - $("#collapse" + forum).collapse('hide'); | ||
82 | - } else { | ||
83 | - $.ajax({ | ||
84 | - url: url, | ||
85 | - data: {'forum': forum}, | ||
86 | - success: function(data) { | ||
87 | - $("#collapse" + forum).find(".well").html(data); | ||
88 | - } | ||
89 | - }); | ||
90 | - | ||
91 | - $("#collapse" + forum).collapse('show'); | ||
92 | - } | ||
93 | -} | ||
94 | - | ||
95 | -function showPostsAnswers(url, post) { | ||
96 | - if ($("#collapse" + post).hasClass('in')) { | ||
97 | - $("#collapse" + post).collapse('hide'); | ||
98 | - } else { | ||
99 | - $.ajax({ | ||
100 | - url: url, | ||
101 | - data: {'post': post}, | ||
102 | - success: function(data) { | ||
103 | - $("#collapse" + post).find(".well").html(data); | ||
104 | - } | ||
105 | - }); | ||
106 | - | ||
107 | - $("#collapse" + post).collapse('show'); | ||
108 | - } | ||
109 | } | 125 | } |
110 | \ No newline at end of file | 126 | \ No newline at end of file |
forum/templates/post/post_list.html
@@ -17,17 +17,24 @@ | @@ -17,17 +17,24 @@ | ||
17 | <i class="material-icons">more_horiz</i> | 17 | <i class="material-icons">more_horiz</i> |
18 | </a> | 18 | </a> |
19 | <ul class="dropdown-menu" aria-labelledby="dropdownMenu1"> | 19 | <ul class="dropdown-menu" aria-labelledby="dropdownMenu1"> |
20 | - <li><a href="javascript:void(0)"><i class="material-icons">create</i> {% trans 'Edit' %}</a></li> | 20 | + <li><a href="javascript:edit_post('{% url 'forum:update_post' post.id %}', '{{ post.id }}')"><i class="material-icons">create</i> {% trans 'Edit' %}</a></li> |
21 | <li><a href="javascript:javascript:delete_post('{% url 'forum:delete_post' post.id %}', '{{ post.id }}')"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li> | 21 | <li><a href="javascript:javascript:delete_post('{% url 'forum:delete_post' post.id %}', '{{ post.id }}')"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li> |
22 | </ul> | 22 | </ul> |
23 | </div> | 23 | </div> |
24 | {% endif %} | 24 | {% endif %} |
25 | </div> | 25 | </div> |
26 | </h3> | 26 | </h3> |
27 | - <div class="card-data"> | ||
28 | - <p class="comment-date"><i class="fa fa-clock-o"></i> {{ post.post_date }}</p> | 27 | + <div class="post_content"> |
28 | + <div class="card-data"> | ||
29 | + <p class="comment-date"> | ||
30 | + <i class="fa fa-clock-o"></i> {{ post.post_date }} | ||
31 | + {% if post.is_modified %} | ||
32 | + <em> - {% trans 'Edited' %}</em> | ||
33 | + {% endif %} | ||
34 | + </p> | ||
35 | + </div> | ||
36 | + <p class="comment-text">{{ post.message|linebreaks }}</p> | ||
29 | </div> | 37 | </div> |
30 | - <p class="comment-text">{{ post.message|linebreaks }}</p> | ||
31 | <div class="answer_post"></div> | 38 | <div class="answer_post"></div> |
32 | </div> | 39 | </div> |
33 | </div> | 40 | </div> |
forum/templates/post/post_render.html
@@ -15,17 +15,24 @@ | @@ -15,17 +15,24 @@ | ||
15 | <i class="material-icons">more_horiz</i> | 15 | <i class="material-icons">more_horiz</i> |
16 | </a> | 16 | </a> |
17 | <ul class="dropdown-menu" aria-labelledby="dropdownMenu1"> | 17 | <ul class="dropdown-menu" aria-labelledby="dropdownMenu1"> |
18 | - <li><a href="javascript:void(0)"><i class="material-icons">create</i> {% trans 'Edit' %}</a></li> | 18 | + <li><a href="javascript:edit_post('{% url 'forum:update_post' post.id %}', '{{ post.id }}')"></li> |
19 | <li><a href="javascript:delete_post('{% url 'forum:delete_post' post.id %}', '{{ post.id }}')"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li> | 19 | <li><a href="javascript:delete_post('{% url 'forum:delete_post' post.id %}', '{{ post.id }}')"><i class="material-icons">delete_sweep</i> {% trans 'Remove' %}</a></li> |
20 | </ul> | 20 | </ul> |
21 | </div> | 21 | </div> |
22 | {% endif %} | 22 | {% endif %} |
23 | </div> | 23 | </div> |
24 | </h3> | 24 | </h3> |
25 | - <div class="card-data"> | ||
26 | - <p class="comment-date"><i class="fa fa-clock-o"></i> {{ post.post_date }}</p> | 25 | + <div class="post_content"> |
26 | + <div class="card-data"> | ||
27 | + <p class="comment-date"> | ||
28 | + <i class="fa fa-clock-o"></i> {{ post.post_date }} | ||
29 | + {% if post.post_date != post.modifiction_date %} | ||
30 | + <em> - {% trans 'Edited' %}</em> | ||
31 | + {% endif %} | ||
32 | + </p> | ||
33 | + </div> | ||
34 | + <p class="comment-text">{{ post.message|linebreaks }}</p> | ||
27 | </div> | 35 | </div> |
28 | - <p class="comment-text">{{ post.message|linebreaks }}</p> | ||
29 | <div class="answer_post"></div> | 36 | <div class="answer_post"></div> |
30 | </div> | 37 | </div> |
31 | </div> | 38 | </div> |
32 | \ No newline at end of file | 39 | \ No newline at end of file |
@@ -0,0 +1,37 @@ | @@ -0,0 +1,37 @@ | ||
1 | +{% load i18n permission_tags list_post %} | ||
2 | +{% load widget_tweaks %} | ||
3 | + | ||
4 | +<form class="edit_post_form" method="post" action="{% url 'forum:update_post' post.id %}" enctype="multipart/form-data"> | ||
5 | + {% csrf_token %} | ||
6 | + {% for field in form %} | ||
7 | + {% if field.field.widget.input_type == 'hidden' %} | ||
8 | + {% render_field field class='form-control' %} | ||
9 | + {% else %} | ||
10 | + <div class="form-group {% if form.has_error %} has-error {% endif %} is-fileinput"> | ||
11 | + <div class="input-group"> | ||
12 | + {% render_field field class='form-control' placeholder="Post a message" %} | ||
13 | + <span class="help-block">{{ field.help_text }}</span> | ||
14 | + {% if field.errors %} | ||
15 | + <div class="row"> | ||
16 | + <br /> | ||
17 | + <div class="alert alert-danger alert-dismissible" role="alert"> | ||
18 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | ||
19 | + <span aria-hidden="true">×</span> | ||
20 | + </button> | ||
21 | + <ul> | ||
22 | + {% for error in field.errors %} | ||
23 | + <li>{{ error }}</li> | ||
24 | + {% endfor %} | ||
25 | + </ul> | ||
26 | + </div> | ||
27 | + </div> | ||
28 | + {% endif %} | ||
29 | + </div> | ||
30 | + </div> | ||
31 | + <div class="pull-right"> | ||
32 | + <button type="button" onclick="cancelEditPost('{{ post.id }}')" class="btn btn-danger btn-raised">{% trans 'Cancel' %}</button> | ||
33 | + <button type="submit" class="btn btn-primary btn-raised">{% trans 'Save changes' %}</button> | ||
34 | + </div> | ||
35 | + {% endif %} | ||
36 | + {% endfor %} | ||
37 | +</form> | ||
0 | \ No newline at end of file | 38 | \ No newline at end of file |
forum/templatetags/list_post.py
@@ -14,6 +14,6 @@ def list_posts(request, forum): | @@ -14,6 +14,6 @@ def list_posts(request, forum): | ||
14 | 'request': request, | 14 | 'request': request, |
15 | } | 15 | } |
16 | 16 | ||
17 | - context['posts'] = Post.objects.filter(forum = forum) | 17 | + context['posts'] = Post.objects.filter(forum = forum).order_by('post_date') |
18 | 18 | ||
19 | return context | 19 | return context |
20 | \ No newline at end of file | 20 | \ No newline at end of file |
forum/urls.py
@@ -6,10 +6,10 @@ from . import views | @@ -6,10 +6,10 @@ from . import views | ||
6 | urlpatterns = [ | 6 | urlpatterns = [ |
7 | url(r'^$', views.ForumIndex.as_view(), name='index'), | 7 | url(r'^$', views.ForumIndex.as_view(), name='index'), |
8 | url(r'^create$', views.CreateForumView.as_view(), name='create'), | 8 | url(r'^create$', views.CreateForumView.as_view(), name='create'), |
9 | - url(r'^posts$', views.PostIndex.as_view(), name='posts'), | ||
10 | url(r'^create_post$', views.CreatePostView.as_view(), name='create_post'), | 9 | url(r'^create_post$', views.CreatePostView.as_view(), name='create_post'), |
11 | - url(r'^render_post/([\w_-]+)/$', views.render_post, name='render_post'), | 10 | + url(r'^update_post/(?P<pk>[\w_-]+)/$', views.PostUpdateView.as_view(), name='update_post'), |
12 | url(r'^delete_post/(?P<pk>[\w_-]+)/$', views.PostDeleteView.as_view(), name='delete_post'), | 11 | url(r'^delete_post/(?P<pk>[\w_-]+)/$', views.PostDeleteView.as_view(), name='delete_post'), |
12 | + url(r'^render_post/([\w_-]+)/$', views.render_post, name='render_post'), | ||
13 | url(r'^post_deleted/$', views.post_deleted, name='deleted_post'), | 13 | url(r'^post_deleted/$', views.post_deleted, name='deleted_post'), |
14 | url(r'^post_answers$', views.PostAnswerIndex.as_view(), name='post_answers'), | 14 | url(r'^post_answers$', views.PostAnswerIndex.as_view(), name='post_answers'), |
15 | url(r'^reply_post$', views.CreatePostAnswerView.as_view(), name='reply_post'), | 15 | url(r'^reply_post$', views.CreatePostAnswerView.as_view(), name='reply_post'), |
forum/views.py
@@ -36,20 +36,6 @@ class CreateForumView(LoginRequiredMixin, generic.edit.CreateView): | @@ -36,20 +36,6 @@ class CreateForumView(LoginRequiredMixin, generic.edit.CreateView): | ||
36 | form_class = ForumForm | 36 | form_class = ForumForm |
37 | success_url = reverse_lazy('forum:index') | 37 | success_url = reverse_lazy('forum:index') |
38 | 38 | ||
39 | -class PostIndex(LoginRequiredMixin, generic.ListView): | ||
40 | - login_url = reverse_lazy("core:home") | ||
41 | - redirect_field_name = 'next' | ||
42 | - | ||
43 | - template_name = "post/post_list.html" | ||
44 | - context_object_name = 'posts' | ||
45 | - | ||
46 | - def get_queryset(self): | ||
47 | - forum = get_object_or_404(Forum, slug = self.request.GET.get('forum', '')) | ||
48 | - | ||
49 | - context = Post.objects.filter(forum = forum) | ||
50 | - | ||
51 | - return context | ||
52 | - | ||
53 | class CreatePostView(LoginRequiredMixin, generic.edit.CreateView): | 39 | class CreatePostView(LoginRequiredMixin, generic.edit.CreateView): |
54 | login_url = reverse_lazy("core:home") | 40 | login_url = reverse_lazy("core:home") |
55 | redirect_field_name = 'next' | 41 | redirect_field_name = 'next' |
@@ -77,6 +63,19 @@ def render_post(request, post): | @@ -77,6 +63,19 @@ def render_post(request, post): | ||
77 | 63 | ||
78 | return render(request, "post/post_render.html", context) | 64 | return render(request, "post/post_render.html", context) |
79 | 65 | ||
66 | +class PostUpdateView(LoginRequiredMixin, generic.UpdateView): | ||
67 | + login_url = reverse_lazy("core:home") | ||
68 | + redirect_field_name = 'next' | ||
69 | + | ||
70 | + form_class = PostForm | ||
71 | + model = Post | ||
72 | + template_name = "post/post_update_form.html" | ||
73 | + | ||
74 | + def get_success_url(self): | ||
75 | + self.success_url = reverse('forum:render_post', args = (self.object.id, )) | ||
76 | + | ||
77 | + return self.success_url | ||
78 | + | ||
80 | class PostDeleteView(LoginRequiredMixin, generic.DeleteView): | 79 | class PostDeleteView(LoginRequiredMixin, generic.DeleteView): |
81 | login_url = reverse_lazy("core:home") | 80 | login_url = reverse_lazy("core:home") |
82 | redirect_field_name = 'next' | 81 | redirect_field_name = 'next' |