From 8ca10a835644fc4fa06da6c0b786b63169009f19 Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Fri, 28 Sep 2012 23:27:41 -0400 Subject: [PATCH] Separate unit page from vertical implementation for editing --- cms/djangoapps/contentstore/views.py | 80 ++++++----- cms/static/coffee/src/models/module.coffee | 6 - .../coffee/src/views/module_edit.coffee | 56 ++++---- cms/static/js/base.js | 79 ++--------- cms/static/sass/_base.scss | 132 +++++++++--------- cms/templates/component.html | 12 ++ cms/templates/unit.html | 43 +++++- cms/urls.py | 2 +- common/static/coffee/src/xmodule.coffee | 4 +- common/templates/xmodule_edit.html | 17 +-- 10 files changed, 196 insertions(+), 235 deletions(-) create mode 100644 cms/templates/component.html diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py index ade2ac8028..7ff13fea96 100644 --- a/cms/djangoapps/contentstore/views.py +++ b/cms/djangoapps/contentstore/views.py @@ -43,6 +43,9 @@ from cache_toolbox.core import set_cached_content, get_cached_content, del_cache log = logging.getLogger(__name__) +COMPONENT_TYPES = ['customtag', 'discussion', 'html', 'problem', 'video'] + + # ==== Public views ================================================== @ensure_csrf_cookie @@ -142,11 +145,49 @@ def edit_unit(request, location): else: lms_link = None +<<<<<<< HEAD return render_to_response('unit.html', { 'module': item, 'editable_preview': get_module_previews(request, item)[0], }) +======= + component_templates = defaultdict(list) +>>>>>>> Separate unit page from vertical implementation for editing + + templates = modulestore().get_items(Location('i4x', 'edx', 'templates')) + for template in templates: + if template.location.category in COMPONENT_TYPES: + component_templates[template.location.category].append(( + template.display_name, + template.location.url(), + )) + + components = [ + component.location.url() + for component + in item.get_children() + ] + + return render_to_response('unit.html', { + 'unit_name': item.display_name, + 'components': components, + 'component_templates': component_templates, + }) + + +@login_required +def preview_component(request, location): + # TODO (vshnayder): change name from id to location in coffee+html as well. + if not has_access(request.user, location): + raise Http404 # TODO (vshnayder): better error + + component = modulestore().get_item(location) + + return render_to_response('component.html', { + 'preview': get_module_previews(request, component)[0], + 'editor': wrap_xmodule(component.get_html, component, 'xmodule_edit.html')(), + }) @login_required @@ -154,33 +195,6 @@ def delete_unit(request, location): pass -@login_required -def new_item(request): - """ - Display a page where the user can create a new item from a template - - Expects a GET request with the parameter 'parent_location', which is the element to add - the newly created item to as a child. - - parent_location: A Location URL - """ - - parent_location = request.GET['parent_location'] - if not has_access(request.user, parent_location): - raise Http404 - - parent = modulestore().get_item(parent_location) - templates = modulestore().get_items(Location('i4x', 'edx', 'templates')) - - templates.sort(key=attrgetter('location.category', 'display_name')) - - return render_to_response('new_item.html', { - 'parent_name': parent.display_name, - 'parent_location': parent.location.url(), - 'templates': groupby(templates, attrgetter('location.category')), - }) - - def user_author_string(user): '''Get an author string for commits by this user. Format: first last . @@ -321,20 +335,10 @@ def load_preview_module(request, preview_id, descriptor, instance_state, shared_ error_msg=exc_info_to_str(sys.exc_info()) ).xmodule_constructor(system)(None, None) - module.get_html = wrap_xmodule( module.get_html, module, - "xmodule_edit.html", - { - 'location': descriptor.location.url(), - 'editor_content': descriptor.get_html(), - 'editor_type': descriptor.js_module_name, - 'editor_class': descriptor.__class__.__name__, - # TODO (cpennington): Make descriptors know if they have data that can be editng - 'editable_data': descriptor.definition.get('data'), - 'editable_class': 'editable' if descriptor.definition.get('data') else '', - } + "xmodule_display.html", ) module.get_html = replace_static_urls( module.get_html, diff --git a/cms/static/coffee/src/models/module.coffee b/cms/static/coffee/src/models/module.coffee index 6e5c8ac785..41bd3f4b7d 100644 --- a/cms/static/coffee/src/models/module.coffee +++ b/cms/static/coffee/src/models/module.coffee @@ -4,9 +4,3 @@ class CMS.Models.Module extends Backbone.Model data: '' children: '' metadata: {} - - initialize: (attributes) -> - @module = attributes.module - @unset('module') - delete attributes.module - super(attributes) diff --git a/cms/static/coffee/src/views/module_edit.coffee b/cms/static/coffee/src/views/module_edit.coffee index 6fc6d8d32a..b36a099aa3 100644 --- a/cms/static/coffee/src/views/module_edit.coffee +++ b/cms/static/coffee/src/views/module_edit.coffee @@ -1,24 +1,22 @@ class CMS.Views.ModuleEdit extends Backbone.View - tagName: 'div' - className: 'xmodule_edit' + tagName: 'li' + className: 'component' + + events: + "click .component-editor .cancel-button": 'clickCancelButton' + "click .component-editor .save-button": 'clickSaveButton' + "click .component-actions .edit-button": 'clickEditButton' + initialize: -> @module = @options.module - @module.onUpdate(@save) + @render() - @setEvents() + $component_editor: => @$el.find('.component-editor') - $component_editor: -> @$el.find('.component-editor') - - setEvents: -> - id = @$el.data('id') - - @events = {} - @events["click .component-editor[data-id=#{ id }] .cancel-button"] = 'clickCancelButton' - @events["click .component-editor[data-id=#{ id }] .save-button"] = 'clickSaveButton' - @events["click .component-actions[data-id=#{ id }] .edit-button"] = 'clickEditButton' - - @delegateEvents() + loadModules: -> + @module = XModule.loadModule(@$el.find('.xmodule_edit')) + XModule.loadModule(@$el.find('.xmodule_display')) metadata: -> # cdodge: package up metadata which is separated into a number of input fields @@ -32,30 +30,26 @@ class CMS.Views.ModuleEdit extends Backbone.View # build up a object to pass back to the server on the subsequent POST _metadata[$(el).data("metadata-name")] = el.value for el in $('[data-metadata-name]', $metadata) - _metadata + return _metadata - save: (data) => - @model.unset('preview') - @model.set(data) - @model.save().done( (resp) => - alert("Your changes have been saved.") - - $preview = $(resp.preview) - @$el.replaceWith($preview) - @setElement($preview) - @module.constructor(@$el) - XModule.loadModules(@$el) - - ).fail( -> - alert("There was an error saving your changes. Please try again.") + render: -> + @$el.load("/preview_component/#{@model.id}", => + @loadModules() + @delegateEvents() ) clickSaveButton: (event) => event.preventDefault() data = @module.save() data.metadata = @metadata() + @model.save(data).done( => + alert("Your changes have been saved.") - @save(data) + @render() + @$el.removeClass('editing') + ).fail( -> + alert("There was an error saving your changes. Please try again.") + ) clickCancelButton: (event) -> event.preventDefault() diff --git a/cms/static/js/base.js b/cms/static/js/base.js index 78b61fff0f..006891be5b 100644 --- a/cms/static/js/base.js +++ b/cms/static/js/base.js @@ -10,32 +10,23 @@ $(document).ready(function() { $modal = $('.history-modal'); $modalCover = $('.modal-cover'); $newComponentItem = $('.new-component-item'); - $newComponentStep1 = $('.new-component-step-1'); - $newComponentStep2 = $('.new-component-step-2'); + $newComponentChooser = $('.new-component'); $newComponentButton = $('.new-component-button'); - $(document).bind('XModule.loaded.edit', function(e, element, module) { - var previewType = $(element).data('preview-type'); - var moduleType = $(element).data('type'); + $('li.component').each(function(idx, element) { new CMS.Views.ModuleEdit({ el: element, - module: module, model: new CMS.Models.Module({ id: $(element).data('id'), - type: moduleType == 'None' ? null : moduleType, - previewType: previewType == 'None' ? null : previewType, }) }); }); - XModule.loadModules() $('.expand-collapse-icon').bind('click', toggleSubmodules); $('.visibility-options').bind('change', setVisibility); $newComponentButton.bind('click', showNewComponentForm); - $newComponentStep1.find('.new-component-type a').bind('click', showNewComponentProperties); - $newComponentStep2.find('.save-button').bind('click', saveNewComponent); - $newComponentStep2.find('.cancel-button').bind('click', cancelNewComponent); + $newComponentChooser.find('.new-component-type a').bind('click', showComponentTemplates); $('.unit-history ol a').bind('click', showHistoryModal); $modal.bind('click', hideHistoryModal); @@ -64,70 +55,18 @@ function closeComponentEditor(e) { } function showNewComponentForm(e) { - e.preventDefault(); + e.preventDefault(); $newComponentItem.addClass('adding'); $(this).slideUp(150); - $newComponentStep1.slideDown(150); + $newComponentChooser.slideDown(150); } -function showNewComponentProperties(e) { +function showComponentTemplates(e) { e.preventDefault(); - var displayName; - var componentSource; - var selectionRange; - var $renderedComponent; - - switch($(this).attr('data-type')) { - case 'video': - displayName = 'Video'; - componentSource = '