Commit 11044ebd by Nimisha Asthagiri

MA-614 Mobile Push Notification Studio UI

parent b124485e
...@@ -45,37 +45,37 @@ def check_no_update(_step, text): ...@@ -45,37 +45,37 @@ def check_no_update(_step, text):
@step(u'I modify the text to "([^"]*)"$') @step(u'I modify the text to "([^"]*)"$')
def modify_update(_step, text): def modify_update(_step, text):
button_css = 'div.post-preview a.edit-button' button_css = 'div.post-preview .edit-button'
world.css_click(button_css) world.css_click(button_css)
change_text(text) change_text(text)
@step(u'I change the update from "([^"]*)" to "([^"]*)"$') @step(u'I change the update from "([^"]*)" to "([^"]*)"$')
def change_existing_update(_step, before, after): def change_existing_update(_step, before, after):
verify_text_in_editor_and_update('div.post-preview a.edit-button', before, after) verify_text_in_editor_and_update('div.post-preview .edit-button', before, after)
@step(u'I change the handout from "([^"]*)" to "([^"]*)"$') @step(u'I change the handout from "([^"]*)" to "([^"]*)"$')
def change_existing_handout(_step, before, after): def change_existing_handout(_step, before, after):
verify_text_in_editor_and_update('div.course-handouts a.edit-button', before, after) verify_text_in_editor_and_update('div.course-handouts .edit-button', before, after)
@step(u'I delete the update$') @step(u'I delete the update$')
def click_button(_step): def click_button(_step):
button_css = 'div.post-preview a.delete-button' button_css = 'div.post-preview .delete-button'
world.css_click(button_css) world.css_click(button_css)
@step(u'I edit the date to "([^"]*)"$') @step(u'I edit the date to "([^"]*)"$')
def change_date(_step, new_date): def change_date(_step, new_date):
button_css = 'div.post-preview a.edit-button' button_css = 'div.post-preview .edit-button'
world.css_click(button_css) world.css_click(button_css)
date_css = 'input.date' date_css = 'input.date'
date = world.css_find(date_css) date = world.css_find(date_css)
for i in range(len(date.value)): for i in range(len(date.value)):
date._element.send_keys(Keys.END, Keys.BACK_SPACE) date._element.send_keys(Keys.END, Keys.BACK_SPACE)
date._element.send_keys(new_date) date._element.send_keys(new_date)
save_css = 'a.save-button' save_css = '.save-button'
world.css_click(save_css) world.css_click(save_css)
...@@ -87,7 +87,7 @@ def check_date(_step, date): ...@@ -87,7 +87,7 @@ def check_date(_step, date):
@step(u'I modify the handout to "([^"]*)"$') @step(u'I modify the handout to "([^"]*)"$')
def edit_handouts(_step, text): def edit_handouts(_step, text):
edit_css = 'div.course-handouts > a.edit-button' edit_css = 'div.course-handouts > .edit-button'
world.css_click(edit_css) world.css_click(edit_css)
change_text(text) change_text(text)
...@@ -114,7 +114,7 @@ def check_handout_error(_step): ...@@ -114,7 +114,7 @@ def check_handout_error(_step):
@step(u'I see handout save button disabled') @step(u'I see handout save button disabled')
def check_handout_error(_step): def check_handout_error(_step):
handout_save_button = 'form.edit-handouts-form a.save-button' handout_save_button = 'form.edit-handouts-form .save-button'
assert world.css_has_class(handout_save_button, 'is-disabled') assert world.css_has_class(handout_save_button, 'is-disabled')
...@@ -125,19 +125,19 @@ def edit_handouts(_step, text): ...@@ -125,19 +125,19 @@ def edit_handouts(_step, text):
@step(u'I see handout save button re-enabled') @step(u'I see handout save button re-enabled')
def check_handout_error(_step): def check_handout_error(_step):
handout_save_button = 'form.edit-handouts-form a.save-button' handout_save_button = 'form.edit-handouts-form .save-button'
assert not world.css_has_class(handout_save_button, 'is-disabled') assert not world.css_has_class(handout_save_button, 'is-disabled')
@step(u'I save handout edit') @step(u'I save handout edit')
def check_handout_error(_step): def check_handout_error(_step):
save_css = 'a.save-button' save_css = '.save-button'
world.css_click(save_css) world.css_click(save_css)
def change_text(text): def change_text(text):
type_in_codemirror(0, text) type_in_codemirror(0, text)
save_css = 'a.save-button' save_css = '.save-button'
world.css_click(save_css) world.css_click(save_css)
......
...@@ -22,7 +22,7 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model ...@@ -22,7 +22,7 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model
delete window.analytics delete window.analytics
delete window.course_location_analytics delete window.course_location_analytics
describe "Course Updates", -> describe "Course Updates without Push notification", ->
courseInfoTemplate = readFixtures('course_info_update.underscore') courseInfoTemplate = readFixtures('course_info_update.underscore')
beforeEach -> beforeEach ->
...@@ -100,7 +100,7 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model ...@@ -100,7 +100,7 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model
else else
modalCover.click() modalCover.click()
it "does not rewrite links on save", -> it "does send expected data on save", ->
requests = AjaxHelpers["requests"](this) requests = AjaxHelpers["requests"](this)
# Create a new update, verifying that the model is created # Create a new update, verifying that the model is created
...@@ -116,9 +116,12 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model ...@@ -116,9 +116,12 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model
@courseInfoEdit.$el.find('.save-button').click() @courseInfoEdit.$el.find('.save-button').click()
expect(model.save).toHaveBeenCalled() expect(model.save).toHaveBeenCalled()
# Verify content sent to server does not have rewritten links. # Verify push_notification_selected is set to false.
contentSaved = JSON.parse(requests[requests.length - 1].requestBody).content requestSent = JSON.parse(requests[requests.length - 1].requestBody)
expect(contentSaved).toEqual('/static/image.jpg') expect(requestSent.push_notification_selected).toEqual(false)
# Verify the link is not rewritten when saved.
expect(requestSent.content).toEqual('/static/image.jpg')
it "does rewrite links for preview", -> it "does rewrite links for preview", ->
# Create a new update. # Create a new update.
...@@ -147,6 +150,41 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model ...@@ -147,6 +150,41 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model
it "does not remove existing course info on click outside modal", -> it "does not remove existing course info on click outside modal", ->
@cancelExistingCourseInfo(false) @cancelExistingCourseInfo(false)
describe "Course Updates WITH Push notification", ->
courseInfoTemplate = readFixtures('course_info_update.underscore')
beforeEach ->
setFixtures($("<script>", {id: "course_info_update-tpl", type: "text/template"}).text(courseInfoTemplate))
appendSetFixtures courseInfoPage
@collection = new CourseUpdateCollection()
@collection.url = 'course_info_update/'
@courseInfoEdit = new CourseInfoUpdateView({
el: $('.course-updates'),
collection: @collection,
base_asset_url : 'base-asset-url/',
push_notification_enabled : true
})
@courseInfoEdit.render()
@event = {preventDefault : () -> 'no op'}
@courseInfoEdit.onNew(@event)
@requests = AjaxHelpers["requests"](this)
it "shows push notification checkbox as selected by default", ->
expect(@courseInfoEdit.$el.find('.toggle-checkbox')).toBeChecked()
it "sends correct default value for push_notification_selected", ->
@courseInfoEdit.$el.find('.save-button').click()
requestSent = JSON.parse(@requests[@requests.length - 1].requestBody)
expect(requestSent.push_notification_selected).toEqual(true)
it "sends correct value for push_notification_selected when it is unselected", ->
# unselect push notification
@courseInfoEdit.$el.find('.toggle-checkbox').attr('checked', false);
@courseInfoEdit.$el.find('.save-button').click()
requestSent = JSON.parse(@requests[@requests.length - 1].requestBody)
expect(requestSent.push_notification_selected).toEqual(false)
describe "Course Handouts", -> describe "Course Handouts", ->
handoutsTemplate = readFixtures('course_info_handouts.underscore') handoutsTemplate = readFixtures('course_info_handouts.underscore')
......
...@@ -3,7 +3,7 @@ define([ ...@@ -3,7 +3,7 @@ define([
'js/models/course_info', 'js/views/course_info_edit' 'js/models/course_info', 'js/views/course_info_edit'
], function($, CourseUpdateCollection, ModuleInfoModel, CourseInfoModel, CourseInfoEditView) { ], function($, CourseUpdateCollection, ModuleInfoModel, CourseInfoModel, CourseInfoEditView) {
'use strict'; 'use strict';
return function (updatesUrl, handoutsLocator, baseAssetUrl) { return function (updatesUrl, handoutsLocator, baseAssetUrl, push_notification_enabled) {
var course_updates = new CourseUpdateCollection(), var course_updates = new CourseUpdateCollection(),
course_handouts, editor; course_handouts, editor;
...@@ -18,7 +18,8 @@ define([ ...@@ -18,7 +18,8 @@ define([
updates : course_updates, updates : course_updates,
base_asset_url : baseAssetUrl, base_asset_url : baseAssetUrl,
handouts : course_handouts handouts : course_handouts
}) }),
push_notification_enabled: push_notification_enabled
}); });
editor.render(); editor.render();
}; };
......
...@@ -3,7 +3,9 @@ define(["backbone", "jquery", "jquery.ui"], function(Backbone, $) { ...@@ -3,7 +3,9 @@ define(["backbone", "jquery", "jquery.ui"], function(Backbone, $) {
var CourseUpdate = Backbone.Model.extend({ var CourseUpdate = Backbone.Model.extend({
defaults: { defaults: {
"date" : $.datepicker.formatDate('MM d, yy', new Date()), "date" : $.datepicker.formatDate('MM d, yy', new Date()),
"content" : "" "content" : "",
"push_notification_enabled": false,
"push_notification_selected" : false
} }
}); });
return CourseUpdate; return CourseUpdate;
......
...@@ -15,7 +15,8 @@ var CourseInfoEdit = BaseView.extend({ ...@@ -15,7 +15,8 @@ var CourseInfoEdit = BaseView.extend({
new CourseInfoUpdateView({ new CourseInfoUpdateView({
el: $('body.updates'), el: $('body.updates'),
collection: this.model.get('updates'), collection: this.model.get('updates'),
base_asset_url: this.model.get('base_asset_url') base_asset_url: this.model.get('base_asset_url'),
push_notification_enabled: this.options.push_notification_enabled
}); });
new CourseInfoHandoutView({ new CourseInfoHandoutView({
......
...@@ -3,6 +3,7 @@ define(["js/views/baseview", "codemirror", "js/models/course_update", ...@@ -3,6 +3,7 @@ define(["js/views/baseview", "codemirror", "js/models/course_update",
function(BaseView, CodeMirror, CourseUpdateModel, PromptView, NotificationView, CourseInfoHelper, ModalUtils) { function(BaseView, CodeMirror, CourseUpdateModel, PromptView, NotificationView, CourseInfoHelper, ModalUtils) {
var CourseInfoUpdateView = BaseView.extend({ var CourseInfoUpdateView = BaseView.extend({
// collection is CourseUpdateCollection // collection is CourseUpdateCollection
events: { events: {
"click .new-update-button" : "onNew", "click .new-update-button" : "onNew",
...@@ -29,7 +30,8 @@ define(["js/views/baseview", "codemirror", "js/models/course_update", ...@@ -29,7 +30,8 @@ define(["js/views/baseview", "codemirror", "js/models/course_update",
try { try {
CourseInfoHelper.changeContentToPreview( CourseInfoHelper.changeContentToPreview(
update, 'content', self.options['base_asset_url']); update, 'content', self.options['base_asset_url']);
var newEle = self.template({ updateModel : update }); // push notification is always disabled for existing updates
var newEle = self.template({ updateModel : update, push_notification_enabled : false });
$(updateEle).append(newEle); $(updateEle).append(newEle);
} catch (e) { } catch (e) {
// ignore // ignore
...@@ -47,7 +49,12 @@ define(["js/views/baseview", "codemirror", "js/models/course_update", ...@@ -47,7 +49,12 @@ define(["js/views/baseview", "codemirror", "js/models/course_update",
var newModel = new CourseUpdateModel(); var newModel = new CourseUpdateModel();
this.collection.add(newModel, {at : 0}); this.collection.add(newModel, {at : 0});
var $newForm = $(this.template({ updateModel : newModel })); var $newForm = $(
this.template({
updateModel : newModel,
push_notification_enabled : this.options.push_notification_enabled
})
);
var updateEle = this.$el.find("#course-update-list"); var updateEle = this.$el.find("#course-update-list");
$(updateEle).prepend($newForm); $(updateEle).prepend($newForm);
...@@ -74,7 +81,11 @@ define(["js/views/baseview", "codemirror", "js/models/course_update", ...@@ -74,7 +81,11 @@ define(["js/views/baseview", "codemirror", "js/models/course_update",
onSave: function(event) { onSave: function(event) {
event.preventDefault(); event.preventDefault();
var targetModel = this.eventModel(event); var targetModel = this.eventModel(event);
targetModel.set({ date : this.dateEntry(event).val(), content : this.$codeMirror.getValue() }); targetModel.set({
date : this.dateEntry(event).val(),
content : this.$codeMirror.getValue(),
push_notification_selected : this.push_notification_selected(event)
});
// push change to display, hide the editor, submit the change // push change to display, hide the editor, submit the change
var saving = new NotificationView.Mini({ var saving = new NotificationView.Mini({
title: gettext('Saving') title: gettext('Saving')
...@@ -196,6 +207,11 @@ define(["js/views/baseview", "codemirror", "js/models/course_update", ...@@ -196,6 +207,11 @@ define(["js/views/baseview", "codemirror", "js/models/course_update",
} }
this.$currentPost.find('form').hide(); this.$currentPost.find('form').hide();
this.$currentPost.find('.CodeMirror').remove(); this.$currentPost.find('.CodeMirror').remove();
// hide the push notification checkbox for subsequent edits to the Post
var push_notification_ele = this.$currentPost.find(".new-update-push-notification");
if (push_notification_ele)
push_notification_ele.hide();
} }
ModalUtils.hideModalCover(this.$modalCover); ModalUtils.hideModalCover(this.$modalCover);
...@@ -222,16 +238,15 @@ define(["js/views/baseview", "codemirror", "js/models/course_update", ...@@ -222,16 +238,15 @@ define(["js/views/baseview", "codemirror", "js/models/course_update",
if (li) return $(li).find(".date").first(); if (li) return $(li).find(".date").first();
}, },
contentEntry: function(event) { push_notification_selected: function(event) {
return $(event.currentTarget).closest("li").find(".new-update-content").first(); var push_notification_checkbox;
}, var li = $(event.currentTarget).closest("li");
if (li) {
dateDisplay: function(event) { push_notification_checkbox = li.find(".new-update-push-notification .toggle-checkbox");
return $(event.currentTarget).closest("li").find("#date-display").first(); if (push_notification_checkbox) {
}, return push_notification_checkbox.is(":checked");
}
contentDisplay: function(event) { }
return $(event.currentTarget).closest("li").find(".update-contents").first();
} }
}); });
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
<%inherit file="base.html" /> <%inherit file="base.html" />
<%def name="online_help_token()"><% return "updates" %></%def> <%def name="online_help_token()"><% return "updates" %></%def>
<%namespace name='static' file='static_content.html'/> <%namespace name='static' file='static_content.html'/>
<%! import json %>
<!-- TODO decode course # from context_course into title --> <!-- TODO decode course # from context_course into title -->
<%block name="title">${_("Course Updates")}</%block> <%block name="title">${_("Course Updates")}</%block>
...@@ -21,7 +22,12 @@ ...@@ -21,7 +22,12 @@
<%block name="requirejs"> <%block name="requirejs">
require(["js/factories/course_info"], function(CourseInfoFactory) { require(["js/factories/course_info"], function(CourseInfoFactory) {
CourseInfoFactory("${updates_url}", "${handouts_locator | escapejs}", "${base_asset_url}"); CourseInfoFactory(
"${updates_url}",
"${handouts_locator | escapejs}",
"${base_asset_url}",
${json.dumps(push_notification_enabled)}
);
}); });
</%block> </%block>
......
...@@ -2,23 +2,29 @@ ...@@ -2,23 +2,29 @@
<!-- FIXME what style should we use for initially hidden? --> <!-- TODO decide whether this should use codemirror --> <!-- FIXME what style should we use for initially hidden? --> <!-- TODO decide whether this should use codemirror -->
<form class="new-update-form"> <form class="new-update-form">
<div class="row"> <div class="row">
<label class="inline-label">Date:</label> <label for="update-date-<%= updateModel.cid %>" class="inline-label">Date:</label>
<!-- TODO replace w/ date widget and actual date (problem is that persisted version is "Month day" not an actual date obj --> <!-- TODO replace w/ date widget and actual date (problem is that persisted version is "Month day" not an actual date obj -->
<input type="text" class="date" value="<%= updateModel.get('date') %>"> <input id="update-date-<%= updateModel.cid %>" type="text" class="date" value="<%= updateModel.get('date') %>">
</div> </div>
<div class="row"> <div class="row">
<textarea class="new-update-content text-editor"><%= updateModel.get('content') %></textarea> <textarea class="new-update-content text-editor"><%= updateModel.get('content') %></textarea>
</div> </div>
<%if (push_notification_enabled) { %>
<div class="row new-update-push-notification">
<input id="update-notification-checkbox-<%= updateModel.cid %>" type="checkbox" class="toggle-checkbox" data-tooltip="<%= gettext('Send push notification to mobile apps') %>" checked />
<label for="update-notification-checkbox-<%= updateModel.cid %>" class="inline-label"><%= gettext('Send notification to mobile apps') %></label>
</div>
<% } %>
<div class="row"> <div class="row">
<!-- cid rather than id b/c new ones have cid's not id's --> <!-- cid rather than id b/c new ones have cid's not id's -->
<a href="#" class="save-button" name="<%= updateModel.cid %>">Save</a> <button class="save-button" name="<%= updateModel.cid %>"><%= gettext('Post') %></button>
<a href="#" class="cancel-button" name="<%= updateModel.cid %>">Cancel</a> <button class="cancel-button" name="<%= updateModel.cid %>"><%= gettext('Cancel') %></button>
</div> </div>
</form> </form>
<div class="post-preview"> <div class="post-preview">
<div class="post-actions"> <div class="post-actions">
<a href="#" class="edit-button" name="<%- updateModel.cid %>"><span class="edit-icon"></span>Edit</a> <button class="edit-button" name="<%= updateModel.cid %>"><span class="edit-icon"></span>Edit</button>
<a href="#" class="delete-button" name="<%- updateModel.cid %>"><span class="delete-icon"></span>Delete</a> <button class="delete-button" name="<%= updateModel.cid %>"><span class="delete-icon"></span>Delete</button>
</div> </div>
<h2> <h2>
<span class="calendar-icon"></span><span class="date-display"><%= <span class="calendar-icon"></span><span class="date-display"><%=
...@@ -26,4 +32,4 @@ ...@@ -26,4 +32,4 @@
</h2> </h2>
<div class="update-contents"><%= updateModel.get('content') %></div> <div class="update-contents"><%= updateModel.get('content') %></div>
</div> </div>
</li> </li>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment