diff --git a/cms/djangoapps/contentstore/course_info_model.py b/cms/djangoapps/contentstore/course_info_model.py index b2ee3bf9c8..3c107f4cd3 100644 --- a/cms/djangoapps/contentstore/course_info_model.py +++ b/cms/djangoapps/contentstore/course_info_model.py @@ -30,20 +30,21 @@ def get_course_updates(location): # Confirm that root is
    , iterate over
  1. , pull out

    subs and then rest of val course_upd_collection = [] if course_html_parsed.tag == 'ol': - # 0 is the oldest so that new ones get unique idx - for idx, update in enumerate(course_html_parsed.iter("li")): + # 0 is the newest + for idx, update in enumerate(course_html_parsed): if (len(update) == 0): continue elif (len(update) == 1): - content = update.find("h2").tail + # could enforce that update[0].tag == 'h2' + content = update[0].tail else: content = etree.tostring(update[1]) - course_upd_collection.append({"id" : location_base + "/" + str(idx), + # make the id on the client be 1..len w/ 1 being the oldest and len being the newest + course_upd_collection.append({"id" : location_base + "/" + str(len(course_html_parsed) - idx), "date" : update.findtext("h2"), "content" : content}) - # return newest to oldest - course_upd_collection.reverse() + return course_upd_collection def update_course_updates(location, update, passed_id=None): @@ -72,7 +73,9 @@ def update_course_updates(location, update, passed_id=None): if course_html_parsed.tag == 'ol': # ??? Should this use the id in the json or in the url or does it matter? if passed_id: - element = course_html_parsed.findall("li")[get_idx(passed_id)] + idx = get_idx(passed_id) + # idx is count from end of list + element = course_html_parsed[-idx] element[0].text = update['date'] if (len(element) == 1): if new_html_parsed is not None: @@ -87,15 +90,17 @@ def update_course_updates(location, update, passed_id=None): element.pop(1) element[0].tail = update['content'] else: - idx = len(course_html_parsed.findall("li")) - passed_id = course_updates.location.url() + "/" + str(idx) - element = etree.SubElement(course_html_parsed, "li") + element = etree.Element("li") + course_html_parsed.insert(0, element) date_element = etree.SubElement(element, "h2") date_element.text = update['date'] if new_html_parsed is not None: element.append(new_html_parsed) else: date_element.tail = update['content'] + + idx = len(course_html_parsed) + passed_id = course_updates.location.url() + "/" + str(idx) # update db record course_updates.definition['data'] = etree.tostring(course_html_parsed) @@ -127,9 +132,11 @@ def delete_course_update(location, update, passed_id): if course_html_parsed.tag == 'ol': # ??? Should this use the id in the json or in the url or does it matter? - element_to_delete = course_html_parsed.xpath('/ol/li[position()=' + str(get_idx(passed_id) + 1) + "]") + idx = get_idx(passed_id) + # idx is count from end of list + element_to_delete = course_html_parsed[-idx] if element_to_delete: - course_html_parsed.remove(element_to_delete[0]) + course_html_parsed.remove(element_to_delete) # update db record course_updates.definition['data'] = etree.tostring(course_html_parsed) @@ -143,6 +150,6 @@ def get_idx(passed_id): From the url w/ idx appended, get the idx. """ # TODO compile this regex into a class static and reuse for each call - idx_matcher = re.search(r'.*/(\d)+$', passed_id) + idx_matcher = re.search(r'.*/(\d+)$', passed_id) if idx_matcher: return int(idx_matcher.group(1)) \ No newline at end of file diff --git a/cms/static/js/models/course_relative.js b/cms/static/js/models/course_relative.js index 56111cc1c8..99bb1c6d77 100644 --- a/cms/static/js/models/course_relative.js +++ b/cms/static/js/models/course_relative.js @@ -34,10 +34,10 @@ CMS.Models.Location = Backbone.Model.extend({ this._fieldPattern.lastIndex = this._tagPattern.lastIndex + 1; // skip over the colon return { tag: foundTag[0], - org: this._fieldPattern.exec(payload)[0], - course: this._fieldPattern.exec(payload)[0], - category: this._fieldPattern.exec(payload)[0], - name: this._fieldPattern.exec(payload)[0] + org: this.getNextField(payload), + course: this.getNextField(payload), + category: this.getNextField(payload), + name: this.getNextField(payload) } } else return null; @@ -45,6 +45,14 @@ CMS.Models.Location = Backbone.Model.extend({ else { return payload; } + }, + getNextField : function(payload) { + try { + return this._fieldPattern.exec(payload)[0]; + } + catch (err) { + return ""; + } } }); diff --git a/cms/static/js/views/settings/main_settings_view.js b/cms/static/js/views/settings/main_settings_view.js index e8b19c85ff..3ff5d97cce 100644 --- a/cms/static/js/views/settings/main_settings_view.js +++ b/cms/static/js/views/settings/main_settings_view.js @@ -331,7 +331,7 @@ CMS.Views.Settings.Grading = CMS.Views.ValidatingView.extend({ // instantiates an editor template for each update in the collection // Because this calls render, put it after everything which render may depend upon to prevent race condition. - window.templateLoader.loadRemoteTemplate("course_info_update", + window.templateLoader.loadRemoteTemplate("course_grade_policy", "/static/client_templates/course_grade_policy.html", function (raw_template) { self.template = _.template(raw_template);