Skip to content

Commit

Permalink
feat: Add an option to launch a lab in a new window
Browse files Browse the repository at this point in the history
Add a new view to the XBlock for launching a lab in a new window.
Consolidate the use of the guacamole-common-js library between
the inline LMS lab and the lab launched in a new window.
  • Loading branch information
Maari Tamm committed Nov 29, 2023
1 parent 0b9cb0a commit 1212fae
Show file tree
Hide file tree
Showing 7 changed files with 500 additions and 317 deletions.
4 changes: 4 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
Unreleased
-------------------------
* [Enhancement] Add an option to launch the lab in a new window.

Version 7.7.2 (2023-09-15)
-------------------------
* [Bug fix] Fix editing the `stack_key_type` field in Studio; include
Expand Down
134 changes: 91 additions & 43 deletions hastexo/hastexo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import re
import string
import textwrap
from webob import Response

from xblock.core import XBlock, XML_NAMESPACES
from xblock.fields import Scope, Float, String, Dict, List, Integer, Boolean
Expand Down Expand Up @@ -565,20 +566,92 @@ def get_stack_name(self):

return stack_name

@staticmethod
def _get_text_js_url():
def get_js_urls(self):
"""
Returns the Javascript translation file
for the currently selected language, if supported.
Returns a dict of urls for the Javascript files.
"""
settings = get_xblock_settings()
plugins_url = self.runtime.local_resource_url(
self, 'public/js/plugins.js')

# guacamole common library url
guac_js_version = settings.get("guacamole_js_version", "1.5.2")
guac_common_url = (
self.runtime.local_resource_url(
self,
f'public/js/guacamole-common-js/{guac_js_version}-all.min.js'))

# HastexoGuacamoleClient url
guac_client_url = self.runtime.local_resource_url(
self, 'public/js/client.js')

# HastexoXBlock url
main_js_url = self.runtime.local_resource_url(
self, 'public/js/main.js')

js_urls = {
"plugins_url": plugins_url,
"guac_common_url": guac_common_url,
"guac_client_url": guac_client_url,
"main_js_url": main_js_url,
}

# Translation file url (if supported)
lang_code = translation.get_language()
if lang_code and lang_code in SUPPORTED_LANGUAGES:
text_js = f'public/js/translations/{lang_code}/text.js'
if pkg_resources.resource_exists(loader.module_name, text_js):
return text_js
logger.warning(
"Javascript translation file missing or language is not supported")
return None
text_js_url = f'public/js/translations/{lang_code}/text.js'
if pkg_resources.resource_exists(loader.module_name, text_js_url):
js_urls["text_js_url"] = text_js_url
else:
logger.warning("Javascript translation file missing or "
"language is not supported")
return js_urls

def get_context(self, stack=None):
settings = get_xblock_settings()
stack = stack or self.get_stack()

context = {
"stack_name": stack.name,
"terminal_url": settings.get("terminal_url"),
"keepalive_url": self.runtime.handler_url(self, 'keepalive'),
"timeouts": settings.get("js_timeouts"),
"has_tests": len(self.tests) > 0,
"protocol": self.stack_protocol,
"ports": self.ports,
"port": stack.port,
"instructions_layout": settings.get("instructions_layout"),
"read_only": self.read_only or self.hidden,
"hidden": self.hidden,
"progress_check_label": self.progress_check_label,
"show_hints_on_error": self.show_hints_on_error,
"show_feedback": self.show_feedback,
"progress_check_result_heading": self.progress_check_result_heading
}

return context

@XBlock.handler
def launch_new_window(self, request, suffix=''):
"""
The fullscreen lab view, opened in a new browser window.
"""
# Get context
context = self.get_context()

# Pass the token (for keepalives)
context["csrftoken"] = request.cookies.get('csrftoken')

# Get the JavaScript urls
js_urls = self.get_js_urls().items()
for key, value in js_urls:
context[key] = value

# Render the lab template
template = loader.render_django_template(
"static/html/lab.html", context)

return Response(template)

def student_view(self, context=None):
"""
Expand Down Expand Up @@ -612,47 +685,22 @@ def student_view(self, context=None):
i18n_service=i18n_service
))

# Add the public CSS and JS
# Add the public CSS and JS files
frag.add_css_url(
self.runtime.local_resource_url(self, 'public/css/main.css')
)
frag.add_javascript_url(
self.runtime.local_resource_url(self, 'public/js/plugins.js')
)
frag.add_javascript_url(
self.runtime.local_resource_url(self, 'public/js/main.js')
)
text_js_url = self._get_text_js_url()
if text_js_url:
frag.add_javascript_url(
self.runtime.local_resource_url(self, text_js_url)
)
guac_js_version = settings.get("guacamole_js_version", "1.5.2")
frag.add_javascript_url(
self.runtime.local_resource_url(
self,
f'public/js/guacamole-common-js/{guac_js_version}-all.min.js')
)
js_urls = list(self.get_js_urls().values())
for url in js_urls:
frag.add_javascript_url(url)

# Create the stack in the database
stack = self.create_stack(settings, course_id, student_id)

# Get context
context = self.get_context(stack)

# Call the JS initialization function
frag.initialize_js('HastexoXBlock', {
"terminal_url": settings.get("terminal_url"),
"timeouts": settings.get("js_timeouts"),
"has_tests": len(self.tests) > 0,
"protocol": self.stack_protocol,
"ports": self.ports,
"port": stack.port,
"instructions_layout": settings.get("instructions_layout"),
"read_only": self.read_only or self.hidden,
"hidden": self.hidden,
"progress_check_label": self.progress_check_label,
"show_hints_on_error": self.show_hints_on_error,
"show_feedback": self.show_feedback,
"progress_check_result_heading": self.progress_check_result_heading
})
frag.initialize_js('HastexoXBlock', context)

return frag

Expand Down
Loading

0 comments on commit 1212fae

Please sign in to comment.