From 6c540351976d4c35217fe35cf7d3277eed3e867d Mon Sep 17 00:00:00 2001 From: Andy Armstrong Date: Mon, 6 Jun 2016 18:21:27 -0400 Subject: [PATCH] Add a content header to the discussion board --- common/static/common/js/discussion/main.js | 73 --- common/static/common/js/discussion/utils.js | 4 - .../js/spec_helpers/discussion_spec_helper.js | 70 ++- .../test/acceptance/pages/lms/discussion.py | 8 +- .../discussion/js/discussion_board_factory.js | 56 +- .../js/discussion_profile_page_factory.js | 18 +- .../static/discussion/js/discussion_router.js | 307 +++++------ .../js/spec/discussion_board_factory_spec.js | 57 ++ .../discussion_profile_page_factory_spec.js | 41 ++ .../discussion_user_profile_view_spec.js | 520 +++++++++--------- .../js/views/discussion_user_profile_view.js | 188 +++---- .../templates}/user-profile.underscore | 2 +- .../discussion/discussion_board.html | 68 ++- .../discussion/discussion_profile_page.html | 69 ++- .../templates/discussion/maintenance.html | 26 +- .../templates/discussion/user_profile.html | 62 --- lms/djangoapps/discussion/tests/test_views.py | 15 +- lms/djangoapps/discussion/views.py | 37 +- .../django_comment_client/tests/group_id.py | 4 +- .../js/spec/views/team_discussion_spec.js | 13 +- .../teams/js/spec/views/team_profile_spec.js | 30 +- .../static/teams/js/views/team_discussion.js | 2 +- .../teams/templates/teams/teams.html | 4 - lms/static/discussion | 1 + .../courseware/link_clicked_events_spec.js | 2 +- lms/static/karma_lms.conf.js | 25 +- lms/static/lms/js/build.js | 3 +- lms/static/lms/js/spec/main.js | 119 ++-- lms/static/sass/discussion/_build.scss | 2 +- lms/static/sass/discussion/_discussion.scss | 265 +++++---- lms/static/sass/discussion/_layouts.scss | 18 +- lms/static/sass/discussion/_mixins.scss | 23 +- .../sass/discussion/elements/_actions.scss | 14 +- .../sass/discussion/elements/_editor.scss | 14 +- .../sass/discussion/elements/_navigation.scss | 30 +- .../sass/discussion/utilities/_developer.scss | 4 +- .../sass/discussion/utilities/_shame.scss | 18 +- .../utilities/_v1-compatibility.scss | 120 +--- .../discussion/utilities/_variables-v1.scss | 9 + .../discussion/utilities/_variables-v2.scss | 9 + .../discussion/views/_create-edit-post.scss | 33 +- lms/static/sass/discussion/views/_home.scss | 12 +- .../sass/discussion/views/_response.scss | 26 +- lms/static/sass/discussion/views/_thread.scss | 38 +- lms/static/sass/shared-v2/_layouts.scss | 4 +- .../courseware/courseware-chromeless.html | 1 - lms/templates/courseware/courseware.html | 4 +- .../_discussion_course_navigation.html | 14 - .../discussion/_js_body_dependencies.html | 36 +- .../discussion/_underscore_templates.html | 2 +- .../ux/reference/course-skeleton.html | 26 +- 51 files changed, 1241 insertions(+), 1305 deletions(-) delete mode 100644 common/static/common/js/discussion/main.js create mode 100644 lms/djangoapps/discussion/static/discussion/js/spec/discussion_board_factory_spec.js create mode 100644 lms/djangoapps/discussion/static/discussion/js/spec/discussion_profile_page_factory_spec.js rename {common/static/common/templates/discussion => lms/djangoapps/discussion/static/discussion/templates}/user-profile.underscore (75%) delete mode 100644 lms/djangoapps/discussion/templates/discussion/user_profile.html create mode 120000 lms/static/discussion delete mode 100644 lms/templates/discussion/_discussion_course_navigation.html diff --git a/common/static/common/js/discussion/main.js b/common/static/common/js/discussion/main.js deleted file mode 100644 index 410813c2c0..0000000000 --- a/common/static/common/js/discussion/main.js +++ /dev/null @@ -1,73 +0,0 @@ -/* global $$course_id, Content, Discussion, DiscussionRouter, DiscussionCourseSettings, - DiscussionUser, DiscussionUserProfileView, DiscussionUtil */ -(function() { - 'use strict'; - var DiscussionApp, DiscussionProfileApp; - - if (typeof Backbone !== 'undefined' && Backbone !== null) { - DiscussionApp = { - start: function(elem) { - var content_info, course_settings, discussion, element, sort_preference, thread_pages, threads, - user, user_info; - DiscussionUtil.loadRolesFromContainer(); - element = $(elem); - window.$$course_id = element.data('course-id'); - window.courseName = element.data('course-name'); - user_info = element.data('user-info'); - sort_preference = element.data('sort-preference'); - threads = element.data('threads'); - thread_pages = element.data('thread-pages'); - content_info = element.data('content-info'); - user = new DiscussionUser(user_info); - DiscussionUtil.setUser(user); - window.user = user; - Content.loadContentInfos(content_info); - discussion = new Discussion(threads, { - pages: thread_pages, - sort: sort_preference - }); - course_settings = new DiscussionCourseSettings(element.data('course-settings')); - new DiscussionRouter({ // eslint-disable-line no-new - discussion: discussion, - course_settings: course_settings - }); - if (!Backbone.History.started) { - Backbone.history.start({pushState: true, root: '/courses/' + $$course_id + '/discussion/forum/'}); - } else { - Backbone.history.loadUrl(window.location.pathname); - } - } - }; - DiscussionProfileApp = { - start: function(elem) { - var element, numPages, page, threads, user_info; - DiscussionUtil.loadRoles({ - 'Moderator': [], - 'Administrator': [], - 'Community TA': [] - }); - element = $(elem); - window.$$course_id = element.data('course-id'); - threads = element.data('threads'); - user_info = element.data('user-info'); - window.user = new DiscussionUser(user_info); - page = element.data('page'); - numPages = element.data('num-pages'); - return new DiscussionUserProfileView({ - el: element, - collection: threads, - page: page, - numPages: numPages - }); - } - }; - $(function() { - $('section.discussion').each(function(index, elem) { - return DiscussionApp.start(elem); - }); - return $('section.discussion-user-threads').each(function(index, elem) { - return DiscussionProfileApp.start(elem); - }); - }); - } -}).call(window); diff --git a/common/static/common/js/discussion/utils.js b/common/static/common/js/discussion/utils.js index 18ed34e5c9..6e5e564c3e 100644 --- a/common/static/common/js/discussion/utils.js +++ b/common/static/common/js/discussion/utils.js @@ -23,10 +23,6 @@ this.roleIds = roles; }; - DiscussionUtil.loadRolesFromContainer = function() { - return this.loadRoles($('#discussion-container').data('roles')); - }; - DiscussionUtil.isStaff = function(userId) { var staff; if (_.isUndefined(userId)) { diff --git a/common/static/common/js/spec_helpers/discussion_spec_helper.js b/common/static/common/js/spec_helpers/discussion_spec_helper.js index d24ca59101..a41368ca17 100644 --- a/common/static/common/js/spec_helpers/discussion_spec_helper.js +++ b/common/static/common/js/spec_helpers/discussion_spec_helper.js @@ -6,18 +6,26 @@ } DiscussionSpecHelper.setUpGlobals = function() { - DiscussionUtil.loadRoles({ - 'Moderator': [], - 'Administrator': [], - 'Community TA': [] - }); + DiscussionUtil.loadRoles(DiscussionSpecHelper.getTestRoleInfo()); window.$$course_id = 'edX/999/test'; - window.user = new DiscussionUser({ + window.user = new DiscussionUser(DiscussionSpecHelper.getTestUserInfo()); + return DiscussionUtil.setUser(window.user); + }; + + DiscussionSpecHelper.getTestUserInfo = function() { + return { username: 'test_user', id: '567', upvoted_ids: [] - }); - return DiscussionUtil.setUser(window.user); + }; + }; + + DiscussionSpecHelper.getTestRoleInfo = function() { + return { + 'Moderator': [], + 'Administrator': [], + 'Community TA': [] + }; }; DiscussionSpecHelper.makeTA = function() { @@ -42,69 +50,75 @@ return jasmine.createSpyObj('event', ['preventDefault', 'target']); }; - DiscussionSpecHelper.makeCourseSettings = function(is_cohorted) { - if (typeof is_cohorted === 'undefined' || is_cohorted === null) { - is_cohorted = true; + DiscussionSpecHelper.makeCourseSettings = function(isCohorted) { + if (typeof isCohorted === 'undefined' || isCohorted === null) { + isCohorted = true; } return new DiscussionCourseSettings({ category_map: { children: ['Test Topic', 'Other Topic'], entries: { 'Test Topic': { - is_cohorted: is_cohorted, + is_cohorted: isCohorted, id: 'test_topic' }, 'Other Topic': { - is_cohorted: is_cohorted, + is_cohorted: isCohorted, id: 'other_topic' } } }, - is_cohorted: is_cohorted + is_cohorted: isCohorted }); }; DiscussionSpecHelper.setUnderscoreFixtures = function() { - var templateFixture, templateName, templateNames, templateNamesNoTrailingTemplate, _i, _j, _len, _len1; + var templateFixture, templateName, templateNames, templateNamesNoTrailingTemplate, i, j, len; templateNames = [ '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', 'nav-loading' + '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', 'alert-popup', 'nav-load-more-link' ]; - for (_i = 0, _len = templateNames.length; _i < _len; _i++) { - templateName = templateNames[_i]; + for (i = 0, len = templateNames.length; i < len; i++) { + templateName = templateNames[i]; templateFixture = readFixtures('common/templates/discussion/' + templateName + '.underscore'); appendSetFixtures($('"); + + appendSetFixtures( + '
\n' + + '
' ); }; return DiscussionSpecHelper; - })(); + }()); }).call(this); diff --git a/common/test/acceptance/pages/lms/discussion.py b/common/test/acceptance/pages/lms/discussion.py index 37dd50786c..39abb9984c 100644 --- a/common/test/acceptance/pages/lms/discussion.py +++ b/common/test/acceptance/pages/lms/discussion.py @@ -577,11 +577,11 @@ class DiscussionUserProfilePage(CoursePage): def is_browser_on_page(self): return ( - self.q(css='section.discussion-user-threads[data-course-id="{}"]'.format(self.course_id)).present + self.q(css='.discussion-user-threads[data-course-id="{}"]'.format(self.course_id)).present and - self.q(css='section.user-profile a.learner-profile-link').present + self.q(css='.user-profile .learner-profile-link').present and - self.q(css='section.user-profile a.learner-profile-link').text[0] == self.username + self.q(css='.user-profile .learner-profile-link').text[0] == self.username ) @wait_for_js @@ -721,7 +721,7 @@ class DiscussionTabHomePage(CoursePage, DiscussionPageMixin): """ Returns the new post button. """ - elements = self.q(css="ol.course-tabs .new-post-btn") + elements = self.q(css=".new-post-btn") return elements.first if elements.visible and len(elements) == 1 else None @property diff --git a/lms/djangoapps/discussion/static/discussion/js/discussion_board_factory.js b/lms/djangoapps/discussion/static/discussion/js/discussion_board_factory.js index 66e45b005a..e122ae4f3f 100644 --- a/lms/djangoapps/discussion/static/discussion/js/discussion_board_factory.js +++ b/lms/djangoapps/discussion/static/discussion/js/discussion_board_factory.js @@ -1,36 +1,52 @@ -;(function(define) { +(function(define) { 'use strict'; - define(['jquery', 'backbone'], - function($, Backbone) { + define( + [ + 'jquery', + 'backbone', + 'discussion/js/discussion_router', + 'common/js/discussion/views/new_post_view' + ], + function($, Backbone, DiscussionRouter, NewPostView) { return function(options) { - var element = options.el, - userInfo = element.data('user-info'), - sortPreference = element.data('sort-preference'), - threads = element.data('threads'), - threadPages = element.data('thread-pages'), - contentInfo = element.data('content-info'), + var userInfo = options.user_info, + sortPreference = options.sort_preference, + threads = options.threads, + threadPages = options.thread_pages, + contentInfo = options.content_info, user = new window.DiscussionUser(userInfo), discussion, - courseSettings; + courseSettings, + newPostView, + router; // TODO: Perhaps eliminate usage of global variables when possible - window.DiscussionUtil.loadRolesFromContainer(); + window.DiscussionUtil.loadRoles(options.roles); window.$$course_id = options.courseId; - window.courseName = element.data('course-name'); + window.courseName = options.course_name; window.DiscussionUtil.setUser(user); window.user = user; window.Content.loadContentInfos(contentInfo); discussion = new window.Discussion(threads, {pages: threadPages, sort: sortPreference}); - courseSettings = new window.DiscussionCourseSettings(element.data('course-settings')); - // jshint nonew:false - new window.DiscussionRouter({ + courseSettings = new window.DiscussionCourseSettings(options.course_settings); + + // Create the new post view + newPostView = new NewPostView({ + el: $('.new-post-article'), + collection: discussion, + course_settings: courseSettings, + mode: 'tab' + }); + newPostView.render(); + + // Set up the router to manage the page's history + router = new DiscussionRouter({ + courseId: options.courseId, discussion: discussion, - course_settings: courseSettings - }); - Backbone.history.start({ - pushState: true, - root: '/courses/' + options.courseId + '/discussion/forum/' + courseSettings: courseSettings, + newPostView: newPostView }); + router.start(); }; }); }).call(this, define || RequireJS.define); diff --git a/lms/djangoapps/discussion/static/discussion/js/discussion_profile_page_factory.js b/lms/djangoapps/discussion/static/discussion/js/discussion_profile_page_factory.js index 79e3ad4b85..8af348f2b2 100644 --- a/lms/djangoapps/discussion/static/discussion/js/discussion_profile_page_factory.js +++ b/lms/djangoapps/discussion/static/discussion/js/discussion_profile_page_factory.js @@ -1,25 +1,25 @@ -;(function(define) { +(function(define) { 'use strict'; - define(['jquery', 'DiscussionUserProfileView'], + define(['jquery', 'discussion/js/views/discussion_user_profile_view'], function($, DiscussionUserProfileView) { return function(options) { - var element = options.el, - threads = element.data('threads'), - userInfo = element.data('user-info'), - page = element.data('page'), - numPages = element.data('num-pages'); + var $element = options.$el, + threads = options.threads, + userInfo = options.userInfo, + page = options.page, + numPages = options.numPages; // Roles are not included in user profile page, but they are not used for anything window.DiscussionUtil.loadRoles({ 'Moderator': [], 'Administrator': [], 'Community TA': [] }); - window.$$course_id = element.data('course-id'); + window.$$course_id = options.courseId; window.user = new window.DiscussionUser(userInfo); // jshint nonew:false new DiscussionUserProfileView({ - el: element, + el: $element, collection: threads, page: page, numPages: numPages diff --git a/lms/djangoapps/discussion/static/discussion/js/discussion_router.js b/lms/djangoapps/discussion/static/discussion/js/discussion_router.js index e5c3127281..1280940c2a 100644 --- a/lms/djangoapps/discussion/static/discussion/js/discussion_router.js +++ b/lms/djangoapps/discussion/static/discussion/js/discussion_router.js @@ -1,199 +1,142 @@ -/* globals DiscussionThreadListView, DiscussionThreadView, DiscussionUtil, NewPostView, Thread */ -(function() { +(function(define) { 'use strict'; - var __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { - for (var key in parent) { - if (__hasProp.call(parent, key)) { - child[key] = parent[key]; - } - } - function ctor() { - this.constructor = child; - } - ctor.prototype = parent.prototype; - child.prototype = new ctor(); - child.__super__ = parent.prototype; - return child; - }; + define( + [ + 'underscore', + 'backbone', + 'common/js/discussion/utils', + 'common/js/discussion/views/discussion_thread_list_view', + 'common/js/discussion/views/discussion_thread_view' + ], + function(_, Backbone, DiscussionUtil, DiscussionThreadListView, DiscussionThreadView) { + var DiscussionRouter = Backbone.Router.extend({ + routes: { + '': 'allThreads', + ':forum_name/threads/:thread_id': 'showThread' + }, - function getSingleThreadRoute(commentable_id, thread_id) { - return commentable_id + '/threads/' + thread_id; - } + initialize: function(options) { + Backbone.Router.prototype.initialize.call(this); + _.bindAll(this, 'allThreads', 'showThread'); + this.courseId = options.courseId; + this.discussion = options.discussion; + this.course_settings = options.courseSettings; + this.newPostView = options.newPostView; + this.nav = new DiscussionThreadListView({ + collection: this.discussion, + el: $('.forum-nav'), + courseSettings: this.course_settings + }); + this.nav.render(); + }, - if (typeof Backbone !== 'undefined' && Backbone !== null) { - this.DiscussionRouter = (function(_super) { - var allThreadsRoute = '', - singleThreadRoute = getSingleThreadRoute(':forum_name', ':thread_id'), // :forum_name/threads/:thread_id - routes = {}; + start: function() { + var self = this, + $newPostButton = $('.new-post-btn'); + this.listenTo(this.newPostView, 'newPost:cancel', this.hideNewPost); + $newPostButton.bind('click', _.bind(this.showNewPost, this)); + $newPostButton.bind('keydown', function(event) { + DiscussionUtil.activateOnSpace(event, self.showNewPost); + }); - routes[allThreadsRoute] = 'allThreads'; - routes[singleThreadRoute] = 'showThread'; + // Automatically navigate when the user selects threads + this.nav.on('thread:selected', _.bind(this.navigateToThread, this)); + this.nav.on('thread:removed', _.bind(this.navigateToAllThreads, this)); + this.nav.on('threads:rendered', _.bind(this.setActiveThread, this)); + this.nav.on('thread:created', _.bind(this.navigateToThread, this)); - __extends(DiscussionRouter, _super); + Backbone.history.start({ + pushState: true, + root: '/courses/' + this.courseId + '/discussion/forum/' + }); + }, - function DiscussionRouter() { - var self = this; - this.hideNewPost = function() { - return DiscussionRouter.prototype.hideNewPost.apply(self, arguments); - }; - this.showNewPost = function() { - return DiscussionRouter.prototype.showNewPost.apply(self, arguments); - }; - this.navigateToAllThreads = function() { - return DiscussionRouter.prototype.navigateToAllThreads.apply(self, arguments); - }; - this.navigateToThread = function() { - return DiscussionRouter.prototype.navigateToThread.apply(self, arguments); - }; - 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); - } + stop: function() { + Backbone.history.stop(); + }, - DiscussionRouter.prototype.routes = routes; + allThreads: function() { + this.nav.updateSidebar(); + return this.nav.goHome(); + }, - DiscussionRouter.prototype.initialize = function(options) { - var self = this; - this.discussion = options.discussion; - this.course_settings = options.course_settings; - this.nav = new DiscussionThreadListView({ - collection: this.discussion, - el: $('.forum-nav'), - courseSettings: this.course_settings - }); - this.nav.on('thread:selected', this.navigateToThread); - this.nav.on('thread:removed', this.navigateToAllThreads); - this.nav.on('threads:rendered', this.setActiveThread); - this.nav.on('thread:created', this.navigateToThread); - this.nav.render(); - this.newPost = $('.new-post-article'); - this.newPostView = new NewPostView({ - el: this.newPost, - collection: this.discussion, - course_settings: this.course_settings, - mode: 'tab' - }); - this.newPostView.render(); - this.listenTo(this.newPostView, 'newPost:cancel', this.hideNewPost); - $('.new-post-btn').bind('click', this.showNewPost); - return $('.new-post-btn').bind('keydown', function(event) { - return DiscussionUtil.activateOnSpace(event, self.showNewPost); - }); - }; - - DiscussionRouter.prototype.allThreads = function() { - this.nav.updateSidebar(); - this.nav.goHome(); - }; - - DiscussionRouter.prototype.setActiveThread = function() { - if (this.thread) { - 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.'); + setActiveThread: function() { + if (this.thread) { + return this.nav.setActiveThread(this.thread.get('id')); } else { - errorMsg = gettext('We had some trouble loading more responses. Please try again.'); + return this.nav.goHome; } - 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(); - this.showMain(); - }; + showThread: function(forumName, threadId) { + this.thread = this.discussion.get(threadId); + this.thread.set('unread_comments_count', 0); + this.thread.set('read', true); + this.setActiveThread(); + return this.showMain(); + }, - DiscussionRouter.prototype.showMain = function() { - var self = this; - if (this.main) { - this.main.cleanup(); - this.main.undelegateEvents(); - } - if (!($('.forum-content').is(':visible'))) { - $('.forum-content').fadeIn(); - } - if (this.newPost.is(':visible')) { - this.newPost.fadeOut(); - } - this.main = new DiscussionThreadView({ - el: $('.forum-content'), - model: this.thread, - mode: 'tab', - course_settings: this.course_settings - }); - this.main.render(); - this.main.on('thread:responses:rendered', function() { - return self.nav.updateSidebar(); - }); - this.thread.on('thread:thread_type_updated', this.showMain); - }; - - DiscussionRouter.prototype.navigateToThread = function(thread_id) { - var thread, targetThreadRoute; - thread = this.discussion.get(thread_id); - targetThreadRoute = getSingleThreadRoute(thread.get('commentable_id'), thread_id); - this.navigate(targetThreadRoute, {trigger: true}); - }; - - DiscussionRouter.prototype.navigateToAllThreads = function() { - this.navigate(allThreadsRoute, {trigger: true}); - }; - - DiscussionRouter.prototype.showNewPost = function() { - var self = this; - $('.forum-content').fadeOut({ - duration: 200, - complete: function() { - return self.newPost.fadeIn(200).focus(); + showMain: function() { + var self = this; + if (this.main) { + this.main.cleanup(); + this.main.undelegateEvents(); } - }); - }; - - DiscussionRouter.prototype.hideNewPost = function() { - this.newPost.fadeOut({ - duration: 200, - complete: function() { - return $('.forum-content').fadeIn(200).find('.thread-wrapper').focus(); + if (!($('.forum-content').is(':visible'))) { + $('.forum-content').fadeIn(); } - }); - }; + if (this.newPostView.$el.is(':visible')) { + this.newPostView.$el.fadeOut(); + } + this.main = new DiscussionThreadView({ + el: $('.forum-content'), + model: this.thread, + mode: 'tab', + course_settings: this.course_settings + }); + this.main.render(); + this.main.on('thread:responses:rendered', function() { + return self.nav.updateSidebar(); + }); + return this.thread.on('thread:thread_type_updated', this.showMain); + }, + + navigateToThread: function(threadId) { + var thread; + thread = this.discussion.get(threadId); + return this.navigate('' + (thread.get('commentable_id')) + '/threads/' + threadId, { + trigger: true + }); + }, + + navigateToAllThreads: function() { + return this.navigate('', { + trigger: true + }); + }, + + showNewPost: function() { + var self = this; + return $('.forum-content').fadeOut({ + duration: 200, + complete: function() { + return self.newPostView.$el.fadeIn(200).focus(); + } + }); + }, + + hideNewPost: function() { + return this.newPostView.$el.fadeOut({ + duration: 200, + complete: function() { + return $('.forum-content').fadeIn(200).find('.thread-wrapper') + .focus(); + } + }); + } + }); return DiscussionRouter; - })(Backbone.Router); - } -}).call(window); + }); +}).call(this, define || RequireJS.define); diff --git a/lms/djangoapps/discussion/static/discussion/js/spec/discussion_board_factory_spec.js b/lms/djangoapps/discussion/static/discussion/js/spec/discussion_board_factory_spec.js new file mode 100644 index 0000000000..53e49dbd70 --- /dev/null +++ b/lms/djangoapps/discussion/static/discussion/js/spec/discussion_board_factory_spec.js @@ -0,0 +1,57 @@ +define( + [ + 'jquery', + 'backbone', + 'common/js/spec_helpers/page_helpers', + 'common/js/spec_helpers/discussion_spec_helper', + 'discussion/js/discussion_board_factory' + ], + function($, Backbone, PageHelpers, DiscussionSpecHelper, DiscussionBoardFactory) { + 'use strict'; + + // TODO: re-enable when this doesn't interact badly with other history tests + xdescribe('Discussion Board Factory', function() { + var initializeDiscussionBoardFactory = function() { + DiscussionBoardFactory({ + el: $('.discussion-board'), + courseId: 'test_course_id', + course_name: 'Test Course', + user_info: DiscussionSpecHelper.getTestUserInfo(), + roles: DiscussionSpecHelper.getTestRoleInfo(), + sort_preference: null, + threads: [], + thread_pages: [], + content_info: null, + course_settings: { + is_cohorted: false, + allow_anonymous: false, + allow_anonymous_to_peers: false, + cohorts: [], + category_map: {} + } + }); + }; + + beforeEach(function() { + PageHelpers.preventBackboneChangingUrl(); + + // Install the fixtures + setFixtures( + '
' + + '
' + + '
' + ); + DiscussionSpecHelper.setUnderscoreFixtures(); + }); + + afterEach(function() { + Backbone.history.stop(); + }); + + it('can render itself', function() { + initializeDiscussionBoardFactory(); + expect($('.discussion-board').text()).toContain('All Discussions'); + }); + }); + } +); diff --git a/lms/djangoapps/discussion/static/discussion/js/spec/discussion_profile_page_factory_spec.js b/lms/djangoapps/discussion/static/discussion/js/spec/discussion_profile_page_factory_spec.js new file mode 100644 index 0000000000..1a1c3d4770 --- /dev/null +++ b/lms/djangoapps/discussion/static/discussion/js/spec/discussion_profile_page_factory_spec.js @@ -0,0 +1,41 @@ +define( + [ + 'underscore', + 'jquery', + 'backbone', + 'common/js/spec_helpers/discussion_spec_helper', + 'discussion/js/discussion_profile_page_factory' + ], + function(_, $, Backbone, DiscussionSpecHelper, DiscussionProfilePageFactory) { + 'use strict'; + + describe('Discussion Profile Page Factory', function() { + var testCourseId = 'test_course', + initializeDiscussionProfilePageFactory = function(options) { + DiscussionProfilePageFactory(_.extend( + { + courseId: testCourseId, + $el: $('.discussion-user-threads'), + user_info: DiscussionSpecHelper.getTestUserInfo(), + roles: DiscussionSpecHelper.getTestRoleInfo(), + sort_preference: null, + threads: [], + page: 1, + numPages: 5 + }, + options + )); + }; + + beforeEach(function() { + setFixtures('
'); + DiscussionSpecHelper.setUnderscoreFixtures(); + }); + + it('can render itself', function() { + initializeDiscussionProfilePageFactory(); + expect($('.discussion-user-threads').text()).toContain('Active Threads'); + }); + }); + } +); diff --git a/lms/djangoapps/discussion/static/discussion/js/spec/views/discussion_user_profile_view_spec.js b/lms/djangoapps/discussion/static/discussion/js/spec/views/discussion_user_profile_view_spec.js index 85ecf34b9e..6e231bfc0a 100644 --- a/lms/djangoapps/discussion/static/discussion/js/spec/views/discussion_user_profile_view_spec.js +++ b/lms/djangoapps/discussion/static/discussion/js/spec/views/discussion_user_profile_view_spec.js @@ -1,256 +1,286 @@ -/* globals DiscussionSpecHelper, DiscussionThreadProfileView, DiscussionUserProfileView, URI, DiscussionUtil */ -(function() { - 'use strict'; - describe('DiscussionUserProfileView', function() { - var makeThreads, makeView; - beforeEach(function() { - DiscussionSpecHelper.setUpGlobals(); - DiscussionSpecHelper.setUnderscoreFixtures(); - return spyOn(DiscussionThreadProfileView.prototype, 'render'); - }); - makeThreads = function(numThreads) { - return _.map(_.range(numThreads), function(i) { - return { - id: i.toString(), - body: 'dummy body' - }; - }); - }; - makeView = function(threads, page, numPages) { - return new DiscussionUserProfileView({ - collection: threads, - page: page, - numPages: numPages - }); - }; - describe('thread rendering should be correct', function() { - var checkRender; - checkRender = function(numThreads) { - var threads, view; - threads = makeThreads(numThreads); - view = makeView(threads, 1, 1); - expect(view.$('.discussion').children().length).toEqual(numThreads); - return _.each(threads, function(thread) { - return expect(view.$('#thread_' + thread.id).length).toEqual(1); - }); - }; - it('with no threads', function() { - return checkRender(0); - }); - it('with one thread', function() { - return checkRender(1); - }); - it('with several threads', function() { - return checkRender(5); - }); - }); - describe('pagination rendering should be correct', function() { - var baseUri, checkRender, pageInfo; - baseUri = URI(window.location); - pageInfo = function(page) { - return { - url: baseUri.clone().addSearch('page', page).toString(), - number: page - }; - }; - checkRender = function(params) { - var get_page_number, paginator, view; - view = makeView([], params.page, params.numPages); - paginator = view.$('.discussion-paginator'); - expect(paginator.find('.current-page').text()).toEqual(params.page.toString()); - expect(paginator.find('.first-page').length).toBe(params.first ? 1 : 0); - expect(paginator.find('.previous-page').length).toBe(params.previous ? 1 : 0); - expect(paginator.find('.previous-ellipses').length).toBe(params.leftdots ? 1 : 0); - expect(paginator.find('.next-page').length).toBe(params.next ? 1 : 0); - expect(paginator.find('.next-ellipses').length).toBe(params.rightdots ? 1 : 0); - expect(paginator.find('.last-page').length).toBe(params.last ? 1 : 0); - get_page_number = function(element) { - return parseInt($(element).text()); - }; - expect(_.map(paginator.find('.lower-page a'), get_page_number)).toEqual(params.lowPages); - return expect(_.map(paginator.find('.higher-page a'), get_page_number)).toEqual(params.highPages); - }; - it('for one page', function() { - return checkRender({ - page: 1, - numPages: 1, - previous: null, - first: null, - leftdots: false, - lowPages: [], - highPages: [], - rightdots: false, - last: null, - next: null - }); - }); - it('for first page of three (max with no last)', function() { - return checkRender({ - page: 1, - numPages: 3, - previous: null, - first: null, - leftdots: false, - lowPages: [], - highPages: [2, 3], - rightdots: false, - last: null, - next: 2 - }); - }); - it('for first page of four (has last but no dots)', function() { - return checkRender({ - page: 1, - numPages: 4, - previous: null, - first: null, - leftdots: false, - lowPages: [], - highPages: [2, 3], - rightdots: false, - last: 4, - next: 2 - }); - }); - it('for first page of five (has dots)', function() { - return checkRender({ - page: 1, - numPages: 5, - previous: null, - first: null, - leftdots: false, - lowPages: [], - highPages: [2, 3], - rightdots: true, - last: 5, - next: 2 - }); - }); - it('for last page of three (max with no first)', function() { - return checkRender({ - page: 3, - numPages: 3, - previous: 2, - first: null, - leftdots: false, - lowPages: [1, 2], - highPages: [], - rightdots: false, - last: null, - next: null - }); - }); - it('for last page of four (has first but no dots)', function() { - return checkRender({ - page: 4, - numPages: 4, - previous: 3, - first: 1, - leftdots: false, - lowPages: [2, 3], - highPages: [], - rightdots: false, - last: null, - next: null - }); - }); - it('for last page of five (has dots)', function() { - return checkRender({ - page: 5, - numPages: 5, - previous: 4, - first: 1, - leftdots: true, - lowPages: [3, 4], - highPages: [], - rightdots: false, - last: null, - next: null - }); - }); - it('for middle page of five (max with no first/last)', function() { - return checkRender({ - page: 3, - numPages: 5, - previous: 2, - first: null, - leftdots: false, - lowPages: [1, 2], - highPages: [4, 5], - rightdots: false, - last: null, - next: 4 - }); - }); - it('for middle page of seven (has first/last but no dots)', function() { - return checkRender({ - page: 4, - numPages: 7, - previous: 3, - first: 1, - leftdots: false, - lowPages: [2, 3], - highPages: [5, 6], - rightdots: false, - last: 7, - next: 5 - }); - }); - it('for middle page of nine (has dots)', function() { - return checkRender({ - page: 5, - numPages: 9, - previous: 4, - first: 1, - leftdots: true, - lowPages: [3, 4], - highPages: [6, 7], - rightdots: true, - last: 9, - next: 6 - }); - }); - }); - describe('pagination interaction', function() { +define( + [ + 'underscore', + 'jquery', + 'URI', + 'common/js/discussion/utils', + 'common/js/discussion/views/discussion_thread_profile_view', + 'common/js/spec_helpers/discussion_spec_helper', + 'discussion/js/views/discussion_user_profile_view' + ], + function(_, $, URI, DiscussionUtil, DiscussionThreadProfileView, DiscussionSpecHelper, DiscussionUserProfileView) { + 'use strict'; + + describe('DiscussionUserProfileView', function() { + var makeThreads, makeView; beforeEach(function() { - var deferred; - this.view = makeView(makeThreads(3), 1, 2); - deferred = $.Deferred(); - return spyOn($, 'ajax').and.returnValue(deferred); + DiscussionSpecHelper.setUpGlobals(); + DiscussionSpecHelper.setUnderscoreFixtures(); + return spyOn(DiscussionThreadProfileView.prototype, 'render'); }); - it('causes updated rendering', function() { - $.ajax.and.callFake(function(params) { - params.success({ - discussion_data: [ - { - id: 'on_page_42', - body: 'dummy body' - } - ], - page: 42, - num_pages: 99 + + makeThreads = function(numThreads) { + return _.map(_.range(numThreads), function(i) { + return { + id: i.toString(), + body: 'dummy body' + }; + }); + }; + + makeView = function(threads, page, numPages) { + return new DiscussionUserProfileView({ + collection: threads, + page: page, + numPages: numPages + }); + }; + + describe('thread rendering should be correct', function() { + var checkRender; + checkRender = function(numThreads) { + var threads, view; + threads = makeThreads(numThreads); + view = makeView(threads, 1, 1); + expect(view.$('.discussion').children().length).toEqual(numThreads); + return _.each(threads, function(thread) { + return expect(view.$('#thread_' + thread.id).length).toEqual(1); }); - return { - always: function() { - } - }; + }; + + it('with no threads', function() { + return checkRender(0); + }); + + it('with one thread', function() { + return checkRender(1); + }); + + it('with several threads', function() { + return checkRender(5); }); - this.view.$('.discussion-pagination a').first().click(); - expect(this.view.$('.current-page').text()).toEqual('42'); - return expect(this.view.$('.last-page').text()).toEqual('99'); }); - it('handles AJAX errors', function() { - spyOn(DiscussionUtil, 'discussionAlert'); - $.ajax.and.callFake(function(params) { - params.error(); + + describe('pagination rendering should be correct', function() { + var baseUri, checkRender, pageInfo; + baseUri = URI(window.location); + pageInfo = function(page) { return { - always: function() { - } + url: baseUri.clone().addSearch('page', page).toString(), + number: page }; + }; + checkRender = function(params) { + var getPageNumber, paginator, view; + view = makeView([], params.page, params.numPages); + paginator = view.$('.discussion-paginator'); + expect(paginator.find('.current-page').text()).toEqual(params.page.toString()); + expect(paginator.find('.first-page').length).toBe(params.first ? 1 : 0); + expect(paginator.find('.previous-page').length).toBe(params.previous ? 1 : 0); + expect(paginator.find('.previous-ellipses').length).toBe(params.leftdots ? 1 : 0); + expect(paginator.find('.next-page').length).toBe(params.next ? 1 : 0); + expect(paginator.find('.next-ellipses').length).toBe(params.rightdots ? 1 : 0); + expect(paginator.find('.last-page').length).toBe(params.last ? 1 : 0); + getPageNumber = function(element) { + return parseInt($(element).text(), 10); + }; + expect(_.map(paginator.find('.lower-page a'), getPageNumber)).toEqual(params.lowPages); + return expect(_.map(paginator.find('.higher-page a'), getPageNumber)).toEqual(params.highPages); + }; + + it('for one page', function() { + return checkRender({ + page: 1, + numPages: 1, + previous: null, + first: null, + leftdots: false, + lowPages: [], + highPages: [], + rightdots: false, + last: null, + next: null + }); + }); + + it('for first page of three (max with no last)', function() { + return checkRender({ + page: 1, + numPages: 3, + previous: null, + first: null, + leftdots: false, + lowPages: [], + highPages: [2, 3], + rightdots: false, + last: null, + next: 2 + }); + }); + + it('for first page of four (has last but no dots)', function() { + return checkRender({ + page: 1, + numPages: 4, + previous: null, + first: null, + leftdots: false, + lowPages: [], + highPages: [2, 3], + rightdots: false, + last: 4, + next: 2 + }); + }); + + it('for first page of five (has dots)', function() { + return checkRender({ + page: 1, + numPages: 5, + previous: null, + first: null, + leftdots: false, + lowPages: [], + highPages: [2, 3], + rightdots: true, + last: 5, + next: 2 + }); + }); + + it('for last page of three (max with no first)', function() { + return checkRender({ + page: 3, + numPages: 3, + previous: 2, + first: null, + leftdots: false, + lowPages: [1, 2], + highPages: [], + rightdots: false, + last: null, + next: null + }); + }); + + it('for last page of four (has first but no dots)', function() { + return checkRender({ + page: 4, + numPages: 4, + previous: 3, + first: 1, + leftdots: false, + lowPages: [2, 3], + highPages: [], + rightdots: false, + last: null, + next: null + }); + }); + + it('for last page of five (has dots)', function() { + return checkRender({ + page: 5, + numPages: 5, + previous: 4, + first: 1, + leftdots: true, + lowPages: [3, 4], + highPages: [], + rightdots: false, + last: null, + next: null + }); + }); + + it('for middle page of five (max with no first/last)', function() { + return checkRender({ + page: 3, + numPages: 5, + previous: 2, + first: null, + leftdots: false, + lowPages: [1, 2], + highPages: [4, 5], + rightdots: false, + last: null, + next: 4 + }); + }); + + it('for middle page of seven (has first/last but no dots)', function() { + return checkRender({ + page: 4, + numPages: 7, + previous: 3, + first: 1, + leftdots: false, + lowPages: [2, 3], + highPages: [5, 6], + rightdots: false, + last: 7, + next: 5 + }); + }); + + it('for middle page of nine (has dots)', function() { + return checkRender({ + page: 5, + numPages: 9, + previous: 4, + first: 1, + leftdots: true, + lowPages: [3, 4], + highPages: [6, 7], + rightdots: true, + last: 9, + next: 6 + }); + }); + }); + + describe('pagination interaction', function() { + beforeEach(function() { + var deferred; + this.view = makeView(makeThreads(3), 1, 2); + deferred = $.Deferred(); + return spyOn($, 'ajax').and.returnValue(deferred); + }); + + it('causes updated rendering', function() { + $.ajax.and.callFake(function(params) { + params.success({ + discussion_data: [ + { + id: 'on_page_42', + body: 'dummy body' + } + ], + page: 42, + num_pages: 99 + }); + return { + always: function() { + } + }; + }); + this.view.$('.discussion-pagination a').first().click(); + expect(this.view.$('.current-page').text()).toEqual('42'); + return expect(this.view.$('.last-page').text()).toEqual('99'); + }); + + it('handles AJAX errors', function() { + spyOn(DiscussionUtil, 'discussionAlert'); + $.ajax.and.callFake(function(params) { + params.error(); + return { + always: function() { + } + }; + }); + this.view.$('.discussion-pagination a').first().click(); + return expect(DiscussionUtil.discussionAlert).toHaveBeenCalled(); }); - this.view.$('.discussion-pagination a').first().click(); - return expect(DiscussionUtil.discussionAlert).toHaveBeenCalled(); }); }); }); -}).call(this); diff --git a/lms/djangoapps/discussion/static/discussion/js/views/discussion_user_profile_view.js b/lms/djangoapps/discussion/static/discussion/js/views/discussion_user_profile_view.js index 69c773199f..12d062e7ac 100644 --- a/lms/djangoapps/discussion/static/discussion/js/views/discussion_user_profile_view.js +++ b/lms/djangoapps/discussion/static/discussion/js/views/discussion_user_profile_view.js @@ -1,104 +1,92 @@ -/* globals Discussion, DiscussionThreadProfileView, DiscussionUtil, URI */ -(function() { +(function(define) { 'use strict'; - var __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { - for (var key in parent) { - if (__hasProp.call(parent, key)) { - child[key] = parent[key]; + + define([ + 'underscore', + 'jquery', + 'backbone', + 'gettext', + 'URI', + 'edx-ui-toolkit/js/utils/html-utils', + 'common/js/components/utils/view_utils', + 'common/js/discussion/discussion', + 'common/js/discussion/utils', + 'common/js/discussion/views/discussion_thread_profile_view', + 'text!discussion/templates/user-profile.underscore', + 'text!common/templates/discussion/pagination.underscore' + ], + function(_, $, Backbone, gettext, URI, HtmlUtils, ViewUtils, Discussion, DiscussionUtil, + DiscussionThreadProfileView, userProfileTemplate, paginationTemplate) { + var DiscussionUserProfileView = Backbone.View.extend({ + events: { + 'click .discussion-paginator a': 'changePage' + }, + + initialize: function(options) { + Backbone.View.prototype.initialize.call(this); + this.page = options.page; + this.numPages = options.numPages; + this.discussion = new Discussion(); + this.discussion.on('reset', _.bind(this.render, this)); + this.discussion.reset(this.collection, {silent: false}); + }, + + render: function() { + var self = this, + baseUri = URI(window.location).removeSearch('page'), + pageUrlFunc, + paginationParams; + HtmlUtils.setHtml(this.$el, HtmlUtils.template(userProfileTemplate)({ + threads: self.discussion.models + })); + this.discussion.map(function(thread) { + var view = new DiscussionThreadProfileView({ + el: self.$('article#thread_' + thread.id), + model: thread + }); + view.render(); + return view; + }); + pageUrlFunc = function(page) { + return baseUri.clone().addSearch('page', page).toString(); + }; + paginationParams = DiscussionUtil.getPaginationParams(this.page, this.numPages, pageUrlFunc); + HtmlUtils.setHtml( + this.$el.find('.discussion-pagination'), + HtmlUtils.template(paginationTemplate)(paginationParams) + ); + return this; + }, + + changePage: function(event) { + var self = this, + url; + event.preventDefault(); + url = $(event.target).attr('href'); + DiscussionUtil.safeAjax({ + $elem: this.$el, + $loading: $(event.target), + takeFocus: true, + url: url, + type: 'GET', + dataType: 'json', + success: function(response) { + self.page = response.page; + self.numPages = response.num_pages; + self.discussion.reset(response.discussion_data, {silent: false}); + history.pushState({}, '', url); + ViewUtils.setScrollTop(0); + }, + error: function() { + DiscussionUtil.discussionAlert( + gettext('Sorry'), + gettext('We had some trouble loading the page you requested. Please try again.') + ); + } + }); } - } - function ctor() { - this.constructor = child; - } - - ctor.prototype = parent.prototype; - child.prototype = new ctor(); - child.__super__ = parent.prototype; - return child; - }; - - if (typeof Backbone !== 'undefined' && Backbone !== null) { - this.DiscussionUserProfileView = (function(_super) { - __extends(DiscussionUserProfileView, _super); - - function DiscussionUserProfileView() { - var self = this; - this.render = function() { - return DiscussionUserProfileView.prototype.render.apply(self, arguments); - }; - return DiscussionUserProfileView.__super__.constructor.apply(this, arguments); - } - - DiscussionUserProfileView.prototype.events = { - 'click .discussion-paginator a': 'changePage' - }; - - DiscussionUserProfileView.prototype.initialize = function(options) { - DiscussionUserProfileView.__super__.initialize.call(this); - this.page = options.page; - this.numPages = options.numPages; - this.discussion = new Discussion(); - this.discussion.on('reset', this.render); - return this.discussion.reset(this.collection, { - silent: false - }); - }; - - DiscussionUserProfileView.prototype.render = function() { - var baseUri, pageUrlFunc, paginationParams, - self = this; - this.$el.html(_.template($('#user-profile-template').html())({ - threads: this.discussion.models - })); - this.discussion.map(function(thread) { - return new DiscussionThreadProfileView({ - el: self.$('article#thread_' + thread.id), - model: thread - }).render(); - }); - baseUri = URI(window.location).removeSearch('page'); - pageUrlFunc = function(page) { - return baseUri.clone().addSearch('page', page); - }; - paginationParams = DiscussionUtil.getPaginationParams(this.page, this.numPages, pageUrlFunc); - this.$el.find('.discussion-pagination') - .html(_.template($('#pagination-template').html())(paginationParams)); - }; - - DiscussionUserProfileView.prototype.changePage = function(event) { - var url, - self = this; - event.preventDefault(); - url = $(event.target).attr('href'); - return DiscussionUtil.safeAjax({ - $elem: this.$el, - $loading: $(event.target), - takeFocus: true, - url: url, - type: 'GET', - dataType: 'json', - success: function(response) { - self.page = response.page; - self.numPages = response.num_pages; - self.discussion.reset(response.discussion_data, { - silent: false - }); - history.pushState({}, '', url); - return $('html, body').animate({ - scrollTop: 0 - }); - }, - error: function() { - return DiscussionUtil.discussionAlert( - gettext('Sorry'), - gettext('We had some trouble loading the page you requested. Please try again.') - ); - } - }); - }; + }); return DiscussionUserProfileView; - })(Backbone.View); - } -}).call(window); + }); +}).call(this, define || RequireJS.define); diff --git a/common/static/common/templates/discussion/user-profile.underscore b/lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore similarity index 75% rename from common/static/common/templates/discussion/user-profile.underscore rename to lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore index b4e683ae72..71d726711f 100644 --- a/common/static/common/templates/discussion/user-profile.underscore +++ b/lms/djangoapps/discussion/static/discussion/templates/user-profile.underscore @@ -1,7 +1,7 @@

<%- gettext("Active Threads") %>

<% _.each(threads, function(thread) { %> -
+
<% }); %>
diff --git a/lms/djangoapps/discussion/templates/discussion/discussion_board.html b/lms/djangoapps/discussion/templates/discussion/discussion_board.html index 9d44984873..c67802da57 100644 --- a/lms/djangoapps/discussion/templates/discussion/discussion_board.html +++ b/lms/djangoapps/discussion/templates/discussion/discussion_board.html @@ -9,9 +9,9 @@ from django.utils.translation import ugettext as _ from django.template.defaultfilters import escapejs from django.core.urlresolvers import reverse -from openedx.core.djangolib.js_utils import ( - dump_js_escaped_json, js_escaped_string -) + +from django_comment_client.permissions import has_permission +from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_string %> <%block name="bodyclass">discussion @@ -21,44 +21,58 @@ from openedx.core.djangolib.js_utils import ( <%include file="../discussion/_js_head_dependencies.html" /> -<%block name="js_extra"> -## Enable fast preview to fix discussion MathJax rendering bug when page first loads. -<%include file="/discussion/_js_body_dependencies.html" args="disable_fast_preview=False"/> -<%static:js group='discussion'/> - +<%block name="base_js_dependencies"> + ## Enable fast preview to fix discussion MathJax rendering bug when page first loads. + <%include file="/discussion/_js_body_dependencies.html" args="disable_fast_preview=False"/> + +<%block name="js_extra"> <%static:require_module module_name="discussion/js/discussion_board_factory" class_name="DiscussionBoardFactory"> - DiscussionBoardFactory({ - courseId: '${unicode(course.id) | n, js_escaped_string}', - el: $(".discussion-board") - }); +DiscussionBoardFactory({ + courseId: '${unicode(course.id) | n, js_escaped_string}', + $el: $(".discussion-board"), + user_info: ${user_info | n, dump_js_escaped_json}, + roles: ${roles | n, dump_js_escaped_json}, + sort_preference: '${sort_preference | n, js_escaped_string}', + threads: ${threads | n, dump_js_escaped_json}, + thread_pages: '${thread_pages | n, js_escaped_string}', + content_info: ${annotated_content_info | n, dump_js_escaped_json}, + course_name: '${course.display_name_with_default | n, js_escaped_string}', + course_settings: ${course_settings | n, dump_js_escaped_json} +}); -<%include file="/discussion/_discussion_course_navigation.html" args="active_page='discussion'" /> +<%include file="../courseware/course_navigation.html" args="active_page='discussion'" /> <%block name="content">
-
- -
-
+ data-user-cohort-id="${user_cohort}"> + +
+
+ + +
diff --git a/lms/djangoapps/discussion/templates/discussion/discussion_profile_page.html b/lms/djangoapps/discussion/templates/discussion/discussion_profile_page.html index 5fc18182a1..1d2f4025f2 100644 --- a/lms/djangoapps/discussion/templates/discussion/discussion_profile_page.html +++ b/lms/djangoapps/discussion/templates/discussion/discussion_profile_page.html @@ -1,41 +1,78 @@ -<%inherit file="../main.html" /> +## mako + +<%! main_css = "style-discussion-main" %> + <%page expression_filter="h"/> +<%inherit file="../main.html" /> <%namespace name='static' file='../static_content.html'/> <%! from django.utils.translation import ugettext as _ from django.template.defaultfilters import escapejs +from openedx.core.djangolib.js_utils import ( + dump_js_escaped_json, js_escaped_string +) %> -<%block name="bodyclass">discussion +<%block name="bodyclass">discussion-user-profile <%block name="pagetitle">${_("Discussion - {course_number}").format(course_number=course.display_number_with_default)} <%block name="headextra"> -<%static:css group='style-course-vendor'/> -<%static:css group='style-course'/> - <%include file="_js_head_dependencies.html" /> <%block name="js_extra"> <%include file="_js_body_dependencies.html" /> -<%static:js group='discussion'/> + +<%static:require_module module_name="discussion/js/discussion_profile_page_factory" class_name="DiscussionProfilePageFactory"> + <% + profile_page_context = { + 'courseId': unicode(course.id), + 'courseName': course.display_name_with_default, + 'userInfo': user_info, + 'threads': threads, + 'page': page, + 'numPages': num_pages, + } + %> + DiscussionProfilePageFactory(_.extend( + { + $el: $('.discussion-user-threads') + }, + ${profile_page_context | n, dump_js_escaped_json} + )); + <%include file="../courseware/course_navigation.html" args="active_page='discussion'" />
-
- -
-
+ + + +
+
+
+
+
+
<%include file="_underscore_templates.html" /> diff --git a/lms/djangoapps/discussion/templates/discussion/maintenance.html b/lms/djangoapps/discussion/templates/discussion/maintenance.html index c5f73c02ba..63c55c6dbf 100644 --- a/lms/djangoapps/discussion/templates/discussion/maintenance.html +++ b/lms/djangoapps/discussion/templates/discussion/maintenance.html @@ -1,4 +1,26 @@ +## mako + +<%! main_css = "style-discussion-main" %> + <%! from django.utils.translation import ugettext as _ %> +<%page expression_filter="h"/> <%inherit file="../main.html" /> -

${_("We're sorry")}

-

${_("The forums are currently undergoing maintenance. We'll have them back up shortly!")}

+ +<%block name="bodyclass">discussion + +<%block name="headextra"> +<%include file="../discussion/_js_head_dependencies.html" /> + + +<%block name="content"> +

${_("Discussion unavailable")}

+ + diff --git a/lms/djangoapps/discussion/templates/discussion/user_profile.html b/lms/djangoapps/discussion/templates/discussion/user_profile.html deleted file mode 100644 index 0807cddbd7..0000000000 --- a/lms/djangoapps/discussion/templates/discussion/user_profile.html +++ /dev/null @@ -1,62 +0,0 @@ -## mako - -<%! main_css = "style-discussion-main" %> - -<%page expression_filter="h"/> -<%inherit file="../main.html" /> -<%namespace name='static' file='../static_content.html'/> -<%! -from django.utils.translation import ugettext as _ -from django.template.defaultfilters import escapejs -from openedx.core.djangolib.js_utils import ( - dump_js_escaped_json, js_escaped_string -) -%> - -<%block name="bodyclass">discussion-user-profile -<%block name="pagetitle">${_("Discussion - {course_number}").format(course_number=course.display_number_with_default)} - -<%block name="headextra"> -<%include file="_js_head_dependencies.html" /> - - -<%block name="js_extra"> -<%include file="_js_body_dependencies.html" /> -<%static:js group='discussion'/> - - -<%static:require_module module_name="discussion/js/discussion_profile_page_factory" class_name="DiscussionProfilePageFactory"> - DiscussionProfilePageFactory({ - courseId: '${unicode(course.id) | n, js_escaped_string}', - el: $(".discussion-user-threads") - }); - - - -<%include file="../courseware/course_navigation.html" args="active_page='discussion'" /> - -
-
- -
-
-
-
-
-
-
- -<%include file="_underscore_templates.html" /> diff --git a/lms/djangoapps/discussion/tests/test_views.py b/lms/djangoapps/discussion/tests/test_views.py index 69a76bdc90..01dde903e3 100644 --- a/lms/djangoapps/discussion/tests/test_views.py +++ b/lms/djangoapps/discussion/tests/test_views.py @@ -459,7 +459,7 @@ class SingleCohortedThreadTestCase(CohortedTestCase): html = response.content # Verify that the group name is correctly included in the HTML - self.assertRegexpMatches(html, r'"group_name": "student_cohort"') + self.assertRegexpMatches(html, r'"group_name": "student_cohort"') @patch('lms.lib.comment_client.utils.requests.request', autospec=True) @@ -812,7 +812,7 @@ class ForumFormDiscussionGroupIdTestCase(CohortedTestCase, CohortedTopicGroupIdT self.client.login(username=user.username, password='test') return self.client.get( - reverse(views.forum_form_discussion, args=[unicode(self.course.id)]), + reverse("discussion.views.forum_form_discussion", args=[unicode(self.course.id)]), data=request_data, **headers ) @@ -1147,10 +1147,10 @@ class UserProfileTestCase(UrlResetMixin, ModuleStoreTestCase): self.assertRegexpMatches(html, r'data-num-pages="1"') self.assertRegexpMatches(html, r'1 discussion started') self.assertRegexpMatches(html, r'2 comments') - self.assertRegexpMatches(html, r'"id": "{}"'.format(self.TEST_THREAD_ID)) - self.assertRegexpMatches(html, r'"title": "{}"'.format(self.TEST_THREAD_TEXT)) - self.assertRegexpMatches(html, r'"body": "{}"'.format(self.TEST_THREAD_TEXT)) - self.assertRegexpMatches(html, r'"username": "{}"'.format(self.student.username)) + self.assertRegexpMatches(html, r''id': '{}''.format(self.TEST_THREAD_ID)) + self.assertRegexpMatches(html, r''title': '{}''.format(self.TEST_THREAD_TEXT)) + self.assertRegexpMatches(html, r''body': '{}''.format(self.TEST_THREAD_TEXT)) + self.assertRegexpMatches(html, r''username': u'{}''.format(self.student.username)) def check_ajax(self, mock_request, **params): response = self.get_response(mock_request, params, HTTP_X_REQUESTED_WITH="XMLHttpRequest") @@ -1360,6 +1360,7 @@ class ForumDiscussionXSSTestCase(UrlResetMixin, ModuleStoreTestCase): """ Test that XSS attack is prevented """ + mock_user.return_value.to_dict.return_value = {} reverse_url = "%s%s" % (reverse( "discussion.views.forum_form_discussion", kwargs={"course_id": unicode(self.course.id)}), '/forum_form_discussion') @@ -1377,7 +1378,7 @@ class ForumDiscussionXSSTestCase(UrlResetMixin, ModuleStoreTestCase): Test that XSS attack is prevented """ mock_threads.return_value = [], 1, 1 - mock_from_django_user.return_value = Mock() + mock_from_django_user.return_value.to_dict.return_value = {} mock_request.side_effect = make_mock_request_impl(course=self.course, text='dummy') url = reverse('discussion.views.user_profile', diff --git a/lms/djangoapps/discussion/views.py b/lms/djangoapps/discussion/views.py index 2de4d10541..0abab446f3 100644 --- a/lms/djangoapps/discussion/views.py +++ b/lms/djangoapps/discussion/views.py @@ -3,7 +3,6 @@ Views handling read (GET) requests for the Discussion tab and inline discussions """ from functools import wraps -import json import logging from django.contrib.auth.decorators import login_required @@ -248,9 +247,9 @@ def forum_form_discussion(request, course_key): 'course': course, #'recent_active_threads': recent_active_threads, 'staff_access': bool(has_access(request.user, 'staff', course)), - 'threads': json.dumps(threads), + 'threads': threads, 'thread_pages': query_params['num_pages'], - 'user_info': json.dumps(user_info, default=lambda x: None), + 'user_info': user_info, 'can_create_comment': has_permission(request.user, "create_comment", course.id), 'can_create_subcomment': has_permission(request.user, "create_sub_comment", course.id), 'can_create_thread': has_permission(request.user, "create_thread", course.id), @@ -258,16 +257,16 @@ def forum_form_discussion(request, course_key): has_permission(request.user, 'openclose_thread', course.id) or has_access(request.user, 'staff', course) ), - 'annotated_content_info': json.dumps(annotated_content_info), + 'annotated_content_info': annotated_content_info, 'course_id': course.id.to_deprecated_string(), - 'roles': json.dumps(utils.get_role_ids(course_key)), + 'roles': utils.get_role_ids(course_key), 'is_moderator': has_permission(request.user, "see_all_cohorts", course_key), 'cohorts': course_settings["cohorts"], # still needed to render _thread_list_template 'user_cohort': user_cohort_id, # read from container in NewPostView 'is_course_cohorted': is_course_cohorted(course_key), # still needed to render _thread_list_template 'sort_preference': user.default_sort_key, 'category_map': course_settings["category_map"], - 'course_settings': json.dumps(course_settings), + 'course_settings': course_settings, 'disable_courseware_js': True, 'uses_pattern_library': True, } @@ -360,17 +359,17 @@ def single_thread(request, course_key, discussion_id, thread_id): 'discussion_id': discussion_id, 'csrf': csrf(request)['csrf_token'], 'init': '', # TODO: What is this? - 'user_info': json.dumps(user_info), + 'user_info': user_info, 'can_create_comment': has_permission(request.user, "create_comment", course.id), 'can_create_subcomment': has_permission(request.user, "create_sub_comment", course.id), 'can_create_thread': has_permission(request.user, "create_thread", course.id), - 'annotated_content_info': json.dumps(annotated_content_info), + 'annotated_content_info': annotated_content_info, 'course': course, #'recent_active_threads': recent_active_threads, 'course_id': course.id.to_deprecated_string(), # TODO: Why pass both course and course.id to template? 'thread_id': thread_id, - 'threads': json.dumps(threads), - 'roles': json.dumps(utils.get_role_ids(course_key)), + 'threads': threads, + 'roles': utils.get_role_ids(course_key), 'is_moderator': is_moderator, 'thread_pages': query_params['num_pages'], 'is_course_cohorted': is_course_cohorted(course_key), @@ -382,7 +381,7 @@ def single_thread(request, course_key, discussion_id, thread_id): 'user_cohort': user_cohort, 'sort_preference': cc_user.default_sort_key, 'category_map': course_settings["category_map"], - 'course_settings': json.dumps(course_settings), + 'course_settings': course_settings, 'disable_courseware_js': True, 'uses_pattern_library': True, } @@ -433,7 +432,7 @@ def user_profile(request, course_key, user_id): 'discussion_data': threads, 'page': query_params['page'], 'num_pages': query_params['num_pages'], - 'annotated_content_info': json.dumps(annotated_content_info), + 'annotated_content_info': annotated_content_info, }) else: django_user = User.objects.get(id=user_id) @@ -442,9 +441,9 @@ def user_profile(request, course_key, user_id): 'user': request.user, 'django_user': django_user, 'profiled_user': profiled_user.to_dict(), - 'threads': json.dumps(threads), - 'user_info': json.dumps(user_info, default=lambda x: None), - 'annotated_content_info': json.dumps(annotated_content_info), + 'threads': threads, + 'user_info': user_info, + 'annotated_content_info': annotated_content_info, 'page': query_params['page'], 'num_pages': query_params['num_pages'], 'learner_profile_page_url': reverse('learner_profile', kwargs={'username': django_user.username}), @@ -452,7 +451,7 @@ def user_profile(request, course_key, user_id): 'uses_pattern_library': True, } - return render_to_response('discussion/user_profile.html', context) + return render_to_response('discussion/discussion_profile_page.html', context) except User.DoesNotExist: raise Http404 @@ -531,9 +530,9 @@ def followed_threads(request, course_key, user_id): 'user': request.user, 'django_user': User.objects.get(id=user_id), 'profiled_user': profiled_user.to_dict(), - 'threads': json.dumps(paginated_results.collection), - 'user_info': json.dumps(user_info), - 'annotated_content_info': json.dumps(annotated_content_info), + 'threads': paginated_results.collection, + 'user_info': user_info, + 'annotated_content_info': annotated_content_info, # 'content': content, } diff --git a/lms/djangoapps/django_comment_client/tests/group_id.py b/lms/djangoapps/django_comment_client/tests/group_id.py index 1c8eea1c2d..b25e6d091e 100644 --- a/lms/djangoapps/django_comment_client/tests/group_id.py +++ b/lms/djangoapps/django_comment_client/tests/group_id.py @@ -24,10 +24,10 @@ class GroupIdAssertionMixin(object): def _assert_html_response_contains_group_info(self, response): group_info = {"group_id": None, "group_name": None} - match = re.search(r'"group_id": ([\d]*)', response.content) + match = re.search(r'"group_id": (\d*),', response.content) if match and match.group(1) != '': group_info["group_id"] = int(match.group(1)) - match = re.search(r'"group_name": "([^&]*)"', response.content) + match = re.search(r'"group_name": "(\w*)",', response.content) if match: group_info["group_name"] = match.group(1) self._assert_thread_contains_group_info(group_info) diff --git a/lms/djangoapps/teams/static/teams/js/spec/views/team_discussion_spec.js b/lms/djangoapps/teams/static/teams/js/spec/views/team_discussion_spec.js index 4043a8a9a9..9ce818673c 100644 --- a/lms/djangoapps/teams/static/teams/js/spec/views/team_discussion_spec.js +++ b/lms/djangoapps/teams/static/teams/js/spec/views/team_discussion_spec.js @@ -1,8 +1,10 @@ define([ - 'underscore', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'teams/js/views/team_discussion', + 'underscore', + 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', + 'common/js/spec_helpers/discussion_spec_helper', 'teams/js/spec_helpers/team_spec_helpers', - 'xmodule_js/common_static/common/js/spec_helpers/discussion_spec_helper' -], function(_, AjaxHelpers, TeamDiscussionView, TeamSpecHelpers, DiscussionSpecHelper) { + 'teams/js/views/team_discussion' +], function(_, AjaxHelpers, DiscussionSpecHelper, TeamSpecHelpers, TeamDiscussionView) { 'use strict'; xdescribe('TeamDiscussionView', function() { var discussionView, createDiscussionView, createPost, expandReplies, postReply; @@ -115,7 +117,7 @@ define([ body: reply, comments_count: 1 }), - 'annotated_content_info': TeamSpecHelpers.createAnnotatedContentInfo() + annotated_content_info: TeamSpecHelpers.createAnnotatedContentInfo() }); }; @@ -202,8 +204,7 @@ define([ it('cannot move a new thread to a different topic', function() { var requests = AjaxHelpers.requests(this), - view = createDiscussionView(requests), - postTopicButton; + view = createDiscussionView(requests); createPost(requests, view); expandReplies(requests, view); view.$('.action-more .icon').first().click(); diff --git a/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_spec.js b/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_spec.js index 80f8db1dd1..e9362173b5 100644 --- a/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_spec.js +++ b/lms/djangoapps/teams/static/teams/js/spec/views/team_profile_spec.js @@ -1,8 +1,11 @@ define([ - 'underscore', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'teams/js/models/team', - 'teams/js/views/team_profile', 'teams/js/spec_helpers/team_spec_helpers', - 'xmodule_js/common_static/common/js/spec_helpers/discussion_spec_helper' -], function(_, AjaxHelpers, TeamModel, TeamProfileView, TeamSpecHelpers, DiscussionSpecHelper) { + 'underscore', + 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', + 'common/js/spec_helpers/discussion_spec_helper', + 'teams/js/spec_helpers/team_spec_helpers', + 'teams/js/models/team', + 'teams/js/views/team_profile' +], function(_, AjaxHelpers, DiscussionSpecHelper, TeamSpecHelpers, TeamModel, TeamProfileView) { 'use strict'; describe('TeamProfileView', function() { var profileView, createTeamProfileView, createTeamModelData, clickLeaveTeam, @@ -10,11 +13,11 @@ define([ leaveTeamLinkSelector = '.leave-team-link', DEFAULT_MEMBERSHIP = [ { - 'user': { - 'username': TeamSpecHelpers.testUser, - 'profile_image': { - 'has_image': true, - 'image_url_medium': '/image-url' + user: { + username: TeamSpecHelpers.testUser, + profile_image: { + has_image: true, + image_url_medium: '/image-url' } } } @@ -198,7 +201,7 @@ define([ it('shows correct error messages', function() { var requests = AjaxHelpers.requests(this); - var verifyErrorMessage = function(requests, errorMessage, expectedMessage) { + var verifyErrorMessage = function(errorMessage, expectedMessage) { var view = createTeamProfileView( requests, {country: 'US', language: 'en', membership: DEFAULT_MEMBERSHIP} ); @@ -212,22 +215,19 @@ define([ // verify user_message verifyErrorMessage( - requests, - JSON.stringify({'user_message': "can't remove user from team"}), + JSON.stringify({user_message: "can't remove user from team"}), "can't remove user from team" ); // verify generic error message verifyErrorMessage( - requests, '', 'An error occurred. Try again.' ); // verify error message when json parsing succeeded but error message format is incorrect verifyErrorMessage( - requests, - JSON.stringify({'blah': "can't remove user from team"}), + JSON.stringify({blah: "can't remove user from team"}), 'An error occurred. Try again.' ); }); diff --git a/lms/djangoapps/teams/static/teams/js/views/team_discussion.js b/lms/djangoapps/teams/static/teams/js/views/team_discussion.js index 81134530d0..49f87a2ace 100644 --- a/lms/djangoapps/teams/static/teams/js/views/team_discussion.js +++ b/lms/djangoapps/teams/static/teams/js/views/team_discussion.js @@ -3,7 +3,7 @@ */ (function(define) { 'use strict'; - define(['backbone', 'underscore', 'gettext', 'DiscussionModuleView'], + define(['backbone', 'underscore', 'gettext', 'common/js/discussion/discussion_module_view'], function(Backbone, _, gettext, DiscussionModuleView) { var TeamDiscussionView = Backbone.View.extend({ initialize: function() { diff --git a/lms/djangoapps/teams/templates/teams/teams.html b/lms/djangoapps/teams/templates/teams/teams.html index aed9a40f4a..58a43a1b0b 100644 --- a/lms/djangoapps/teams/templates/teams/teams.html +++ b/lms/djangoapps/teams/templates/teams/teams.html @@ -32,10 +32,6 @@ from openedx.core.djangolib.js_utils import ( <%block name="js_extra"> <%include file="../discussion/_js_body_dependencies.html" /> -<%static:js group='discussion'/> - <%static:require_module module_name="teams/js/teams_tab_factory" class_name="TeamsTabFactory"> TeamsTabFactory({ diff --git a/lms/static/discussion b/lms/static/discussion new file mode 120000 index 0000000000..0a54d42149 --- /dev/null +++ b/lms/static/discussion @@ -0,0 +1 @@ +../djangoapps/discussion/static/discussion \ No newline at end of file diff --git a/lms/static/js/spec/courseware/link_clicked_events_spec.js b/lms/static/js/spec/courseware/link_clicked_events_spec.js index 7e4ee220fb..9ca1886864 100644 --- a/lms/static/js/spec/courseware/link_clicked_events_spec.js +++ b/lms/static/js/spec/courseware/link_clicked_events_spec.js @@ -20,7 +20,7 @@ define(['jquery', 'logger', 'js/courseware/courseware_factory'], function($, Log $('.internal-link').click(); expect(Logger.log).toHaveBeenCalledWith('edx.ui.lms.link_clicked', { target_url: 'http://' + window.location.host + '/some/internal/link', - current_url: 'http://' + window.location.host + '/context.html' + current_url: window.location.toString() }); }); diff --git a/lms/static/karma_lms.conf.js b/lms/static/karma_lms.conf.js index 0c48fa9784..04deb9c5f0 100644 --- a/lms/static/karma_lms.conf.js +++ b/lms/static/karma_lms.conf.js @@ -12,11 +12,11 @@ var options = { // Avoid adding files to this list. Use RequireJS. libraryFilesToInclude: [ - {pattern: 'common/js/vendor/jquery.js', included: true}, - {pattern: 'common/js/vendor/jquery-migrate.js', included: true}, - {pattern: 'xmodule_js/common_static/js/vendor/jquery.event.drag-2.2.js', included: true}, - {pattern: 'xmodule_js/common_static/js/vendor/slick.core.js', included: true}, - {pattern: 'xmodule_js/common_static/js/vendor/slick.grid.js', included: true} + {pattern: '../../common/static/common/js/vendor/jquery.js', included: true}, + {pattern: '../../common/static/common/js/vendor/jquery-migrate.js', included: true}, + {pattern: '../../common/static/js/vendor/jquery.event.drag-2.2.js', included: true}, + {pattern: '../../common/static/js/vendor/slick.core.js', included: true}, + {pattern: '../../common/static/js/vendor/slick.grid.js', included: true} ], libraryFiles: [ @@ -27,6 +27,7 @@ var options = { // Otherwise Istanbul which is used for coverage tracking will cause tests to not run. sourceFiles: [ {pattern: 'coffee/src/**/!(*spec).js'}, + {pattern: 'discussion/js/**/!(*spec).js'}, {pattern: 'js/**/!(*spec|djangojs).js'}, {pattern: 'lms/js/**/!(*spec).js'}, {pattern: 'support/js/**/!(*spec).js'}, @@ -34,19 +35,13 @@ var options = { ], specFiles: [ - {pattern: 'js/spec/**/*spec.js'}, - {pattern: 'lms/js/spec/**/*spec.js'}, - {pattern: 'support/js/spec/**/*spec.js'}, - {pattern: 'teams/js/spec/**/*spec.js'}, - {pattern: 'xmodule_js/common_static/coffee/spec/**/*.js'} + {pattern: '../**/*spec.js'} ], fixtureFiles: [ - {pattern: 'js/fixtures/**/*.html'}, - {pattern: 'lms/fixtures/**/*.html'}, - {pattern: 'support/templates/**/*.*'}, - {pattern: 'teams/templates/**/*.*'}, - {pattern: 'templates/**/*.*'} + {pattern: '../**/fixtures/**/*.html'}, + {pattern: '../**/templates/**/*.html'}, + {pattern: '../**/*.underscore'} ], runFiles: [ diff --git a/lms/static/lms/js/build.js b/lms/static/lms/js/build.js index 0da320d920..c9a088cce8 100644 --- a/lms/static/lms/js/build.js +++ b/lms/static/lms/js/build.js @@ -19,6 +19,7 @@ */ modules: getModulesList([ 'discussion/js/discussion_board_factory', + 'discussion/js/discussion_profile_page_factory', 'js/api_admin/catalog_preview_factory', 'js/courseware/courseware_factory', 'js/discovery/discovery_factory', @@ -77,7 +78,7 @@ 'logger': 'empty:', 'utility': 'empty:', 'URI': 'empty:', - 'DiscussionModuleView': 'empty:', + 'common/js/discussion/discussion_module_view': 'empty:', 'modernizr': 'empty', // Don't bundle UI Toolkit helpers as they are loaded into the "edx" namespace diff --git a/lms/static/lms/js/spec/main.js b/lms/static/lms/js/spec/main.js index f7a8066c08..fb14af08d3 100644 --- a/lms/static/lms/js/spec/main.js +++ b/lms/static/lms/js/spec/main.js @@ -8,8 +8,8 @@ paths: { 'gettext': 'xmodule_js/common_static/js/test/i18n', 'codemirror': 'xmodule_js/common_static/js/vendor/CodeMirror/codemirror', - 'jquery': 'xmodule_js/common_static/common/js/vendor/jquery', - 'jquery-migrate': 'xmodule_js/common_static/common/js/vendor/jquery-migrate', + 'jquery': 'common/js/vendor/jquery', + 'jquery-migrate': 'common/js/vendor/jquery-migrate', 'jquery.ui': 'xmodule_js/common_static/js/vendor/jquery-ui.min', 'jquery.eventDrag': 'xmodule_js/common_static/js/vendor/jquery.event.drag-2.2', 'jquery.flot': 'xmodule_js/common_static/js/vendor/flot/jquery.flot.min', @@ -87,9 +87,6 @@ 'js/student_profile/views/learner_profile_view': 'js/student_profile/views/learner_profile_view', 'js/ccx/schedule': 'js/ccx/schedule', - // Discussion classes loaded explicitly until they are converted to use RequireJS - 'DiscussionModuleView': 'xmodule_js/common_static/common/js/discussion/discussion_module_view', - 'js/bookmarks/collections/bookmarks': 'js/bookmarks/collections/bookmarks', 'js/bookmarks/models/bookmark': 'js/bookmarks/models/bookmark', 'js/bookmarks/views/bookmarks_list_button': 'js/bookmarks/views/bookmarks_list_button', @@ -517,7 +514,7 @@ exports: 'Slick' }, // Discussions - 'xmodule_js/common_static/common/js/discussion/utils': { + 'common/js/discussion/utils': { deps: [ 'jquery', 'jquery.timeago', @@ -536,135 +533,128 @@ }); } }, - 'xmodule_js/common_static/common/js/discussion/content': { + 'common/js/discussion/content': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' + 'common/js/discussion/utils' ], exports: 'Content' }, - 'xmodule_js/common_static/common/js/discussion/discussion': { + 'common/js/discussion/discussion': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils', + 'common/js/discussion/utils', 'xmodule_js/common_static/common/js/discussion/content' ], exports: 'Discussion' }, - 'xmodule_js/common_static/common/js/discussion/models/discussion_course_settings': { + 'common/js/discussion/discussion_course_settings': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' + 'common/js/discussion/utils' ], exports: 'DiscussionCourseSettings' }, - 'xmodule_js/common_static/common/js/discussion/models/discussion_user': { + 'common/js/discussion/models/discussion_user': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' + 'common/js/discussion/utils' ], exports: 'DiscussionUser' }, - 'xmodule_js/common_static/common/js/discussion/views/discussion_content_view': { + 'common/js/discussion/views/discussion_content_view': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' + 'common/js/discussion/utils' ], exports: 'DiscussionContentView' }, - 'xmodule_js/common_static/common/js/discussion/views/discussion_thread_edit_view': { + 'common/js/discussion/views/discussion_thread_edit_view': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' + 'common/js/discussion/utils' ], exports: 'DiscussionThreadEditView' }, - 'xmodule_js/common_static/common/js/discussion/views/discussion_thread_list_view': { + 'common/js/discussion/views/discussion_thread_list_view': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' + 'common/js/discussion/utils' ], exports: 'DiscussionThreadListView' }, - 'xmodule_js/common_static/common/js/discussion/views/discussion_thread_profile_view': { + 'common/js/discussion/views/discussion_thread_profile_view': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' + 'common/js/discussion/utils' ], exports: 'DiscussionThreadProfileView' }, 'xmodule_js/common_static/common/js/discussion/views/discussion_thread_show_view': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils', - 'xmodule_js/common_static/common/js/discussion/views/discussion_content_view' + 'common/js/discussion/utils', + 'common/js/discussion/views/discussion_content_view' ], exports: 'DiscussionThreadShowView' }, - 'xmodule_js/common_static/common/js/discussion/views/discussion_thread_view': { + 'common/js/discussion/views/discussion_thread_view': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils', - 'xmodule_js/common_static/common/js/discussion/views/discussion_content_view' + 'common/js/discussion/utils', + 'common/js/discussion/views/discussion_content_view' ], exports: 'DiscussionThreadView' }, - 'xmodule_js/common_static/common/js/discussion/views/discussion_topic_menu_view': { + 'common/js/discussion/views/discussion_topic_menu_view': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' + 'common/js/discussion/utils' ], exports: 'DiscussionTopicMenuView' }, - 'xmodule_js/common_static/common/js/discussion/views/discussion_user_profile_view': { + 'common/js/discussion/views/new_post_view': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' - ], - exports: 'DiscussionUserProfileView' - }, - 'xmodule_js/common_static/common/js/discussion/views/new_post_view': { - deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' + 'common/js/discussion/utils' ], exports: 'NewPostView' }, - 'xmodule_js/common_static/common/js/discussion/views/thread_response_edit_view': { + 'common/js/discussion/views/thread_response_edit_view': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' + 'common/js/discussion/utils' ], exports: 'ThreadResponseEditView' }, - 'xmodule_js/common_static/common/js/discussion/views/thread_response_show_view': { + 'common/js/discussion/views/thread_response_show_view': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' + 'common/js/discussion/utils' ], exports: 'ThreadResponseShowView' }, - 'xmodule_js/common_static/common/js/discussion/views/thread_response_view': { + 'common/js/discussion/views/thread_response_view': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' + 'common/js/discussion/utils' ], exports: 'ThreadResponseView' }, - 'DiscussionModuleView': { + 'common/js/discussion/discussion_module_view': { deps: [ 'jquery', 'underscore', 'backbone', 'gettext', 'URI', - 'xmodule_js/common_static/common/js/discussion/content', - 'xmodule_js/common_static/common/js/discussion/discussion', - 'xmodule_js/common_static/common/js/discussion/utils', - 'xmodule_js/common_static/common/js/discussion/models/discussion_course_settings', - 'xmodule_js/common_static/common/js/discussion/models/discussion_user', - 'xmodule_js/common_static/common/js/discussion/views/discussion_content_view', - 'xmodule_js/common_static/common/js/discussion/views/discussion_thread_edit_view', - 'xmodule_js/common_static/common/js/discussion/views/discussion_thread_list_view', - 'xmodule_js/common_static/common/js/discussion/views/discussion_thread_profile_view', - 'xmodule_js/common_static/common/js/discussion/views/discussion_thread_show_view', - 'xmodule_js/common_static/common/js/discussion/views/discussion_thread_view', - 'xmodule_js/common_static/common/js/discussion/views/discussion_topic_menu_view', - 'xmodule_js/common_static/common/js/discussion/views/discussion_user_profile_view', - 'xmodule_js/common_static/common/js/discussion/views/new_post_view', - 'xmodule_js/common_static/common/js/discussion/views/thread_response_edit_view', - 'xmodule_js/common_static/common/js/discussion/views/thread_response_show_view', - 'xmodule_js/common_static/common/js/discussion/views/thread_response_view' + 'common/js/discussion/content', + 'common/js/discussion/discussion', + 'common/js/discussion/models/discussion_course_settings', + 'common/js/discussion/models/discussion_user', + 'common/js/discussion/utils', + 'common/js/discussion/views/discussion_content_view', + 'common/js/discussion/views/discussion_thread_edit_view', + 'common/js/discussion/views/discussion_thread_list_view', + 'common/js/discussion/views/discussion_thread_profile_view', + 'common/js/discussion/views/discussion_thread_show_view', + 'common/js/discussion/views/discussion_thread_view', + 'common/js/discussion/views/discussion_topic_menu_view', + 'common/js/discussion/views/new_post_view', + 'common/js/discussion/views/thread_response_edit_view', + 'common/js/discussion/views/thread_response_show_view', + 'common/js/discussion/views/thread_response_view' ], exports: 'DiscussionModuleView' }, - 'xmodule_js/common_static/common/js/spec_helpers/discussion_spec_helper': { + 'common/js/spec_helpers/discussion_spec_helper': { deps: [ - 'xmodule_js/common_static/common/js/discussion/utils' + 'common/js/discussion/utils' ], exports: 'DiscussionSpecHelper' } @@ -672,6 +662,9 @@ }); var testFiles = [ + 'discussion/js/spec/discussion_board_factory_spec.js', + 'discussion/js/spec/discussion_profile_page_factory_spec.js', + 'discussion/js/spec/views/discussion_user_profile_view_spec.js', 'lms/js/spec/preview/preview_factory_spec.js', 'js/spec/api_admin/catalog_preview_spec.js', 'js/spec/courseware/bookmark_button_view_spec.js', diff --git a/lms/static/sass/discussion/_build.scss b/lms/static/sass/discussion/_build.scss index 288f4ff0c7..67375adf8d 100644 --- a/lms/static/sass/discussion/_build.scss +++ b/lms/static/sass/discussion/_build.scss @@ -21,8 +21,8 @@ $static-path: '../..' !default; @import '../shared-v2/help-tab'; // Compatibility support for non-Pattern Library mixins and extensions -@import 'utilities/v1-compatibility'; @import 'utilities/variables-v2'; +@import 'utilities/v1-compatibility'; // Discussion styling @import 'mixins'; diff --git a/lms/static/sass/discussion/_discussion.scss b/lms/static/sass/discussion/_discussion.scss index 88b01dd076..384bd153bf 100644 --- a/lms/static/sass/discussion/_discussion.scss +++ b/lms/static/sass/discussion/_discussion.scss @@ -10,7 +10,7 @@ body.discussion { width: 100%; h1 { - font-size: 20px; + font-size: $forum-x-large-font-size; } .form-row { @@ -19,13 +19,13 @@ body.discussion { .post-cancel { @include white-button; - float: left; + @include float(left); margin: ($baseline/2) 0 0 ($baseline*0.75); } .post-update { @include blue-button; - float: left; + @include float(left); margin-top: ($baseline/2); padding-bottom: ($baseline/10); height: 37px; @@ -38,19 +38,19 @@ body.discussion { .edit-post-title { box-sizing: border-box; border: 1px solid $forum-color-border; - border-radius: 3px; + border-radius: $forum-border-radius; padding: 0 ($baseline/2); width: 100%; height: 40px; box-shadow: 0 1px 3px $shadow-l1 inset; color: $dark-gray; - font-size: 16px; + font-size: $forum-large-font-size; font-family: $sans-serif; } } .comments .edit-post-form h1 { - @extend %t-title6; + font-size: $forum-large-font-size; } .thread-title { @@ -58,7 +58,7 @@ body.discussion { margin-bottom: $baseline; color: $gray-d3; font-weight: 700; - font-size: 21px; + font-size: $forum-x-large-font-size; } .wmd-panel { @@ -71,13 +71,13 @@ body.discussion { } .wmd-input { - @include border-radius(3px, 3px, 0, 0); + @include border-radius($forum-border-radius, $forum-border-radius, 0, 0); border: 1px solid $forum-color-border; width: 100%; height: 150px; background-color: $gray-l4; font-style: normal; - font-size: 0.8em; + font-size: $forum-base-font-size; font-family: $f-sans-serif; line-height: 1.6em; @@ -149,22 +149,22 @@ body.discussion { padding: $baseline; > div { - font-size: 0.8em; + font-size: $forum-base-font-size; font-family: $sans-serif; } b { - font-size: 16px; + font-size: $forum-large-font-size; } > form > input[type="text"] { - border-radius: 3px; + border-radius: $forum-border-radius; color: $gray-d3; } > form > input[type="button"] { border: 1px solid #888; - font-size: 14px; + font-size: $forum-base-font-size; font-family: $sans-serif; } @@ -184,7 +184,7 @@ body.discussion { .bottom-post-status { padding: 30px; - font-size: 20px; + font-size: $forum-x-large-font-size; font-weight: 700; color: $gray-l3; text-align: center; @@ -192,7 +192,6 @@ body.discussion { .discussion-article { position: relative; - min-height: 500px; a { word-wrap: break-word; @@ -210,9 +209,9 @@ body.discussion { blockquote { background: $gray-l5; - border-radius: 3px; + border-radius: $forum-border-radius; padding: ($baseline/4) ($baseline/2); - font-size: 14px; + font-size: $forum-base-font-size; } .comment-form { @@ -237,7 +236,7 @@ body.discussion { padding: 0 ($baseline/2); box-sizing: border-box; border: 1px solid $forum-color-border; - border-radius: 3px; + border-radius: $forum-border-radius; box-shadow: 0 1px 3px $shadow-l1 inset; @include transition(border-color .1s linear 0s); @@ -257,7 +256,7 @@ body.discussion { padding: 0 ($baseline/2); h4 { - font-size: 16px; + font-size: $forum-large-font-size; font-weight: 700; } } @@ -298,7 +297,7 @@ body.discussion { // ==================== -// inline discussion module and profile thread styling +// inline discussion module .discussion-module { @extend .discussion-body; @@ -306,11 +305,11 @@ body.discussion { margin: $baseline 0; padding: $baseline; background: #f6f6f6 !important; - border-radius: 3px; + border-radius: $forum-border-radius; header { .anonymous{ - font-size: 15px; + font-size: $forum-base-font-size; } } @@ -328,129 +327,94 @@ body.discussion { .loading-animation { background-image: url('#{$static-path}/images/spinner.gif'); } +} - .discussion-show { - position: relative; - top: 3px; - font-size: 14px; - text-align: center; - - &.shown { - .show-hide-discussion-icon { - background-position: 0 0; - } - } +.discussion-show { + position: relative; + top: 3px; + font-size: $forum-base-font-size; + text-align: center; + &.shown { .show-hide-discussion-icon { - display: inline-block; - position: relative; - top: 5px; - @include margin-right(6px); - width: 21px; - height: 19px; - background: url('#{$static-path}/images/show-hide-discussion-icon.png') no-repeat; - background-position: -21px 0; + background-position: 0 0; } } - section.discussion { - clear: both; - padding-top: $baseline; + .show-hide-discussion-icon { + display: inline-block; + position: relative; + top: 5px; + @include margin-right(6px); + width: 21px; + height: 19px; + background: url('#{$static-path}/images/show-hide-discussion-icon.png') no-repeat; + background-position: -21px 0; + } +} - .threads { - } +section.discussion { + @include clearfix(); +} + +.new-post-article { + display: none; + margin-top: $baseline; + + .inner-wrapper { + max-width: 1180px; + min-width: 760px; + margin: auto; } - .new-post-article { - display: none; - margin-top: $baseline; - - .inner-wrapper { - max-width: 1180px; - min-width: 760px; - margin: auto; - } - - .thread-title { - display: block; - margin-bottom: $baseline; - font-size: 21px; - color: $gray-d3; - font-weight: 700; - } - } - - section.discussion-pagination { - margin-top: ($baseline*1.5); - - nav.discussion-paginator { - float: right; - - ol { - li { - list-style: none; - display: inline-block; - padding-right: 0.5em; - a { - @include white-button; - } - &.current-page span { - display: inline-block; - height: 35px; - padding: 0 ($baseline*0.75); - border: 1px solid $forum-color-border; - border-radius: 3px; - font-size: 13px; - font-weight: 700; - line-height: 32px; - color: $gray-d3; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6); - } - } - } - } - } - - .edit-post-form { - width: 100%; + .thread-title { + display: block; margin-bottom: $baseline; - @include clearfix(); + font-size: $forum-x-large-font-size; + color: $gray-d3; + font-weight: 700; + } +} + +.edit-post-form { + @include clearfix(); + width: 100%; + margin-bottom: $baseline; + box-sizing: border-box; + + .form-row { + margin-top: $baseline; + } + + .post-cancel { + @include white-button; + @include float(left); + @include margin($baseline/2, 0, 0, $baseline*0.75); + } + + .post-update { + @include blue-button; + @include float(left); + height: 37px; + margin-top: ($baseline/2); + padding-bottom: 2px; + + &:hover, &:focus { + border-color: #222; + } + } + + .edit-post-title { + width: 100%; + height: 40px; + padding: 0 ($baseline/2); box-sizing: border-box; - - .form-row { - margin-top: $baseline; - } - - .post-cancel { - @include white-button; - float: left; - margin: ($baseline/2) 0 0 ($baseline*0.75); - } - - .post-update { - @include blue-button; - float: left; - height: 37px; - margin-top: ($baseline/2); - padding-bottom: 2px; - - &:hover, &:focus { - border-color: #222; - } - } - - .edit-post-title { - width: 100%; - height: 40px; - padding: 0 ($baseline/2); - box-sizing: border-box; - border-radius: 3px; - border: 1px solid $forum-color-border; - font-size: 16px; - font-family: $sans-serif; - color: $gray-d3; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15) inset; - } + border-radius: $forum-border-radius; + border: 1px solid $forum-color-border; + font-size: $forum-large-font-size; + font-family: $sans-serif; + color: $gray-d3; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15) inset; } } @@ -461,6 +425,37 @@ body.discussion { // ==================== // post pagination +section.discussion-pagination { + margin-top: ($baseline*1.5); + + nav.discussion-paginator { + @include float(right); + + ol { + li { + list-style: none; + display: inline-block; + padding-right: 0.5em; + a { + @include white-button; + } + &.current-page span { + display: inline-block; + height: 35px; + padding: 0 ($baseline*0.75); + border: 1px solid $forum-color-border; + border-radius: $forum-border-radius; + font-size: $forum-base-font-size; + font-weight: 700; + line-height: 32px; + color: $gray-d3; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6); + } + } + } + } +} + .response-count { @include float(right); } @@ -477,7 +472,7 @@ body.discussion { display: block; padding: ($baseline/2) 0; color: $gray; - font-size: 14px; + font-size: $forum-base-font-size; } .load-response-button { diff --git a/lms/static/sass/discussion/_layouts.scss b/lms/static/sass/discussion/_layouts.scss index 016ee2c442..2ae3c67204 100644 --- a/lms/static/sass/discussion/_layouts.scss +++ b/lms/static/sass/discussion/_layouts.scss @@ -1,26 +1,26 @@ // Layouts for discussion pages -section.user-profile { +.user-profile { background-color: $sidebar-color; .user-profile { - padding: 32px 36px; + padding: $baseline; min-height: 500px; } .sidebar-username { font-weight: 700; - font-size: 18px; + font-size: $forum-large-font-size; } .sidebar-user-roles { - margin-top: 6px; + margin-top: $baseline/2; font-style: italic; - font-size: 13px; + font-size: $forum-base-font-size; } .sidebar-threads-count { - margin-top: 14px; + margin-top: $baseline/2; } .sidebar-threads-count span, @@ -30,11 +30,5 @@ section.user-profile { } .discussion-column { - @include float(right); - box-sizing: border-box; - padding-left: ($baseline/2); - width: 68%; - max-width: 800px; min-height: 500px; - border-radius: 3px; } diff --git a/lms/static/sass/discussion/_mixins.scss b/lms/static/sass/discussion/_mixins.scss index a974c5eb78..9a3de6eac3 100644 --- a/lms/static/sass/discussion/_mixins.scss +++ b/lms/static/sass/discussion/_mixins.scss @@ -4,10 +4,11 @@ @mixin discussion-button() { display: block; border: 1px solid; - border-radius: 3px; + border-radius: $forum-border-radius; height: 35px; + color: $white; line-height: 35px; - font-size: 13px; + font-size: $forum-base-font-size; white-space: nowrap; // Prevent word-break in Arabic in Google Chrome text-shadow: none; padding: 0 ($baseline*0.75); @@ -52,20 +53,20 @@ box-sizing: border-box; margin-top: 0; border: 1px solid $forum-color-border; - border-radius: 3px 3px 0 0; + border-radius: $forum-border-radius $forum-border-radius 0 0; padding: ($baseline/2); width: 100%; height: 125px; background: $forum-color-background; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15) inset; - font-size: 13px; + font-size: $forum-base-font-size; font-family: $sans-serif; line-height: 1.6; } @mixin discussion-wmd-preview-container { box-sizing: border-box; - @include border-radius(0, 0, 3px, 3px); + @include border-radius(0, 0, $forum-border-radius, $forum-border-radius); border: 1px solid $gray-l1; border-top: none; width: 100%; @@ -84,7 +85,7 @@ padding-top: 3px; width: 100%; color: $gray-l2; - font-size: 11px; + font-size: $forum-small-font-size; } @mixin discussion-wmd-preview { @@ -113,11 +114,11 @@ @mixin forum-post-label($color) { @extend %t-weight4; - @include font-size(9); + font-size: $forum-small-font-size; display: inline; margin-top: ($baseline/4); border: 1px solid; - border-radius: 3px; + border-radius: $forum-border-radius; padding: 1px 6px; white-space: nowrap; @@ -138,11 +139,11 @@ } @mixin forum-user-label($color) { - @include font-size(9); + @include margin-left($baseline/4); @extend %t-weight5; + font-size: $forum-small-font-size; vertical-align: middle; - margin-left: ($baseline/4); - border-radius: 2px; + border-radius: $forum-border-radius; padding: 0 ($baseline/5); background: $color; font-style: normal; diff --git a/lms/static/sass/discussion/elements/_actions.scss b/lms/static/sass/discussion/elements/_actions.scss index 2953334ae5..605f6924e6 100644 --- a/lms/static/sass/discussion/elements/_actions.scss +++ b/lms/static/sass/discussion/elements/_actions.scss @@ -70,7 +70,7 @@ box-shadow: 0 1px 1px $shadow-l1; position: relative; width: 100%; - border-radius: 3px; + border-radius: $forum-border-radius; margin: ($baseline/4) 0 0 0; border: 1px solid $gray-l3; padding: ($baseline/2) ($baseline*0.75); @@ -121,16 +121,16 @@ box-sizing: border-box; display: inline-block; border: 1px solid transparent; - border-radius: ($baseline/4); + border-radius: $forum-border-radius; color: $gray-l1; .action-icon { - @extend %t-icon7; display: inline-block; + font-size: $forum-small-font-size; height: $baseline; width: $baseline; - border: 1px solid $gray-l3; - border-radius: 3px; + border: 1px solid $forum-color-border; + border-radius: $forum-border-radius; text-align: center; color: $gray-l1; @@ -156,7 +156,7 @@ } .action-icon { - border-radius: 0 3px 3px 0; + border-radius: 0 $forum-border-radius $forum-border-radius 0; } } @@ -287,9 +287,9 @@ } .action-icon { + @include margin-left($baseline/4); display: inline-block; width: ($baseline/2); - margin-left: ($baseline/4); color: inherit; } diff --git a/lms/static/sass/discussion/elements/_editor.scss b/lms/static/sass/discussion/elements/_editor.scss index eb63beeffa..4c09e74ef4 100644 --- a/lms/static/sass/discussion/elements/_editor.scss +++ b/lms/static/sass/discussion/elements/_editor.scss @@ -54,9 +54,9 @@ .wmd-input { width: 100%; height: 150px; - border-radius: 3px 3px 0 0; + border-radius: $forum-border-radius $forum-border-radius 0 0; font-style: normal; - font-size: 0.8em; + font-size: $forum-base-font-size; font-family: Monaco, 'Lucida Console', monospace; line-height: 1.6em; @@ -75,9 +75,9 @@ } .wmd-spacer { + @include margin-left(14px); position: absolute; display: inline-block; - margin-left: 14px; width: 1px; height: 20px; background-color: Silver; @@ -129,23 +129,23 @@ padding: $baseline; > div { - font-size: 0.8em; + font-size: $forum-base-font-size; font-family: arial, helvetica, sans-serif; } b { - font-size: 16px; + font-size: $forum-large-font-size; } > form > input[type="text"] { - border-radius: 3px; + border-radius: $forum-border-radius; color: #333; } > form > input[type="button"] { border: 1px solid #888; font-family: $sans-serif; - font-size: 14px; + font-size: $forum-x-large-font-size; } > form > input[type="file"] { diff --git a/lms/static/sass/discussion/elements/_navigation.scss b/lms/static/sass/discussion/elements/_navigation.scss index 1f00bcf29a..cca01a90df 100644 --- a/lms/static/sass/discussion/elements/_navigation.scss +++ b/lms/static/sass/discussion/elements/_navigation.scss @@ -2,12 +2,8 @@ // ==================== .forum-nav { - box-sizing: border-box; - @include float(left); - position: relative; - width: 31%; border: 1px solid #aaa; - border-radius: 3px; + border-radius: $forum-border-radius; } // ------ @@ -45,13 +41,13 @@ } .icon { - @include font-size(14); @include margin-right($baseline/4); + font-size: $forum-base-font-size; } } .forum-nav-browse-current { - @include font-size(12); + font-size: $forum-small-font-size; } .forum-nav-browse-drop-arrow { @@ -69,7 +65,7 @@ } .forum-nav-search .icon { - @include font-size(12); + font-size: $forum-small-font-size; position: absolute; margin-top: -6px; top: 50%; @@ -95,7 +91,7 @@ } .forum-nav-browse-filter .icon { - @include font-size(12); + font-size: $forum-small-font-size; position: absolute; margin-top: -6px; top: 50%; @@ -134,7 +130,7 @@ } .forum-nav-browse-menu { - @include font-size(14); + font-size: $forum-base-font-size; overflow-y: scroll; list-style: none; } @@ -156,7 +152,7 @@ // ------------------- .forum-nav-refine-bar { @include clearfix(); - @include font-size(11); + font-size: $forum-small-font-size; border-bottom: 1px solid $forum-color-border; background-color: $gray-l5; padding: ($baseline/4) ($baseline/2); @@ -284,7 +280,7 @@ width: 7%; .icon { - @include font-size(14); + font-size: $forum-base-font-size; &:before { @@ -319,19 +315,19 @@ } .forum-nav-thread-title { - @extend %t-title7; + font-size: $forum-base-font-size; display: block; } %forum-nav-thread-wrapper-2-content { - @include font-size(11); + @include margin-right($baseline/4); + font-size: $forum-small-font-size; display: inline-block; - margin-right: ($baseline/4); text-align: center; color: $black; &:last-child { - margin-right: 0; + @include margin-right(0); } } @@ -345,7 +341,7 @@ position: relative; @include margin-left($baseline/4); margin-bottom: ($baseline/4); // Because tail is position: absolute - border-radius: 2px; + border-radius: $forum-border-radius; padding: ($baseline/10) ($baseline/5); min-width: 2em; // Fit most comment counts but allow expansion if necessary background-color: $gray-l4; diff --git a/lms/static/sass/discussion/utilities/_developer.scss b/lms/static/sass/discussion/utilities/_developer.scss index c5be0700e2..ff0747606c 100644 --- a/lms/static/sass/discussion/utilities/_developer.scss +++ b/lms/static/sass/discussion/utilities/_developer.scss @@ -44,7 +44,7 @@ body.discussion { // alert copy .message { - @include font-size(12); + font-size: $forum-small-font-size; color: $white; em { @@ -66,11 +66,11 @@ body.discussion { text-align: right; .control { - @include font-size(14); @include transition(none); @extend %t-weight5; padding: ($baseline/4) ($baseline/2); color: $white; + font-size: $forum-base-font-size; // reseting poorly globally scoped hover/focus state for this control &:hover, &:focus { diff --git a/lms/static/sass/discussion/utilities/_shame.scss b/lms/static/sass/discussion/utilities/_shame.scss index 0b676dc42c..3f6a83fd6d 100644 --- a/lms/static/sass/discussion/utilities/_shame.scss +++ b/lms/static/sass/discussion/utilities/_shame.scss @@ -14,13 +14,13 @@ // Override global input rules .forum-nav-search-input { - box-shadow: none !important; - border: 1px solid $forum-color-border !important; - border-radius: 3px !important; - height: auto !important; @include padding-left($baseline/4 !important); @include padding-right($baseline/2 + 12px !important); // Leave room for icon - font-size: 12px !important; + box-shadow: none !important; + border: 1px solid $forum-color-border !important; + border-radius: $forum-border-radius !important; + height: auto !important; + font-size: $forum-small-font-size !important; } // Firefox does not compute the correct containing box for absolute positioning @@ -45,12 +45,12 @@ // Override global input rules .forum-nav-browse-filter-input { + @include padding-left($baseline/4); + @include padding-right($baseline/2 + 12px); // Leave room for icon box-shadow: none !important; - border-radius: 3px !important; + border-radius: $forum-border-radius !important; height: auto !important; - padding-left: ($baseline/4) !important; - padding-right: ($baseline/2 + 12px) !important; // Leave room for icon - font-size: 12px !important; + font-size: $forum-small-font-size !important; } // Override global ul rules diff --git a/lms/static/sass/discussion/utilities/_v1-compatibility.scss b/lms/static/sass/discussion/utilities/_v1-compatibility.scss index d4b4d9f754..afdd9fa799 100644 --- a/lms/static/sass/discussion/utilities/_v1-compatibility.scss +++ b/lms/static/sass/discussion/utilities/_v1-compatibility.scss @@ -31,46 +31,6 @@ %ui-depth4 { z-index: 10000; } %ui-depth5 { z-index: 100000; } -%t-icon1 { - @include font-size(48); -} - -%t-icon2 { - @include font-size(36); -} - -%t-icon3 { - @include font-size(24); -} - -%t-icon4 { - @include font-size(18); -} - -%t-icon5 { - @include font-size(16); -} - -%t-icon6 { - @include font-size(14); -} - -%t-icon7 { - @include font-size(12); -} - -%t-icon8 { - @include font-size(11); -} - -%t-icon9 { - @include font-size(10); -} - -%t-icon-solo { - @include line-height(0); -} - // weights %t-ultrastrong { font-weight: 700; @@ -91,97 +51,21 @@ font-weight: 200; } -// headings/titles -%t-title { - font-family: $f-sans-serif; -} - -%t-title1 { - @extend %t-title; - @include font-size(60); - @include line-height(60); -} - -%t-title2 { - @extend %t-title; - @include font-size(48); - @include line-height(48); -} - -%t-title3 { - @include font-size(36); - @include line-height(36); -} - -%t-title4 { - @extend %t-title; - @include font-size(24); - @include line-height(24); -} - -%t-title5 { - @extend %t-title; - @include font-size(18); - @include line-height(18); -} - -%t-title6 { - @extend %t-title; - @include font-size(16); - @include line-height(16); -} - -%t-title7 { - @extend %t-title; - @include font-size(14); - @include line-height(14); -} - -%t-title8 { - @extend %t-title; - @include font-size(12); - @include line-height(12); -} - -%t-title9 { - @extend %t-title; - @include font-size(11); - @include line-height(11); -} - // copy %t-copy { font-family: $f-sans-serif; } -%t-copy-base { - @extend %t-copy; - @include font-size(16); - @include line-height(16); -} - -%t-copy-lead1 { - @extend %t-copy; - @include font-size(18); - @include line-height(18); -} - -%t-copy-lead2 { - @extend %t-copy; - @include font-size(24); - @include line-height(24); -} - %t-copy-sub1 { @extend %t-copy; - @include font-size(14); @include line-height(14); + font-size: $forum-base-font-size; } %t-copy-sub2 { @extend %t-copy; - @include font-size(12); @include line-height(12); + font-size: $forum-small-font-size; } // extends - UI - removes list styling/spacing when using uls, ols for navigation and less content-centric cases diff --git a/lms/static/sass/discussion/utilities/_variables-v1.scss b/lms/static/sass/discussion/utilities/_variables-v1.scss index 4d1347d75b..4c6eb96775 100644 --- a/lms/static/sass/discussion/utilities/_variables-v1.scss +++ b/lms/static/sass/discussion/utilities/_variables-v1.scss @@ -21,3 +21,12 @@ $forum-color-reading-thread: $gray-d3 !default; $post-image-dimension: ($baseline*3) !default; // image size + margin $response-image-dimension: ($baseline*2.5) !default; // image size + margin $comment-image-dimension: ($baseline*2) !default; // image size + margin + +// font sizes +$forum-base-font-size: 14px; +$forum-x-large-font-size: 21px; +$forum-large-font-size: 16px; +$forum-small-font-size: 12px; + +// borders +$forum-border-radius: 3px; diff --git a/lms/static/sass/discussion/utilities/_variables-v2.scss b/lms/static/sass/discussion/utilities/_variables-v2.scss index 3d194886b7..d39dd0af77 100644 --- a/lms/static/sass/discussion/utilities/_variables-v2.scss +++ b/lms/static/sass/discussion/utilities/_variables-v2.scss @@ -21,3 +21,12 @@ $forum-color-reading-thread: palette(grayscale, dark) !default; $post-image-dimension: ($baseline*3) !default; // image size + margin $response-image-dimension: ($baseline*2.5) !default; // image size + margin $comment-image-dimension: ($baseline*2) !default; // image size + margin + +// font sizes +$forum-base-font-size: font-size(small); +$forum-x-large-font-size: font-size(x-large); +$forum-large-font-size: font-size(base); +$forum-small-font-size: font-size(x-small); + +// borders +$forum-border-radius: $component-border-radius; diff --git a/lms/static/sass/discussion/views/_create-edit-post.scss b/lms/static/sass/discussion/views/_create-edit-post.scss index e6c49df06f..9594f6be77 100644 --- a/lms/static/sass/discussion/views/_create-edit-post.scss +++ b/lms/static/sass/discussion/views/_create-edit-post.scss @@ -7,7 +7,7 @@ @include clearfix(); box-sizing: border-box; margin: 0; - border-radius: 3px; + border-radius: $forum-border-radius; padding: $baseline; max-width: 1180px; @@ -32,7 +32,7 @@ display: inline-block; width: 25%; vertical-align: top; - font-size: 12px; + font-size: $forum-small-font-size; line-height: 40px; } @@ -47,7 +47,8 @@ display: inline-block; @include padding-left($baseline); width: 50%; - font-size: 12px; + font-size: $forum-small-font-size; + } } @@ -73,11 +74,11 @@ padding: 0 $baseline 0 ($baseline*0.75); width: 100%; height: 40px; - font-size: 14px; + font-size: $forum-base-font-size; line-height: 36px; .drop-arrow { - float: right; + @include float(right); color: #999; } } @@ -89,7 +90,7 @@ .post-type-label { @extend %cont-truncated; @include white-button; - @include font-size(14); + font-size: $forum-base-font-size; box-sizing: border-box; display: inline-block; padding: 0 ($baseline/2); @@ -101,7 +102,7 @@ line-height: 36px; .icon { - margin-right: ($baseline/4); + @include margin-right($baseline/4); } } @@ -119,13 +120,13 @@ input[type=text].field-input { box-sizing: border-box; border: 1px solid $forum-color-border; - border-radius: 3px; + border-radius: $forum-border-radius; padding: 0 $baseline/2; height: 40px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15) inset; color: #333; font-weight: 700; - font-size: 16px; + font-size: $forum-large-font-size; font-family: 'Open Sans', sans-serif; } @@ -134,7 +135,7 @@ display: inline-block; @include margin-right($baseline); border: 1px solid transparent; - border-radius: 3px; + border-radius: $forum-border-radius; padding: ($baseline/2); &:hover { @@ -147,11 +148,11 @@ } .post-option-input { - margin-right: ($baseline/2); + @include margin-right($baseline/2); } .icon { - margin-right: 0.5em; + @include margin-right($baseline/2); } } } @@ -162,8 +163,8 @@ .forum-new-post-form { .submit { @include blue-button; + @include margin-right($baseline/2); display: inline-block; - margin-right: ($baseline/2); } .cancel { @@ -179,7 +180,7 @@ .edit-post-form { .post-errors { margin-bottom: $baseline; - border-radius: 3px; + border-radius: $forum-border-radius; padding: 0; background: $error-color; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3) inset, 0 1px 0 rgba(255, 255, 255, .2); @@ -230,7 +231,7 @@ width: 100%; height: 30px; color: #333; - font-size: 11px; + font-size: $forum-small-font-size; line-height: 16px; } @@ -249,7 +250,7 @@ .topic-title { display: block; padding: ($baseline/4) ($baseline/2); - font-size: 14px; + font-size: $forum-base-font-size; } a.topic-title { diff --git a/lms/static/sass/discussion/views/_home.scss b/lms/static/sass/discussion/views/_home.scss index 08fc6965a8..d7f27ed179 100644 --- a/lms/static/sass/discussion/views/_home.scss +++ b/lms/static/sass/discussion/views/_home.scss @@ -24,7 +24,7 @@ } .home-title { - @extend %t-title5; + font-size: $forum-large-font-size; color: $black; margin-bottom: ($baseline/4); } @@ -58,7 +58,7 @@ vertical-align: middle; .count { - @extend %t-title4; + font-size: $forum-x-large-font-size; display: inline-block; padding: 0 ($baseline/2); vertical-align: middle; @@ -73,7 +73,7 @@ .home-helpgrid { border-bottom: none; - border-radius: 3px; + border-radius: $forum-border-radius; border: 1px solid $forum-color-border; box-shadow: 0 1px 3px rgba(0, 0, 0, .15); } @@ -84,11 +84,11 @@ .row-title { padding: ($baseline*1.5) $baseline; background-color: #dedede; - font-size: 12px; + font-size: $forum-small-font-size; } .row-item-full, .row-item { - font-size: 12px; + font-size: $forum-small-font-size; padding: 0 ($baseline/2); width: 26%; vertical-align: middle; @@ -118,7 +118,7 @@ @include margin-right($baseline/2); display: inline-block; @include padding($baseline/4, 0, $baseline/2, 0); - border-radius: 5px; + border-radius: $forum-border-radius; border: 1px solid gray; .email-setting { diff --git a/lms/static/sass/discussion/views/_response.scss b/lms/static/sass/discussion/views/_response.scss index b9eba9e5a7..2100274b41 100644 --- a/lms/static/sass/discussion/views/_response.scss +++ b/lms/static/sass/discussion/views/_response.scss @@ -24,14 +24,14 @@ position: relative; margin: $baseline 0; border: 1px solid $forum-color-border; - border-radius: 3px; + border-radius: $forum-border-radius; box-shadow: 0 0 1px $shadow; } // wrapper - main response area .discussion-response { box-sizing: border-box; - @include border-radius(3px, 3px, 0, 0); + @include border-radius($forum-border-radius, $forum-border-radius, 0, 0); padding: $baseline; background-color: $forum-color-background; } @@ -48,8 +48,8 @@ // CASE: larger username for responses .username { - @include font-size(14); @extend %t-weight5; + font-size: $forum-base-font-size; } } @@ -68,7 +68,7 @@ // +CASE: answered question - collapsed comments in answers .forum-response .action-show-comments { - @include font-size(13); + font-size: $forum-base-font-size; box-sizing: border-box; display: block; padding: ($baseline/2) $baseline; @@ -95,6 +95,7 @@ // CASE: banner - staff response .staff-banner { + @include border-radius($forum-border-radius, $forum-border-radius, 0, 0); position: absolute; top: 0; left: 0; @@ -102,9 +103,8 @@ height: 14px; padding: 1px ($baseline/4); box-sizing: border-box; - border-radius: 2px 2px 0 0; background: #009fe2; - font-size: 9px; + font-size: $forum-small-font-size; font-weight: 700; color: $white; } @@ -118,9 +118,9 @@ height: 14px; padding: 1px ($baseline/4); box-sizing: border-box; - border-radius: 2px 2px 0 0; + border-radius: $forum-border-radius $forum-border-radius 0 0; background: $forum-color-community-ta; - font-size: 9px; + font-size: $forum-small-font-size; font-weight: 700; color: $white; } @@ -138,7 +138,7 @@ // +comments styling .container .discussion-body .comments { @extend %ui-no-list; - border-radius: 0 0 3px 3px; + border-radius: 0 0 $forum-border-radius $forum-border-radius; background: $gray-l6; box-shadow: 0 1px 3px -1px $shadow inset; @@ -149,9 +149,9 @@ blockquote { background: $gray-l4; - border-radius: 3px; + border-radius: $forum-border-radius; padding: ($baseline/4) ($baseline/2); - font-size: 14px; + font-size: $forum-base-font-size; } .comment-form { @@ -160,12 +160,12 @@ .comment-form-input { padding: ($baseline/4) ($baseline/2); background-color: $forum-color-background; - font-size: 14px; + font-size: $forum-base-font-size; } .discussion-submit-comment { @include blue-button; - float: left; + @include float(left); margin-top: 8px; } diff --git a/lms/static/sass/discussion/views/_thread.scss b/lms/static/sass/discussion/views/_thread.scss index 8ab2ffc6fb..3211511a3b 100644 --- a/lms/static/sass/discussion/views/_thread.scss +++ b/lms/static/sass/discussion/views/_thread.scss @@ -127,7 +127,7 @@ body.discussion { } img { - border-radius: 3px; + border-radius: $forum-border-radius; } } } @@ -138,21 +138,17 @@ body.discussion { } // +post - individual element styling -body.discussion .discussion-post, -body.discussion .discussion-article, -body.view-in-course .discussion-post, -body.view-in-course .discussion-article { - // NOTE: discussion-article is used for inline discussion modules. +// NOTE: discussion-article is used for inline discussion modules. +.discussion-post, +.discussion-article { @include clearfix(); .post-header-content { // post title .post-title { - @extend %t-title4; - @extend %t-ultrastrong; + font-size: $forum-x-large-font-size; margin-bottom: ($baseline/4); - letter-spacing: 0; } } @@ -211,14 +207,14 @@ body.view-in-course .discussion-article { .discussion-article { @include transition(all .2s linear 0s); border: 1px solid $forum-color-border; - border-radius: 3px; + border-radius: $forum-border-radius; min-height: 0; background: $forum-color-background; box-shadow: 0 1px 0 $shadow; @include transition(all .2s linear 0s); .thread-wrapper { - @include border-radius(3px, 3px, 0, 0); + @include border-radius($forum-border-radius, $forum-border-radius, 0, 0); position: relative; overflow-x: hidden; overflow-y: auto; @@ -228,16 +224,16 @@ body.view-in-course .discussion-article { .discussion-post { .inline-comment-count { + @include margin-right($baseline/2); @extend %ui-depth2; + @include float(right); position: relative; - float: right; display: block; height: 27px; margin-top: 6px; - margin-right: 8px; padding: 0 8px; - border-radius: ($baseline/4); - font-size: 12px; + border-radius: $forum-border-radius; + font-size: $forum-small-font-size; font-weight: 400; line-height: 25px; color: #888; @@ -250,15 +246,15 @@ body.view-in-course .discussion-article { margin-bottom: ($baseline*0.75); .posted-by { - float: left; - margin-right: ($baseline/4); - font-size: 16px; + @include margin-right($baseline/4); + @include float(left); + font-size: $forum-large-font-size; } } .response-body { margin-bottom: 0.2em; - font-size: 14px; + font-size: $forum-base-font-size; } } @@ -289,12 +285,12 @@ body.view-in-course .discussion-article { a { display: block; padding: ($baseline*0.25) $baseline; - font-size: 12px; + font-size: $forum-small-font-size; line-height: 30px; .icon { + @include margin-right($baseline*0.25); color: $link-color; - margin-right: ($baseline*0.25); } } } diff --git a/lms/static/sass/shared-v2/_layouts.scss b/lms/static/sass/shared-v2/_layouts.scss index 66b30fb46f..aac7e92089 100644 --- a/lms/static/sass/shared-v2/_layouts.scss +++ b/lms/static/sass/shared-v2/_layouts.scss @@ -11,12 +11,12 @@ @include clearfix(); border: 1px solid $lms-border-color; background-color: $lms-container-background-color; - padding: $baseline; } .page-header { @include clearfix(); border-bottom: 1px solid $lms-border-color; + padding: $baseline; .page-title { @extend %t-title4; @@ -67,6 +67,6 @@ } .page-content { - padding-top: $baseline; + padding: $baseline; } } diff --git a/lms/templates/courseware/courseware-chromeless.html b/lms/templates/courseware/courseware-chromeless.html index 2648e3fd9f..644ca0839b 100644 --- a/lms/templates/courseware/courseware-chromeless.html +++ b/lms/templates/courseware/courseware-chromeless.html @@ -52,7 +52,6 @@ ${static.get_page_title_breadcrumbs(course_name())} <%static:js group='courseware'/> - <%static:js group='discussion'/> <%include file="../discussion/_js_body_dependencies.html" /> % if staff_access: diff --git a/lms/templates/courseware/courseware.html b/lms/templates/courseware/courseware.html index 7897372b37..46cfb6549b 100644 --- a/lms/templates/courseware/courseware.html +++ b/lms/templates/courseware/courseware.html @@ -73,7 +73,8 @@ ${static.get_page_title_breadcrumbs(course_name())} <%static:js group='courseware'/> - <%static:js group='discussion'/> + <%include file="../discussion/_js_body_dependencies.html" /> + % if settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH'): <%static:require_module module_name="js/search/course/course_search_factory" class_name="CourseSearchFactory"> var courseId = $('.courseware-results').data('courseId'); @@ -85,7 +86,6 @@ ${static.get_page_title_breadcrumbs(course_name())} CoursewareFactory(); - <%include file="../discussion/_js_body_dependencies.html" /> % if staff_access: <%include file="xqa_interface.html"/> % endif diff --git a/lms/templates/discussion/_discussion_course_navigation.html b/lms/templates/discussion/_discussion_course_navigation.html deleted file mode 100644 index 94faa3c4ba..0000000000 --- a/lms/templates/discussion/_discussion_course_navigation.html +++ /dev/null @@ -1,14 +0,0 @@ -<%page expression_filter="h"/> -<%inherit file="../courseware/course_navigation.html" /> -<%! -from django.utils.translation import ugettext as _ -from django_comment_client.permissions import has_permission -%> - -<%block name="extratabs"> -% if has_permission(user, 'create_thread', course.id): -
  • - -
  • -% endif - diff --git a/lms/templates/discussion/_js_body_dependencies.html b/lms/templates/discussion/_js_body_dependencies.html index 447af19652..fda375a109 100644 --- a/lms/templates/discussion/_js_body_dependencies.html +++ b/lms/templates/discussion/_js_body_dependencies.html @@ -1,3 +1,37 @@ -<%page args="disable_fast_preview=True"/> +## mako + +<%namespace name='static' file='/static_content.html'/> + +<%page args="disable_fast_preview=True" expression_filter="h"/> + +<%! +from openedx.core.djangolib.js_utils import js_escaped_string +%> <%include file="/mathjax_include.html" args="disable_fast_preview=disable_fast_preview"/> + +<%static:js group='discussion'/> + +## Add RequireJS definitions for each discussion class +<% +discussion_classes = [ + ['Discussion', 'common/js/discussion/discussion'], + ['DiscussionModuleView', 'common/js/discussion/discussion_module_view'], + ['DiscussionThreadView', 'common/js/discussion/views/discussion_thread_view'], + ['DiscussionThreadListView', 'common/js/discussion/views/discussion_thread_list_view'], + ['DiscussionThreadProfileView', 'common/js/discussion/views/discussion_thread_profile_view'], + ['DiscussionUtil', 'common/js/discussion/utils'], + ['NewPostView', 'common/js/discussion/views/new_post_view'], +] +%> + diff --git a/lms/templates/discussion/_underscore_templates.html b/lms/templates/discussion/_underscore_templates.html index e3e440c5d3..571da7b815 100644 --- a/lms/templates/discussion/_underscore_templates.html +++ b/lms/templates/discussion/_underscore_templates.html @@ -16,7 +16,7 @@ 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', 'nav-loading' + 'inline-discussion', 'pagination', 'profile-thread', 'customwmd-prompt', 'nav-loading' ] ## same, but without trailing "-template" in script ID - these templates does not contain any free variables diff --git a/lms/templates/ux/reference/course-skeleton.html b/lms/templates/ux/reference/course-skeleton.html index 4e2ee6f8b8..c793092d24 100644 --- a/lms/templates/ux/reference/course-skeleton.html +++ b/lms/templates/ux/reference/course-skeleton.html @@ -64,8 +64,30 @@
    -

    This is where the page content belongs

    -

    Useful stuff goes here

    +
    + + +
    +
    +

    Main content goes here.

    +

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis molestie, orci at viverra ornare, + augue urna fermentum ex, vitae dignissim magna est sit amet diam. Nunc sodales dolor finibus + pulvinar placerat. Suspendisse vitae tellus auctor, sodales erat ac, venenatis quam. Etiam + purus est, consequat nec erat vel, bibendum volutpat ex. Fusce vitae consectetur ante. + Suspendisse elit mauris, iaculis sed diam eu, efficitur tempor dui. Praesent tristique nunc + quam, in tincidunt ligula accumsan et. Etiam augue sem, commodo ac ipsum vel, fringilla dapibus + lacus. Sed facilisis euismod felis, non malesuada massa scelerisque sed. Etiam et placerat + lorem. Nullam quis tincidunt sapien.

    +
    +
    +