Commit 9f3b8ddf by Eugeny Kolpakov Committed by GitHub

Merge pull request #12914 from open-craft/ekolpakov/discussion_fixes_from_solutions

Discussion fixes from solutions
parents e1dbfe3a e0c7228d
/* globals DiscussionThreadListView, DiscussionThreadView, DiscussionUtil, NewPostView */
/* globals DiscussionThreadListView, DiscussionThreadView, DiscussionUtil, NewPostView, Thread */
(function() {
'use strict';
var __hasProp = {}.hasOwnProperty,
......@@ -18,9 +18,20 @@
return child;
};
function getSingleThreadRoute(commentable_id, thread_id) {
return commentable_id + "/threads/" + thread_id;
}
if (typeof Backbone !== "undefined" && Backbone !== null) {
this.DiscussionRouter = (function(_super) {
var allThreadsRoute = "",
singleThreadRoute = getSingleThreadRoute(":forum_name", ":thread_id"), // :forum_name/threads/:thread_id
routes = {};
routes[allThreadsRoute] = "allThreads";
routes[singleThreadRoute] = "showThread";
__extends(DiscussionRouter, _super);
function DiscussionRouter() {
......@@ -40,16 +51,16 @@
this.showMain = function() {
return DiscussionRouter.prototype.showMain.apply(self, arguments);
};
this.renderThreadView = function() {
return DiscussionRouter.prototype.renderThreadView.apply(self, arguments);
};
this.setActiveThread = function() {
return DiscussionRouter.prototype.setActiveThread.apply(self, arguments);
};
return DiscussionRouter.__super__.constructor.apply(this, arguments);
}
DiscussionRouter.prototype.routes = {
"": "allThreads",
":forum_name/threads/:thread_id": "showThread"
};
DiscussionRouter.prototype.routes = routes;
DiscussionRouter.prototype.initialize = function(options) {
var self = this;
......@@ -82,23 +93,50 @@
DiscussionRouter.prototype.allThreads = function() {
this.nav.updateSidebar();
return this.nav.goHome();
this.nav.goHome();
};
DiscussionRouter.prototype.setActiveThread = function() {
if (this.thread) {
return this.nav.setActiveThread(this.thread.get("id"));
} else {
return this.nav.goHome;
this.nav.setActiveThread(this.thread.get("id"));
}
};
DiscussionRouter.prototype.showThread = function(forum_name, thread_id) {
var self = this;
this.thread = this.discussion.get(thread_id);
if (this.thread) {
this.renderThreadView();
return;
}
// if thread is not loaded yet for some reason - try loading it
DiscussionUtil.safeAjax({
url: DiscussionUtil.urlFor('retrieve_single_thread', forum_name, thread_id)
}).done(function(data) {
// if succeded - proceed normally
self.thread = new Thread(data.content);
self.discussion.add(self.thread);
self.renderThreadView();
}).fail(function(xhr) {
// otherwise display error message and navigate to all threads view
var errorMsg;
if (xhr.status === 404) {
errorMsg = gettext("The thread you selected has been deleted. Please select another thread.");
} else {
errorMsg = gettext("We had some trouble loading more responses. Please try again.");
}
DiscussionUtil.discussionAlert(gettext("Sorry"), errorMsg);
this.allThreads();
});
};
DiscussionRouter.prototype.renderThreadView = function() {
this.thread.set("unread_comments_count", 0);
this.thread.set("read", true);
this.setActiveThread();
return this.showMain();
this.showMain();
};
DiscussionRouter.prototype.showMain = function() {
......@@ -123,26 +161,23 @@
this.main.on("thread:responses:rendered", function() {
return self.nav.updateSidebar();
});
return this.thread.on("thread:thread_type_updated", this.showMain);
this.thread.on("thread:thread_type_updated", this.showMain);
};
DiscussionRouter.prototype.navigateToThread = function(thread_id) {
var thread;
var thread, targetThreadRoute;
thread = this.discussion.get(thread_id);
return this.navigate("" + (thread.get("commentable_id")) + "/threads/" + thread_id, {
trigger: true
});
targetThreadRoute = getSingleThreadRoute(thread.get("commentable_id"), thread_id);
this.navigate(targetThreadRoute, {trigger: true});
};
DiscussionRouter.prototype.navigateToAllThreads = function() {
return this.navigate("", {
trigger: true
});
this.navigate(allThreadsRoute, {trigger: true});
};
DiscussionRouter.prototype.showNewPost = function() {
var self = this;
return $('.forum-content').fadeOut({
$('.forum-content').fadeOut({
duration: 200,
complete: function() {
return self.newPost.fadeIn(200).focus();
......@@ -151,7 +186,7 @@
};
DiscussionRouter.prototype.hideNewPost = function() {
return this.newPost.fadeOut({
this.newPost.fadeOut({
duration: 200,
complete: function() {
return $('.forum-content').fadeIn(200).find('.thread-wrapper').focus();
......
......@@ -34,10 +34,11 @@
course_settings: course_settings
});
/* jshint +W031*/
return Backbone.history.start({
pushState: true,
root: "/courses/" + $$course_id + "/discussion/forum/"
});
if (!Backbone.History.started) {
Backbone.history.start({pushState: true, root: "/courses/" + $$course_id + "/discussion/forum/"});
} else {
Backbone.history.loadUrl(window.location.pathname);
}
}
};
DiscussionProfileApp = {
......
......@@ -271,20 +271,22 @@
return $button.toggleClass("is-checked", endorsed);
},
votes: function(votes) {
var button, numVotes, selector, votesHtml, votesCountMsg;
var button, numVotes, selector, votesText, votesCountMsg;
selector = ".action-vote";
this.updateButtonState(selector, window.user.voted(this.model));
button = this.$el.find(selector);
numVotes = votes.up_count;
votesCountMsg = ngettext(
"there is currently %(numVotes)s vote", "there are currently %(numVotes)s votes", numVotes
"there is currently {numVotes} vote", "there are currently {numVotes} votes", numVotes
);
button.find(".js-sr-vote-count").html(interpolate(votesCountMsg, {numVotes: numVotes }, true));
votesHtml = interpolate(ngettext("%(numVotes)s Vote", "%(numVotes)s Votes", numVotes), {
numVotes: numVotes
}, true);
button.find(".vote-count").html(votesHtml);
return this.$el.find('.display-vote .vote-count').html(votesHtml);
button.find(".js-sr-vote-count").empty().text(
edx.StringUtils.interpolate(votesCountMsg, {numVotes: numVotes })
);
votesText = edx.StringUtils.interpolate(
ngettext("{numVotes} Vote", "{numVotes} Votes", numVotes),
{ numVotes: numVotes });
button.find(".vote-count").empty().text(votesText);
this.$el.find('.display-vote .vote-count').empty().text(votesText);
},
pinned: function(pinned) {
this.updateButtonState(".action-pin", pinned);
......@@ -389,18 +391,18 @@
msg = gettext("We had some trouble removing this endorsement. Please try again.");
}
}
beforeFunc = function() {
return self.trigger("comment:endorse");
};
return DiscussionUtil.updateWithUndo(this.model, updates, {
url: url,
type: "POST",
data: {
endorsed: is_endorsing
return DiscussionUtil.updateWithUndo(
this.model,
updates,
{
url: url,
type: "POST",
data: { endorsed: is_endorsing },
$elem: $(event.currentTarget)
},
beforeSend: beforeFunc,
$elem: $(event.currentTarget)
}, msg).always(this.trigger("comment:endorse"));
msg,
function() { return self.trigger("comment:endorse"); }
).always(this.trigger("comment:endorse"));
};
DiscussionContentShowView.prototype.toggleVote = function(event) {
......
......@@ -25,13 +25,14 @@
},
render: function() {
var threadTypeTemplate,
formId = _.uniqueId("form-");
this.template = _.template($('#thread-edit-template').html());
this.$el.html(this.template(this.model.toJSON())).appendTo(this.container);
this.submitBtn = this.$('.post-update');
threadTypeTemplate = _.template($("#thread-type-template").html());
this.addField(threadTypeTemplate({form_id: formId}));
var formId = _.uniqueId("form-"),
threadTypeTemplate = edx.HtmlUtils.template($("#thread-type-template").html()),
$threadTypeSelector = $(threadTypeTemplate({form_id: formId}).toString()),
mainTemplate = edx.HtmlUtils.template($('#thread-edit-template').html());
edx.HtmlUtils.setHtml(this.$el, mainTemplate(this.model.toJSON()));
this.container.append(this.$el);
this.$submitBtn = this.$('.post-update');
this.addField($threadTypeSelector);
this.$("#" + formId + "-post-type-" + this.threadType).attr('checked', true);
// Only allow the topic field for course threads, as standalone threads
// cannot be moved.
......@@ -46,8 +47,8 @@
return this;
},
addField: function(fieldView) {
this.$('.forum-edit-post-form-wrapper').append(fieldView);
addField: function($fieldView) {
this.$('.forum-edit-post-form-wrapper').append($fieldView);
return this;
},
......@@ -69,8 +70,8 @@
}
return DiscussionUtil.safeAjax({
$elem: this.submitBtn,
$loading: this.submitBtn,
$elem: this.$submitBtn,
$loading: this.$submitBtn,
url: DiscussionUtil.urlFor('update_thread', this.model.id),
type: 'POST',
dataType: 'json',
......
......@@ -28,7 +28,7 @@
}
DiscussionThreadProfileView.prototype.render = function() {
var element, params;
var params;
this.convertMath();
this.abbreviateBody();
params = $.extend(this.model.toJSON(), {
......@@ -42,26 +42,24 @@
}
});
}
this.$el.html(_.template($("#profile-thread-template").html())(params));
edx.HtmlUtils.setHtml(
this.$el,
edx.HtmlUtils.template($("#profile-thread-template").html())(params)
);
this.$("span.timeago").timeago();
element = this.$(".post-body");
if (typeof MathJax !== "undefined" && MathJax !== null) {
MathJax.Hub.Queue(["Typeset", MathJax.Hub, element[0]]);
}
DiscussionUtil.typesetMathJax(this.$(".post-body"));
return this;
};
DiscussionThreadProfileView.prototype.convertMath = function() {
return this.model.set(
'markdownBody',
DiscussionUtil.postMathJaxProcessor(DiscussionUtil.markdownWithHighlight(this.model.get('body')))
);
var htmlSnippet = DiscussionUtil.markdownWithHighlight(this.model.get('body'));
this.model.set('markdownBody', htmlSnippet);
};
DiscussionThreadProfileView.prototype.abbreviateBody = function() {
var abbreviated;
abbreviated = DiscussionUtil.abbreviateHTML(this.model.get('markdownBody'), 140);
return this.model.set('abbreviatedBody', abbreviated);
this.model.set('abbreviatedBody', abbreviated);
};
return DiscussionThreadProfileView;
......
......@@ -38,7 +38,6 @@
DiscussionThreadShowView.prototype.renderTemplate = function() {
var context;
this.template = _.template($("#thread-show-template").html());
context = $.extend({
mode: this.mode,
flagged: this.model.isFlagged(),
......@@ -46,27 +45,25 @@
cid: this.model.cid,
readOnly: $('.discussion-module').data('read-only')
}, this.model.attributes);
return this.template(context);
return edx.HtmlUtils.template($("#thread-show-template").html())(context);
};
DiscussionThreadShowView.prototype.render = function() {
this.$el.html(this.renderTemplate());
edx.HtmlUtils.setHtml(
this.$el,
this.renderTemplate()
);
this.delegateEvents();
this.renderAttrs();
this.$("span.timeago").timeago();
this.convertMath();
this.highlight(this.$(".post-body"));
this.highlight(this.$("h1,h3"));
this.$(".post-body");
this.$("h1,h3");
return this;
};
DiscussionThreadShowView.prototype.convertMath = function() {
var element;
element = this.$(".post-body");
element.html(DiscussionUtil.postMathJaxProcessor(DiscussionUtil.markdownWithHighlight(element.text())));
if (typeof MathJax !== "undefined" && MathJax !== null) {
return MathJax.Hub.Queue(["Typeset", MathJax.Hub, element[0]]);
}
DiscussionUtil.convertMath(this.$(".post-body"));
};
DiscussionThreadShowView.prototype.edit = function(event) {
......@@ -77,12 +74,6 @@
return this.trigger("thread:_delete", event);
};
DiscussionThreadShowView.prototype.highlight = function(el) {
if (el.html()) {
return el.html(el.html().replace(/&lt;mark&gt;/g, "<mark>").replace(/&lt;\/mark&gt;/g, "</mark>"));
}
};
return DiscussionThreadShowView;
})(DiscussionContentShowView);
......
......@@ -91,6 +91,7 @@
id = self.model.get("id");
if (collection.get(id)) {
self.model = collection.get(id);
self.rerender();
}
});
this.createShowView();
......@@ -133,7 +134,9 @@
DiscussionThreadView.prototype.render = function() {
var self = this;
this.$el.html(this.renderTemplate());
var $element = $(this.renderTemplate());
this.$el.empty();
this.$el.append($element);
this.delegateEvents();
this.renderShowView();
this.renderAttrs();
......@@ -215,7 +218,7 @@
}
};
DiscussionThreadView.prototype.loadResponses = function(responseLimit, elem, firstLoad) {
DiscussionThreadView.prototype.loadResponses = function(responseLimit, $elem, firstLoad) {
var takeFocus,
self = this;
takeFocus = this.mode === "tab" ? false : true;
......@@ -227,8 +230,8 @@
resp_skip: this.responses.size(),
resp_limit: responseLimit ? responseLimit : void 0
},
$elem: elem,
$loading: elem,
$elem: $elem,
$loading: $elem,
takeFocus: takeFocus,
complete: function() {
self.responsesRequest = null;
......@@ -279,20 +282,20 @@
};
DiscussionThreadView.prototype.renderResponseCountAndPagination = function(responseTotal) {
var buttonText, loadMoreButton, responseCountFormat, responseLimit, responsePagination,
var buttonText, $loadMoreButton, responseCountFormat, responseLimit, responsePagination,
responsesRemaining, showingResponsesText, self = this;
if (this.isQuestion() && this.markedAnswers.length !== 0) {
responseCountFormat = ngettext(
"%(numResponses)s other response", "%(numResponses)s other responses", responseTotal
"{numResponses} other response", "{numResponses} other responses", responseTotal
);
} else {
responseCountFormat = ngettext(
"%(numResponses)s response", "%(numResponses)s responses", responseTotal
"{numResponses} response", "{numResponses} responses", responseTotal
);
}
this.$el.find(".response-count").html(interpolate(responseCountFormat, {
numResponses: responseTotal
}, true));
this.$el.find(".response-count").text(
edx.StringUtils.interpolate(responseCountFormat, {numResponses: responseTotal}, true)
);
responsePagination = this.$el.find(".response-pagination");
responsePagination.empty();
if (responseTotal > 0) {
......@@ -301,9 +304,9 @@
showingResponsesText = gettext("Showing all responses");
}
else {
showingResponsesText = interpolate(
showingResponsesText = edx.StringUtils.interpolate(
ngettext(
"Showing first response", "Showing first %(numResponses)s responses",
"Showing first response", "Showing first {numResponses} responses",
this.responses.size()
),
{ numResponses: this.responses.size() },
......@@ -312,22 +315,22 @@
}
responsePagination.append($("<span>")
.addClass("response-display-count").html(_.escape(showingResponsesText)));
.addClass("response-display-count").text(showingResponsesText));
if (responsesRemaining > 0) {
if (responsesRemaining < SUBSEQUENT_RESPONSE_PAGE_SIZE) {
responseLimit = null;
buttonText = gettext("Load all responses");
} else {
responseLimit = SUBSEQUENT_RESPONSE_PAGE_SIZE;
buttonText = interpolate(gettext("Load next %(numResponses)s responses"), {
buttonText = edx.StringUtils.interpolate(gettext("Load next {numResponses} responses"), {
numResponses: responseLimit
}, true);
}
loadMoreButton = $("<button>").addClass("load-response-button").html(_.escape(buttonText));
loadMoreButton.click(function() {
return self.loadResponses(responseLimit, loadMoreButton);
$loadMoreButton = $("<button>").addClass("load-response-button").text(buttonText);
$loadMoreButton.click(function() {
return self.loadResponses(responseLimit, $loadMoreButton);
});
return responsePagination.append(loadMoreButton);
return responsePagination.append($loadMoreButton);
}
}
};
......
......@@ -37,12 +37,14 @@
ResponseCommentShowView.prototype.tagName = "li";
ResponseCommentShowView.prototype.render = function() {
this.template = _.template($("#response-comment-show-template").html());
this.$el.html(this.template(_.extend({
var template = edx.HtmlUtils.template($("#response-comment-show-template").html());
var context = _.extend({
cid: this.model.cid,
author_display: this.getAuthorDisplay(),
readOnly: $('.discussion-module').data('read-only')
}, this.model.attributes)));
}, this.model.attributes);
edx.HtmlUtils.setHtml(this.$el, template(context));
this.delegateEvents();
this.renderAttrs();
this.$el.find(".timeago").timeago();
......@@ -52,22 +54,25 @@
};
ResponseCommentShowView.prototype.addReplyLink = function() {
var html, name, p, _ref;
var html, name;
if (this.model.hasOwnProperty('parent')) {
name = (_ref = this.model.parent.get('username')) !== null ? _ref : gettext("anonymous");
html = "<a href='#comment_" + this.model.parent.id + "'>@" + name + "</a>: ";
p = this.$('.response-body p:first');
return p.prepend(html);
name = this.model.parent.get('username') || gettext("anonymous");
html = edx.HtmlUtils.interpolateHtml(
edx.HtmlUtils.HTML("<a href='#comment_{parent_id}'>@{name}</a>: "),
{
parent_id: this.model.parent.id,
name: name
}
);
return edx.HtmlUtils.prepend(
this.$('.response-body p:first'),
html
);
}
};
ResponseCommentShowView.prototype.convertMath = function() {
var body;
body = this.$el.find(".response-body");
body.html(DiscussionUtil.postMathJaxProcessor(DiscussionUtil.markdownWithHighlight(body.text())));
if (typeof MathJax !== "undefined" && MathJax !== null) {
return MathJax.Hub.Queue(["Typeset", MathJax.Hub, body[0]]);
}
DiscussionUtil.convertMath(this.$el.find(".response-body"));
};
ResponseCommentShowView.prototype._delete = function(event) {
......
......@@ -33,19 +33,18 @@
};
ThreadResponseShowView.prototype.renderTemplate = function() {
var context;
this.template = _.template($("#thread-response-show-template").html());
context = _.extend({
cid: this.model.cid,
author_display: this.getAuthorDisplay(),
endorser_display: this.getEndorserDisplay(),
readOnly: $('.discussion-module').data('read-only')
}, this.model.attributes);
return this.template(context);
var template = edx.HtmlUtils.template($("#thread-response-show-template").html()),
context = _.extend({
cid: this.model.cid,
author_display: this.getAuthorDisplay(),
endorser_display: this.getEndorserDisplay(),
readOnly: $('.discussion-module').data('read-only')
}, this.model.attributes);
return template(context);
};
ThreadResponseShowView.prototype.render = function() {
this.$el.html(this.renderTemplate());
edx.HtmlUtils.setHtml(this.$el, this.renderTemplate());
this.delegateEvents();
this.renderAttrs();
this.$el.find(".posted-details .timeago").timeago();
......@@ -54,12 +53,7 @@
};
ThreadResponseShowView.prototype.convertMath = function() {
var element;
element = this.$(".response-body");
element.html(DiscussionUtil.postMathJaxProcessor(DiscussionUtil.markdownWithHighlight(element.text())));
if (typeof MathJax !== "undefined" && MathJax !== null) {
return MathJax.Hub.Queue(["Typeset", MathJax.Hub, element[0]]);
}
DiscussionUtil.convertMath(this.$(".response-body"));
};
ThreadResponseShowView.prototype.edit = function(event) {
......
......@@ -3,9 +3,10 @@
'use strict';
describe('DiscussionUtil', function() {
beforeEach(function() {
return DiscussionSpecHelper.setUpGlobals();
DiscussionSpecHelper.setUpGlobals();
});
return describe("updateWithUndo", function() {
describe("updateWithUndo", function() {
it("calls through to safeAjax with correct params, and reverts the model in case of failure", function() {
var deferred, model, res, updates;
deferred = $.Deferred();
......@@ -45,13 +46,13 @@
updates = {
hello: "world"
};
$elem = jasmine.createSpyObj('$elem', ['attr']);
$elem.attr.and.returnValue(true);
$elem = jasmine.createSpyObj('$elem', ['prop']);
$elem.prop.and.returnValue(true);
res = DiscussionUtil.updateWithUndo(model, updates, {
foo: "bar",
$elem: $elem
}, "error message");
expect($elem.attr).toHaveBeenCalledWith("disabled");
expect($elem.prop).toHaveBeenCalledWith("disabled");
expect(DiscussionUtil.safeAjax).toHaveBeenCalled();
expect(model.attributes).toEqual({
hello: false,
......@@ -64,6 +65,30 @@
return expect(failed).toBe(true);
});
});
describe('safeAjax', function() {
function dismissAlert() {
$(".modal#discussion-alert").remove();
}
it('respects global beforeSend', function() {
var beforeSendSpy = jasmine.createSpy();
$.ajaxSetup({beforeSend: beforeSendSpy});
var $elem = jasmine.createSpyObj('$elem', ['prop']);
DiscussionUtil.safeAjax({
$elem: $elem,
url: "/",
type: "GET",
dataType: "json"
}).always(function() {
dismissAlert();
});
expect($elem.prop).toHaveBeenCalledWith("disabled", true);
expect(beforeSendSpy).toHaveBeenCalled();
});
});
});
}).call(this);
......@@ -261,7 +261,7 @@
});
});
describe("search alerts", function() {
var testAlertMessages;
var testAlertMessages, getAlertMessagesAndClasses;
testAlertMessages = function(expectedMessages) {
return expect($(".search-alert .message").map(function() {
......@@ -269,6 +269,15 @@
}).get()).toEqual(expectedMessages);
};
getAlertMessagesAndClasses = function() {
return $(".search-alert").map(function() {
return {
text: $('.message', this).html(),
css_class: $(this).attr('class')
};
}).get();
};
it("renders and removes search alerts", function() {
var bar, foo;
testAlertMessages([]);
......@@ -282,6 +291,27 @@
return testAlertMessages([]);
});
it("renders search alert with custom class", function() {
var foo, messages;
testAlertMessages([]);
this.view.addSearchAlert("foo", "custom-class");
messages = getAlertMessagesAndClasses();
expect(messages.length).toEqual(1);
expect(messages[0].text).toEqual("foo");
expect(messages[0].css_class).toEqual("search-alert custom-class");
foo = this.view.addSearchAlert("bar", "other-class");
messages = getAlertMessagesAndClasses();
expect(messages.length).toEqual(2);
expect(messages[0].text).toEqual("foo");
expect(messages[0].css_class).toEqual("search-alert custom-class");
expect(messages[1].text).toEqual("bar");
expect(messages[1].css_class).toEqual("search-alert other-class");
});
it("clears all search alerts", function() {
this.view.addSearchAlert("foo");
this.view.addSearchAlert("bar");
......
......@@ -94,7 +94,7 @@
this.view.render();
expectedGroupId = null;
DiscussionSpecHelper.makeAjaxSpy(function(params) {
return expect(params.data.group_id).toEqual(expectedGroupId);
expect(params.data.group_id).toEqual(expectedGroupId);
});
return _.each(["1", "2", ""], function(groupIdStr) {
expectedGroupId = groupIdStr;
......@@ -103,6 +103,7 @@
self.view.$(".js-post-body textarea").val("dummy body");
self.view.$(".forum-new-post-form").submit();
expect($.ajax).toHaveBeenCalled();
self.view.$(".forum-new-post-form").prop("disabled", false);
return $.ajax.calls.reset();
});
});
......
......@@ -33,8 +33,10 @@
}
});
this.event = DiscussionSpecHelper.makeEventSpy();
this.event.target = $("body");
spyOn(this.comment, "remove");
return spyOn(this.view.$el, "remove");
spyOn(this.view.$el, "remove");
$(this.event.target).prop("disabled", false);
});
setAjaxResult = function(isSuccess) {
return spyOn($, "ajax").and.callFake(function(params) {
......@@ -151,7 +153,7 @@
this.view.$el.find(".edit-comment-body").html($("<textarea></textarea>"));
this.view.$el.find(".edit-comment-body textarea").val(this.updatedBody);
spyOn(this.view, 'cancelEdit');
return spyOn($, "ajax").and.callFake(function(params) {
spyOn($, "ajax").and.callFake(function(params) {
if (self.ajaxSucceed) {
params.success();
} else {
......@@ -164,10 +166,17 @@
}
};
});
this.event = DiscussionSpecHelper.makeEventSpy();
// All the way down in discussion/utils.js there's this line
// element.after(...);
// element is event.target in this case. This causes a JS exception, so we override the target
this.event.target = $("body");
$(this.event.target).prop("disabled", false);
});
it('calls the update endpoint correctly and displays the show view on success', function() {
this.ajaxSucceed = true;
this.view.update(DiscussionSpecHelper.makeEventSpy());
this.view.update(this.event);
expect($.ajax).toHaveBeenCalled();
expect($.ajax.calls.mostRecent().args[0].url._parts.path)
.toEqual('/courses/edX/999/test/discussion/comments/01234567/update');
......@@ -179,7 +188,7 @@
var originalBody;
originalBody = this.comment.get("body");
this.ajaxSucceed = false;
this.view.update(DiscussionSpecHelper.makeEventSpy());
this.view.update(this.event);
expect($.ajax).toHaveBeenCalled();
expect($.ajax.calls.mostRecent().args[0].url._parts.path)
.toEqual('/courses/edX/999/test/discussion/comments/01234567/update');
......
......@@ -72,12 +72,12 @@
'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'
'user-profile', 'profile-thread', 'customwmd-prompt', 'nav-loading'
];
templateNamesNoTrailingTemplate = [
'forum-action-endorse', 'forum-action-answer', 'forum-action-follow', 'forum-action-vote',
'forum-action-report', 'forum-action-pin', 'forum-action-close', 'forum-action-edit',
'forum-action-delete', 'forum-actions'
'forum-action-report', 'forum-action-pin', 'forum-action-close', 'forum-action-edit',
'forum-action-delete', 'forum-actions', 'alert-popup', 'nav-load-more-link'
];
for (_i = 0, _len = templateNames.length; _i < _len; _i++) {
templateName = templateNames[_i];
......
<div class='modal' role='alertdialog' id='discussion-alert' aria-describedby='discussion-alert-message'>
<div class='inner-wrapper discussion-alert-wrapper'>
<button class='close-modal dismiss' title='<%- gettext("Close") %>''>
<span class='icon fa fa-times' aria-hidden='true'></span>
</button>
<header>
<h2/></h2>
<hr/>
</header>
<p id='discussion-alert-message'></p>
<hr/>
<button class='dismiss'><%- gettext("OK") %></button>
</div>
</div>
<li class='forum-nav-load-more'>
<a href='#' class='forum-nav-load-more-link'>
<%- gettext("Load more") %>
</a>
</li>
<div class="forum-nav-loading" tabindex="0">
<span class="icon fa fa-spinner fa-spin"/>
<span class="sr" role="alert"><%- srText %></span>
</div>
<div class="search-alert" id="search-alert-<%- cid %>">
<div class="search-alert <%- css_class %>" id="search-alert-<%- cid %>">
<div class="search-alert-content">
<p class="message"><%= message %></p>
<p class="message"><%= HtmlUtils.ensureHtml(messageHtml) %></p>
</div>
<div class="search-alert-controls">
......
......@@ -35,6 +35,8 @@ var options = {
{pattern: 'common/js/vendor/backbone.js', included: true},
{pattern: 'edx-ui-toolkit/js/utils/global-loader.js', included: true},
{pattern: 'edx-ui-toolkit/js/utils/string-utils.js', included: true},
{pattern: 'edx-ui-toolkit/js/utils/html-utils.js', included: true},
{pattern: 'js/vendor/jasmine-imagediff.js', included: true},
{pattern: 'common/js/spec_helpers/jasmine-extensions.js', included: true},
......
<%page expression_filter="h"/>
<%namespace name='static' file='../static_content.html'/>
<%! import json %>
<%! from openedx.core.djangolib.js_utils import js_escaped_string %>
<script type="text/javascript">
window.PLATFORM_NAME = ${json.dumps(settings.PLATFORM_NAME)};
window.ENABLE_DISCUSSION_HOME_PANEL = ${json.dumps(settings.FEATURES.get('ENABLE_DISCUSSION_HOME_PANEL', False))};
window.PLATFORM_NAME = "${settings.PLATFORM_NAME | n, js_escaped_string}";
% if settings.FEATURES.get('ENABLE_DISCUSSION_HOME_PANEL', False):
window.ENABLE_DISCUSSION_HOME_PANEL = true;
% else:
window.ENABLE_DISCUSSION_HOME_PANEL = false;
% endif
</script>
<%
......@@ -11,7 +16,14 @@ 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', 'customwmd-prompt'
'inline-discussion', 'pagination', 'user-profile', 'profile-thread', 'customwmd-prompt', 'nav-loading'
]
## same, but without trailing "-template" in script ID - these templates does not contain any free variables
template_names_no_suffix = [
'forum-action-endorse', 'forum-action-answer', 'forum-action-follow', 'forum-action-vote', 'forum-action-report',
'forum-action-pin', 'forum-action-close', 'forum-action-edit', 'forum-action-delete', 'forum-actions',
'alert-popup', 'nav-load-more-link'
]
%>
......@@ -21,8 +33,8 @@ template_names = [
</script>
% endfor
## same, but without trailing "-template" in script ID
% for template_name in ['forum-action-endorse', 'forum-action-answer', 'forum-action-follow', 'forum-action-vote', 'forum-action-report', 'forum-action-pin', 'forum-action-close', 'forum-action-edit', 'forum-action-delete', 'forum-actions']:
% for template_name in template_names_no_suffix:
<script aria-hidden="true" type="text/template" id="${template_name}">
<%static:include path="common/templates/discussion/${template_name}.underscore" />
</script>
......
<%inherit file="../main.html" />
<%page expression_filter="h"/>
<%namespace name='static' file='../static_content.html'/>
<%!
from django.utils.translation import ugettext as _
......@@ -6,7 +7,7 @@ from django.template.defaultfilters import escapejs
%>
<%block name="bodyclass">discussion</%block>
<%block name="pagetitle">${_("Discussion - {course_number}").format(course_number=course.display_number_with_default) | h}</%block>
<%block name="pagetitle">${_("Discussion - {course_number}").format(course_number=course.display_number_with_default)}</%block>
<%block name="headextra">
<%static:css group='style-course-vendor'/>
......@@ -33,7 +34,7 @@ from django.template.defaultfilters import escapejs
</nav>
</section>
<section class="course-content container discussion-user-threads" data-course-id="${course.id | h}" data-course-name="${course.display_name_with_default_escaped | h}" data-threads="${threads | h}" data-user-info="${user_info | h}" data-page="${page | h}" data-num-pages="${num_pages | h}"/>
<section class="course-content container discussion-user-threads" data-course-id="${course.id}" data-course-name="${course.display_name_with_default}" data-threads="${threads}" data-user-info="${user_info}" data-page="${page}" data-num-pages="${num_pages}"/>
</div>
</section>
......
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