forked from appsembler/xblock-video
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Download and upload handout file on MongoDB
- Loading branch information
Showing
6 changed files
with
431 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -91,3 +91,5 @@ ENV/ | |
# Bower components | ||
bower_components/ | ||
|
||
#Pycharm | ||
.idea/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
.wrapper-comp-settings .file-uploader .xblock-edit-settings .upload-setting, | ||
.wrapper-comp-settings .file-uploader .xblock-edit-settings .download-setting { | ||
width: 47%; | ||
} | ||
.upload-success { | ||
position: absolute; | ||
} | ||
|
||
.wrapper-downloads-custom { | ||
margin: 0; | ||
padding: 0; | ||
background-color: #f0f3f5; | ||
} | ||
|
||
.video-download-button-custom { | ||
display: inline-block; | ||
vertical-align: top; | ||
margin: 10px; | ||
} | ||
|
||
.video-download-button-custom a { | ||
transition: all 0.25s ease-in-out 0s; | ||
font-size: 14px; | ||
line-height: 14px; | ||
float: left; | ||
border-radius: 3px; | ||
background-color: #fff; | ||
padding: 15px; | ||
} | ||
|
||
.video-download-button-custom a:hover { | ||
background-color: #1aa1de; | ||
color: #fff; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
{% load i18n %} | ||
<div class="editor-with-buttons"> | ||
<div class="wrapper-comp-settings is-active editor-with-buttons" id="settings-tab"> | ||
<ul class="list-input settings-list"> | ||
{% for field in fields %} | ||
<li | ||
class="field comp-setting-entry metadata_entry {% if field.is_set %}is-set{% endif %}" | ||
data-field-name="{{field.name}}" | ||
data-default="{% if field.type == 'boolean' %}{{ field.default|yesno:'1,0' }}{% else %}{{ field.default|default_if_none:"" }}{% endif %}" | ||
data-cast="{{field.type}}" | ||
> | ||
<div class='wrapper-comp-setting {% if field.type == "set" %}metadata-list-enum{% endif %} {% if field.type == "file_uploader" %}file-uploader{% endif %}'> | ||
<label class="label setting-label" for="xb-field-edit-{{field.name}}">{{field.display_name}}</label> | ||
|
||
{% if field.type == "boolean" %} | ||
<select | ||
class="field-data-control" | ||
id="xb-field-edit-{{field.name}}" | ||
> | ||
<option value="1" {% if field.value %}selected{% endif %}> | ||
True {% if field.default %} (Default){% endif %} | ||
</option> | ||
<option value="0" {% if not field.value %}selected{% endif %}> | ||
False {% if not field.default %} (Default){% endif %} | ||
</option> | ||
</select> | ||
{% elif field.has_values %} | ||
<select | ||
class="field-data-control" | ||
id="xb-field-edit-{{field.name}}" | ||
> | ||
{% for option in field.values %} | ||
<option value="{{option.value}}" {% if field.value == option.value %}selected{% endif %}> | ||
{{option.display_name}} {% if option.value == field.default %} (Default){% endif %} | ||
</option> | ||
{% endfor %} | ||
</select> | ||
{% elif field.type == "string" or field.type == "datepicker" %} | ||
<input | ||
type="text" | ||
class="field-data-control" | ||
id="xb-field-edit-{{field.name}}" | ||
value="{{field.value|default_if_none:""}}" | ||
> | ||
{% elif field.type == "integer" or field.type == "float" %} | ||
<input | ||
type="number" | ||
class="field-data-control" | ||
id="xb-field-edit-{{field.name}}" | ||
{% if field.step %} step="{{field.step}}" {% elif field.type == "integer" %} step=1 {% endif %} | ||
{% if field.max %} max="{{field.max}}" {% endif %} | ||
{% if field.min %} min="{{field.min}}" {% endif %} | ||
value="{{field.value|default_if_none:""}}" | ||
> | ||
{% elif field.type == "text" or field.type == "html" %} | ||
<textarea class="field-data-control" data-field-name="{{field.name}}" id="xb-field-edit-{{field.name}}" rows=10 cols=70>{{field.value}}</textarea> | ||
{% elif field.type == 'set' and field.has_list_values %} | ||
{% comment %} | ||
TODO: If len(list_values) is high, show an alternate editor | ||
with a select box and a growing list of selected choices | ||
{% endcomment %} | ||
<div class="wrapper-list-settings"> | ||
<ul class="list-settings list-set"> | ||
{% for choice in field.list_values %} | ||
<li class="list-settings-item"> | ||
<input | ||
id="xb-field-edit-{{field.name}}-{{forloop.counter}}" | ||
type="checkbox" | ||
value="{{choice.value}}" | ||
style="width:auto;min-width:auto;height:auto;float:left;margin-top:3px;" | ||
{% if choice.value in field.value %}checked="checked"{% endif %} | ||
> | ||
<label for="xb-field-edit-{{field.name}}-{{forloop.counter}}" style="display:block;margin-left:1.1em;"> | ||
{{choice.display_name}} | ||
</label> | ||
</li> | ||
{% empty %} | ||
<li>{% trans "None Available" %}</li> | ||
{% endfor %} | ||
</ul> | ||
</div> | ||
{% elif field.type == 'generic' or field.type == 'list' or field.type == 'set' %} | ||
{# Show a textarea so we can edit it as a JSON string #} | ||
<textarea class="field-data-control" data-field-name="{{field.name}}" id="xb-field-edit-{{field.name}}" rows=5 cols=70>{{field.value}}</textarea> | ||
|
||
<!-- Raccoongang addons --> | ||
{% elif field.type == 'file_uploader' %} | ||
|
||
<div class="wrapper-uploader-actions xblock-edit-settings"> | ||
<a href="#" class="upload-action upload-setting" data-change-field-name="{{field.name}}">{% trans "Upload" %}</a> | ||
{% if field.value %} | ||
<a href="/{{ field.value }}" target="_blank" class="download-action download-setting" download="{{ field.file_name}}">{% trans "Download" %}</a> | ||
{% endif %} | ||
</div> | ||
<input type="hidden" class="field-data-control" data-field-name="{{field.name}}" id="metadata-file-uploader-{{ field.name }}" value="{{ field.value }}"> | ||
<!-- End of Raccoongang addons --> | ||
|
||
{% else %} | ||
Unsupported field type. This setting cannot be edited. | ||
{% endif %} | ||
|
||
{% if field.allow_reset %} | ||
<button class="action setting-clear {% if field.is_set %}active{%else%}inactive{% endif %}" type="button" name="setting-clear" value="{% trans "Clear" %}" data-tooltip="{% trans "Clear" %}"> | ||
<i class="icon fa fa-undo"></i><span class="sr">{% trans "Clear Value" %}</span> | ||
</button> | ||
{% endif %} | ||
</div> | ||
{% if field.help %} | ||
<span class="tip setting-help"> {{ field.help|safe }} </span> | ||
{% endif %} | ||
</li> | ||
{% endfor %} | ||
</ul> | ||
<!-- Raccoongang addons --> | ||
<form method="POST" action="/assets/{{ courseKey }}/" class="is-hidden" enctype="multipart/form-data"> | ||
<input class="input-file-uploader" name="file" type="file" data-change-field-name=""> | ||
</form> | ||
<!-- End of Raccoongang addons --> | ||
</div> | ||
|
||
<div class="xblock-actions"> | ||
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
function StudioEditableXBlock(runtime, element) { | ||
"use strict"; | ||
|
||
var fields = []; | ||
var tinyMceAvailable = (typeof $.fn.tinymce !== 'undefined'); // Studio includes a copy of tinyMCE and its jQuery plugin | ||
var datepickerAvailable = (typeof $.fn.datepicker !== 'undefined'); // Studio includes datepicker jQuery plugin | ||
|
||
$(element).find('.field-data-control').each(function() { | ||
var $field = $(this); | ||
var $wrapper = $field.closest('li'); | ||
var $resetButton = $wrapper.find('button.setting-clear'); | ||
var type = $wrapper.data('cast'); | ||
fields.push({ | ||
name: $wrapper.data('field-name'), | ||
isSet: function() { return $wrapper.hasClass('is-set'); }, | ||
hasEditor: function() { return tinyMceAvailable && $field.tinymce(); }, | ||
val: function() { | ||
var val = $field.val(); | ||
// Cast values to the appropriate type so that we send nice clean JSON over the wire: | ||
if (type == 'boolean') | ||
return (val == 'true' || val == '1'); | ||
if (type == "integer") | ||
return parseInt(val, 10); | ||
if (type == "float") | ||
return parseFloat(val); | ||
if (type == "generic" || type == "list" || type == "set") { | ||
val = val.trim(); | ||
if (val === "") | ||
val = null; | ||
else | ||
val = JSON.parse(val); // TODO: handle parse errors | ||
} | ||
return val; | ||
}, | ||
removeEditor: function() { | ||
$field.tinymce().remove(); | ||
} | ||
}); | ||
var fieldChanged = function() { | ||
// Field value has been modified: | ||
$wrapper.addClass('is-set'); | ||
$resetButton.removeClass('inactive').addClass('active'); | ||
}; | ||
$field.bind("change input paste", fieldChanged); | ||
$resetButton.click(function() { | ||
$field.val($wrapper.attr('data-default')); // Use attr instead of data to force treating the default value as a string | ||
$wrapper.removeClass('is-set'); | ||
$resetButton.removeClass('active').addClass('inactive'); | ||
}); | ||
if (type == 'html' && tinyMceAvailable) { | ||
tinyMCE.baseURL = baseUrl + "/js/vendor/tinymce/js/tinymce"; | ||
$field.tinymce({ | ||
theme: 'modern', | ||
skin: 'studio-tmce4', | ||
height: '200px', | ||
formats: { code: { inline: 'code' } }, | ||
codemirror: { path: "" + baseUrl + "/js/vendor" }, | ||
convert_urls: false, | ||
plugins: "link codemirror", | ||
menubar: false, | ||
statusbar: false, | ||
toolbar_items_size: 'small', | ||
toolbar: "formatselect | styleselect | bold italic underline forecolor wrapAsCode | bullist numlist outdent indent blockquote | link unlink | code", | ||
resize: "both", | ||
setup : function(ed) { | ||
ed.on('change', fieldChanged); | ||
} | ||
}); | ||
} | ||
|
||
if (type == 'datepicker' && datepickerAvailable) { | ||
$field.datepicker('destroy'); | ||
$field.datepicker({dateFormat: "m/d/yy"}); | ||
} | ||
}); | ||
|
||
$(element).find('.wrapper-list-settings .list-set').each(function() { | ||
var $optionList = $(this); | ||
var $checkboxes = $(this).find('input'); | ||
var $wrapper = $optionList.closest('li'); | ||
var $resetButton = $wrapper.find('button.setting-clear'); | ||
|
||
fields.push({ | ||
name: $wrapper.data('field-name'), | ||
isSet: function() { return $wrapper.hasClass('is-set'); }, | ||
hasEditor: function() { return false; }, | ||
val: function() { | ||
var val = []; | ||
$checkboxes.each(function() { | ||
if ($(this).is(':checked')) { | ||
val.push(JSON.parse($(this).val())); | ||
} | ||
}); | ||
return val; | ||
} | ||
}); | ||
var fieldChanged = function() { | ||
// Field value has been modified: | ||
$wrapper.addClass('is-set'); | ||
$resetButton.removeClass('inactive').addClass('active'); | ||
}; | ||
$checkboxes.bind("change input", fieldChanged); | ||
|
||
$resetButton.click(function() { | ||
var defaults = JSON.parse($wrapper.attr('data-default')); | ||
$checkboxes.each(function() { | ||
var val = JSON.parse($(this).val()); | ||
$(this).prop('checked', defaults.indexOf(val) > -1); | ||
}); | ||
$wrapper.removeClass('is-set'); | ||
$resetButton.removeClass('active').addClass('inactive'); | ||
}); | ||
}); | ||
|
||
var studio_submit = function(data) { | ||
var handlerUrl = runtime.handlerUrl(element, 'submit_studio_edits'); | ||
runtime.notify('save', {state: 'start', message: gettext("Saving")}); | ||
$.ajax({ | ||
type: "POST", | ||
url: handlerUrl, | ||
data: JSON.stringify(data), | ||
dataType: "json", | ||
global: false, // Disable Studio's error handling that conflicts with studio's notify('save') and notify('cancel') :-/ | ||
success: function(response) { runtime.notify('save', {state: 'end'}); } | ||
}).fail(function(jqXHR) { | ||
var message = gettext("This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online."); | ||
if (jqXHR.responseText) { // Is there a more specific error message we can show? | ||
try { | ||
message = JSON.parse(jqXHR.responseText).error; | ||
if (typeof message === "object" && message.messages) { | ||
// e.g. {"error": {"messages": [{"text": "Unknown user 'bob'!", "type": "error"}, ...]}} etc. | ||
message = $.map(message.messages, function(msg) { return msg.text; }).join(", "); | ||
} | ||
} catch (error) { message = jqXHR.responseText.substr(0, 300); } | ||
} | ||
runtime.notify('error', {title: gettext("Unable to update settings"), message: message}); | ||
}); | ||
}; | ||
|
||
$('.save-button', element).bind('click', function(e) { | ||
e.preventDefault(); | ||
var values = {}; | ||
var notSet = []; // List of field names that should be set to default values | ||
for (var i in fields) { | ||
var field = fields[i]; | ||
if (field.isSet()) { | ||
values[field.name] = field.val(); | ||
} else { | ||
notSet.push(field.name); | ||
} | ||
// Remove TinyMCE instances to make sure jQuery does not try to access stale instances | ||
// when loading editor for another block: | ||
if (field.hasEditor()) { | ||
field.removeEditor(); | ||
} | ||
} | ||
studio_submit({values: values, defaults: notSet}); | ||
}); | ||
|
||
// Raccoongang addons | ||
|
||
var $fileUploader = $('.input-file-uploader', element); | ||
|
||
$fileUploader.on('change', function(e) { | ||
var fieldName = $fileUploader.data('change-field-name'); | ||
$('form', element).ajaxSubmit({ | ||
success: function(response, statusText, xhr, form) { | ||
$('input[data-field-name=' + fieldName + ']').val(response['asset']['id']).change(); | ||
} | ||
}) | ||
}); | ||
|
||
$('.upload-setting', element).on('click', function(e) { | ||
e.preventDefault(); | ||
var fieldName = $(e.currentTarget).data('change-field-name'); | ||
$fileUploader.attr('data-change-field-name', fieldName); | ||
$fileUploader.click(); | ||
}); | ||
// End of Raccoongang addons | ||
|
||
$(element).find('.cancel-button').bind('click', function(e) { | ||
// Remove TinyMCE instances to make sure jQuery does not try to access stale instances | ||
// when loading editor for another block: | ||
for (var i in fields) { | ||
var field = fields[i]; | ||
if (field.hasEditor()) { | ||
field.removeEditor(); | ||
} | ||
} | ||
e.preventDefault(); | ||
runtime.notify('cancel', {}); | ||
}); | ||
} |
Oops, something went wrong.