Commit b22ce8a3 by marjev

Enabled editing of google calendar component

parent b96ada9d
...@@ -58,7 +58,7 @@ Access it at [http://localhost:8000/](http://localhost:8000). ...@@ -58,7 +58,7 @@ Access it at [http://localhost:8000/](http://localhost:8000).
Running tests Running tests
------------- -------------
From the xblock-mentoring repository root, run the tests with the From the xblock-google-drive repository root, run the tests with the
following command: following command:
```bash ```bash
...@@ -78,6 +78,6 @@ you might also have to prepend `PYTHONPATH=".:/path/to/xblock"` to the command a ...@@ -78,6 +78,6 @@ you might also have to prepend `PYTHONPATH=".:/path/to/xblock"` to the command a
License License
------- -------
The Image Explorer XBlock is available under the GNU Affero General The Google Drive & Calendar XBlocks are available under the GNU Affero General
Public License (AGPLv3). Public License (AGPLv3).
...@@ -12,7 +12,7 @@ import textwrap ...@@ -12,7 +12,7 @@ import textwrap
#from xml.etree import ElementTree as ET #from xml.etree import ElementTree as ET
from xblock.core import XBlock from xblock.core import XBlock
from xblock.fields import Scope, String from xblock.fields import Scope, String, Integer
from xblock.fragment import Fragment from xblock.fragment import Fragment
# from StringIO import StringIO # from StringIO import StringIO
...@@ -38,20 +38,22 @@ class GoogleCalendarBlock(XBlock): ...@@ -38,20 +38,22 @@ class GoogleCalendarBlock(XBlock):
default="Example Google Calendar" default="Example Google Calendar"
) )
embed_code = String( calendar_id = String(
display_name="Embed Code", display_name="Public Calendar ID",
help="Google provides an embed code for Drive calendars with a variety of settings. From inside a Google Drive calendar, select Publish to the Web from within the File menu to get to your Embed Code with your desired settings.", help="This is the Calendar ID for the publically available Google calendar you would like to embed. To find this ID, go to your Calendar Settings and copy the ID found in the Calendar Address section.",
scope=Scope.settings, scope=Scope.settings,
default=textwrap.dedent(""" default="edx.org_vme83q0j2v52mbhjncvfd5uqs8@group.calendar.google.com"
<iframe )
src="https://www.google.com/calendar/embed?src=ode5942aqjk6g9lm0r1p6kripo%40group.calendar.google.com&ctz=Europe/Belgrade"
style="border: 0" # 0=Week, 1=Month, 2=Agenda
width="800" default_view = Integer(
height="600" display_name="Default View",
frameborder="0" help="The view of the calendar initially presented to students.",
scrolling="no"> scope=Scope.settings,
</iframe> default=1
""")) )
views = ["Week", "Month", "Agenda"]
def student_view(self, context={}): def student_view(self, context={}):
""" """
...@@ -59,14 +61,20 @@ class GoogleCalendarBlock(XBlock): ...@@ -59,14 +61,20 @@ class GoogleCalendarBlock(XBlock):
""" """
fragment = Fragment() fragment = Fragment()
view = "Week" if self.default_view==0 else "Month" if self.default_view==1 else "Agenda"
iframe = "<iframe src=\"https://www.google.com/calendar/embed?mode={}&amp;src={}\"></iframe>".format(view, self.calendar_id)
context.update({ context.update({
"self": self, "self": self,
"iframe": iframe
}) })
fragment.add_content(render_template('/templates/html/google_docs.html', context)) fragment.add_content(render_template('/templates/html/google_calendar.html', context))
fragment.add_css(load_resource('public/css/google_docs.css')) fragment.add_css(load_resource('public/css/google_calendar.css'))
fragment.add_javascript(load_resource('public/js/google_docs.js')) fragment.add_javascript(load_resource('public/js/google_calendar.js'))
fragment.initialize_js('GoogleDocumentBlock') fragment.initialize_js('GoogleCalendarBlock')
return fragment return fragment
...@@ -75,12 +83,12 @@ class GoogleCalendarBlock(XBlock): ...@@ -75,12 +83,12 @@ class GoogleCalendarBlock(XBlock):
Editing view in Studio Editing view in Studio
""" """
fragment = Fragment() fragment = Fragment()
fragment.add_content(render_template('/templates/html/google_docs_edit.html', { fragment.add_content(render_template('/templates/html/google_calendar_edit.html', {
'self': self, 'self': self
})) }))
fragment.add_javascript(load_resource('public/js/google_docs_edit.js')) fragment.add_javascript(load_resource('public/js/google_calendar_edit.js'))
fragment.initialize_js('GoogleDocumentEditBlock') fragment.initialize_js('GoogleCalendarEditBlock')
return fragment return fragment
...@@ -88,7 +96,8 @@ class GoogleCalendarBlock(XBlock): ...@@ -88,7 +96,8 @@ class GoogleCalendarBlock(XBlock):
def studio_submit(self, submissions, suffix=''): def studio_submit(self, submissions, suffix=''):
self.display_name = submissions['display_name'] self.display_name = submissions['display_name']
self.embed_code = submissions['embed_code'] self.calendar_id = submissions['calendar_id']
self.default_view = submissions['default_view']
return { return {
'result': 'success', 'result': 'success',
......
.google-calendar-xblock-wrapper{
position: relative;
padding-bottom: 56.25%; /* 16:9 */
padding-top: 25px;
height: 0;
}
.google-calendar-xblock-wrapper iframe{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* Javascript for GoogleDocumentBlock. */
function GoogleCalendarBlock(runtime, element) {
$(function ($) {
/* Here's where you'd do things on page load. */
});
}
function GoogleCalendarEditBlock(runtime, element) {
$('.save-button', element).bind('click', function() {
var data = {
'display_name': $('.edit-display-name', element).val(),
'calendar_id': $('.edit-calendar-id', element).val(),
'default_view': $('select.edit-label_type > option:selected', element).val(),
};
$('.xblock-editor-error-message', element).html();
$('.xblock-editor-error-message', element).css('display', 'none');
var handlerUrl = runtime.handlerUrl(element, 'studio_submit');
$.post(handlerUrl, JSON.stringify(data)).done(function(response) {
if (response.result === 'success') {
window.location.reload(false);
} else {
$('.xblock-editor-error-message', element).html('Error: '+response.message);
$('.xblock-editor-error-message', element).css('display', 'block');
}
});
});
$('.cancel-button', element).bind('click', function() {
runtime.notify('cancel', {});
});
}
{% autoescape off %}
<div class="google-calendar-xblock-wrapper">
{{ iframe }}
</div>
{% endautoescape %}
{% load i18n %}
<!-- TODO: Replace by default edit view once available in Studio -->
<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">
<label class="label setting-label" for="edit_display_name">{% trans "Display Name" %}</label>
<input class="input setting-input edit-display-name" id="edit_display_name" value="{{ self.display_name }}" type="text">
</div>
<span class="tip setting-help">{% trans "This name appears in the horizontal navigation at the top of the page." %}</span>
</li>
<li class="field comp-setting-entry is-set">
<div class="wrapper-comp-setting">
<label class="label setting-label" for="edit_calendar_id">{% trans "Public Calendar ID" %}</label>
<textarea rows="3" cols="60" class="input setting-input edit-calendar-id" id="edit_calendar_id">
{{ self.calendar_id }}
</textarea>
</div>
<span class="tip setting-help">{% trans "This is the Calendar ID for the publically available Google calendar you would like to embed. To find this ID, go to your Calendar Settings and copy the ID found in the Calendar Address section. You can also " %}
<a href="https://support.google.com/calendar/answer/34578?ctx=tltp" target="_blank">learn more here</a>.
</span>
</li>
<li class="field comp-setting-entry is-set">
<div class="wrapper-comp-setting">
<label class="label setting-label" for="edit_default_view">{% trans "Default View" %}</label>
<select class="input setting-input edit-label_type" id="edit_label_type" value="{{self.default_view}}">
{% for view in self.views %}
<option value="{{forloop.counter0}}" {% if forloop.counter0 == self.default_view %}selected="selected"{% endif %}>
{{view}}
</option>
{% endfor %}
</select>
</div>
<span class="tip setting-help">{% trans "The view of the calendar initially presented to students." %}</span>
</li>
<li class="field comp-setting-entry is-set"></li>
</ul>
<div class="xblock-actions">
<span class="xblock-editor-error-message"></span>
<ul>
<li class="action-item">
<a href="#" class="button action-primary save-button">{% trans "Save" %}</a>
</li>
<li class="action-item">
<a href="#" class="button cancel-button">{% trans "Cancel" %}</a>
</li>
</ul>
</div>
</div>
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
</div> </div>
<span class="tip setting-help">{% trans "Google provides an embed code for Drive documents with a variety of settings. From inside a Google Drive document, select Publish to the Web from within the File menu to get to your Embed Code with your desired settings." %}</span> <span class="tip setting-help">{% trans "Google provides an embed code for Drive documents with a variety of settings. From inside a Google Drive document, select Publish to the Web from within the File menu to get to your Embed Code with your desired settings." %}</span>
</li> </li>
<li class="field comp-setting-entry is-set"></li>
</ul> </ul>
<div class="xblock-actions"> <div class="xblock-actions">
<span class="xblock-editor-error-message"></span> <span class="xblock-editor-error-message"></span>
......
...@@ -6,11 +6,10 @@ from mock import Mock ...@@ -6,11 +6,10 @@ from mock import Mock
from workbench.runtime import WorkbenchRuntime from workbench.runtime import WorkbenchRuntime
from xblock.runtime import KvsFieldData, DictKeyValueStore from xblock.runtime import KvsFieldData, DictKeyValueStore
from google_drive import GoogleDocumentBlock from google_drive import GoogleDocumentBlock, GoogleCalendarBlock
from nose.tools import ( from nose.tools import (
assert_equals, assert_true, assert_false, assert_equals
assert_in
) )
def make_request(body, method='POST'): def make_request(body, method='POST'):
...@@ -20,14 +19,20 @@ def make_request(body, method='POST'): ...@@ -20,14 +19,20 @@ def make_request(body, method='POST'):
request.method = method request.method = method
return request return request
def make_block(): def make_document_block():
runtime = WorkbenchRuntime() runtime = WorkbenchRuntime()
key_store = DictKeyValueStore() key_store = DictKeyValueStore()
db_model = KvsFieldData(key_store) db_model = KvsFieldData(key_store)
return GoogleDocumentBlock(runtime, db_model, Mock()) return GoogleDocumentBlock(runtime, db_model, Mock())
def test_studio_submit(): def make_calendar_block():
block = make_block() runtime = WorkbenchRuntime()
key_store = DictKeyValueStore()
db_model = KvsFieldData(key_store)
return GoogleCalendarBlock(runtime, db_model, Mock())
def test_studio_document_submit():
block = make_document_block()
body = json.dumps({ body = json.dumps({
'display_name': "Google Document", 'display_name': "Google Document",
...@@ -39,3 +44,19 @@ def test_studio_submit(): ...@@ -39,3 +44,19 @@ def test_studio_submit():
assert_equals(block.display_name, "Google Document") assert_equals(block.display_name, "Google Document")
assert_equals(block.embed_code, "<iframe>") assert_equals(block.embed_code, "<iframe>")
def test_calendar_document_submit():
block = make_calendar_block()
body = json.dumps({
'display_name': "Google Calendar",
'calendar_id': "google1234",
'default_view': 1
})
res = block.handle('studio_submit', make_request(body))
assert_equals(json.loads(res.body), {'result': 'success'})
assert_equals(block.display_name, "Google Calendar")
assert_equals(block.calendar_id, "google1234")
assert_equals(block.default_view, 1)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment