From 1b8a45ba4a881cd1cab8d06b1ec16bf67cdce3ad Mon Sep 17 00:00:00 2001 From: Anand Chitipothu Date: Tue, 6 Jul 2021 13:20:02 +0530 Subject: [PATCH] refactor: removed sketch doctype and portal page for home Both of these will be moved to mon_school. --- community/lms/doctype/exercise/exercise.py | 1 - community/lms/doctype/lms_sketch/__init__.py | 0 community/lms/doctype/lms_sketch/livecode.py | 126 --------------- .../lms/doctype/lms_sketch/lms_sketch.js | 8 - .../lms/doctype/lms_sketch/lms_sketch.json | 62 -------- .../lms/doctype/lms_sketch/lms_sketch.py | 105 ------------- community/lms/doctype/lms_sketch/svg.py | 143 ------------------ .../lms/doctype/lms_sketch/test_lms_sketch.py | 10 -- community/lms/models.py | 1 - community/www/home/index.html | 49 ------ community/www/home/index.py | 7 - 11 files changed, 512 deletions(-) delete mode 100644 community/lms/doctype/lms_sketch/__init__.py delete mode 100644 community/lms/doctype/lms_sketch/livecode.py delete mode 100644 community/lms/doctype/lms_sketch/lms_sketch.js delete mode 100644 community/lms/doctype/lms_sketch/lms_sketch.json delete mode 100644 community/lms/doctype/lms_sketch/lms_sketch.py delete mode 100644 community/lms/doctype/lms_sketch/svg.py delete mode 100644 community/lms/doctype/lms_sketch/test_lms_sketch.py delete mode 100644 community/www/home/index.html delete mode 100644 community/www/home/index.py diff --git a/community/lms/doctype/exercise/exercise.py b/community/lms/doctype/exercise/exercise.py index 9fb83621..a7e3308d 100644 --- a/community/lms/doctype/exercise/exercise.py +++ b/community/lms/doctype/exercise/exercise.py @@ -3,7 +3,6 @@ import frappe from frappe.model.document import Document -# from ..lms_sketch.livecode import livecode_to_svg class Exercise(Document): def get_user_submission(self): diff --git a/community/lms/doctype/lms_sketch/__init__.py b/community/lms/doctype/lms_sketch/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/community/lms/doctype/lms_sketch/livecode.py b/community/lms/doctype/lms_sketch/livecode.py deleted file mode 100644 index ab5d8dc5..00000000 --- a/community/lms/doctype/lms_sketch/livecode.py +++ /dev/null @@ -1,126 +0,0 @@ -"""Utilities to work with livecode service. -""" -import websocket -import json -from .svg import SVG -import frappe -from urllib.parse import urlparse - -# Files to pass to livecode server -# The same code is part of livecode-canvas.js -# TODO: generate livecode-canvas.js from this file -START = ''' -import sketch -code = open("main.py").read() -env = dict(sketch.__dict__) -exec(code, env) -''' - -SKETCH = ''' -import json - -def sendmsg(msgtype, function, args): - """Sends a message to the frontend. - - The frontend will receive the specified message whenever - this function is called. The frontend can decide to some - action on each of these messages. - """ - msg = dict(msgtype=msgtype, function=function, args=args) - print("--MSG--", json.dumps(msg)) - -def _draw(func, **kwargs): - sendmsg(msgtype="draw", function=func, args=kwargs) - -def circle(x, y, d): - """Draws a circle of diameter d with center (x, y). - """ - _draw("circle", x=x, y=y, d=d) - -def line(x1, y1, x2, y2): - """Draws a line from point (x1, y1) to point (x2, y2). - """ - _draw("line", x1=x1, y1=y1, x2=x2, y2=y2) - -def rect(x, y, w, h): - """Draws a rectangle on the canvas. - - Parameters - ---------- - x: x coordinate of the top-left corner of the rectangle - y: y coordinate of the top-left corner of the rectangle - w: width of the rectangle - h: height of the rectangle - """ - _draw("rect", x=x, y=y, w=w, h=h) - -def clear(): - _draw("clear") - -# clear the canvas on start -clear() -''' - -def get_livecode_url(): - doc = frappe.get_cached_doc("LMS Settings") - return doc.livecode_url - -def get_livecode_ws_url(): - url = urlparse(get_livecode_url()) - protocol = "wss" if url.scheme == "https" else "ws" - return protocol + "://" + url.netloc + "/livecode" - -def livecode_to_svg(livecode_ws_url, code, *, timeout=3): - """Renders the code as svg. - """ - if livecode_ws_url is None: - livecode_ws_url = get_livecode_ws_url() - - try: - ws = websocket.WebSocket() - ws.settimeout(timeout) - ws.connect(livecode_ws_url) - - msg = { - "msgtype": "exec", - "runtime": "python", - "code": code, - "files": [ - {"filename": "start.py", "contents": START}, - {"filename": "sketch.py", "contents": SKETCH}, - ], - "command": ["python", "start.py"] - } - ws.send(json.dumps(msg)) - - messages = _read_messages(ws) - commands = [m for m in messages if m['msgtype'] == 'draw'] - img = draw_image(commands) - return img.tostring() - except websocket.WebSocketException as e: - frappe.log_error(frappe.get_traceback(), 'livecode_to_svg failed') - -def _read_messages(ws): - messages = [] - try: - while True: - msg = ws.recv() - if not msg: - break - messages.append(json.loads(msg)) - except websocket.WebSocketTimeoutException as e: - print("Error:", e) - pass - return messages - -def draw_image(commands): - img = SVG(width=300, height=300, viewBox="0 0 300 300", fill='none', stroke='black') - for c in commands: - args = c['args'] - if c['function'] == 'circle': - img.circle(cx=args['x'], cy=args['y'], r=args['d']/2) - elif c['function'] == 'line': - img.line(x1=args['x1'], y1=args['y1'], x2=args['x2'], y2=args['y2']) - elif c['function'] == 'rect': - img.rect(x=args['x'], y=args['y'], width=args['w'], height=args['h']) - return img diff --git a/community/lms/doctype/lms_sketch/lms_sketch.js b/community/lms/doctype/lms_sketch/lms_sketch.js deleted file mode 100644 index 020c5909..00000000 --- a/community/lms/doctype/lms_sketch/lms_sketch.js +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2021, FOSS United and contributors -// For license information, please see license.txt - -frappe.ui.form.on('LMS Sketch', { - // refresh: function(frm) { - - // } -}); diff --git a/community/lms/doctype/lms_sketch/lms_sketch.json b/community/lms/doctype/lms_sketch/lms_sketch.json deleted file mode 100644 index c236db10..00000000 --- a/community/lms/doctype/lms_sketch/lms_sketch.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "actions": [], - "autoname": "format:SKETCH-{#}", - "creation": "2021-03-09 16:31:50.523524", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "title", - "runtime", - "code", - "svg" - ], - "fields": [ - { - "fieldname": "title", - "fieldtype": "Data", - "label": "Title" - }, - { - "fieldname": "runtime", - "fieldtype": "Data", - "label": "Runtime" - }, - { - "fieldname": "code", - "fieldtype": "Code", - "label": "Code" - }, - { - "fieldname": "svg", - "fieldtype": "Code", - "label": "SVG", - "read_only": 1 - } - ], - "index_web_pages_for_search": 1, - "links": [], - "modified": "2021-03-12 08:42:56.671658", - "modified_by": "Administrator", - "module": "LMS", - "name": "LMS Sketch", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "share": 1, - "write": 1 - } - ], - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_views": 1 -} \ No newline at end of file diff --git a/community/lms/doctype/lms_sketch/lms_sketch.py b/community/lms/doctype/lms_sketch/lms_sketch.py deleted file mode 100644 index 008bc024..00000000 --- a/community/lms/doctype/lms_sketch/lms_sketch.py +++ /dev/null @@ -1,105 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2021, FOSS United and contributors -# For license information, please see license.txt - -from __future__ import unicode_literals -import hashlib -from urllib.parse import urlparse -import frappe -from frappe.model.document import Document -from . import livecode - -DEFAULT_IMAGE = """ - - -""" - -class LMSSketch(Document): - @property - def sketch_id(self): - """Returns the numeric part of the name. - - For example, the skech_id will be "123" for sketch with name "SKETCH-123". - """ - return self.name.replace("SKETCH-", "") - - def get_owner(self): - """Returns the owner of this sketch as a document. - """ - return frappe.get_doc("User", self.owner) - - def get_owner_name(self): - return self.get_owner().full_name - - def get_livecode_url(self): - doc = frappe.get_cached_doc("LMS Settings") - return doc.livecode_url - - def get_livecode_ws_url(self): - url = urlparse(self.get_livecode_url()) - protocol = "wss" if url.scheme == "https" else "ws" - return protocol + "://" + url.netloc + "/livecode" - - def to_svg(self): - return self.svg or self.render_svg() - - def render_svg(self): - h = hashlib.md5(self.code.encode('utf-8')).hexdigest() - cache = frappe.cache() - key = "sketch-" + h - value = cache.get(key) - if value: - value = value.decode('utf-8') - else: - ws_url = self.get_livecode_ws_url() - value = livecode.livecode_to_svg(ws_url, self.code) - if value: - cache.set(key, value) - return value or DEFAULT_IMAGE - - @staticmethod - def get_recent_sketches(limit=100, owner=None): - """Returns the recent sketches. - """ - filters = {} - if owner: - filters = {"owner": owner} - sketches = frappe.get_all( - "LMS Sketch", - filters=filters, - fields='*', - order_by='modified desc', - page_length=limit - ) - return [frappe.get_doc(doctype='LMS Sketch', **doc) for doc in sketches] - - def __repr__(self): - return f"" - -@frappe.whitelist() -def save_sketch(name, title, code): - if not name or name == "new": - doc = frappe.new_doc('LMS Sketch') - doc.title = title - doc.code = code - doc.runtime = 'python-canvas' - doc.insert(ignore_permissions=True) - status = "created" - else: - doc = frappe.get_doc("LMS Sketch", name) - - if doc.owner != frappe.session.user: - return { - "ok": False, - "error": "Permission Denied" - } - doc.title = title - doc.code = code - doc.svg = '' - doc.save() - status = "updated" - return { - "ok": True, - "status": status, - "name": doc.name, - } diff --git a/community/lms/doctype/lms_sketch/svg.py b/community/lms/doctype/lms_sketch/svg.py deleted file mode 100644 index 596be7ef..00000000 --- a/community/lms/doctype/lms_sketch/svg.py +++ /dev/null @@ -1,143 +0,0 @@ -"""SVG rendering library. - -USAGE: - from svg import SVG - - svg = SVG(width=200, height=200) - svg.circle(cx=100, cy=200, r=50) - print(svg.tostring()) -""" -from xml.etree import ElementTree - -TAGNAMES = set([ - "circle", "ellipse", - "line", "path", "rect", "polygon", "polyline", - "text", "textPath", "title", - "marker", "defs", - "g" -]) - -class Node: - """SVG Node""" - def __init__(self, tag, **attrs): - self.tag = tag - self.attrs = dict((k.replace('_', '-'), str(v)) for k, v in attrs.items()) - self.children = [] - - def node(self, tag, **attrs): - n = Node(tag, **attrs) - self.children.append(n) - return n - - def apply(self, func): - """Applies a function to this node and - all the children recursively. - """ - func(self) - for n in self.children: - n.apply(func) - - def clone(self): - node = Node(self.tag, **self.attrs) - node.children = [n.clone() for n in self.children] - return node - - def add_node(self, node): - if not isinstance(node, Node): - node = Text(node) - self.children.append(node) - - def __getattr__(self, tag): - if tag not in TAGNAMES: - raise AttributeError(tag) - return lambda **attrs: self.node(tag, **attrs) - - def translate(self, x, y): - return self.g(transform="translate(%s, %s)" % (x, y)) - - def scale(self, *args): - return self.g(transform="scale(%s)" % ", ".join(str(a) for a in args)) - - def __repr__(self): - return "<%s .../>" % self.tag - - def __enter__(self): - return self - - def __exit__(self, type, value, traceback): - pass - - def build_tree(self, builder): - builder.start(self.tag, self.attrs) - for node in self.children: - node.build_tree(builder) - return builder.end(self.tag) - - def _indent(self, elem, level=0): - """Indent etree node for prettyprinting.""" - - i = "\n" + level*" " - if len(elem): - if not elem.text or not elem.text.strip(): - elem.text = i + " " - if not elem.tail or not elem.tail.strip(): - elem.tail = i - for elem in elem: - self._indent(elem, level+1) - if not elem.tail or not elem.tail.strip(): - elem.tail = i - else: - if level and (not elem.tail or not elem.tail.strip()): - elem.tail = i - - def save(self, filename, encoding='utf-8'): - f = open(filename, 'w') - f.write(self.tostring()) - f.close() - - def tostring(self, encoding='utf-8'): - builder = ElementTree.TreeBuilder() - self.build_tree(builder) - e = builder.close() - self._indent(e) - return ElementTree.tostring(e, encoding).decode(encoding) - -class Text(Node): - """Text Node - - >>> p = Node("p") - >>> p.add_node("hello, world!") - >>> p.tostring() - '

hello, world!

' - """ - def __init__(self, text): - Node.__init__(self, "__text__") - self._text = text - - def build_tree(self, builder): - builder.data(str(self._text)) - -class SVG(Node): - """ - >>> svg = SVG(width=200, height=200) - >>> svg.rect(x=0, y=0, width=200, height=200, fill="blue") - - >>> with svg.translate(-50, -50) as g: - ... g.rect(x=0, y=0, width=50, height=100, fill="red") - ... g.rect(x=50, y=0, width=50, height=100, fill="green") - - - >>> print(svg.tostring()) - - - - - - - - - """ - def __init__(self, **attrs): - attrs['xmlns'] = "http://www.w3.org/2000/svg" - Node.__init__(self, 'svg', **attrs) - diff --git a/community/lms/doctype/lms_sketch/test_lms_sketch.py b/community/lms/doctype/lms_sketch/test_lms_sketch.py deleted file mode 100644 index b07262a6..00000000 --- a/community/lms/doctype/lms_sketch/test_lms_sketch.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2021, FOSS United and Contributors -# See license.txt -from __future__ import unicode_literals - -# import frappe -import unittest - -class TestLMSSketch(unittest.TestCase): - pass diff --git a/community/lms/models.py b/community/lms/models.py index 2e7249d7..83d0c673 100644 --- a/community/lms/models.py +++ b/community/lms/models.py @@ -1,5 +1,4 @@ """Handy module to make access to all doctypes from a single place. """ from .doctype.lms_course.lms_course import LMSCourse as Course -from .doctype.lms_sketch.lms_sketch import LMSSketch as Sketch from .doctype.lms_batch_membership.lms_batch_membership import LMSBatchMembership as Membership diff --git a/community/www/home/index.html b/community/www/home/index.html deleted file mode 100644 index 49f11da8..00000000 --- a/community/www/home/index.html +++ /dev/null @@ -1,49 +0,0 @@ -{% extends "templates/base.html" %} - -{% block content %} - {{ HeroSection() }} - {{ ExploreCourses(courses) }} - {{ RecentSketches(recent_sketches) }} -{% endblock %} - -{% macro HeroSection() %} -
-
-
-

Guided online programming courses, with a
mentor at your back.

-

Hands-on programming courses designed by experts, delivered by passionate mentors.

- {{ widgets.RequestInvite() }} -
-
-
-{% endmacro %} - -{% macro ExploreCourses(courses) %} -
-
-

Explore Courses

-
- {% for course in courses %} -
- {{ widgets.CourseTeaser(course=course) }} -
- {% endfor %} -
-
-
-{% endmacro %} - -{% macro RecentSketches(sketches) %} -
-
-

Recent Sketches

-
- {% for sketch in sketches %} -
- {{ widgets.SketchTeaser(sketch=sketch) }} -
- {% endfor %} -
-
-
-{% endmacro %} diff --git a/community/www/home/index.py b/community/www/home/index.py deleted file mode 100644 index 34f55b61..00000000 --- a/community/www/home/index.py +++ /dev/null @@ -1,7 +0,0 @@ -import frappe -from community.lms.models import Course, Sketch - -def get_context(context): - context.no_cache = 1 - context.courses = Course.find_all() - context.recent_sketches = Sketch.get_recent_sketches(limit=8)