Merge pull request #15182 from edx/diana/dismiss-button
Add a dismiss button to welcome message.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
define ["js/models/uploads", "js/views/uploads", "js/models/chapter",
|
||||
define ["sinon", "js/models/uploads", "js/views/uploads", "js/models/chapter",
|
||||
"edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers", "js/spec_helpers/modal_helpers"],
|
||||
(FileUpload, UploadDialog, Chapter, AjaxHelpers, modal_helpers) ->
|
||||
(sinon, FileUpload, UploadDialog, Chapter, AjaxHelpers, modal_helpers) ->
|
||||
|
||||
describe "UploadDialog", ->
|
||||
tpl = readFixtures("upload-dialog.underscore")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
define(['js/utils/drag_and_drop', 'common/js/components/views/feedback_notification',
|
||||
define(['sinon', 'js/utils/drag_and_drop', 'common/js/components/views/feedback_notification',
|
||||
'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'jquery', 'underscore'],
|
||||
function(ContentDragger, Notification, AjaxHelpers, $, _) {
|
||||
function(sinon, ContentDragger, Notification, AjaxHelpers, $, _) {
|
||||
'use strict';
|
||||
describe('Overview drag and drop functionality', function() {
|
||||
beforeEach(function() {
|
||||
setFixtures(readFixtures('mock/mock-outline.underscore'));
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
/* global define, sinon */
|
||||
/* global define */
|
||||
define([
|
||||
'jquery',
|
||||
'sinon',
|
||||
'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers',
|
||||
'js/certificates/models/certificate_exception',
|
||||
'js/certificates/views/certificate_whitelist',
|
||||
'js/certificates/views/certificate_whitelist_editor',
|
||||
'js/certificates/collections/certificate_whitelist'
|
||||
],
|
||||
function($, AjaxHelpers, CertificateExceptionModel, CertificateWhiteListView, CertificateWhiteListEditorView,
|
||||
function($, sinon, AjaxHelpers, CertificateExceptionModel, CertificateWhiteListView, CertificateWhiteListEditorView,
|
||||
CertificateWhiteListCollection) {
|
||||
'use strict';
|
||||
|
||||
describe('edx.certificates.models.certificates_exception.CertificateExceptionModel', function() {
|
||||
var certificate_exception = null;
|
||||
var certificateException = null;
|
||||
var assertValid = function(fields, isValid, expectedErrors) {
|
||||
certificate_exception.set(fields);
|
||||
var errors = certificate_exception.validate(certificate_exception.attributes);
|
||||
var errors;
|
||||
certificateException.set(fields);
|
||||
errors = certificateException.validate(certificateException.attributes);
|
||||
|
||||
if (isValid) {
|
||||
expect(errors).toBe(undefined);
|
||||
@@ -29,8 +32,8 @@ define([
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
certificate_exception = new CertificateExceptionModel({user_name: 'test_user'}, {url: 'test/url/'});
|
||||
certificate_exception.set({
|
||||
certificateException = new CertificateExceptionModel({user_name: 'test_user'}, {url: 'test/url/'});
|
||||
certificateException.set({
|
||||
notes: 'Test notes'
|
||||
});
|
||||
});
|
||||
@@ -50,9 +53,9 @@ define([
|
||||
});
|
||||
|
||||
describe('edx.certificates.collections.certificate_whitelist.CertificateWhiteList', function() {
|
||||
var certificate_white_list = null,
|
||||
certificate_exception_url = 'test/url/';
|
||||
var certificates_exceptions_json = [
|
||||
var certificateWhiteList = null,
|
||||
certificateExceptionUrl = 'test/url/';
|
||||
var certificatesExceptionsJson = [
|
||||
{
|
||||
id: 1,
|
||||
user_id: 1,
|
||||
@@ -74,38 +77,48 @@ define([
|
||||
];
|
||||
|
||||
beforeEach(function() {
|
||||
certificate_white_list = new CertificateWhiteListCollection(certificates_exceptions_json, {
|
||||
certificateWhiteList = new CertificateWhiteListCollection(certificatesExceptionsJson, {
|
||||
parse: true,
|
||||
canBeEmpty: true,
|
||||
url: certificate_exception_url,
|
||||
generate_certificates_url: certificate_exception_url
|
||||
url: certificateExceptionUrl,
|
||||
generate_certificates_url: certificateExceptionUrl
|
||||
});
|
||||
});
|
||||
|
||||
it('has 2 models in the collection after initialization', function() {
|
||||
expect(certificate_white_list.models.length).toEqual(2);
|
||||
expect(certificateWhiteList.models.length).toEqual(2);
|
||||
});
|
||||
|
||||
it("returns correct model on getModel call and 'undefined' if queried model is not present", function() {
|
||||
expect(certificate_white_list.getModel({user_name: 'test1'})).not.toBe(undefined);
|
||||
expect(certificate_white_list.getModel({user_name: 'test_invalid_user'})).toBe(undefined);
|
||||
expect(certificateWhiteList.getModel({user_name: 'test1'})).not.toBe(undefined);
|
||||
expect(certificateWhiteList.getModel({user_name: 'test_invalid_user'})).toBe(undefined);
|
||||
|
||||
expect(certificate_white_list.getModel({user_email: 'test1@test.com'})).not.toBe(undefined);
|
||||
expect(certificate_white_list.getModel({user_email: 'test_invalid_user@test.com'})).toBe(undefined);
|
||||
expect(certificateWhiteList.getModel({user_email: 'test1@test.com'})).not.toBe(undefined);
|
||||
expect(certificateWhiteList.getModel({user_email: 'test_invalid_user@test.com'})).toBe(undefined);
|
||||
|
||||
expect(certificate_white_list.getModel({user_name: 'test1'}).attributes).toEqual(
|
||||
expect(certificateWhiteList.getModel({user_name: 'test1'}).attributes).toEqual(
|
||||
{
|
||||
id: 1, user_id: 1, user_name: 'test1', user_email: 'test1@test.com',
|
||||
course_id: 'edX/test/course', created: 'Thursday, October 29, 2015',
|
||||
notes: 'test notes for test certificate exception', certificate_generated: ''
|
||||
id: 1,
|
||||
user_id: 1,
|
||||
user_name: 'test1',
|
||||
user_email: 'test1@test.com',
|
||||
course_id: 'edX/test/course',
|
||||
created: 'Thursday, October 29, 2015',
|
||||
notes: 'test notes for test certificate exception',
|
||||
certificate_generated: ''
|
||||
}
|
||||
);
|
||||
|
||||
expect(certificate_white_list.getModel({user_email: 'test2@test.com'}).attributes).toEqual(
|
||||
expect(certificateWhiteList.getModel({user_email: 'test2@test.com'}).attributes).toEqual(
|
||||
{
|
||||
id: 2, user_id: 2, user_name: 'test2', user_email: 'test2@test.com',
|
||||
course_id: 'edX/test/course', created: 'Thursday, October 29, 2015',
|
||||
notes: 'test notes for test certificate exception', certificate_generated: ''
|
||||
id: 2,
|
||||
user_id: 2,
|
||||
user_name: 'test2',
|
||||
user_email: 'test2@test.com',
|
||||
course_id: 'edX/test/course',
|
||||
created: 'Thursday, October 29, 2015',
|
||||
notes: 'test notes for test certificate exception',
|
||||
certificate_generated: ''
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -114,13 +127,13 @@ define([
|
||||
var successCallback = sinon.spy(),
|
||||
errorCallback = sinon.spy(),
|
||||
requests = AjaxHelpers.requests(this),
|
||||
add_students = 'all';
|
||||
addStudents = 'all';
|
||||
var expected = {
|
||||
url: certificate_exception_url + add_students,
|
||||
url: certificateExceptionUrl + addStudents,
|
||||
postData: []
|
||||
};
|
||||
|
||||
certificate_white_list.sync({success: successCallback, error: errorCallback}, add_students);
|
||||
certificateWhiteList.sync({success: successCallback, error: errorCallback}, addStudents);
|
||||
AjaxHelpers.expectJsonRequest(requests, 'POST', expected.url, expected.postData);
|
||||
});
|
||||
|
||||
@@ -128,21 +141,22 @@ define([
|
||||
var successCallback = sinon.spy(),
|
||||
errorCallback = sinon.spy(),
|
||||
requests = AjaxHelpers.requests(this),
|
||||
add_students = 'new';
|
||||
addStudents = 'new',
|
||||
expected;
|
||||
|
||||
certificate_white_list.add({user_name: 'test3', notes: 'test3 notes', new: true});
|
||||
certificate_white_list.sync({success: successCallback, error: errorCallback}, add_students);
|
||||
certificateWhiteList.add({user_name: 'test3', notes: 'test3 notes', new: true});
|
||||
certificateWhiteList.sync({success: successCallback, error: errorCallback}, addStudents);
|
||||
|
||||
var expected = {
|
||||
url: certificate_exception_url + add_students,
|
||||
expected = {
|
||||
url: certificateExceptionUrl + addStudents,
|
||||
postData: [
|
||||
{user_id: '',
|
||||
user_name: 'test3',
|
||||
user_email: '',
|
||||
created: '',
|
||||
notes: 'test3 notes',
|
||||
certificate_generated: '',
|
||||
new: true}
|
||||
user_name: 'test3',
|
||||
user_email: '',
|
||||
created: '',
|
||||
notes: 'test3 notes',
|
||||
certificate_generated: '',
|
||||
new: true}
|
||||
]
|
||||
};
|
||||
AjaxHelpers.expectJsonRequest(requests, 'POST', expected.url, expected.postData);
|
||||
@@ -151,9 +165,9 @@ define([
|
||||
|
||||
describe('edx.certificates.views.certificate_whitelist.CertificateWhiteListView', function() {
|
||||
var view = null,
|
||||
certificate_exception_url = 'test/url/';
|
||||
certificateExceptionUrl = 'test/url/';
|
||||
|
||||
var certificates_exceptions_json = [
|
||||
var certificatesExceptionsJson = [
|
||||
{
|
||||
id: 1,
|
||||
user_id: 1,
|
||||
@@ -175,17 +189,17 @@ define([
|
||||
];
|
||||
|
||||
beforeEach(function() {
|
||||
var fixture;
|
||||
setFixtures();
|
||||
var fixture =
|
||||
readFixtures('templates/instructor/instructor_dashboard_2/certificate-white-list.underscore');
|
||||
fixture = readFixtures('templates/instructor/instructor_dashboard_2/certificate-white-list.underscore');
|
||||
setFixtures("<script type='text/template' id='certificate-white-list-tpl'>" + fixture + '</script>' +
|
||||
"<div class='white-listed-students' id='white-listed-students'></div>");
|
||||
|
||||
this.certificate_white_list = new CertificateWhiteListCollection(certificates_exceptions_json, {
|
||||
this.certificate_white_list = new CertificateWhiteListCollection(certificatesExceptionsJson, {
|
||||
parse: true,
|
||||
canBeEmpty: true,
|
||||
url: certificate_exception_url,
|
||||
generate_certificates_url: certificate_exception_url
|
||||
url: certificateExceptionUrl,
|
||||
generate_certificates_url: certificateExceptionUrl
|
||||
|
||||
});
|
||||
|
||||
@@ -231,10 +245,10 @@ define([
|
||||
{user_name: user, notes: notes, user_email: email}
|
||||
]);
|
||||
|
||||
expect(view.$el.find('table tbody tr td:contains("' + user + '")').parent().html()).
|
||||
toMatch(notes);
|
||||
expect(view.$el.find('table tbody tr td:contains("' + user + '")').parent().html()).
|
||||
toMatch(email);
|
||||
expect(view.$el.find('table tbody tr td:contains("' + user + '")').parent().html())
|
||||
.toMatch(notes);
|
||||
expect(view.$el.find('table tbody tr td:contains("' + user + '")').parent().html())
|
||||
.toMatch(email);
|
||||
});
|
||||
|
||||
it('verifies collection sync is called when "Generate Exception Certificates" is clicked', function() {
|
||||
@@ -248,8 +262,8 @@ define([
|
||||
view.$el.find('#generate-exception-certificates').click();
|
||||
|
||||
expect(view.collection.sync.called).toBe(true);
|
||||
expect(view.collection.sync.calledWith({success: successCallback, error: errorCallback})).
|
||||
toBe(true);
|
||||
expect(view.collection.sync.calledWith({success: successCallback, error: errorCallback}))
|
||||
.toBe(true);
|
||||
});
|
||||
|
||||
it('verifies sync is called with "new/all" argument depending upon selected radio button', function() {
|
||||
@@ -263,24 +277,24 @@ define([
|
||||
view.$el.find('#generate-exception-certificates').click();
|
||||
|
||||
// By default 'Generate a Certificate for all New additions to the Exception list ' is selected
|
||||
expect(view.collection.sync.calledWith({success: successCallback, error: errorCallback}), 'new').
|
||||
toBe(true);
|
||||
expect(view.collection.sync.calledWith({success: successCallback, error: errorCallback}), 'new')
|
||||
.toBe(true);
|
||||
|
||||
// Select 'Generate a Certificate for all users on the Exception list ' option
|
||||
view.$el.find('input:radio[name=generate-exception-certificates-radio][value=all]').click();
|
||||
view.$el.find('#generate-exception-certificates').click();
|
||||
expect(view.collection.sync.calledWith({success: successCallback, error: errorCallback}), 'all').
|
||||
toBe(true);
|
||||
expect(view.collection.sync.calledWith({success: successCallback, error: errorCallback}), 'all')
|
||||
.toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('edx.certificates.views.certificate_whitelist_editor.CertificateWhiteListEditorView', function() {
|
||||
var view = null,
|
||||
list_view = null,
|
||||
certificate_exception_url = 'test/url/';
|
||||
var certificates_exceptions_json = [
|
||||
listView = null,
|
||||
certificateExceptionUrl = 'test/url/';
|
||||
var certificatesExceptionsJson = [
|
||||
{
|
||||
url: certificate_exception_url,
|
||||
url: certificateExceptionUrl,
|
||||
id: 1,
|
||||
user_id: 1,
|
||||
user_name: 'test1',
|
||||
@@ -291,7 +305,7 @@ define([
|
||||
new: true
|
||||
},
|
||||
{
|
||||
url: certificate_exception_url,
|
||||
url: certificateExceptionUrl,
|
||||
id: 2,
|
||||
user_id: 2,
|
||||
user_name: 'test2',
|
||||
@@ -303,41 +317,42 @@ define([
|
||||
];
|
||||
|
||||
beforeEach(function() {
|
||||
var fixture, fixture2, certificateWhiteList;
|
||||
setFixtures();
|
||||
|
||||
var fixture = readFixtures(
|
||||
fixture = readFixtures(
|
||||
'templates/instructor/instructor_dashboard_2/certificate-white-list-editor.underscore'
|
||||
);
|
||||
|
||||
var fixture_2 = readFixtures(
|
||||
fixture2 = readFixtures(
|
||||
'templates/instructor/instructor_dashboard_2/certificate-white-list.underscore'
|
||||
);
|
||||
|
||||
setFixtures(
|
||||
"<script type='text/template' id='certificate-white-list-editor-tpl'>" + fixture + '</script>' +
|
||||
"<script type='text/template' id='certificate-white-list-tpl'>" + fixture_2 + '</script>' +
|
||||
"<script type='text/template' id='certificate-white-list-tpl'>" + fixture2 + '</script>' +
|
||||
"<div id='certificate-white-list-editor'></div>" +
|
||||
"<div class='white-listed-students' id='white-listed-students'></div>"
|
||||
);
|
||||
|
||||
var certificate_white_list = new CertificateWhiteListCollection(certificates_exceptions_json, {
|
||||
certificateWhiteList = new CertificateWhiteListCollection(certificatesExceptionsJson, {
|
||||
parse: true,
|
||||
canBeEmpty: true,
|
||||
url: certificate_exception_url,
|
||||
generate_certificates_url: certificate_exception_url
|
||||
url: certificateExceptionUrl,
|
||||
generate_certificates_url: certificateExceptionUrl
|
||||
});
|
||||
|
||||
view = new CertificateWhiteListEditorView({
|
||||
collection: certificate_white_list,
|
||||
url: certificate_exception_url
|
||||
collection: certificateWhiteList,
|
||||
url: certificateExceptionUrl
|
||||
});
|
||||
view.render();
|
||||
|
||||
list_view = new CertificateWhiteListView({
|
||||
collection: certificate_white_list,
|
||||
listView = new CertificateWhiteListView({
|
||||
collection: certificateWhiteList,
|
||||
certificateWhiteListEditorView: view
|
||||
});
|
||||
list_view.render();
|
||||
listView.render();
|
||||
});
|
||||
|
||||
it('verifies view is initialized and rendered successfully', function() {
|
||||
@@ -348,16 +363,16 @@ define([
|
||||
});
|
||||
|
||||
it('verifies success and error messages', function() {
|
||||
var message_selector = '.message',
|
||||
success_message = 'test_user has been successfully added to the exception list. Click Generate' +
|
||||
var messageSelector = '.message',
|
||||
successMessage = 'test_user has been successfully added to the exception list. Click Generate' +
|
||||
' Exception Certificate below to send the certificate.',
|
||||
requests = AjaxHelpers.requests(this),
|
||||
duplicate_user = 'test_user';
|
||||
duplicateUser = 'test_user';
|
||||
|
||||
var error_messages = {
|
||||
var errorMessages = {
|
||||
empty_user_name_email: 'Student username/email field is required and can not be empty. ' +
|
||||
'Kindly fill in username/email and then press "Add to Exception List" button.',
|
||||
duplicate_user: '<p>' + (duplicate_user) + ' already in exception list.</p>'
|
||||
duplicate_user: '<p>' + (duplicateUser) + ' already in exception list.</p>'
|
||||
};
|
||||
|
||||
// click 'Add Exception' button with empty username/email field
|
||||
@@ -365,10 +380,10 @@ define([
|
||||
view.$el.find('#add-exception').click();
|
||||
|
||||
// Verify error message for missing username/email
|
||||
expect(view.$el.find(message_selector).html()).toMatch(error_messages.empty_user_name_email);
|
||||
expect(view.$el.find(messageSelector).html()).toMatch(errorMessages.empty_user_name_email);
|
||||
|
||||
// Add a new Exception to list
|
||||
view.$el.find('#certificate-exception').val(duplicate_user);
|
||||
view.$el.find('#certificate-exception').val(duplicateUser);
|
||||
view.$el.find('#notes').val('test user notes');
|
||||
view.$el.find('#add-exception').click();
|
||||
|
||||
@@ -377,7 +392,7 @@ define([
|
||||
{
|
||||
id: 3,
|
||||
user_id: 3,
|
||||
user_name: duplicate_user,
|
||||
user_name: duplicateUser,
|
||||
user_email: 'test2@test.com',
|
||||
course_id: 'edX/test/course',
|
||||
created: 'Thursday, October 29, 2015',
|
||||
@@ -386,29 +401,29 @@ define([
|
||||
);
|
||||
|
||||
// Verify success message
|
||||
expect(view.$el.find(message_selector).html()).toMatch(success_message);
|
||||
expect(view.$el.find(messageSelector).html()).toMatch(successMessage);
|
||||
|
||||
// Add a duplicate Certificate Exception
|
||||
view.$el.find('#certificate-exception').val(duplicate_user);
|
||||
view.$el.find('#certificate-exception').val(duplicateUser);
|
||||
view.$el.find('#notes').val('test user notes');
|
||||
view.$el.find('#add-exception').click();
|
||||
|
||||
// Verify success message
|
||||
expect(view.$el.find(message_selector).html()).toEqual(error_messages.duplicate_user);
|
||||
expect(view.$el.find(messageSelector).html()).toEqual(errorMessages.duplicate_user);
|
||||
});
|
||||
|
||||
it('verifies certificate exception can be deleted by clicking "delete" ', function() {
|
||||
var user_name = 'test1',
|
||||
certificate_exception_selector = "div.white-listed-students table tr:contains('" + user_name + "')",
|
||||
delete_btn_selector =
|
||||
certificate_exception_selector + ' td .delete-exception',
|
||||
var username = 'test1',
|
||||
certificateExceptionSelector = "div.white-listed-students table tr:contains('" + username + "')",
|
||||
deleteBtnSelector =
|
||||
certificateExceptionSelector + ' td .delete-exception',
|
||||
requests = AjaxHelpers.requests(this);
|
||||
|
||||
$(delete_btn_selector).click();
|
||||
$(deleteBtnSelector).click();
|
||||
AjaxHelpers.respondWithJson(requests, {});
|
||||
|
||||
// Verify the certificate exception is removed from the list
|
||||
expect($(certificate_exception_selector).length).toBe(0);
|
||||
expect($(certificateExceptionSelector).length).toBe(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
font-weight: $font-bold;
|
||||
color: $black;
|
||||
}
|
||||
|
||||
.dismiss-message {
|
||||
@include float(right);
|
||||
}
|
||||
}
|
||||
|
||||
// Course sidebar
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(function(define) {
|
||||
'use strict';
|
||||
|
||||
define(['gettext', 'jquery', 'underscore', 'backbone', 'js/views/message_banner'],
|
||||
function(gettext, $, _, Backbone, MessageBannerView) {
|
||||
return Backbone.View.extend({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(function(define) {
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'gettext', 'jquery', 'underscore', 'backbone', 'logger', 'moment', 'edx-ui-toolkit/js/utils/html-utils',
|
||||
'common/js/components/views/paging_header', 'common/js/components/views/paging_footer',
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<div class="welcome-message">
|
||||
<div class="dismiss-message">
|
||||
<button type="button" class="btn-link">${_("Dismiss")}</button>
|
||||
</div>
|
||||
This is a useful welcome message!
|
||||
</div>
|
||||
@@ -0,0 +1,20 @@
|
||||
/* globals $ */
|
||||
import 'jquery.cookie';
|
||||
|
||||
export class WelcomeMessage { // eslint-disable-line import/prefer-default-export
|
||||
|
||||
constructor(dismissUrl) {
|
||||
$('.dismiss-message button').click(() => {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: dismissUrl,
|
||||
headers: {
|
||||
'X-CSRFToken': $.cookie('csrftoken'),
|
||||
},
|
||||
success: () => {
|
||||
$('.welcome-message').hide();
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/* globals $, loadFixtures */
|
||||
|
||||
import {
|
||||
expectRequest,
|
||||
requests as mockRequests,
|
||||
respondWithJson,
|
||||
} from 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers';
|
||||
import { WelcomeMessage } from '../WelcomeMessage';
|
||||
|
||||
describe('Welcome Message factory', () => {
|
||||
describe('Ensure button click', () => {
|
||||
const endpointUrl = '/course/course_id/dismiss_message/';
|
||||
|
||||
beforeEach(() => {
|
||||
loadFixtures('course_experience/fixtures/welcome-message-fragment.html');
|
||||
new WelcomeMessage(endpointUrl); // eslint-disable-line no-new
|
||||
});
|
||||
|
||||
it('When button click is made, ajax call is made and message is hidden.', () => {
|
||||
const $message = $('.welcome-message');
|
||||
const requests = mockRequests(this);
|
||||
document.querySelector('.dismiss-message button').dispatchEvent(new Event('click'));
|
||||
expectRequest(
|
||||
requests,
|
||||
'POST',
|
||||
endpointUrl,
|
||||
);
|
||||
respondWithJson(requests);
|
||||
expect($message.attr('style')).toBe('display: none;');
|
||||
requests.restore();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -4,11 +4,21 @@
|
||||
<%namespace name='static' file='../static_content.html'/>
|
||||
|
||||
<%!
|
||||
from openedx.core.djangolib.js_utils import js_escaped_string
|
||||
from django.utils.translation import ugettext as _
|
||||
from openedx.core.djangolib.markup import HTML
|
||||
%>
|
||||
|
||||
<%block name="content">
|
||||
<div class="welcome-message">
|
||||
<div class="dismiss-message">
|
||||
<button type="button" class="btn-link">${_("Dismiss")}</button>
|
||||
</div>
|
||||
|
||||
${HTML(welcome_message_html)}
|
||||
</div>
|
||||
</%block>
|
||||
|
||||
<%static:webpack entry="WelcomeMessage">
|
||||
new WelcomeMessage("${dismiss_url | n, js_escaped_string}");
|
||||
</%static:webpack>
|
||||
|
||||
@@ -89,7 +89,7 @@ class TestCourseHomePage(SharedModuleStoreTestCase):
|
||||
course_home_url(self.course)
|
||||
|
||||
# Fetch the view and verify the query counts
|
||||
with self.assertNumQueries(48):
|
||||
with self.assertNumQueries(49):
|
||||
with check_mongo_calls(5):
|
||||
url = course_home_url(self.course)
|
||||
self.client.get(url)
|
||||
|
||||
@@ -27,6 +27,18 @@ def welcome_message_url(course):
|
||||
)
|
||||
|
||||
|
||||
def dismiss_message_url(course):
|
||||
"""
|
||||
Returns the URL for the dismiss message endpoint.
|
||||
"""
|
||||
return reverse(
|
||||
'openedx.course_experience.dismiss_welcome_message',
|
||||
kwargs={
|
||||
'course_id': unicode(course.id),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class TestWelcomeMessageView(ModuleStoreTestCase):
|
||||
"""
|
||||
Tests for the course welcome message fragment view.
|
||||
@@ -41,10 +53,8 @@ class TestWelcomeMessageView(ModuleStoreTestCase):
|
||||
chapter = ItemFactory.create(category='chapter', parent_location=self.course.location)
|
||||
section = ItemFactory.create(category='sequential', parent_location=chapter.location)
|
||||
ItemFactory.create(category='vertical', parent_location=section.location)
|
||||
|
||||
self.user = UserFactory(password=TEST_PASSWORD)
|
||||
CourseEnrollment.enroll(self.user, self.course.id)
|
||||
|
||||
self.client.login(username=self.user.username, password=TEST_PASSWORD)
|
||||
|
||||
def tearDown(self):
|
||||
@@ -58,6 +68,7 @@ class TestWelcomeMessageView(ModuleStoreTestCase):
|
||||
response = self.client.get(welcome_message_url(self.course))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, 'Second Update')
|
||||
self.assertContains(response, 'Dismiss')
|
||||
|
||||
def test_replace_urls(self):
|
||||
img_url = 'img.png'
|
||||
@@ -72,3 +83,15 @@ class TestWelcomeMessageView(ModuleStoreTestCase):
|
||||
def test_empty_welcome_message(self):
|
||||
response = self.client.get(welcome_message_url(self.course))
|
||||
self.assertEqual(response.status_code, 204)
|
||||
|
||||
def test_dismiss_message(self):
|
||||
create_course_update(self.course, self.user, 'First Update', date='January 1, 2017')
|
||||
|
||||
response = self.client.get(welcome_message_url(self.course))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, 'First Update')
|
||||
|
||||
self.client.post(dismiss_message_url(self.course))
|
||||
response = self.client.get(welcome_message_url(self.course))
|
||||
self.assertNotIn('First Update', response)
|
||||
self.assertEqual(response.status_code, 204)
|
||||
|
||||
@@ -7,8 +7,8 @@ from django.conf.urls import url
|
||||
from views.course_home import CourseHomeFragmentView, CourseHomeView
|
||||
from views.course_outline import CourseOutlineFragmentView
|
||||
from views.course_updates import CourseUpdatesFragmentView, CourseUpdatesView
|
||||
from views.welcome_message import WelcomeMessageFragmentView
|
||||
from views.course_sock import CourseSockFragmentView
|
||||
from views.welcome_message import WelcomeMessageFragmentView, dismiss_welcome_message
|
||||
|
||||
urlpatterns = [
|
||||
url(
|
||||
@@ -46,4 +46,9 @@ urlpatterns = [
|
||||
CourseSockFragmentView.as_view(),
|
||||
name='openedx.course_experience.course_sock_fragment_view',
|
||||
),
|
||||
url(
|
||||
r'^dismiss_welcome_message$',
|
||||
dismiss_welcome_message,
|
||||
name='openedx.course_experience.dismiss_welcome_message',
|
||||
),
|
||||
]
|
||||
|
||||
@@ -2,13 +2,19 @@
|
||||
View logic for handling course welcome messages.
|
||||
"""
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponse, HttpResponseBadRequest
|
||||
from django.template.loader import render_to_string
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from web_fragments.fragment import Fragment
|
||||
|
||||
from course_updates import CourseUpdatesFragmentView
|
||||
from courseware.courses import get_course_info_section_module, get_course_with_access
|
||||
from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
|
||||
from openedx.core.djangoapps.user_api.course_tag.api import set_course_tag, get_course_tag
|
||||
|
||||
PREFERENCE_KEY = 'view-welcome-message'
|
||||
|
||||
|
||||
class WelcomeMessageFragmentView(EdxFragmentView):
|
||||
@@ -27,12 +33,20 @@ class WelcomeMessageFragmentView(EdxFragmentView):
|
||||
if not welcome_message_html:
|
||||
return None
|
||||
|
||||
dismiss_url = reverse(
|
||||
'openedx.course_experience.dismiss_welcome_message', kwargs={'course_id': unicode(course_key)}
|
||||
)
|
||||
|
||||
context = {
|
||||
'dismiss_url': dismiss_url,
|
||||
'welcome_message_html': welcome_message_html,
|
||||
}
|
||||
|
||||
html = render_to_string('course_experience/welcome-message-fragment.html', context)
|
||||
return Fragment(html)
|
||||
if get_course_tag(request.user, course_key, PREFERENCE_KEY) == 'False':
|
||||
return None
|
||||
else:
|
||||
html = render_to_string('course_experience/welcome-message-fragment.html', context)
|
||||
return Fragment(html)
|
||||
|
||||
@classmethod
|
||||
def welcome_message_html(cls, request, course):
|
||||
@@ -51,3 +65,13 @@ class WelcomeMessageFragmentView(EdxFragmentView):
|
||||
content = info_block.system.replace_urls(ordered_updates[0]['content'])
|
||||
|
||||
return content
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
def dismiss_welcome_message(request, course_id):
|
||||
"""
|
||||
Given the course_id in the request, disable displaying the welcome message for the user.
|
||||
"""
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
set_course_tag(request.user, course_key, PREFERENCE_KEY, 'False')
|
||||
return HttpResponse()
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"eslint-config-edx": "^2.0.1",
|
||||
"eslint-config-edx-es5": "^2.0.0",
|
||||
"eslint-import-resolver-webpack": "^0.8.1",
|
||||
"jasmine-core": "^2.4.1",
|
||||
"jasmine-core": "^2.6.4",
|
||||
"jasmine-jquery": "^2.1.1",
|
||||
"karma": "^0.13.22",
|
||||
"karma-chrome-launcher": "^0.2.3",
|
||||
@@ -50,7 +50,7 @@
|
||||
"pa11y": "4.0.1",
|
||||
"pa11y-reporter-json-oldnode": "1.0.0",
|
||||
"plato": "1.2.2",
|
||||
"sinon": "^1.17.7",
|
||||
"sinon": "2.3.5",
|
||||
"squirejs": "^0.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ var wpconfig = {
|
||||
entry: {
|
||||
CourseOutline: './openedx/features/course_experience/static/course_experience/js/CourseOutline.js',
|
||||
CourseSock: './openedx/features/course_experience/static/course_experience/js/CourseSock.js',
|
||||
WelcomeMessage: './openedx/features/course_experience/static/course_experience/js/WelcomeMessage.js',
|
||||
Import: './cms/static/js/features/import/factories/import.js'
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user