<commit_before><%inherit file="base.html" />
<%namespace name='static' file='static_content.html'/>
<%! import json %>

<%block name="title">Textbooks</%block>
<%block name="bodyclass">is-signedin course textbooks</%block>

<%block name="header_extras">
  <script type="text/template" id="new-textbook-tpl">
    <%static:include path="js/textbook-edit.underscore" />
  </script>
  <script type="text/template" id="show-textbook-tpl">
    <%static:include path="js/textbook-show.underscore" />
  </script>
  <script type="text/template" id="new-chapter-tpl">
    <%static:include path="js/chapter.underscore" />
  </script>
  <script type="text/template" id="no-textbooks-tpl">
    <%static:include path="js/no-textbooks.underscore" />
  </script>
  <script type="text/template" id="upload-dialog-tpl">
    <%static:include path="js/upload-dialog.underscore" />
  </script>
</%block>

<%block name="jsextra">
<script type="text/javascript">
window.UPLOAD_ASSET_CALLBACK_URL = "${upload_asset_callback_url}"
window.ASSET_INDEX_URL = "${asset_index_url}"

CMS.Models.Textbook = Backbone.Model.extend({
    defaults: {
        name: "",
        showChapters: false
    },
    initialize: function() {
        this.chapters = new CMS.Collections.ChapterSet;
        this.chapters.add([{}]);
    },
    isEmpty: function() {
        return !this.get('name');
    }
})
CMS.Views.TextbookShow = Backbone.View.extend({
    initialize: function() {
        this.template = _.template($("#show-textbook-tpl").text());
        this.listenTo(this.model, "change", this.render);
    },
    events: {
        "click .edit": "editTextbook",
        "click .delete": "removeSelf",
        "click .show-chapters": "showChapters",
        "click .hide-chapters": "hideChapters"
    },
    render: function() {
        var attrs = $.extend({}, this.model.attributes);
        attrs.chapters = this.model.chapters;
        this.$el.html(this.template(attrs));
        return this;
    },
    editTextbook: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        this.model.collection.trigger("editOne", this.model);
    },
    removeSelf: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        this.model.collection.remove(this.model);
    },
    showChapters: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        this.model.set('showChapters', true);
    },
    hideChapters: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        this.model.set('showChapters', false);
    }
})
CMS.Views.TextbookEdit = Backbone.View.extend({
    initialize: function() {
        this.template = _.template($("#new-textbook-tpl").text());
        this.listenTo(this.model.chapters, "add", this.addOne);
        this.listenTo(this.model.chapters, "reset", this.addAll);
        this.listenTo(this.model.chapters, "all", this.render);
        this.listenTo(this.model.collection, "editOne", this.remove);
    },
    tagName: "form",
    className: "edit-textbook",
    id: "edit_textbook_form",
    render: function() {
        this.$el.html(this.template({
            name: this.model.escape('name'),
            errors: null
        }));
        this.addAll();
        return this;
    },
    events: {
        "submit": "saveAndClose",
        "click .action-cancel": "cancel",
        "click .action-add-chapter": "createChapter"
    },
    addOne: function(chapter) {
        var view = new CMS.Views.ChapterEdit({model: chapter});
        this.$("ol.chapters").append(view.render().el)
        return this;
    },
    addAll: function() {
        this.model.chapters.each(this.addOne, this);
    },
    createChapter: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        this.save();
        this.model.chapters.add([{}])
    },
    save: function() {
        var name = this.$("#textbook-name-input").val();
        var textbook = this.model;
        textbook.set("name", name);
        _.each(this.$("li"), function(li, i) {
            var chapter = textbook.chapters.at(i);
            chapter.set({
                "name": $(".chapter-name", li).val(),
                "asset_path": $(".chapter-asset-path", li).val()
            })
        });
        return this;
    },
    saveAndClose: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        return this.save().close();
    },
    cancel: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        return this.close();
    },
    close: function() {
        var textbooks = this.model.collection;
        delete textbooks.editing;
        this.remove();
        // if the textbook has no content, remove it from the collection
        var chapterIsEmpty = function(chapter) { return chapter.isEmpty(); }
        if(this.model.isEmpty() && this.model.chapters.every(chapterIsEmpty)) {
            textbooks.remove(this.model);
        }
        textbooks.trigger('render');
        return this;
    }
})
CMS.Collections.TextbookSet = Backbone.Collection.extend({
    model: CMS.Models.Textbook,
    url: ASSET_INDEX_URL,
    initialize: function() {
        this.listenTo(this, "editOne", this.editOne);
    },
    editOne: function(textbook) {
        this.editing = textbook;
    }
})
CMS.Views.ListTextbooks = Backbone.View.extend({
    initialize: function() {
        this.emptyTemplate = _.template($("#no-textbooks-tpl").text());
        this.listenTo(this.collection, 'all', this.render);
    },
    tagName: "ul",
    className: "textbooks",
    render: function() {
        var textbooks = this.collection;
        if(textbooks.length === 0) {
            this.$el.html(this.emptyTemplate());
        } else {
            var $el = this.$el;
            $el.empty();
            textbooks.each(function(textbook) {
                var view;
                if (textbook === textbooks.editing) {
                    view = new CMS.Views.TextbookEdit({model: textbook});
                } else {
                    view = new CMS.Views.TextbookShow({model: textbook});
                }
                $el.append(view.render().el);
            })
        }
        return this;
    },
    events: {
        "click .new-button": "addOne"
    },
    addOne: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        var m = new this.collection.model;
        this.collection.add(m);
        this.collection.trigger("editOne", m);
    }
})
CMS.Models.Chapter = Backbone.Model.extend({
    defaults: function() {
        return {
            name: "",
            asset_path: "",
            order: this.collection ? this.collection.nextOrder() : 1
        }
    },
    isEmpty: function() {
        return !this.get('name') && !this.get('asset_path');
    }
})
CMS.Collections.ChapterSet = Backbone.Collection.extend({
    model: CMS.Models.Chapter,
    comparator: "order",
    nextOrder: function() {
        if(!this.length) return 1;
        return this.last().get('order') + 1;
    }
})
CMS.Views.ChapterEdit = Backbone.View.extend({
    initialize: function() {
        this.template = _.template($("#new-chapter-tpl").text());
        this.listenTo(this.model, "change", this.render);
    },
    tagName: "li",
    className: function() {
        return "field-group chapter chapter" + this.model.get('order');
    },
    render: function() {
        this.$el.html(this.template({
            name: this.model.escape('name'),
            asset_path: this.model.escape('asset_path'),
            order: this.model.get('order')
        }));
        return this;
    },
    events: {
        "click .action-close": "removeChapter",<commit_msg>Integrated PDF textbooks with Backbone Associations<commit_after><%inherit file="base.html" />
<%namespace name='static' file='static_content.html'/>
<%! import json %>

<%block name="title">Textbooks</%block>
<%block name="bodyclass">is-signedin course textbooks</%block>

<%block name="header_extras">
  <script type="text/template" id="new-textbook-tpl">
    <%static:include path="js/textbook-edit.underscore" />
  </script>
  <script type="text/template" id="show-textbook-tpl">
    <%static:include path="js/textbook-show.underscore" />
  </script>
  <script type="text/template" id="new-chapter-tpl">
    <%static:include path="js/chapter.underscore" />
  </script>
  <script type="text/template" id="no-textbooks-tpl">
    <%static:include path="js/no-textbooks.underscore" />
  </script>
  <script type="text/template" id="upload-dialog-tpl">
    <%static:include path="js/upload-dialog.underscore" />
  </script>
</%block>

<%block name="jsextra">
<script type="text/javascript" src="${static.url('js/vendor/backbone-associations-min.js')}"></script>
<script type="text/javascript">
window.UPLOAD_ASSET_CALLBACK_URL = "${upload_asset_callback_url}"
window.ASSET_INDEX_URL = "${asset_index_url}"

CMS.Models.Textbook = Backbone.AssociatedModel.extend({
    defaults: function() {
        return {
            name: "",
            chapters: new CMS.Collections.ChapterSet([{}]),
            showChapters: false
        };
    },
    relations: [{
        type: Backbone.Many,
        key: "chapters",
        relatedModel: "CMS.Models.Chapter",
        collectionType: "CMS.Collections.ChapterSet"
    }],
    isEmpty: function() {
        return !this.get('name') && this.get('chapters').isEmpty();
    }
})
CMS.Views.TextbookShow = Backbone.View.extend({
    initialize: function() {
        this.template = _.template($("#show-textbook-tpl").text());
        this.listenTo(this.model, "change", this.render);
    },
    events: {
        "click .edit": "editTextbook",
        "click .delete": "removeSelf",
        "click .show-chapters": "showChapters",
        "click .hide-chapters": "hideChapters"
    },
    render: function() {
        var attrs = $.extend({}, this.model.attributes);
        attrs.chapters = this.model.chapters;
        this.$el.html(this.template(attrs));
        return this;
    },
    editTextbook: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        this.model.collection.trigger("editOne", this.model);
    },
    removeSelf: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        this.model.collection.remove(this.model);
    },
    showChapters: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        this.model.set('showChapters', true);
    },
    hideChapters: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        this.model.set('showChapters', false);
    }
})
CMS.Views.TextbookEdit = Backbone.View.extend({
    initialize: function() {
        this.template = _.template($("#new-textbook-tpl").text());
        this.listenTo(this.model.chapters, "add", this.addOne);
        this.listenTo(this.model.chapters, "reset", this.addAll);
        this.listenTo(this.model.chapters, "all", this.render);
        this.listenTo(this.model.collection, "editOne", this.remove);
    },
    tagName: "form",
    className: "edit-textbook",
    id: "edit_textbook_form",
    render: function() {
        this.$el.html(this.template({
            name: this.model.escape('name'),
            errors: null
        }));
        this.addAll();
        return this;
    },
    events: {
        "submit": "saveAndClose",
        "click .action-cancel": "cancel",
        "click .action-add-chapter": "createChapter"
    },
    addOne: function(chapter) {
        var view = new CMS.Views.ChapterEdit({model: chapter});
        this.$("ol.chapters").append(view.render().el)
        return this;
    },
    addAll: function() {
        this.model.chapters.each(this.addOne, this);
    },
    createChapter: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        this.save();
        this.model.chapters.add([{}])
    },
    save: function() {
        var name = this.$("#textbook-name-input").val();
        var textbook = this.model;
        textbook.set("name", name);
        _.each(this.$("li"), function(li, i) {
            var chapter = textbook.chapters.at(i);
            chapter.set({
                "name": $(".chapter-name", li).val(),
                "asset_path": $(".chapter-asset-path", li).val()
            })
        });
        return this;
    },
    saveAndClose: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        return this.save().close();
    },
    cancel: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        return this.close();
    },
    close: function() {
        var textbooks = this.model.collection;
        delete textbooks.editing;
        this.remove();
        // if the textbook has no content, remove it from the collection
        if(this.model.isEmpty()) {
            textbooks.remove(this.model);
        }
        textbooks.trigger('render');
        return this;
    }
})
CMS.Collections.TextbookSet = Backbone.Collection.extend({
    model: CMS.Models.Textbook,
    url: ASSET_INDEX_URL,
    initialize: function() {
        this.listenTo(this, "editOne", this.editOne);
    },
    editOne: function(textbook) {
        this.editing = textbook;
    }
})
CMS.Views.ListTextbooks = Backbone.View.extend({
    initialize: function() {
        this.emptyTemplate = _.template($("#no-textbooks-tpl").text());
        this.listenTo(this.collection, 'all', this.render);
    },
    tagName: "ul",
    className: "textbooks",
    render: function() {
        var textbooks = this.collection;
        if(textbooks.length === 0) {
            this.$el.html(this.emptyTemplate());
        } else {
            var $el = this.$el;
            $el.empty();
            textbooks.each(function(textbook) {
                var view;
                if (textbook === textbooks.editing) {
                    view = new CMS.Views.TextbookEdit({model: textbook});
                } else {
                    view = new CMS.Views.TextbookShow({model: textbook});
                }
                $el.append(view.render().el);
            })
        }
        return this;
    },
    events: {
        "click .new-button": "addOne"
    },
    addOne: function(e) {
        if(e && e.preventDefault) { e.preventDefault(); }
        var m = new this.collection.model;
        this.collection.add(m);
        this.collection.trigger("editOne", m);
    }
})
CMS.Models.Chapter = Backbone.AssociatedModel.extend({
    defaults: function() {
        return {
            name: "",
            asset_path: "",
            order: this.collection ? this.collection.nextOrder() : 1
        }
    },
    isEmpty: function() {
        return !this.get('name') && !this.get('asset_path');
    }
})
CMS.Collections.ChapterSet = Backbone.Collection.extend({
    model: CMS.Models.Chapter,
    comparator: "order",
    nextOrder: function() {
        if(!this.length) return 1;
        return this.last().get('order') + 1;
    },
    isEmpty: function() {
        return this.length === 0 || this.every(function(m) { return m.isEmpty(); });
    }
})
CMS.Views.ChapterEdit = Backbone.View.extend({
    initialize: function() {
        this.template = _.template($("#new-chapter-tpl").text());
        this.listenTo(this.model, "change", this.render);
    },
    tagName: "li",
    className: function() {
        return "field-group chapter chapter" + this.model.get('order');
    },
    render: function() {
        this.$el.html(this.template({
            name: this.model.escape('name'),
            asset_path: this.model.escape('asset_path'),
            order: this.model.get('order')
        }));
        return this;
    },
    events: {
        "click .action-close": "removeChapter",
{'fraction_non_alphanumeric': 0.16823739174732552, 'fraction_numerical': 0.0005731023942944473, 'mean_word_length': 2.4119052791657616, 'pattern_counts': {'":': 22, '<': 57, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2333532', 'n_tokens_mistral': 4859, 'n_tokens_neox': 4754, 'n_words': 820}