From 2c6e925930cab0a22941c76fb1ee5cfef977fa19 Mon Sep 17 00:00:00 2001 From: Zambom Date: Mon, 24 Oct 2016 15:13:13 -0300 Subject: [PATCH] Fixing new post location [Issue: #215] --- core/static/css/base/amadeus.css | 26 ++++++++++++++++++++++++++ core/static/js/vendor/jscookie.js | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ core/templates/base.html | 1 + forum/static/js/forum.js | 58 +++++++++++++++++++++++++++++----------------------------- forum/templates/post/post_load_more_render.html | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ forum/views.py | 24 ++++++++++++++++++------ 6 files changed, 280 insertions(+), 35 deletions(-) create mode 100644 core/static/js/vendor/jscookie.js create mode 100644 forum/templates/post/post_load_more_render.html diff --git a/core/static/css/base/amadeus.css b/core/static/css/base/amadeus.css index af7fcc4..6ede867 100644 --- a/core/static/css/base/amadeus.css +++ b/core/static/css/base/amadeus.css @@ -368,4 +368,30 @@ ul, li { /* core/reset_password.html classes*/ .send-reset-email{ float: right; +} + +/* forum post loaded */ +@-webkit-keyframes loaded { + 0% { + background-color: Yellow; + opacity: 0.2; + } + 22% { + background-color: Yellow; + opacity: 0.3; + } + 77% { + background-color: Yellow; + opacity: 0.6; + } + 100% { + background-color: White; + } +} + +.loaded { + -webkit-animation-name: loaded; + -webkit-animation-duration: 900ms; + -webkit-animation-iteration-count: 3; + -webkit-animation-timing-function: ease-in-out; } \ No newline at end of file diff --git a/core/static/js/vendor/jscookie.js b/core/static/js/vendor/jscookie.js new file mode 100644 index 0000000..92dbba1 --- /dev/null +++ b/core/static/js/vendor/jscookie.js @@ -0,0 +1,156 @@ +/*! + * JavaScript Cookie v2.1.3 + * https://github.com/js-cookie/js-cookie + * + * Copyright 2006, 2015 Klaus Hartl & Fagner Brack + * Released under the MIT license + */ +;(function (factory) { + var registeredInModuleLoader = false; + if (typeof define === 'function' && define.amd) { + define(factory); + registeredInModuleLoader = true; + } + if (typeof exports === 'object') { + module.exports = factory(); + registeredInModuleLoader = true; + } + if (!registeredInModuleLoader) { + var OldCookies = window.Cookies; + var api = window.Cookies = factory(); + api.noConflict = function () { + window.Cookies = OldCookies; + return api; + }; + } +}(function () { + function extend () { + var i = 0; + var result = {}; + for (; i < arguments.length; i++) { + var attributes = arguments[ i ]; + for (var key in attributes) { + result[key] = attributes[key]; + } + } + return result; + } + + function init (converter) { + function api (key, value, attributes) { + var result; + if (typeof document === 'undefined') { + return; + } + + // Write + + if (arguments.length > 1) { + attributes = extend({ + path: '/' + }, api.defaults, attributes); + + if (typeof attributes.expires === 'number') { + var expires = new Date(); + expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); + attributes.expires = expires; + } + + try { + result = JSON.stringify(value); + if (/^[\{\[]/.test(result)) { + value = result; + } + } catch (e) {} + + if (!converter.write) { + value = encodeURIComponent(String(value)) + .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); + } else { + value = converter.write(value, key); + } + + key = encodeURIComponent(String(key)); + key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); + key = key.replace(/[\(\)]/g, escape); + + return (document.cookie = [ + key, '=', value, + attributes.expires ? '; expires=' + attributes.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE + attributes.path ? '; path=' + attributes.path : '', + attributes.domain ? '; domain=' + attributes.domain : '', + attributes.secure ? '; secure' : '' + ].join('')); + } + + // Read + + if (!key) { + result = {}; + } + + // To prevent the for loop in the first place assign an empty array + // in case there are no cookies at all. Also prevents odd result when + // calling "get()" + var cookies = document.cookie ? document.cookie.split('; ') : []; + var rdecode = /(%[0-9A-Z]{2})+/g; + var i = 0; + + for (; i < cookies.length; i++) { + var parts = cookies[i].split('='); + var cookie = parts.slice(1).join('='); + + if (cookie.charAt(0) === '"') { + cookie = cookie.slice(1, -1); + } + + try { + var name = parts[0].replace(rdecode, decodeURIComponent); + cookie = converter.read ? + converter.read(cookie, name) : converter(cookie, name) || + cookie.replace(rdecode, decodeURIComponent); + + if (this.json) { + try { + cookie = JSON.parse(cookie); + } catch (e) {} + } + + if (key === name) { + result = cookie; + break; + } + + if (!key) { + result[name] = cookie; + } + } catch (e) {} + } + + return result; + } + + api.set = api; + api.get = function (key) { + return api.call(api, key); + }; + api.getJSON = function () { + return api.apply({ + json: true + }, [].slice.call(arguments)); + }; + api.defaults = {}; + + api.remove = function (key, attributes) { + api(key, '', extend(attributes, { + expires: -1 + })); + }; + + api.withConverter = init; + + return api; + } + + return init(function () {}); +})); \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index faf5d86..64fd3bd 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -29,6 +29,7 @@ + diff --git a/forum/static/js/forum.js b/forum/static/js/forum.js index 6db5ed0..ddd69c1 100644 --- a/forum/static/js/forum.js +++ b/forum/static/js/forum.js @@ -1,23 +1,4 @@ -/* -* -* Function to get a cookie stored on browser -* -*/ -function getCookie(name) { - var cookieValue = null; - if (document.cookie && document.cookie !== '') { - var cookies = document.cookie.split(';'); - for (var i = 0; i < cookies.length; i++) { - var cookie = jQuery.trim(cookies[i]); - // Does this cookie string begin with the name we want? - if (cookie.substring(0, name.length + 1) === (name + '=')) { - cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); - break; - } - } - } - return cookieValue; -} +var new_posts = []; //Store the new posts ids /* * @@ -31,8 +12,16 @@ $(document).ready(function (){ type: frm.attr('method'), url: frm.attr('action'), data: frm.serialize(), + dataType: 'json', success: function (data) { - $("#posts_list").append(data); + if ($("#load_more_posts").length == 0) { + $("#posts_list").append(data.html); + } else { + $("#load_more_posts").before(data.html); + } + + new_posts.push(data.new_id); + frm[0].reset(); }, error: function(data) { @@ -86,8 +75,6 @@ function setForumCreateFormSubmit() { $('.foruns_list').append("
  • "+data[2]+"
  • "); $("#createForum").modal('hide'); - - showForum(data[0], data[1]); }, error: function(data) { $(".forum_form").html(data.responseText); @@ -157,7 +144,7 @@ function setForumUpdateFormSubmit(success_message) { */ function delete_forum(url, forum, message, return_url) { alertify.confirm(message, function(){ - var csrftoken = getCookie('csrftoken'); + var csrftoken = Cookies.get('csrftoken'); $.ajax({ method: 'post', @@ -225,7 +212,7 @@ function cancelEditPost(post_id) { * */ function delete_post(url, post) { - var csrftoken = getCookie('csrftoken'); + var csrftoken = Cookies.get('csrftoken'); $.ajax({ method: 'post', @@ -255,6 +242,8 @@ function load_more_posts(pageNum, numberPages, url) { pageNum += 1; + var showing = new_posts.join(','); + // Show loader $("#loading_posts").show(); @@ -262,11 +251,22 @@ function load_more_posts(pageNum, numberPages, url) { setTimeout(function (){ $.ajax({ url: url, - data: {'page': pageNum}, + data: {'page': pageNum, 'showing': showing}, + dataType: 'json', success: function(data) { $("#loading_posts").hide(); - - $("#posts_list").append(data); + + var child = $("#posts_list").find(".new_post:first"); + + if (child.length == 0) { + $("#posts_list").append(data.html); + } else { + child.before(data.html); + } + + if (data.page != data.num_pages) { + $("#posts_list").append('' + data.btn_text + ''); + } }, error: function(data) { console.log(data); @@ -364,7 +364,7 @@ function cancelEditPostAnswer(answer_id) { */ function delete_answer(url, answer, message) { alertify.confirm(message, function(){ - var csrftoken = getCookie('csrftoken'); + var csrftoken = Cookies.get('csrftoken'); $.ajax({ method: 'post', diff --git a/forum/templates/post/post_load_more_render.html b/forum/templates/post/post_load_more_render.html new file mode 100644 index 0000000..0757a8d --- /dev/null +++ b/forum/templates/post/post_load_more_render.html @@ -0,0 +1,50 @@ +{% load i18n permission_tags list_post_answer %} + +{% if posts|length > 0 %} + {% for post in posts %} +
    +
    +

    + {{ post.user }} +
    + + reply + + {% if request.user|has_role:'system_admin' or request.user == post.user %} + {% csrf_token %} + + {% endif %} +
    +

    +
    +
    +

    + {{ post.post_date|timesince }} {% trans 'ago' %} + {% if post.is_modified %} + - {% trans 'Edited' %} + {% endif %} +

    +
    +

    {{ post.message|linebreaks }}

    +
    +
    +
    + {% list_post_answer request post %} +
    + +
    +
    + {% endfor %} +{% endif %} \ No newline at end of file diff --git a/forum/views.py b/forum/views.py index 4bef4ef..434f2d7 100644 --- a/forum/views.py +++ b/forum/views.py @@ -5,15 +5,17 @@ from django.utils.translation import ugettext_lazy as _ from django.views import generic from django.contrib.auth.mixins import LoginRequiredMixin from django.core.paginator import Paginator, EmptyPage -from django.http import Http404 +from django.http import Http404, JsonResponse +from django.urls import reverse +from django.template.loader import render_to_string from .models import Forum, Post, PostAnswer from courses.models import Topic -from core.mixins import NotificationMixin from core.models import Action, Resource from .forms import ForumForm, PostForm, PostAnswerForm -from django.urls import reverse + +from core.mixins import NotificationMixin """ Forum Section @@ -130,7 +132,13 @@ def load_posts(request, forum_id): forum = get_object_or_404(Forum, id = forum_id) - posts = Post.objects.filter(forum = forum).order_by('post_date') + showing = request.GET.get('showing', '') + + if showing == '': + posts = Post.objects.filter(forum = forum).order_by('post_date') + else: + showing = showing.split(',') + posts = Post.objects.filter(forum = forum).exclude(id__in = showing).order_by('post_date') paginator = Paginator(posts, 2) @@ -150,7 +158,9 @@ def load_posts(request, forum_id): context['posts'] = page_obj.object_list context['forum'] = forum - return render(request, 'post/post_list.html', context) + html = render_to_string('post/post_load_more_render.html', context, request) + + return JsonResponse({'num_pages': paginator.num_pages, 'page': page_obj.number, 'btn_text': _('Load more posts'), 'html': html}) class CreatePostView(LoginRequiredMixin, generic.edit.CreateView, NotificationMixin): login_url = reverse_lazy("core:home") @@ -181,7 +191,9 @@ def render_post(request, post): context = {} context['post'] = last_post - return render(request, "post/post_render.html", context) + html = render_to_string("post/post_render.html", context, request) + + return JsonResponse({'new_id': last_post.id, 'html': html}) class PostUpdateView(LoginRequiredMixin, generic.UpdateView): login_url = reverse_lazy("core:home") -- libgit2 0.21.2