From 72eef72d8b60ed737b06401bd9bdaee42a940e2f Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Fri, 22 Jun 2012 10:50:46 -0400 Subject: [PATCH] Html Module can now be editing, saved, and re-opened --- cms/djangoapps/contentstore/views.py | 11 ++++++ cms/envs/common.py | 14 ++++++- cms/static/.gitignore | 1 - cms/static/coffee/.gitignore | 1 + cms/static/coffee/main.coffee | 8 ++-- cms/static/coffee/unit.coffee | 13 +++++++ cms/static/js/jquery.cookie.js | 47 ++++++++++++++++++++++++ cms/templates/base.html | 1 + cms/urls.py | 1 + common/lib/xmodule/js/module/html.coffee | 9 +++-- 10 files changed, 96 insertions(+), 10 deletions(-) delete mode 100644 cms/static/.gitignore create mode 100644 cms/static/coffee/unit.coffee create mode 100644 cms/static/js/jquery.cookie.js diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py index 1ab78c7c90..8bd55bf60f 100644 --- a/cms/djangoapps/contentstore/views.py +++ b/cms/djangoapps/contentstore/views.py @@ -1,7 +1,11 @@ from mitxmako.shortcuts import render_to_response from keystore.django import keystore +from django_future.csrf import ensure_csrf_cookie +from django.http import HttpResponse +import json +@ensure_csrf_cookie def index(request): # TODO (cpennington): These need to be read in from the active user org = 'mit.edu' @@ -20,3 +24,10 @@ def edit_item(request): 'type': item.type, 'name': item.name, }) + + +def save_item(request): + item_id = request.POST['id'] + data = json.loads(request.POST['data']) + keystore().update_item(item_id, data) + return HttpResponse(json.dumps({})) diff --git a/cms/envs/common.py b/cms/envs/common.py index d5e84c836c..fc721ca820 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -22,6 +22,8 @@ Longer TODO: import sys import tempfile import os.path +import os +import errno from path import path ############################ FEATURE CONFIGURATION ############################# @@ -156,7 +158,15 @@ PIPELINE_CSS = { PIPELINE_ALWAYS_RECOMPILE = ['sass/base-style.scss'] from x_module import XModuleDescriptor -js_file_dir = tempfile.mkdtemp('js', dir=PROJECT_ROOT / "static") +js_file_dir = PROJECT_ROOT / "static" / "coffee" / "module" +try: + os.makedirs(js_file_dir) +except OSError as exc: + if exc.errno == errno.EEXIST: + pass + else: + raise + module_js_sources = [] for xmodule in XModuleDescriptor.load_classes(): js = xmodule.get_javascript() @@ -172,7 +182,7 @@ for xmodule in XModuleDescriptor.load_classes(): PIPELINE_JS = { 'main': { - 'source_filenames': ['coffee/main.coffee'], + 'source_filenames': ['coffee/main.coffee', 'coffee/unit.coffee'], 'output_filename': 'js/main.js', }, 'module-js': { diff --git a/cms/static/.gitignore b/cms/static/.gitignore deleted file mode 100644 index 61e4416e07..0000000000 --- a/cms/static/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tmp*js diff --git a/cms/static/coffee/.gitignore b/cms/static/coffee/.gitignore index a6c7c2852d..bb90193362 100644 --- a/cms/static/coffee/.gitignore +++ b/cms/static/coffee/.gitignore @@ -1 +1,2 @@ *.js +module diff --git a/cms/static/coffee/main.coffee b/cms/static/coffee/main.coffee index b74cd3c7d3..ce7f29cc1e 100644 --- a/cms/static/coffee/main.coffee +++ b/cms/static/coffee/main.coffee @@ -3,16 +3,18 @@ bind_edit_links = -> edit_item($(this).attr('id')) return false -edit_item = (id) -> - $.get('/edit_item', {id: id}, (data) -> +edit_item = (id) => + $.get('/edit_item', {id: id}, (data) => $('#module-html').empty().append(data) bind_edit_links() $('section.edit-pane').show() $('body').addClass('content') - new window[$('#unit-wrapper').attr('class')] 'module-html' + new @Unit('unit-wrapper', id) ) $ -> + $.ajaxSetup + headers : { 'X-CSRFToken': $.cookie 'csrftoken' } $('section.main-content').children().hide() $('.editable').inlineEdit() $('.editable-textarea').inlineEdit({control: 'textarea'}) diff --git a/cms/static/coffee/unit.coffee b/cms/static/coffee/unit.coffee new file mode 100644 index 0000000000..f41bd7f96a --- /dev/null +++ b/cms/static/coffee/unit.coffee @@ -0,0 +1,13 @@ +class @Unit + constructor: (@element_id, @module_id) -> + @module = new window[$("##{@element_id}").attr('class')] 'module-html' + + $("##{@element_id} .save-update").click( (event) => + event.preventDefault() + $.post("save_item", { + id: @module_id + data: JSON.stringify(@module.save()) + }) + + ) + diff --git a/cms/static/js/jquery.cookie.js b/cms/static/js/jquery.cookie.js new file mode 100644 index 0000000000..6d5974a2c5 --- /dev/null +++ b/cms/static/js/jquery.cookie.js @@ -0,0 +1,47 @@ +/*! + * jQuery Cookie Plugin + * https://github.com/carhartl/jquery-cookie + * + * Copyright 2011, Klaus Hartl + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://www.opensource.org/licenses/mit-license.php + * http://www.opensource.org/licenses/GPL-2.0 + */ +(function($) { + $.cookie = function(key, value, options) { + + // key and at least value given, set cookie... + if (arguments.length > 1 && (!/Object/.test(Object.prototype.toString.call(value)) || value === null || value === undefined)) { + options = $.extend({}, options); + + if (value === null || value === undefined) { + options.expires = -1; + } + + if (typeof options.expires === 'number') { + var days = options.expires, t = options.expires = new Date(); + t.setDate(t.getDate() + days); + } + + value = String(value); + + return (document.cookie = [ + encodeURIComponent(key), '=', options.raw ? value : encodeURIComponent(value), + options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE + options.path ? '; path=' + options.path : '', + options.domain ? '; domain=' + options.domain : '', + options.secure ? '; secure' : '' + ].join('')); + } + + // key and possibly options given, get cookie... + options = value || {}; + var decode = options.raw ? function(s) { return s; } : decodeURIComponent; + + var pairs = document.cookie.split('; '); + for (var i = 0, pair; pair = pairs[i] && pairs[i].split('='); i++) { + if (decode(pair[0]) === key) return decode(pair[1] || ''); // IE saves cookies with empty string as "c; ", e.g. without "=" as opposed to EOMB, thus pair[1] may be undefined + } + return null; + }; +})(jQuery); diff --git a/cms/templates/base.html b/cms/templates/base.html index 3d35f513ab..12df2b7a28 100644 --- a/cms/templates/base.html +++ b/cms/templates/base.html @@ -34,6 +34,7 @@ <%static:js group='module-js'/> + diff --git a/cms/urls.py b/cms/urls.py index dad9528387..d7314aafae 100644 --- a/cms/urls.py +++ b/cms/urls.py @@ -7,4 +7,5 @@ from django.conf.urls.defaults import patterns, url urlpatterns = patterns('', url(r'^$', 'contentstore.views.index', name='index'), url(r'^edit_item$', 'contentstore.views.edit_item', name='edit_item'), + url(r'^save_item$', 'contentstore.views.save_item', name='save_item'), ) diff --git a/common/lib/xmodule/js/module/html.coffee b/common/lib/xmodule/js/module/html.coffee index e2cba2320c..5e072c27a3 100644 --- a/common/lib/xmodule/js/module/html.coffee +++ b/common/lib/xmodule/js/module/html.coffee @@ -1,8 +1,9 @@ class @HTML constructor: (@id) -> - id = @id - $("##{id} .edit-box").on('input', -> - $("##{id} .preview").empty().append($(this).val()) + @edit_box = $("##{@id} .edit-box") + @preview = $("##{@id} .preview") + @edit_box.on('input', => + @preview.empty().append(@edit_box.val()) ) - save: -> $("##{@id} .edit-box").val() + save: -> {text: @edit_box.val()}