mirror of
				https://github.com/avatao-content/baseimage-tutorial-framework
				synced 2025-11-04 09:02:55 +00:00 
			
		
		
		
	Merge pull request #1 from avatao-content/ace-integration
Ace integration
This commit is contained in:
		
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								README.md
									
									
									
									
									
								
							@@ -11,6 +11,7 @@ downloaded from the following locations:
 | 
				
			|||||||
* [Popper.js](https://github.com/FezVrasta/popper.js#installation)
 | 
					* [Popper.js](https://github.com/FezVrasta/popper.js#installation)
 | 
				
			||||||
* [Highlight.js](https://highlightjs.org/download/)
 | 
					* [Highlight.js](https://highlightjs.org/download/)
 | 
				
			||||||
* [Showdown](https://github.com/showdownjs/showdown/releases)
 | 
					* [Showdown](https://github.com/showdownjs/showdown/releases)
 | 
				
			||||||
 | 
					* [ace](https://github.com/ajaxorg/ace-builds/releases)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Building and running with Docker
 | 
					## Building and running with Docker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -21,16 +22,19 @@ Run with `docker run -p 4242:4242 <id>` to bind the container's port to localhos
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Running locally
 | 
					## Running locally
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Open two terminals in the project root.
 | 
					Create a new virtualenv, preferably with [virtualenvwrapper](https://virtualenvwrapper.readthedocs.io). Install the
 | 
				
			||||||
 | 
					dependencies with `pip install tornado pyzmq transitions`. If using virtualenvwrapper, issue `add2virtualenv lib` from
 | 
				
			||||||
 | 
					the project root to add the local libraries to the virtualenv's PYTHONPATH.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Issue 
 | 
					To start the project issue
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
cd src/app/
 | 
					cd src/app/
 | 
				
			||||||
PYTHONPATH="../../lib/" python app.py
 | 
					python app.py
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
in one, and 
 | 
					in one terminal, and
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
cd src/components/
 | 
					cd src/components/
 | 
				
			||||||
PYTHONPATH="../../lib/" python event_handler_main.py
 | 
					python event_handler_main.py
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
in the other.
 | 
					in another. Prepend the python commands with `PYTHONPATH="../../lib/"` if the folder weren't added to the PYTHONPATH
 | 
				
			||||||
 | 
					permanently.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								lib/debug.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								lib/debug.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					from glob import iglob as glob
 | 
				
			||||||
 | 
					from itertools import chain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from tornado.autoreload import watch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# yo dawg, we heard you like generators, so now you can generate generators
 | 
				
			||||||
 | 
					# with generators
 | 
				
			||||||
 | 
					def _static_files():
 | 
				
			||||||
 | 
					    return chain.from_iterable(
 | 
				
			||||||
 | 
					        glob(pattern) for pattern in (
 | 
				
			||||||
 | 
					            'static/*.js', 'static/*.css', 'templates/*htm?'
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def watch_static_files():
 | 
				
			||||||
 | 
					    for file in _static_files():
 | 
				
			||||||
 | 
					        watch(file)
 | 
				
			||||||
@@ -7,6 +7,7 @@ from tornado.web import Application
 | 
				
			|||||||
from tornado.ioloop import IOLoop
 | 
					from tornado.ioloop import IOLoop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from config import WEB_PORT
 | 
					from config import WEB_PORT
 | 
				
			||||||
 | 
					import debug
 | 
				
			||||||
from handlers import MainHandler, ZMQWebSocketHandler, LoginWebappHandler
 | 
					from handlers import MainHandler, ZMQWebSocketHandler, LoginWebappHandler
 | 
				
			||||||
import ui_modules
 | 
					import ui_modules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -23,6 +24,7 @@ if __name__ == '__main__':
 | 
				
			|||||||
        ui_modules=ui_modules,
 | 
					        ui_modules=ui_modules,
 | 
				
			||||||
        autoreload=True
 | 
					        autoreload=True
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    application.listen(WEB_PORT)
 | 
					    application.listen(WEB_PORT)
 | 
				
			||||||
    logging.getLogger().setLevel(logging.DEBUG)
 | 
					    logging.getLogger().setLevel(logging.DEBUG)
 | 
				
			||||||
    logging.debug('Python version: {}'.format(sys.version[:5]))
 | 
					    logging.debug('Python version: {}'.format(sys.version[:5]))
 | 
				
			||||||
@@ -30,4 +32,5 @@ if __name__ == '__main__':
 | 
				
			|||||||
    logging.debug('ZeroMQ version: {}'.format(zmq.zmq_version()))
 | 
					    logging.debug('ZeroMQ version: {}'.format(zmq.zmq_version()))
 | 
				
			||||||
    logging.debug('PyZMQ version: {}'.format(zmq.pyzmq_version()))
 | 
					    logging.debug('PyZMQ version: {}'.format(zmq.pyzmq_version()))
 | 
				
			||||||
    logging.info('Tornado application listening on port {}'.format(WEB_PORT))
 | 
					    logging.info('Tornado application listening on port {}'.format(WEB_PORT))
 | 
				
			||||||
 | 
					    debug.watch_static_files()
 | 
				
			||||||
    IOLoop.instance().start()
 | 
					    IOLoop.instance().start()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								src/app/static/index.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/app/static/index.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					.tfw-container {
 | 
				
			||||||
 | 
					    min-height: 100%;
 | 
				
			||||||
 | 
					    height: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								src/app/static/module-webide.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/app/static/module-webide.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					#anchor_webide {
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    height: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,6 +1,11 @@
 | 
				
			|||||||
let ws = new WebSocket('ws://' + document.location.host + '/ws');
 | 
					let ws = new WebSocket('ws://' + document.location.host + '/ws');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let converter = new showdown.Converter();
 | 
					let converter = new showdown.Converter();
 | 
				
			||||||
 | 
					// TODO: don't hardcode anchor id
 | 
				
			||||||
 | 
					let editor = ace.edit('anchor_webide');
 | 
				
			||||||
 | 
					editor.setTheme('ace/theme/monokai');
 | 
				
			||||||
 | 
					editor.getSession().setMode('ace/mode/python');
 | 
				
			||||||
 | 
					editor.$blockScrolling = Infinity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$('#container').on('click', '.anchor', ( function (event) {
 | 
					$('#container').on('click', '.anchor', ( function (event) {
 | 
				
			||||||
    let anchorName = $(this).attr('id').replace('_event', '');
 | 
					    let anchorName = $(this).attr('id').replace('_event', '');
 | 
				
			||||||
@@ -42,8 +47,7 @@ ws.onmessage = function (messageEvent) {
 | 
				
			|||||||
    console.log(message);
 | 
					    console.log(message);
 | 
				
			||||||
    let $anchor = $('#' + message['anchor']);
 | 
					    let $anchor = $('#' + message['anchor']);
 | 
				
			||||||
    if (message['anchor'] === 'anchor_webide') {
 | 
					    if (message['anchor'] === 'anchor_webide') {
 | 
				
			||||||
        let code = hljs.highlightAuto(message['data']);
 | 
					        editor.setValue(message['data'], -1);
 | 
				
			||||||
        $anchor.html(code.value);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        let formatted_message = converter.makeHtml(message['data']);
 | 
					        let formatted_message = converter.makeHtml(message['data']);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,12 +6,13 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    <link rel="stylesheet" href="{{ static_url('vendor/css/bootstrap.min.css') }}">
 | 
					    <link rel="stylesheet" href="{{ static_url('vendor/css/bootstrap.min.css') }}">
 | 
				
			||||||
    <link rel="stylesheet" href="{{ static_url('vendor/css/highlight/github.min.css')}}">
 | 
					    <link rel="stylesheet" href="{{ static_url('vendor/css/highlight/github.min.css')}}">
 | 
				
			||||||
 | 
					    <link rel="stylesheet" href="{{ static_url('index.css')}}">
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
<body>
 | 
					<body>
 | 
				
			||||||
    <div class="jumbotron text-center">
 | 
					    <div class="jumbotron text-center">
 | 
				
			||||||
        <h1>Tutorial framework Demo</h1>
 | 
					        <h1>Tutorial framework Demo</h1>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div id="container">
 | 
					    <div id="container" class="container-fluid tfw-container">
 | 
				
			||||||
        <!--div class="row">
 | 
					        <!--div class="row">
 | 
				
			||||||
            {% for aid in ('a', 'b', 'c') %}
 | 
					            {% for aid in ('a', 'b', 'c') %}
 | 
				
			||||||
            <div class="col-sm m-3 p-3">
 | 
					            <div class="col-sm m-3 p-3">
 | 
				
			||||||
@@ -25,13 +26,13 @@
 | 
				
			|||||||
            {% end %}
 | 
					            {% end %}
 | 
				
			||||||
        </div-->
 | 
					        </div-->
 | 
				
			||||||
        <div class="row">
 | 
					        <div class="row">
 | 
				
			||||||
            <div class="col-sm m-3 p-3" id="anchor_login">
 | 
					            <div class="col-sm col-md col-lg m-3 p-3" id="anchor_login">
 | 
				
			||||||
                {% module Login('anchor_login') %}
 | 
					                {% module Login('anchor_login') %}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <div class="col-sm m-3 p-3">
 | 
					            <div class="col-sm-6 col-md-6 col-lg-6 m-3 p-3">
 | 
				
			||||||
                {% module WebIDE('anchor_webide') %}
 | 
					                {% module WebIDE('anchor_webide') %}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <div class="col-sm m-3 p-3">
 | 
					            <div class="col-sm col-md col-lg m-3 p-3">
 | 
				
			||||||
                {% module Logger('anchor_logger') %}
 | 
					                {% module Logger('anchor_logger') %}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
@@ -42,6 +43,7 @@
 | 
				
			|||||||
    <script src="{{ static_url('vendor/js/bootstrap.min.js') }}" defer></script>
 | 
					    <script src="{{ static_url('vendor/js/bootstrap.min.js') }}" defer></script>
 | 
				
			||||||
    <script src="{{ static_url('vendor/js/highlight.min.js') }} defer"></script>
 | 
					    <script src="{{ static_url('vendor/js/highlight.min.js') }} defer"></script>
 | 
				
			||||||
    <script src="{{ static_url('vendor/js/showdown.min.js') }} defer"></script>
 | 
					    <script src="{{ static_url('vendor/js/showdown.min.js') }} defer"></script>
 | 
				
			||||||
 | 
					    <script src="{{ static_url('vendor/js/ace/ace.js') }} defer"></script>
 | 
				
			||||||
    <script src="{{ static_url('ws_listener.js') }}" defer></script>
 | 
					    <script src="{{ static_url('ws_listener.js') }}" defer></script>
 | 
				
			||||||
</body>
 | 
					</body>
 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
@@ -1,9 +1,6 @@
 | 
				
			|||||||
<h1>Source code</h1>
 | 
					<h1>Source code</h1>
 | 
				
			||||||
<pre>
 | 
					<div  id="{{ anchor_id }}" class="mt-3 mb-3">
 | 
				
			||||||
    <code id="{{ anchor_id }}">
 | 
					</div>
 | 
				
			||||||
         
 | 
					 | 
				
			||||||
    </code>
 | 
					 | 
				
			||||||
</pre>
 | 
					 | 
				
			||||||
<button type="button" class="btn btn-outline-primary anchor" id="{{ anchor_id }}_event">
 | 
					<button type="button" class="btn btn-outline-primary anchor" id="{{ anchor_id }}_event">
 | 
				
			||||||
    Next
 | 
					    Next
 | 
				
			||||||
</button>
 | 
					</button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,3 +4,6 @@ from tornado.web import UIModule
 | 
				
			|||||||
class WebIDE(UIModule):
 | 
					class WebIDE(UIModule):
 | 
				
			||||||
    def render(self, anchor_id, *args, **kwargs):
 | 
					    def render(self, anchor_id, *args, **kwargs):
 | 
				
			||||||
        return self.render_string('module-webide.html', anchor_id=anchor_id, **kwargs)
 | 
					        return self.render_string('module-webide.html', anchor_id=anchor_id, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def css_files(self):
 | 
				
			||||||
 | 
					        return ['module-webide.css']
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user