From dd27ef450f94470e31bb64842ea638ed6e68a97f Mon Sep 17 00:00:00 2001 From: paulluh Date: Fri, 9 Mar 2018 17:43:30 -0600 Subject: [PATCH 01/15] [Interface setup] Added JStree and CodeMirror --- course/in_browser_ide.py | 71 +++++++++++++++++++ course/templates/course/in_browser_ide.html | 76 +++++++++++++++++++++ relate/urls.py | 10 ++- 3 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 course/in_browser_ide.py create mode 100644 course/templates/course/in_browser_ide.html diff --git a/course/in_browser_ide.py b/course/in_browser_ide.py new file mode 100644 index 00000000..c1a06ce9 --- /dev/null +++ b/course/in_browser_ide.py @@ -0,0 +1,71 @@ +from django.contrib.auth.decorators import login_required +from django.core.exceptions import PermissionDenied, ObjectDoesNotExist + +from course.utils import course_view, render_course_page +from course.constants import ( + participation_permission as pperm, + ) +from course.content import get_course_repo, get_course_repo_path +from dulwich import porcelain +import io +from collections import defaultdict +# @course_view +@login_required +@course_view +def ide(pctx): + course = pctx.course + data = get_course_directory_structure(course) + return render_course_page(pctx, "course/in_browser_ide.html", { + 'file_structure': data, + 'file_content': 'function(){console.log("hello")}' + }) + + +def get_course_directory_structure(course): + # type: (Course) -> list + repo_path = get_course_repo_path(course) + print(repo_path) + repo = porcelain.open_repo(repo_path) + data = [] + directory_structure = defaultdict() + paths = 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] + files = path.split('/') + parent = None + for file in files: + if file.startswith('.'): + continue + if parent is None: + if parent not in directory_structure: + directory_structure[file] = list() + parent = file + continue + directory_structure[parent].append(file) + parent = file + + counter = 0 + for (parent, children) in directory_structure.items(): + + data.append({ + 'id': str(counter), + 'parent': '#', + 'text': parent + }) + parent_id = str(counter) + counter += 1 + + for child in children: + data.append({ + 'id': str(counter), + 'parent': parent_id, + 'text': child + }) + counter += 1 + return data + + + + diff --git a/course/templates/course/in_browser_ide.html b/course/templates/course/in_browser_ide.html new file mode 100644 index 00000000..c022b9cc --- /dev/null +++ b/course/templates/course/in_browser_ide.html @@ -0,0 +1,76 @@ +{% 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 %}Page Sandbox{% endblocktrans %} + {% endif %} + - + {{ relate_site_name }} +{% endblock %} + +{% block root_container %} +
+
+
+
+
+
+ +
+ +
+
+ + + +
+
+ +
+
+ {# {{{ codemirror resizing #} + + + + +{% endblock %} + diff --git a/relate/urls.py b/relate/urls.py index ddef2e93..b299e41f 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,14 @@ 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), ] -- GitLab From ab9d961e47193d74e629b8b6e04d2856650d45e8 Mon Sep 17 00:00:00 2001 From: paulluh Date: Fri, 9 Mar 2018 17:46:09 -0600 Subject: [PATCH 02/15] [Interface setup] Added JStree and CodeMirror --- course/in_browser_ide.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/course/in_browser_ide.py b/course/in_browser_ide.py index c1a06ce9..81d9fb77 100644 --- a/course/in_browser_ide.py +++ b/course/in_browser_ide.py @@ -1,15 +1,12 @@ from django.contrib.auth.decorators import login_required -from django.core.exceptions import PermissionDenied, ObjectDoesNotExist - from course.utils import course_view, render_course_page -from course.constants import ( - participation_permission as pperm, - ) -from course.content import get_course_repo, get_course_repo_path +from course.content import get_course_repo_path from dulwich import porcelain import io from collections import defaultdict -# @course_view +from course.models import Course + + @login_required @course_view def ide(pctx): @@ -29,7 +26,7 @@ def get_course_directory_structure(course): data = [] directory_structure = defaultdict() paths = io.StringIO() - porcelain.ls_tree(repo, b'HEAD',outstream=paths, recursive=True) + porcelain.ls_tree(repo, b'HEAD', outstream=paths, recursive=True) for path in paths.getvalue().split('\n')[:-1]: path = path.split('\t')[1] @@ -65,7 +62,3 @@ def get_course_directory_structure(course): }) counter += 1 return data - - - - -- GitLab From 6d5f018d4225f53511986938df2b536eaff991d1 Mon Sep 17 00:00:00 2001 From: paulluh Date: Fri, 9 Mar 2018 17:43:30 -0600 Subject: [PATCH 03/15] [Interface setup] Added JStree and CodeMirror --- course/in_browser_ide.py | 71 +++++++++++++++++++ course/templates/course/in_browser_ide.html | 76 +++++++++++++++++++++ relate/urls.py | 10 ++- 3 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 course/in_browser_ide.py create mode 100644 course/templates/course/in_browser_ide.html diff --git a/course/in_browser_ide.py b/course/in_browser_ide.py new file mode 100644 index 00000000..c1a06ce9 --- /dev/null +++ b/course/in_browser_ide.py @@ -0,0 +1,71 @@ +from django.contrib.auth.decorators import login_required +from django.core.exceptions import PermissionDenied, ObjectDoesNotExist + +from course.utils import course_view, render_course_page +from course.constants import ( + participation_permission as pperm, + ) +from course.content import get_course_repo, get_course_repo_path +from dulwich import porcelain +import io +from collections import defaultdict +# @course_view +@login_required +@course_view +def ide(pctx): + course = pctx.course + data = get_course_directory_structure(course) + return render_course_page(pctx, "course/in_browser_ide.html", { + 'file_structure': data, + 'file_content': 'function(){console.log("hello")}' + }) + + +def get_course_directory_structure(course): + # type: (Course) -> list + repo_path = get_course_repo_path(course) + print(repo_path) + repo = porcelain.open_repo(repo_path) + data = [] + directory_structure = defaultdict() + paths = 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] + files = path.split('/') + parent = None + for file in files: + if file.startswith('.'): + continue + if parent is None: + if parent not in directory_structure: + directory_structure[file] = list() + parent = file + continue + directory_structure[parent].append(file) + parent = file + + counter = 0 + for (parent, children) in directory_structure.items(): + + data.append({ + 'id': str(counter), + 'parent': '#', + 'text': parent + }) + parent_id = str(counter) + counter += 1 + + for child in children: + data.append({ + 'id': str(counter), + 'parent': parent_id, + 'text': child + }) + counter += 1 + return data + + + + diff --git a/course/templates/course/in_browser_ide.html b/course/templates/course/in_browser_ide.html new file mode 100644 index 00000000..c022b9cc --- /dev/null +++ b/course/templates/course/in_browser_ide.html @@ -0,0 +1,76 @@ +{% 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 %}Page Sandbox{% endblocktrans %} + {% endif %} + - + {{ relate_site_name }} +{% endblock %} + +{% block root_container %} +
+
+
+
+
+
+ +
+ +
+
+ + + +
+
+ +
+
+ {# {{{ codemirror resizing #} + + + + +{% endblock %} + diff --git a/relate/urls.py b/relate/urls.py index ddef2e93..b299e41f 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,14 @@ 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), ] -- GitLab From 53d06738e7e9a6de3a519384ee370c1866abddb1 Mon Sep 17 00:00:00 2001 From: paulluh Date: Fri, 9 Mar 2018 17:46:09 -0600 Subject: [PATCH 04/15] [Interface setup] Added JStree and CodeMirror --- course/in_browser_ide.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/course/in_browser_ide.py b/course/in_browser_ide.py index c1a06ce9..81d9fb77 100644 --- a/course/in_browser_ide.py +++ b/course/in_browser_ide.py @@ -1,15 +1,12 @@ from django.contrib.auth.decorators import login_required -from django.core.exceptions import PermissionDenied, ObjectDoesNotExist - from course.utils import course_view, render_course_page -from course.constants import ( - participation_permission as pperm, - ) -from course.content import get_course_repo, get_course_repo_path +from course.content import get_course_repo_path from dulwich import porcelain import io from collections import defaultdict -# @course_view +from course.models import Course + + @login_required @course_view def ide(pctx): @@ -29,7 +26,7 @@ def get_course_directory_structure(course): data = [] directory_structure = defaultdict() paths = io.StringIO() - porcelain.ls_tree(repo, b'HEAD',outstream=paths, recursive=True) + porcelain.ls_tree(repo, b'HEAD', outstream=paths, recursive=True) for path in paths.getvalue().split('\n')[:-1]: path = path.split('\t')[1] @@ -65,7 +62,3 @@ def get_course_directory_structure(course): }) counter += 1 return data - - - - -- GitLab From 8a8a5524052e7be296d6647d1c7e3dfd1b5df21b Mon Sep 17 00:00:00 2001 From: paulluh Date: Fri, 20 Apr 2018 10:41:59 -0500 Subject: [PATCH 05/15] resolving style issue --- course/in_browser_ide.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/course/in_browser_ide.py b/course/in_browser_ide.py index 81d9fb77..ccc0d9dc 100644 --- a/course/in_browser_ide.py +++ b/course/in_browser_ide.py @@ -4,7 +4,6 @@ from course.content import get_course_repo_path from dulwich import porcelain import io from collections import defaultdict -from course.models import Course @login_required @@ -25,7 +24,7 @@ def get_course_directory_structure(course): repo = porcelain.open_repo(repo_path) data = [] directory_structure = defaultdict() - paths = io.StringIO() + paths = io.StringIO() # type: StringIO porcelain.ls_tree(repo, b'HEAD', outstream=paths, recursive=True) for path in paths.getvalue().split('\n')[:-1]: -- GitLab From 3889fa7fcfa395cf618a9d9931eefb2cbb215410 Mon Sep 17 00:00:00 2001 From: paulluh Date: Fri, 20 Apr 2018 11:09:10 -0500 Subject: [PATCH 06/15] try fixing style again --- course/in_browser_ide.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/course/in_browser_ide.py b/course/in_browser_ide.py index ccc0d9dc..71675e2d 100644 --- a/course/in_browser_ide.py +++ b/course/in_browser_ide.py @@ -4,7 +4,11 @@ from course.content import get_course_repo_path from dulwich import porcelain import io from collections import defaultdict +# {{{ mypy +if 0: + from course.models import Course # noqa +# }}} @login_required @course_view @@ -24,7 +28,7 @@ def get_course_directory_structure(course): repo = porcelain.open_repo(repo_path) data = [] directory_structure = defaultdict() - paths = io.StringIO() # type: StringIO + paths = io.StringIO() # type: io.StringIO porcelain.ls_tree(repo, b'HEAD', outstream=paths, recursive=True) for path in paths.getvalue().split('\n')[:-1]: -- GitLab From 9b0a79376b71ee806e144aae2b470fdd4e7996a1 Mon Sep 17 00:00:00 2001 From: paulluh Date: Fri, 20 Apr 2018 11:19:41 -0500 Subject: [PATCH 07/15] try fixing style again --- course/in_browser_ide.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/course/in_browser_ide.py b/course/in_browser_ide.py index 71675e2d..b25b0ea7 100644 --- a/course/in_browser_ide.py +++ b/course/in_browser_ide.py @@ -10,6 +10,7 @@ if 0: from course.models import Course # noqa # }}} + @login_required @course_view def ide(pctx): @@ -27,7 +28,7 @@ def get_course_directory_structure(course): print(repo_path) repo = porcelain.open_repo(repo_path) data = [] - directory_structure = defaultdict() + directory_structure = defaultdict() # type: defaultdict paths = io.StringIO() # type: io.StringIO porcelain.ls_tree(repo, b'HEAD', outstream=paths, recursive=True) @@ -65,3 +66,4 @@ def get_course_directory_structure(course): }) counter += 1 return data + -- GitLab From f7cca2259b1dae88b484c4fca4163b0b15d249b9 Mon Sep 17 00:00:00 2001 From: paulluh Date: Fri, 20 Apr 2018 11:23:09 -0500 Subject: [PATCH 08/15] try fixing style again --- course/in_browser_ide.py | 1 - 1 file changed, 1 deletion(-) diff --git a/course/in_browser_ide.py b/course/in_browser_ide.py index b25b0ea7..d9c44451 100644 --- a/course/in_browser_ide.py +++ b/course/in_browser_ide.py @@ -66,4 +66,3 @@ def get_course_directory_structure(course): }) counter += 1 return data - -- GitLab From a1e66b5725eac0f3906bdba2630fad069a8fde15 Mon Sep 17 00:00:00 2001 From: paulluh Date: Fri, 20 Apr 2018 13:05:39 -0500 Subject: [PATCH 09/15] [IDE] can fetch raw text from repo and display on the frontend --- course/in_browser_ide.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/course/in_browser_ide.py b/course/in_browser_ide.py index d9c44451..89d23b21 100644 --- a/course/in_browser_ide.py +++ b/course/in_browser_ide.py @@ -1,9 +1,10 @@ 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 +from course.content import get_course_repo_path, get_repo_blob from dulwich import porcelain import io from collections import defaultdict +import six # {{{ mypy if 0: @@ -15,17 +16,19 @@ if 0: @course_view def ide(pctx): course = pctx.course - data = get_course_directory_structure(course) + data = get_course_directory_structure(pctx) + return render_course_page(pctx, "course/in_browser_ide.html", { 'file_structure': data, - 'file_content': 'function(){console.log("hello")}' + 'file_content': get_raw_file_text(pctx, 'course.yml') }) -def get_course_directory_structure(course): - # type: (Course) -> list +def get_course_directory_structure(pctx): + + course = pctx.course repo_path = get_course_repo_path(course) - print(repo_path) + repo = porcelain.open_repo(repo_path) data = [] directory_structure = defaultdict() # type: defaultdict @@ -33,6 +36,7 @@ def get_course_directory_structure(course): porcelain.ls_tree(repo, b'HEAD', outstream=paths, recursive=True) for path in paths.getvalue().split('\n')[:-1]: + print(path) path = path.split('\t')[1] files = path.split('/') parent = None @@ -66,3 +70,12 @@ def get_course_directory_structure(course): }) counter += 1 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 -- GitLab From 29a209005009dc9a2a5ff3443858ddfb879b58eb Mon Sep 17 00:00:00 2001 From: paulluh Date: Sat, 5 May 2018 14:35:56 -0500 Subject: [PATCH 10/15] [IDE] Finalize retriving file content dynamically --- course/in_browser_ide.py | 61 ++++++++----------- ...n_browser_ide.html => in-browser-ide.html} | 57 +++++++++++++---- relate/urls.py | 5 +- 3 files changed, 76 insertions(+), 47 deletions(-) rename course/templates/course/{in_browser_ide.html => in-browser-ide.html} (55%) diff --git a/course/in_browser_ide.py b/course/in_browser_ide.py index 89d23b21..a05479da 100644 --- a/course/in_browser_ide.py +++ b/course/in_browser_ide.py @@ -3,6 +3,8 @@ 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 +from django import http from collections import defaultdict import six # {{{ mypy @@ -15,12 +17,19 @@ if 0: @login_required @course_view def ide(pctx): - course = pctx.course data = get_course_directory_structure(pctx) - - return render_course_page(pctx, "course/in_browser_ide.html", { + 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': get_raw_file_text(pctx, 'course.yml') + 'file_content': file_content, + 'selected_node': filename }) @@ -31,44 +40,26 @@ def get_course_directory_structure(pctx): repo = porcelain.open_repo(repo_path) data = [] - directory_structure = defaultdict() # type: defaultdict paths = io.StringIO() # type: io.StringIO porcelain.ls_tree(repo, b'HEAD', outstream=paths, recursive=True) for path in paths.getvalue().split('\n')[:-1]: - print(path) - path = path.split('\t')[1] - files = path.split('/') - parent = None - for file in files: - if file.startswith('.'): - continue - if parent is None: - if parent not in directory_structure: - directory_structure[file] = list() - parent = file - continue - directory_structure[parent].append(file) - parent = file - - counter = 0 - for (parent, children) in directory_structure.items(): + path = path.split('\t')[-1] + parent, file = os.path.split(path) + if parent is '': + parent = '#' data.append({ - 'id': str(counter), - 'parent': '#', - 'text': parent + 'id': path, + 'parent': parent, + 'text': file, + 'type': 'file' }) - parent_id = str(counter) - counter += 1 - - for child in children: - data.append({ - 'id': str(counter), - 'parent': parent_id, - 'text': child - }) - counter += 1 + # 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 diff --git a/course/templates/course/in_browser_ide.html b/course/templates/course/in-browser-ide.html similarity index 55% rename from course/templates/course/in_browser_ide.html rename to course/templates/course/in-browser-ide.html index c022b9cc..0bd360da 100644 --- a/course/templates/course/in_browser_ide.html +++ b/course/templates/course/in-browser-ide.html @@ -10,6 +10,7 @@ + {% endblock %} @@ -20,7 +21,7 @@ [SB] {{ title }} {% endblocktrans %} {% else %} - {% blocktrans %}Page Sandbox{% endblocktrans %} + {% blocktrans %}IDE{% endblocktrans %} {% endif %} - {{ relate_site_name }} @@ -28,34 +29,68 @@ {% block root_container %}
+

Course Content Editor

+

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

+
+
+ +
+
+
+ + +
+
+
-
+
-
- +
-
- - - -
+ + {# {{{ codemirror resizing #} + + + +{% endblock %} + +{% block title %} + {% if title %} + {% comment %} Translators: "[SB]" is abbreviation for "Sandbox" {% endcomment %} + {% blocktrans trimmed %} + [SB] {{ title }} + {% endblocktrans %} + {% else %} + {% blocktrans %}Page Sandbox{% endblocktrans %} + {% endif %} + - + {{ relate_site_name }} +{% endblock %} + +{% block root_container %} +
+
+
+
+
+
+ +
+ +
+
+ + + +
+
+ +
+
+ {# {{{ codemirror resizing #} + + + + +{% endblock %} + diff --git a/relate/urls.py b/relate/urls.py index ddef2e93..b299e41f 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,14 @@ 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), ] -- GitLab From 04c539ef0131c9a4ab2cc600a5b4d882b679b43e Mon Sep 17 00:00:00 2001 From: paulluh Date: Fri, 9 Mar 2018 17:46:09 -0600 Subject: [PATCH 12/15] [Interface setup] Added JStree and CodeMirror --- course/in_browser_ide.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/course/in_browser_ide.py b/course/in_browser_ide.py index c1a06ce9..81d9fb77 100644 --- a/course/in_browser_ide.py +++ b/course/in_browser_ide.py @@ -1,15 +1,12 @@ from django.contrib.auth.decorators import login_required -from django.core.exceptions import PermissionDenied, ObjectDoesNotExist - from course.utils import course_view, render_course_page -from course.constants import ( - participation_permission as pperm, - ) -from course.content import get_course_repo, get_course_repo_path +from course.content import get_course_repo_path from dulwich import porcelain import io from collections import defaultdict -# @course_view +from course.models import Course + + @login_required @course_view def ide(pctx): @@ -29,7 +26,7 @@ def get_course_directory_structure(course): data = [] directory_structure = defaultdict() paths = io.StringIO() - porcelain.ls_tree(repo, b'HEAD',outstream=paths, recursive=True) + porcelain.ls_tree(repo, b'HEAD', outstream=paths, recursive=True) for path in paths.getvalue().split('\n')[:-1]: path = path.split('\t')[1] @@ -65,7 +62,3 @@ def get_course_directory_structure(course): }) counter += 1 return data - - - - -- GitLab From bab2667e6ebaafeecfa0726fede18dda450f0dd2 Mon Sep 17 00:00:00 2001 From: paulluh Date: Fri, 9 Mar 2018 17:43:30 -0600 Subject: [PATCH 13/15] [Interface setup] Added JStree and CodeMirror --- course/in_browser_ide.py | 88 ++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/course/in_browser_ide.py b/course/in_browser_ide.py index 81d9fb77..a05479da 100644 --- a/course/in_browser_ide.py +++ b/course/in_browser_ide.py @@ -1,64 +1,72 @@ 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 +from course.content import get_course_repo_path, get_repo_blob from dulwich import porcelain import io +import os +from django import http from collections import defaultdict -from course.models import Course +import six +# {{{ mypy + +if 0: + from course.models import Course # noqa +# }}} @login_required @course_view def ide(pctx): - course = pctx.course - data = get_course_directory_structure(course) - return render_course_page(pctx, "course/in_browser_ide.html", { + 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': 'function(){console.log("hello")}' + 'file_content': file_content, + 'selected_node': filename }) -def get_course_directory_structure(course): - # type: (Course) -> list +def get_course_directory_structure(pctx): + + course = pctx.course repo_path = get_course_repo_path(course) - print(repo_path) + repo = porcelain.open_repo(repo_path) data = [] - directory_structure = defaultdict() - paths = io.StringIO() + 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] - files = path.split('/') - parent = None - for file in files: - if file.startswith('.'): - continue - if parent is None: - if parent not in directory_structure: - directory_structure[file] = list() - parent = file - continue - directory_structure[parent].append(file) - parent = file - - counter = 0 - for (parent, children) in directory_structure.items(): + path = path.split('\t')[-1] + parent, file = os.path.split(path) + if parent is '': + parent = '#' data.append({ - 'id': str(counter), - 'parent': '#', - 'text': parent + 'id': path, + 'parent': parent, + 'text': file, + 'type': 'file' }) - parent_id = str(counter) - counter += 1 - - for child in children: - data.append({ - 'id': str(counter), - 'parent': parent_id, - 'text': child - }) - counter += 1 + # 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 -- GitLab From 888ac7bcb4f3ce8bef14822f4b662bffb9be350b Mon Sep 17 00:00:00 2001 From: paulluh Date: Sat, 5 May 2018 14:35:56 -0500 Subject: [PATCH 14/15] [IDE] Finalize retriving file content dynamically --- ...n_browser_ide.html => in-browser-ide.html} | 57 +++++++++++++++---- relate/urls.py | 5 +- 2 files changed, 50 insertions(+), 12 deletions(-) rename course/templates/course/{in_browser_ide.html => in-browser-ide.html} (55%) diff --git a/course/templates/course/in_browser_ide.html b/course/templates/course/in-browser-ide.html similarity index 55% rename from course/templates/course/in_browser_ide.html rename to course/templates/course/in-browser-ide.html index c022b9cc..0bd360da 100644 --- a/course/templates/course/in_browser_ide.html +++ b/course/templates/course/in-browser-ide.html @@ -10,6 +10,7 @@ + {% endblock %} @@ -20,7 +21,7 @@ [SB] {{ title }} {% endblocktrans %} {% else %} - {% blocktrans %}Page Sandbox{% endblocktrans %} + {% blocktrans %}IDE{% endblocktrans %} {% endif %} - {{ relate_site_name }} @@ -28,34 +29,68 @@ {% block root_container %}
+

Course Content Editor

+

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

+
+
+ +
+
+
+ + +
+
+
-
+
-
- +
-
- - - -
+ + {# {{{ codemirror resizing #}