*.pyc
*.swp
+*.swo
mkwsxb_xblock.egg-info/
--- /dev/null
+settings/static/settings.js
--- /dev/null
+from .mkwsbiblio import MKWSBiblio
--- /dev/null
+"""Embed bibliographic widget from MKWS, the MasterKey Widget Set"""
+
+import pkg_resources
+import random
+
+from xblock.core import XBlock
+from xblock.fields import Integer, Scope, String, Any, Boolean, Dict
+from xblock.fragment import Fragment
+
+class MKWSBiblio(XBlock):
+ """Embed bibliographic widget from MKWS, the MasterKey Widget Set"""
+
+ # Fields
+ query = String(
+ help="Search query",
+ default="water",
+ scope=Scope.content
+ )
+ display_name = String(
+ default="MKWS bibliographic details",
+ scope=Scope.settings
+ )
+
+ def resource_string(self, path):
+ """Helper for accessing resources."""
+ data = pkg_resources.resource_string(__name__, path)
+ return data.decode("utf8")
+
+ def student_view(self, context=None):
+ """The primary view of the MKWS XBlock, shown to students when viewing courses."""
+ html = self.resource_string("static/html/student.html")
+ frag = Fragment(html.format(query=self.query, team=random.randint(0, 100000)))
+ # student.js uses require.js as it cannot guarantee mkws-complete.js has loaded
+ # in studio without it. We'll need to add it if we're in the LMS:
+ frag.add_javascript_url("/static/js/vendor/require.js");
+ # frag.add_resource_url("//mkws.indexdata.com/mkws-complete", "text/javascript", "head");
+ # frag.add_resource('<script src="//mkws.indexdata.com/mkws-complete.js"></script>', "text/html", "head");
+ frag.add_javascript(self.resource_string("static/js/src/student.js"))
+ frag.initialize_js('MKWSBiblio')
+ return frag;
+
+ def author_view(self, context=None):
+ """The primary view of the MKWS XBlock, shown when authoring courses."""
+ # This should closely mirror the student_view. Here all we do is not include
+ # require.js as it's already in Studio and the lms path won't work.
+ html = self.resource_string("static/html/student.html")
+ frag = Fragment(html.format(query=self.query, team=random.randint(0, 100000)))
+ frag.add_javascript(self.resource_string("static/js/src/student.js"))
+ frag.initialize_js('MKWSBiblio')
+ return frag;
+
+ def studio_view(self, context=None):
+ """Studio configuration view."""
+ html = self.resource_string("static/html/settings.html")
+ frag = Fragment(html.format(query=self.query))
+ frag.add_javascript(self.resource_string("static/js/settings.js"))
+ frag.initialize_js('MKWSBiblioSettings')
+ return frag
+
+ @XBlock.json_handler
+ def update_settings(self, data, suffix=''):
+ """Studio configuration callback."""
+ self.query = data['query']
+ return {"result": "success"}
+
+ @staticmethod
+ def workbench_scenarios():
+ """A canned scenario for display in the workbench."""
+ return [
+ ("MKWSBiblio",
+ """<vertical_demo>
+ <mkwsbiblio/>
+ </vertical_demo>
+ """),
+ ]
--- /dev/null
+<div class="wrapper-comp-settings is-active editor-with-buttons" id="settings-tab">
+ <ul class="list-input settings-list">
+ <li class="field comp-setting-entry is-set">
+ <div class="wrapper-comp-setting" id="mkwsCurrentRecordContainer">
+ <h3>Current selection:</h3>
+ <div class="mkwsRecords mkwsTeam_UNIQUE" id="mkwsCurrentRecord" autosearch="{query}" perpage="1">Loading record...</div>
+ </div>
+ </li>
+ <li class="field comp-setting-entry is-set">
+ <div class="wrapper-comp-setting">
+ <h3>Choose a record:</h3>
+ <div class="mkwsSearch mkwsTeam_BlockConfig"></div>
+ <!-- NB: double braces needed to escape edx templateing -->
+ <div class="mkwsRecords mkwsTeam_BlockConfig" data-mkws-config='{{ "template": "EdxChooser", "perpage": 5 }}'></div>
+ </div>
+ </li>
+ </ul>
+ <div class="xblock-actions">
+ <ul>
+ <li class="action-item">
+ <a href="#" class="button action-primary save-button">Save</a>
+ </li>
+ <li class="action-item">
+ <a href="#" class="button cancel-button">Cancel</a>
+ </li>
+ </ul>
+ </div>
+</div>
--- /dev/null
+<div class="mkwsbiblio_block">
+ <div class="mkwsRecords mkwsTeam_{team}" autosearch="{query}" perpage="1">Loading record...</div>
+</div>
--- /dev/null
+(function() {
+ var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
+templates['EdxChooser'] = template(function (Handlebars,depth0,helpers,partials,data) {
+ this.compilerInfo = [4,'>= 1.0.0'];
+helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
+ var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression, self=this;
+
+function program1(depth0,data) {
+
+ var buffer = "", stack1, helper;
+ buffer += "\n <div class=\"";
+ if (helper = helpers.containerClass) { stack1 = helper.call(depth0, {hash:{},data:data}); }
+ else { helper = (depth0 && depth0.containerClass); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
+ buffer += escapeExpression(stack1)
+ + "\">\n <a href=\"#\" id=\"";
+ if (helper = helpers.detailLinkId) { stack1 = helper.call(depth0, {hash:{},data:data}); }
+ else { helper = (depth0 && depth0.detailLinkId); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
+ buffer += escapeExpression(stack1)
+ + "\" onclick=\"$('#mkwsCurrentRecord').attr('autosearch', '";
+ if (helper = helpers['md-title']) { stack1 = helper.call(depth0, {hash:{},data:data}); }
+ else { helper = (depth0 && depth0['md-title']); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
+ buffer += escapeExpression(stack1)
+ + "'); mkws.init('Click select', $('#mkwsCurrentRecordContainer'));\">\n <b>";
+ if (helper = helpers['md-title']) { stack1 = helper.call(depth0, {hash:{},data:data}); }
+ else { helper = (depth0 && depth0['md-title']); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
+ buffer += escapeExpression(stack1)
+ + "</b>\n </a>\n ";
+ stack1 = helpers['if'].call(depth0, (depth0 && depth0['md-title-remainder']), {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n ";
+ stack1 = helpers['if'].call(depth0, (depth0 && depth0['md-title-responsibility']), {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n ";
+ stack1 = helpers['if'].call(depth0, (depth0 && depth0.renderedDetails), {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n </div>\n";
+ return buffer;
+ }
+function program2(depth0,data) {
+
+ var buffer = "", stack1, helper;
+ buffer += "\n <span>";
+ if (helper = helpers['md-title-remainder']) { stack1 = helper.call(depth0, {hash:{},data:data}); }
+ else { helper = (depth0 && depth0['md-title-remainder']); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
+ buffer += escapeExpression(stack1)
+ + "</span>\n ";
+ return buffer;
+ }
+
+function program4(depth0,data) {
+
+ var buffer = "", stack1, helper;
+ buffer += "\n <span><i>";
+ if (helper = helpers['md-title-responsibility']) { stack1 = helper.call(depth0, {hash:{},data:data}); }
+ else { helper = (depth0 && depth0['md-title-responsibility']); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
+ buffer += escapeExpression(stack1)
+ + "</i></span>\n ";
+ return buffer;
+ }
+
+function program6(depth0,data) {
+
+ var buffer = "", stack1, helper;
+ buffer += "\n ";
+ if (helper = helpers.renderedDetails) { stack1 = helper.call(depth0, {hash:{},data:data}); }
+ else { helper = (depth0 && depth0.renderedDetails); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n ";
+ return buffer;
+ }
+
+ buffer += "\n";
+ stack1 = helpers.each.call(depth0, (depth0 && depth0.hits), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n";
+ return buffer;
+ });
+})();
+function MKWSBiblioSettings(runtime, element) {
+ mkws.init("XBlock settings pane", "#settings-tab");
+ $(element).find('.save-button').bind('click', function() {
+ var handlerUrl = runtime.handlerUrl(element, 'update_settings');
+ var data = {
+ query: $(element).find('#mkwsCurrentRecord').attr('autosearch')
+ };
+ $.post(handlerUrl, JSON.stringify(data)).done(function(response) {
+ window.location.reload(false);
+ });
+ });
+
+ $(element).find('.cancel-button').bind('click', function() {
+ runtime.notify('cancel', {});
+ });
+};
--- /dev/null
+{{!
+Records from a search.
+
+hits:
+ containerClass - class attribute for same
+ detailLinkId - id for the element triggering detail display
+ detailClick - a click event handler for details
+ renderedDetails - active record details rendered from the Record template
+ md-* - metadata fields passed through from backend
+}}
+{{#each hits}}
+ <div class="{{containerClass}}">
+ <a href="#" id="{{detailLinkId}}" onclick="$('#mkwsCurrentRecord').attr('autosearch', '{{md-title}}'); mkws.init('Click select', $('#mkwsCurrentRecordContainer'));">
+ <b>{{md-title}}</b>
+ </a>
+ {{#if md-title-remainder}}
+ <span>{{md-title-remainder}}</span>
+ {{/if}}
+ {{#if md-title-responsibility}}
+ <span><i>{{md-title-responsibility}}</i></span>
+ {{/if}}
+ {{#if renderedDetails}}
+ {{{renderedDetails}}}
+ {{/if}}
+ </div>
+{{/each}}
--- /dev/null
+ {{#if md-author}}
+ <span>{{md-author}}</span>
+ {{/if}}
+ <a href="#" id="{{_id}}" onclick="{{_onclick}}">
+ <b>WOO {{md-title}}</b>
+ </a>
--- /dev/null
+handlebars Records.handlebars | cat - settings.js > ../settings.js
--- /dev/null
+function MKWSBiblioSettings(runtime, element) {
+ mkws.init("XBlock settings pane", "#settings-tab");
+ $(element).find('.save-button').bind('click', function() {
+ var handlerUrl = runtime.handlerUrl(element, 'update_settings');
+ var data = {
+ query: $(element).find('#mkwsCurrentRecord').attr('autosearch')
+ };
+ $.post(handlerUrl, JSON.stringify(data)).done(function(response) {
+ window.location.reload(false);
+ });
+ });
+
+ $(element).find('.cancel-button').bind('click', function() {
+ runtime.notify('cancel', {});
+ });
+};
--- /dev/null
+window.mkws_noready = true;
+require.config({
+ paths: {
+ mkws: "//mkws.local/mkws-complete",
+ },
+ shim: {
+ mkws: {
+ exports: "mkws"
+ },
+ }
+});
+function MKWSBiblio(runtime, element) {
+ require(['mkws'], function() {
+ console.log(mkws);
+ mkws.init("XBlock initialised.", element);
+ //mkws.init("XBlock initialised.");
+ } );
+}
--- /dev/null
+"""Setup for mkwsbiblio XBlock."""
+
+import os
+from setuptools import setup
+
+def package_data(pkg, roots):
+ """Generic function to find package_data.
+
+ All of the files under each of the `roots` will be declared as package
+ data for package `pkg`.
+
+ """
+ data = []
+ for root in roots:
+ for dirname, _, files in os.walk(os.path.join(pkg, root)):
+ for fname in files:
+ data.append(os.path.relpath(os.path.join(dirname, fname), pkg))
+
+ return {pkg: data}
+
+setup(
+ name='mkwsbiblio',
+ version='0.1',
+ description='XBlock to embed a bibliographic record via MKWS',
+ packages=[
+ 'mkwsbiblio',
+ ],
+ install_requires=[
+ 'XBlock',
+ ],
+ entry_points={
+ 'xblock.v1': [
+ 'mkwsbiblio = mkwsbiblio:MKWSBiblio',
+ ]
+ },
+ package_data=package_data("mkwsbiblio", ["static", "public"]),
+)