Commit 540e8464 by Andy Armstrong

Remove Mustache usage from discussions

parent 0662f127
...@@ -44,6 +44,7 @@ class @DiscussionSpecHelper ...@@ -44,6 +44,7 @@ class @DiscussionSpecHelper
'thread-list-item', 'discussion-home', 'search-alert', 'thread-list-item', 'discussion-home', 'search-alert',
'new-post', 'thread-type', 'new-post-menu-entry', 'new-post', 'thread-type', 'new-post-menu-entry',
'new-post-menu-category', 'topic', 'post-user-display', 'new-post-menu-category', 'topic', 'post-user-display',
'inline-discussion', 'pagination', 'user-profile', 'profile-thread'
] ]
templateNamesNoTrailingTemplate = [ templateNamesNoTrailingTemplate = [
'forum-action-endorse', 'forum-action-answer', 'forum-action-follow', 'forum-action-endorse', 'forum-action-answer', 'forum-action-follow',
......
...@@ -2,30 +2,22 @@ ...@@ -2,30 +2,22 @@
describe "DiscussionThreadProfileView", -> describe "DiscussionThreadProfileView", ->
beforeEach -> beforeEach ->
DiscussionSpecHelper.setUpGlobals()
setFixtures """ DiscussionSpecHelper.setUnderscoreFixtures()
<article class="discussion-thread" id="thread_1"></article>
<script type='text/template' id='_profile_thread'>
<article class="discussion-article" data-id="{{id}}">
<div class="discussion-post local">
<div class="post-body">{{{abbreviatedBody}}}</div>
</div>
</article>
</script>
"""
@threadData = { @threadData = {
id: "1", id: "1",
body: "dummy body", body: "dummy body",
discussion: new Discussion() discussion: new Discussion()
abuse_flaggers: [], abuse_flaggers: [],
commentable_id: 'dummy_discussion', commentable_id: 'dummy_discussion',
votes: {up_count: "42"} votes: {up_count: "42"},
created_at: "2014-09-09T20:11:08Z"
} }
@imageTag = '<img src="https://www.google.com.pk/images/srpr/logo11w.png">' @imageTag = '<img src="https://www.google.com.pk/images/srpr/logo11w.png">'
window.MathJax = { Hub: { Queue: -> } } window.MathJax = { Hub: { Queue: -> } }
makeView = (thread) -> makeView = (thread) ->
view = new DiscussionThreadProfileView(el: $("article#thread_#{thread.id}"), model: thread) view = new DiscussionThreadProfileView(model: thread)
spyConvertMath(view) spyConvertMath(view)
return view return view
......
describe "DiscussionUserProfileView", -> describe "DiscussionUserProfileView", ->
beforeEach -> beforeEach ->
DiscussionSpecHelper.setUpGlobals() DiscussionSpecHelper.setUpGlobals()
setFixtures( DiscussionSpecHelper.setUnderscoreFixtures()
"""
<script type="text/template" id="_user_profile">
<section class="discussion">
{{#threads}}
<article class="discussion-thread" id="thread_{{id}}"/>
{{/threads}}
</section>
<section class="pagination"/>
</script>
<script type="text/template" id="_profile_thread">
<div class="profile-thread" id="thread_{{id}}"/>
</script>
<script type="text/template" id="_pagination">
<div class="discussion-paginator">
<a href="#different-page"/>
</div>
<div
class="pagination-params"
data-leftdots="{{leftdots}}"
data-page="{{page}}"
data-rightdots="{{rightdots}}"
>
{{#previous}}
<div class="previous" data-url="{{url}}" data-number="{{number}}"/>
{{/previous}}
{{#first}}
<div class="first" data-url="{{url}}" data-number="{{number}}"/>
{{/first}}
{{#lowPages}}
<div class="lowPages" data-url="{{url}}" data-number="{{number}}"/>
{{/lowPages}}
{{#highPages}}
<div class="highPages" data-url="{{url}}" data-number="{{number}}"/>
{{/highPages}}
{{#last}}
<div class="last" data-url="{{url}}" data-number="{{number}}"/>
{{/last}}
{{#next}}
<div class="next" data-url="{{url}}" data-number="{{number}}"/>
{{/next}}
</div>
</script>
<div class="user-profile-fixture"/>
"""
)
spyOn(DiscussionThreadProfileView.prototype, "render") spyOn(DiscussionThreadProfileView.prototype, "render")
makeThreads = (numThreads) ->
_.map(_.range(numThreads), (i) -> {id: i.toString(), body: "dummy body"})
makeView = (threads, page, numPages) -> makeView = (threads, page, numPages) ->
return new DiscussionUserProfileView( new DiscussionUserProfileView(
el: $(".user-profile-fixture")
collection: threads collection: threads
page: page page: page
numPages: numPages numPages: numPages
...@@ -59,7 +16,7 @@ describe "DiscussionUserProfileView", -> ...@@ -59,7 +16,7 @@ describe "DiscussionUserProfileView", ->
describe "thread rendering should be correct", -> describe "thread rendering should be correct", ->
checkRender = (numThreads) -> checkRender = (numThreads) ->
threads = _.map(_.range(numThreads), (i) -> {id: i.toString(), body: "dummy body"}) threads = makeThreads(numThreads)
view = makeView(threads, 1, 1) view = makeView(threads, 1, 1)
expect(view.$(".discussion").children().length).toEqual(numThreads) expect(view.$(".discussion").children().length).toEqual(numThreads)
_.each(threads, (thread) -> expect(view.$("#thread_#{thread.id}").length).toEqual(1)) _.each(threads, (thread) -> expect(view.$("#thread_#{thread.id}").length).toEqual(1))
...@@ -80,28 +37,18 @@ describe "DiscussionUserProfileView", -> ...@@ -80,28 +37,18 @@ describe "DiscussionUserProfileView", ->
checkRender = (params) -> checkRender = (params) ->
view = makeView([], params.page, params.numPages) view = makeView([], params.page, params.numPages)
paramsQuery = view.$(".pagination-params") paginator = view.$(".discussion-paginator")
expect(paramsQuery.length).toEqual(1) expect(paginator.find(".current-page").text()).toEqual(params["page"].toString())
_.each( expect(paginator.find(".first-page").length).toBe(if params["first"] then 1 else 0);
["page", "leftdots", "rightdots"], expect(paginator.find(".previous-page").length).toBe(if params["previous"] then 1 else 0);
(param) -> expect(paginator.find(".previous-ellipses").length).toBe(if params["leftdots"] then 1 else 0);
expect(paramsQuery.data(param)).toEqual(params[param]) expect(paginator.find(".next-page").length).toBe(if params["next"] then 1 else 0);
) expect(paginator.find(".next-ellipses").length).toBe(if params["rightdots"] then 1 else 0);
_.each( expect(paginator.find(".last-page").length).toBe(if params["last"] then 1 else 0);
["previous", "first", "last", "next"],
(param) -> get_page_number = (element) => parseInt($(element).text())
expected = params[param] expect(_.map(paginator.find(".lower-page a"), get_page_number)).toEqual(params["lowPages"])
expect(paramsQuery.find("." + param).data()).toEqual( expect(_.map(paginator.find(".higher-page a"), get_page_number)).toEqual(params["highPages"])
if expected then pageInfo(expected) else null
)
)
_.each(
["lowPages", "highPages"]
(param) ->
expect(paramsQuery.find("." + param).map(-> $(this).data()).get()).toEqual(
_.map(params[param], pageInfo)
)
)
it "for one page", -> it "for one page", ->
checkRender( checkRender(
...@@ -245,7 +192,7 @@ describe "DiscussionUserProfileView", -> ...@@ -245,7 +192,7 @@ describe "DiscussionUserProfileView", ->
describe "pagination interaction", -> describe "pagination interaction", ->
beforeEach -> beforeEach ->
@view = makeView([], 1, 1) @view = makeView(makeThreads(3), 1, 2)
spyOn($, "ajax") spyOn($, "ajax")
it "causes updated rendering", -> it "causes updated rendering", ->
...@@ -259,9 +206,8 @@ describe "DiscussionUserProfileView", -> ...@@ -259,9 +206,8 @@ describe "DiscussionUserProfileView", ->
{always: ->} {always: ->}
) )
@view.$(".pagination a").first().click() @view.$(".pagination a").first().click()
expect(@view.$("#thread_on_page_42").length).toEqual(1) expect(@view.$(".current-page").text()).toEqual("42")
expect(@view.$(".pagination-params").data("page")).toEqual(42) expect(@view.$(".last-page").text()).toEqual("99")
expect(@view.$(".pagination-params .last").data("number")).toEqual(99)
it "handles AJAX errors", -> it "handles AJAX errors", ->
spyOn(DiscussionUtil, "discussionAlert") spyOn(DiscussionUtil, "discussionAlert")
......
...@@ -9,7 +9,6 @@ if Backbone? ...@@ -9,7 +9,6 @@ if Backbone?
(event) -> DiscussionUtil.activateOnSpace(event, @toggleNewPost) (event) -> DiscussionUtil.activateOnSpace(event, @toggleNewPost)
"click .discussion-paginator a": "navigateToPage" "click .discussion-paginator a": "navigateToPage"
paginationTemplate: -> DiscussionUtil.getTemplate("_pagination")
page_re: /\?discussion_page=(\d+)/ page_re: /\?discussion_page=(\d+)/
initialize: -> initialize: ->
@toggleDiscussionBtn = @$(".discussion-show") @toggleDiscussionBtn = @$(".discussion-show")
...@@ -91,7 +90,10 @@ if Backbone? ...@@ -91,7 +90,10 @@ if Backbone?
@discussion = new Discussion() @discussion = new Discussion()
@discussion.reset(response.discussion_data, {silent: false}) @discussion.reset(response.discussion_data, {silent: false})
$discussion = $(Mustache.render $("script#_inline_discussion").html(), {'threads':response.discussion_data, 'discussionId': discussionId}) $discussion = _.template($("#inline-discussion-template").html())(
'threads': response.discussion_data,
'discussionId': discussionId
)
if @$('section.discussion').length if @$('section.discussion').length
@$('section.discussion').replaceWith($discussion) @$('section.discussion').replaceWith($discussion)
else else
...@@ -149,8 +151,8 @@ if Backbone? ...@@ -149,8 +151,8 @@ if Backbone?
pageUrl = (number) -> pageUrl = (number) ->
"?discussion_page=#{number}" "?discussion_page=#{number}"
params = DiscussionUtil.getPaginationParams(@page, numPages, pageUrl) params = DiscussionUtil.getPaginationParams(@page, numPages, pageUrl)
thing = Mustache.render @paginationTemplate(), params pagination = _.template($("#pagination-template").html())(params)
@$('section.pagination').html(thing) @$('section.pagination').html(pagination)
navigateToPage: (event) => navigateToPage: (event) =>
event.preventDefault() event.preventDefault()
......
if Backbone? if Backbone?
class @DiscussionThreadProfileView extends Backbone.View class @DiscussionThreadProfileView extends Backbone.View
render: -> render: ->
@template = DiscussionUtil.getTemplate("_profile_thread")
@convertMath() @convertMath()
@abbreviateBody() @abbreviateBody()
params = $.extend(@model.toJSON(),{permalink: @model.urlFor('retrieve')}) params = $.extend(@model.toJSON(),{permalink: @model.urlFor('retrieve')})
if not @model.get('anonymous') if not @model.get('anonymous')
params = $.extend(params, user:{username: @model.username, user_url: @model.user_url}) params = $.extend(params, user:{username: @model.username, user_url: @model.user_url})
@$el.html(Mustache.render(@template, params)) @$el.html(_.template($("#profile-thread-template").html())(params))
@$("span.timeago").timeago() @$("span.timeago").timeago()
element = @$(".post-body") element = @$(".post-body")
if MathJax? if MathJax?
......
...@@ -12,15 +12,13 @@ if Backbone? ...@@ -12,15 +12,13 @@ if Backbone?
@discussion.reset(@collection, {silent: false}) @discussion.reset(@collection, {silent: false})
render: () => render: () =>
profileTemplate = $("script#_user_profile").html() @$el.html(_.template($("#user-profile-template").html())({threads: @discussion.models}))
@$el.html(Mustache.render(profileTemplate, {threads: @discussion.models}))
@discussion.map (thread) -> @discussion.map (thread) ->
new DiscussionThreadProfileView(el: @$("article#thread_#{thread.id}"), model: thread).render() new DiscussionThreadProfileView(el: @$("article#thread_#{thread.id}"), model: thread).render()
baseUri = URI(window.location).removeSearch("page") baseUri = URI(window.location).removeSearch("page")
pageUrlFunc = (page) -> baseUri.clone().addSearch("page", page) pageUrlFunc = (page) -> baseUri.clone().addSearch("page", page)
paginationParams = DiscussionUtil.getPaginationParams(@page, @numPages, pageUrlFunc) paginationParams = DiscussionUtil.getPaginationParams(@page, @numPages, pageUrlFunc)
paginationTemplate = $("script#_pagination").html() @$el.find(".pagination").html(_.template($("#pagination-template").html())(paginationParams))
@$el.find(".pagination").html(Mustache.render(paginationTemplate, paginationParams))
changePage: (event) -> changePage: (event) ->
event.preventDefault() event.preventDefault()
......
<%! from django.utils.translation import ugettext as _ %> <section class="discussion" data-discussion-id="<%= discussionId %>">
<section class="discussion" data-discussion-id="{{discussionId}}">
<article class="new-post-article"></article> <article class="new-post-article"></article>
<section class="threads"> <section class="threads">
{{#threads}} <% _.each(threads, function(thread) { %>
<article class="discussion-thread" id="thread_{{id}}"> <article class="discussion-thread" id="thread_<%= thread.id %>">
</article> </article>
{{/threads}} <% }); %>
</section> </section>
<section class="pagination"> <section class="pagination">
......
<nav class="discussion-paginator">
<ol>
<% if (previous) { %>
<li class="previous-page"><a class="discussion-pagination" href="<%= previous.url %>" data-page-number="<%= previous.number %>">&lt; <%- gettext("Previous") %></a></li>
<% } %>
<% if (first) { %>
<li class="first-page"><a class="discussion-pagination" href="<%= first.url %>" data-page-number="1">1</a></li>
<% } %>
<% if (leftdots) { %>
<li class="previous-ellipses"><%- gettext("…") %></li>
<% } %>
<% _.each(lowPages, function(page) { %>
<li class="lower-page"><a class="discussion-pagination" href="<%= page.url %>" data-page-number="<%= page.number %>"><%= page.number %></a></li>
<% }); %>
<li class="current-page"><span><%= page %></span></li>
<% _.each(highPages, function(page) { %>
<li class="higher-page"><a class="discussion-pagination" href="<%= page.url %>" data-page-number="<%= page.number %>"><%= page.number %></a></li>
<% }); %>
<% if (rightdots) { %>
<li class="next-ellipses"><%- gettext("…") %></li>
<% } %>
<% if (last) { %>
<li class="last-page"><a class="discussion-pagination" href="<%= last.url %>" data-page-number="<%= last.number %>"><%= last.number %></a></li>
<% } %>
<% if (next) { %>
<li class="next-page"><a class="discussion-pagination" href="<%= next.url %>" data-page-number="<%= next.number %>"><%- gettext("Next") %> &gt;</a></li>
<% } %>
</ol>
</nav>
<article class="discussion-article" data-id="<%- id %>">
<div class="discussion-post">
<header>
<h3><%- title %></h3>
<p class="posted-details">
<% if (user) { %>
<a href="<%- user.url %>" class="username"><%- user.username %></a>
<% } else { %>
<%- gettext("anonymous") %>
<% } %>
<span class="timeago" title="<%- created_at %>"><%- created_at %></span>
<span class="post-status-closed top-post-status" style="display: none">
&bull; <%- gettext("This thread is closed.") %>
</span>
</p>
</header>
<div class="post-body"><%= abbreviatedBody %></div>
</div>
<div class="post-tools">
<a href="<%- permalink %>"><%- gettext("View discussion") %></a>
</div>
</article>
<h2><%- gettext("Active Threads") %></h2>
<section class="discussion">
<% _.each(threads, function(thread) { %>
<article class="discussion-thread" id="thread_<%= thread.id %>"/>
<% }); %>
</section>
<section class="pagination"/>
from django.conf import settings
from mako.template import Template
import os
def include_mustache_templates():
mustache_dir = settings.PROJECT_ROOT / 'templates' / 'discussion' / 'mustache'
def is_valid_file_name(file_name):
return file_name.endswith('.mustache')
def read_file(file_name):
return open(mustache_dir / file_name, "r").read().decode('utf-8')
def template_id_from_file_name(file_name):
return file_name.rpartition('.')[0]
def process_mako(template_content):
return Template(template_content).render_unicode()
def make_script_tag(id, content):
return u"<script type='text/template' id='{0}'>{1}</script>".format(id, content)
return u'\n'.join(
make_script_tag(template_id_from_file_name(file_name), process_mako(read_file(file_name)))
for file_name in os.listdir(mustache_dir)
if is_valid_file_name(file_name)
)
<%! from django_comment_client.helpers import include_mustache_templates %>
<%include file="/mathjax_include.html" /> <%include file="/mathjax_include.html" />
${include_mustache_templates()}
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
<script type="text/javascript" src="${static.url('js/jquery.autocomplete.js')}"></script> <script type="text/javascript" src="${static.url('js/jquery.autocomplete.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/jquery.timeago.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/jquery.timeago.js')}"></script>
<script type="text/javascript" src="${static.url('js/src/jquery.timeago.locale.js')}"></script> <script type="text/javascript" src="${static.url('js/src/jquery.timeago.locale.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/mustache.js')}"></script>
<script type="text/javascript" src="${static.url('js/src/tooltip_manager.js')}"></script> <script type="text/javascript" src="${static.url('js/src/tooltip_manager.js')}"></script>
<link href="${static.url('css/vendor/jquery.autocomplete.css')}" rel="stylesheet" type="text/css"> <link href="${static.url('css/vendor/jquery.autocomplete.css')}" rel="stylesheet" type="text/css">
<%! <%!
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
import django_comment_client.helpers as helpers from django_comment_client.utils import permalink
%> %>
% if recent_active_threads: % if recent_active_threads:
...@@ -11,7 +11,7 @@ import django_comment_client.helpers as helpers ...@@ -11,7 +11,7 @@ import django_comment_client.helpers as helpers
</header> </header>
<ol class="discussion-sidebar-following-list"> <ol class="discussion-sidebar-following-list">
% for thread in recent_active_threads: % for thread in recent_active_threads:
<li><a href="${helpers.permalink(thread) | h}"><span class="sidebar-following-name">${thread['title'] | h}</span> <span class="sidebar-vote-count">${thread['votes']['point'] | h}</span></a></li> <li><a href="${permalink(thread) | h}"><span class="sidebar-following-name">${thread['title'] | h}</span> <span class="sidebar-vote-count">${thread['votes']['point'] | h}</span></a></li>
% endfor % endfor
<ol> <ol>
</article> </article>
......
...@@ -6,7 +6,16 @@ window.PLATFORM_NAME = ${json.dumps(settings.PLATFORM_NAME)}; ...@@ -6,7 +6,16 @@ window.PLATFORM_NAME = ${json.dumps(settings.PLATFORM_NAME)};
window.ENABLE_DISCUSSION_HOME_PANEL = ${json.dumps(settings.FEATURES.get('ENABLE_DISCUSSION_HOME_PANEL', False))}; window.ENABLE_DISCUSSION_HOME_PANEL = ${json.dumps(settings.FEATURES.get('ENABLE_DISCUSSION_HOME_PANEL', False))};
</script> </script>
% for template_name in ['thread', 'thread-show', 'thread-edit', 'thread-response', 'thread-response-show', 'thread-response-edit', 'response-comment-show', 'response-comment-edit', 'thread-list-item', 'discussion-home', 'search-alert', 'new-post', 'thread-type', 'new-post-menu-entry', 'new-post-menu-category', 'topic', 'post-user-display']: <%
template_names = [
'thread', 'thread-show', 'thread-edit', 'thread-response', 'thread-response-show', 'thread-response-edit',
'response-comment-show', 'response-comment-edit', 'thread-list-item', 'discussion-home', 'search-alert',
'new-post', 'thread-type', 'new-post-menu-entry', 'new-post-menu-category', 'topic', 'post-user-display',
'inline-discussion', 'pagination', 'user-profile', 'profile-thread'
]
%>
% for template_name in template_names:
<script aria-hidden="true" type="text/template" id="${template_name}-template"> <script aria-hidden="true" type="text/template" id="${template_name}-template">
<%static:include path="common/templates/discussion/${template_name}.underscore" /> <%static:include path="common/templates/discussion/${template_name}.underscore" />
</script> </script>
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
<%namespace name='static' file='../static_content.html'/> <%namespace name='static' file='../static_content.html'/>
<%! <%!
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
import django_comment_client.helpers as helpers
from django.template.defaultfilters import escapejs from django.template.defaultfilters import escapejs
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
%> %>
......
<%! from django.utils.translation import ugettext as _ %>
<nav class="discussion-{{discussiontype}}-paginator discussion-paginator">
<ol>
{{#previous}}
<li><a class="discussion-pagination" href="{{url}}" data-page-number="{{number}}">&lt; ${_("Previous")}</a></li>
{{/previous}}
{{#first}}
<li><a class="discussion-pagination" href="{{url}}" data-page-number="1">1</a></li>
{{/first}}
{{#leftdots}}
<li>${_(u"…")}</li>
{{/leftdots}}
{{#lowPages}}
<li><a class="discussion-pagination" href="{{url}}" data-page-number="{{number}}">{{number}}</a></li>
{{/lowPages}}
<li class="current-page"><span>{{page}}</span></li>
{{#highPages}}
<li><a class="discussion-pagination" href="{{url}}" data-page-number="{{number}}">{{number}}</a></li>
{{/highPages}}
{{#rightdots}}
<li>${_(u"…")}</li>
{{/rightdots}}
{{#last}}
<li><a class="discussion-pagination" href="{{url}}" data-page-number="{{number}}">{{number}}</a></li>
{{/last}}
{{#next}}
<li><a class="discussion-pagination" href="{{url}}" data-page-number="{{number}}">${_("Next")} &gt;</a></li>
{{/next}}
</ol>
</nav>
<%! from django.utils.translation import ugettext as _ %>
<article class="discussion-article" data-id="{{id}}">
<div class="discussion-post">
<header>
<h3>{{title}}</h3>
<p class="posted-details">
{{#user}}
<a href="{{user_url}}" class="username">{{username}}</a>
{{/user}}
{{^user}}
${_("anonymous")}
{{/user}}
<span class="timeago" title="{{created_at}}">{{created_at}}</span>
<span class="post-status-closed top-post-status" style="display: none">
&bull; ${_("This thread is closed.")}
</span>
</p>
</header>
<div class="post-body">{{{abbreviatedBody}}}</div>
</div>
<div class="post-tools">
<a href="{{permalink}}">${_("View discussion")}</a>
</div>
</article>
<%! from django.utils.translation import ugettext as _ %>
<h2>${_("Active Threads")}</h2>
<section class="discussion">
{{#threads}}
<article class="discussion-thread" id="thread_{{id}}"/>
{{/threads}}
</section>
<section class="pagination"/>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment