diff --git a/course/in_browser_ide.py b/course/in_browser_ide.py new file mode 100644 index 0000000000000000000000000000000000000000..3a81f1844c6306470a2b381d46cc7aeb0f3a777f --- /dev/null +++ b/course/in_browser_ide.py @@ -0,0 +1,69 @@ +from django.contrib.auth.decorators import login_required +from course.utils import course_view, render_course_page +from course.content import get_course_repo_path, get_repo_blob +from dulwich import porcelain +import io +import os +# {{{ mypy + +if 0: + from course.models import Course # noqa +# }}} + + +@login_required +@course_view +def ide(pctx): + data = get_course_directory_structure(pctx) + file_content = '' + filename = None + if 'filename' in pctx.request.GET: + filename = pctx.request.GET['filename'] + if filename.endswith('.yml'): + file_content = get_raw_file_text(pctx, filename) + else: + file_content = 'File type not supported' + return render_course_page(pctx, "course/in-browser-ide.html", { + 'file_structure': data, + 'file_content': file_content, + 'selected_node': filename + }) + + +def get_course_directory_structure(pctx): + + course = pctx.course + repo_path = get_course_repo_path(course) + + repo = porcelain.open_repo(repo_path) + data = [] + paths = io.StringIO() # type: io.StringIO + porcelain.ls_tree(repo, b'HEAD', outstream=paths, recursive=True) + + for path in paths.getvalue().split('\n')[:-1]: + path = path.split('\t')[-1] + + parent, file = os.path.split(path) + if parent is '': + parent = '#' + data.append({ + 'id': path, + 'parent': parent, + 'text': file, + 'type': 'file' + }) + # correct folder type + non_leaf = [item['parent'] for item in data] + for file in data: + if file['id'] in non_leaf: + file['type'] = 'folder' + return data + + +def get_raw_file_text(pctx, file_name): + course = pctx.course + repo_path = get_course_repo_path(course) + repo = porcelain.open_repo(repo_path) + yaml_str = get_repo_blob(repo, file_name, pctx.course_commit_sha).data + yaml_str = yaml_str.decode("utf-8") + return yaml_str diff --git a/course/templates/course/in-browser-ide.html b/course/templates/course/in-browser-ide.html new file mode 100644 index 0000000000000000000000000000000000000000..0bd360da6d6680ece06b3225edca6fc0b98bc6e1 --- /dev/null +++ b/course/templates/course/in-browser-ide.html @@ -0,0 +1,111 @@ +{% extends "course/course-base.html" %} +{% load i18n %} + +{% load crispy_forms_tags %} +{% load static %} + +{%block head_assets_extra %} + + {# load calendar with local language #} + + + + + +{% endblock %} + +{% block title %} + {% if title %} + {% comment %} Translators: "[SB]" is abbreviation for "Sandbox" {% endcomment %} + {% blocktrans trimmed %} + [SB] {{ title }} + {% endblocktrans %} + {% else %} + {% blocktrans %}IDE{% endblocktrans %} + {% endif %} + - + {{ relate_site_name }} +{% endblock %} + +{% block root_container %} +
+

Course Content Editor

+

+ Editing: + {{ selected_node|default_if_none:'no file selected' }} +

+
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+ + + {# {{{ codemirror resizing #} + + + + +{% endblock %} + diff --git a/relate/urls.py b/relate/urls.py index ddef2e932cd69b72e624c97b385409612fb6a5d3..a2cca92dd48db4539c418079a9543fd3e2b308b9 100644 --- a/relate/urls.py +++ b/relate/urls.py @@ -40,6 +40,7 @@ import course.versioning import course.flow import course.analytics import course.exam +import course.in_browser_ide import course.api urlpatterns = [ @@ -358,7 +359,6 @@ urlpatterns = [ "/update/$", course.versioning.update_course, name="relate-update_course"), - # }}} # {{{ flow-related @@ -552,6 +552,17 @@ urlpatterns = [ course.api.get_flow_session_content, name="relate-course_get_flow_session_content"), + # {{{ in-browser-ide + url(r"^course" + "/" + COURSE_ID_REGEX + + "/in-browser-ide", + course.in_browser_ide.ide, + name="relate-in-browser-ide"), + #}}} + + + + url(r'^admin/', admin.site.urls), ]