diff --git a/docs/source/extensions/apps.rst b/docs/source/extensions/apps.rst index b9681acb..53a40b8c 100644 --- a/docs/source/extensions/apps.rst +++ b/docs/source/extensions/apps.rst @@ -69,10 +69,15 @@ Let's start by looking at the file `app.py`. }, ).tag(config=True) + def __init__(self, **kwargs): + NbGrader.__init__(self, **kwargs) + BaseApp.__init__(self, **kwargs) + template_path = os.path.join(os.path.dirname(__file__), "templates") def load_app(self): self.log.info("Loading the convert grades app") + self.initialize([]) # Add the grading scheme to the tornado settings self.update_tornado_settings(dict(e2x_grading_scheme=self.grading_scheme)) self.add_handlers(default_handlers) diff --git a/docs/source/user_docs/cells/cells.rst b/docs/source/user_docs/cells/cells.rst index 8790a362..7fec2a1a 100644 --- a/docs/source/user_docs/cells/cells.rst +++ b/docs/source/user_docs/cells/cells.rst @@ -99,6 +99,24 @@ In student mode the `Edit Cell` button is deactivated and students can not unren .. _diagrams.net: https://diagrams.net +Configuring the Diagram Cells +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can configure the following options for the diagram cells in your ``nbgrader_config.py``: + +* ``drawDomain``: The domain of the diagram instance to use +* ``drawOrigin``: The url of the origin of the diagram instance. This is the url from which the diagram instance sends messages +* ``libraries``: A list of libraries which should be active by default (e.g. *uml*, *general*, *kubernetes*, etc) + +.. code-block:: python + :caption: Example of configuring the diagram editor + + # nbgrader_config.py + + c.DiagramEditor.drawDomain = "https://embed.diagrams.net/" + c.DiagramEditor.drawOrigin = "https://embed.diagrams.net/" + c.DiagramEditor.libraries = ["uml", "general", "arrows2"] + Upload Cells ------------ diff --git a/e2xgrader/server_extensions/apps/diagram_editor/__init__.py b/e2xgrader/server_extensions/apps/diagram_editor/__init__.py new file mode 100644 index 00000000..b9d39bd4 --- /dev/null +++ b/e2xgrader/server_extensions/apps/diagram_editor/__init__.py @@ -0,0 +1,3 @@ +from .diagrameditor import DiagramEditor + +__all__ = ["DiagramEditor"] diff --git a/e2xgrader/server_extensions/apps/diagram_editor/diagrameditor.py b/e2xgrader/server_extensions/apps/diagram_editor/diagrameditor.py new file mode 100644 index 00000000..38d18f6e --- /dev/null +++ b/e2xgrader/server_extensions/apps/diagram_editor/diagrameditor.py @@ -0,0 +1,52 @@ +import json + +from e2xcore import BaseApp +from e2xcore.handlers import E2xApiHandler +from nbgrader.apps.baseapp import NbGrader +from nbgrader.server_extensions.formgrader.base import check_xsrf +from tornado import web +from traitlets import List, Unicode + + +class DiagramConfigHandler(E2xApiHandler): + @web.authenticated + @check_xsrf + def get(self): + self.finish(json.dumps(self.settings.get("diagram_config", dict()))) + + +class DiagramEditor(NbGrader, BaseApp): + drawDomain = Unicode( + default_value=None, allow_none=True, help="The url to drawio" + ).tag(config=True) + drawOrigin = Unicode( + default_value=None, allow_none=True, help="The drawio origin" + ).tag(config=True) + libraries = List(default_value=[], help="A list of activated libraries").tag( + config=True + ) + + def __init__(self, **kwargs): + NbGrader.__init__(self, **kwargs) + BaseApp.__init__(self, **kwargs) + + def get_diagram_config(self): + # self.log.info("My drawDomain is", self.drawDomain) + config = dict() + if self.drawDomain: + config["drawDomain"] = self.drawDomain + if self.drawOrigin: + config["drawOrigin"] = self.drawOrigin + if len(self.libraries) > 0: + config["libs"] = self.libraries + return config + + def load_app(self): + self.log.info("Loading the diagrameditor app") + self.initialize([]) + self.update_tornado_settings(dict(diagram_config=self.get_diagram_config())) + self.add_handlers( + [ + (r"/e2x/diagrams/api", DiagramConfigHandler), + ] + ) diff --git a/e2xgrader/server_extensions/student/student.py b/e2xgrader/server_extensions/student/student.py index dbf8644b..c404d627 100644 --- a/e2xgrader/server_extensions/student/student.py +++ b/e2xgrader/server_extensions/student/student.py @@ -1,6 +1,7 @@ from traitlets import Any, List from ..apps.assignment_list import AssignmentList +from ..apps.diagram_editor import DiagramEditor from ..apps.help import Help from ..apps.validate_assignment import ValidateAssignment from ..base import BaseExtension @@ -9,7 +10,7 @@ class StudentExtension(BaseExtension): apps = List( trait=Any(), - default_value=[AssignmentList, ValidateAssignment, Help], + default_value=[AssignmentList, ValidateAssignment, Help, DiagramEditor], ).tag(config=True) diff --git a/e2xgrader/server_extensions/teacher/teacher.py b/e2xgrader/server_extensions/teacher/teacher.py index 50dceae0..7b608b42 100644 --- a/e2xgrader/server_extensions/teacher/teacher.py +++ b/e2xgrader/server_extensions/teacher/teacher.py @@ -2,6 +2,7 @@ from traitlets import Any, List from ..apps.assignment_list import AssignmentList +from ..apps.diagram_editor import DiagramEditor from ..apps.e2xgraderapi import E2xGraderApi from ..apps.formgrader import FormgradeApp from ..apps.help import Help @@ -21,6 +22,7 @@ class TeacherExtension(BaseExtension): ValidateAssignment, AssignmentList, Help, + DiagramEditor, ], ).tag(config=True) diff --git a/e2xgrader/tests/server_extensions/apps/diagram_editor/test_diagrameditor.py b/e2xgrader/tests/server_extensions/apps/diagram_editor/test_diagrameditor.py new file mode 100644 index 00000000..15d7cd09 --- /dev/null +++ b/e2xgrader/tests/server_extensions/apps/diagram_editor/test_diagrameditor.py @@ -0,0 +1,48 @@ +import unittest + +from traitlets.config import LoggingConfigurable + +from e2xgrader.server_extensions.apps.diagram_editor import DiagramEditor + + +class DummyWebApp: + @property + def settings(self): + return dict() + + +class DummyApp(LoggingConfigurable): + root_dir = "dummy" + name = "dummy" + + @property + def web_app(self): + return DummyWebApp() + + +class TestDiagramEditor(unittest.TestCase): + def setUp(self) -> None: + self.editor = DiagramEditor(parent=DummyApp()) + + def test_empty_config(self): + self.assertDictEqual(self.editor.get_diagram_config(), dict()) + + def test_configure_draw_domain(self): + domain = "myDomain" + self.editor.drawDomain = domain + self.assertDictEqual(self.editor.get_diagram_config(), dict(drawDomain=domain)) + + def test_configure_draw_origin(self): + domain = "myDomain" + self.editor.drawOrigin = domain + self.assertDictEqual(self.editor.get_diagram_config(), dict(drawOrigin=domain)) + + def test_configure_libraries(self): + libraries = ["lib1", "lib2", "lib3"] + self.editor.libraries = libraries + self.assertDictEqual(self.editor.get_diagram_config(), dict(libs=libraries)) + + def tearDown(self) -> None: + self.editor.drawDomain = None + self.editor.drawOrigin = None + self.editor.libraries = [] diff --git a/package-lock.json b/package-lock.json index 1b6e95ba..c46c28bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13762,6 +13762,9 @@ "name": "@e2xgrader/cells", "version": "0.1.1", "license": "ISC", + "dependencies": { + "@e2xgrader/api": "0.1.1" + }, "devDependencies": { "@babel/preset-env": "^7.16.11", "css-loader": "^6.6.0", @@ -15226,6 +15229,7 @@ "version": "file:packages/cells", "requires": { "@babel/preset-env": "^7.16.11", + "@e2xgrader/api": "0.1.1", "css-loader": "^6.6.0", "style-loader": "^3.3.1", "webpack": "^5.70.0", diff --git a/packages/cells/package.json b/packages/cells/package.json index 993dc100..e556fd80 100644 --- a/packages/cells/package.json +++ b/packages/cells/package.json @@ -9,6 +9,9 @@ }, "author": "Tim Metzler", "license": "ISC", + "dependencies": { + "@e2xgrader/api": "0.1.1" + }, "devDependencies": { "@babel/preset-env": "^7.16.11", "css-loader": "^6.6.0", diff --git a/packages/cells/src/cells/diagram-cell.js b/packages/cells/src/cells/diagram-cell.js index ecfb38f2..002b8b02 100644 --- a/packages/cells/src/cells/diagram-cell.js +++ b/packages/cells/src/cells/diagram-cell.js @@ -1,6 +1,6 @@ import { E2xCell } from "./base"; import { AttachmentModel } from "../utils/attachment-model"; -import { DiagramEditor } from "../utils/diagram-editor"; +import DiagramEditor from "../utils/diagram-editor"; class DiagramCellModel extends AttachmentModel { postSaveHook() { @@ -56,7 +56,14 @@ export class DiagramCell extends E2xCell { let button = $("