mirror of
				https://github.com/avatao-content/frontend-tutorial-framework
				synced 2025-10-31 22:52:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			245 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			245 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # frontend-tutorial-framework
 | ||
| 
 | ||
| This is the Angular frontend of TFW.
 | ||
| 
 | ||
| The main exposed features are our pre-implemented components based on the `src/app/services/websocket.service.ts` service.
 | ||
| This service provides an RxJS based communication API to the framework backend (TFW server and event handlers).
 | ||
| 
 | ||
| Another useful features are a bunch of pre-designed layouts and dynamic switching between them.
 | ||
| 
 | ||
| To learn more about the framework, see the [baseimage-tutorial-framework](https://github.com/avatao-content/baseimage-tutorial-framework) repo.
 | ||
| For more on creating, building and running TFW-based tutorials (not just the frontend) consult [test-tutorial-framework](https://github.com/avatao-content/test-tutorial-framework).
 | ||
| 
 | ||
| ## Components
 | ||
| 
 | ||
| In this section we are going to explore the various pre-made components this project offers.
 | ||
| 
 | ||
| Generally these components connect to a TFW event handler running on the backend.
 | ||
| Communication is handled via simpe APIs exposed by these event handlers – over TFW messages.
 | ||
| 
 | ||
| These APIs are documented in the [baseimage-tutorial-framework](https://github.com/avatao-content/baseimage-tutorial-framework) repository README and as docstrings in the [lib/tfw/components](https://github.com/avatao-content/baseimage-tutorial-framework/tree/master/lib/tfw/components) directory (this is where the implementations of our pre-written event handlers live).
 | ||
| 
 | ||
| Frontend components expose APIs as well (e.g. changing layouts).
 | ||
| These are documented in the API section of this README.
 | ||
| 
 | ||
| ## Configuration
 | ||
| 
 | ||
| Generally it is unadvised to directly modify the source code of our pre-written components (this is hard for us to support and is prone to break).
 | ||
| 
 | ||
| For this reason most components are extensively configurable through the `src/app/config.ts` file.
 | ||
| These configurations range from the enabling of different layouts to how frequently should our IDE save automatically.
 | ||
| 
 | ||
| Should you encounter any missing features, feel free to contact team TFW and we'll consider implementing them as configuration options (a common example would be making a configuration option dynamic).
 | ||
| 
 | ||
| ### Terminal (webshell)
 | ||
| 
 | ||
| This is a full-fledged xterm terminal emulator which runs right in your browser and is based on xterm.js.
 | ||
| The emulator is connected to a `TerminalEventHandler` instance on the backend over websockets.
 | ||
| 
 | ||
| This event handler spawns a `bash` session and a `pty` (pseudoterminal).
 | ||
| It connects the master end of the `pty` to the emulator running in your browser and the slave end to `bash`.
 | ||
| 
 | ||
| This essentially provides a fully functional terminal session for your users in the browser (a convenient alternative for an SSH session).
 | ||
| 
 | ||
| This terminal is fully under your control:
 | ||
| You can write to it (and thus execute commands) and read what commands were executed by the user using the API exposed by the `TerminalEventHandler`.
 | ||
| 
 | ||
| This enables you to pre-type or execute commands for the user and figure out what they are doing in the terminal.
 | ||
| 
 | ||
| ### Console
 | ||
| 
 | ||
| Not unlike how a desktop IDE displays the output of your application, TFW provides a similar component as well.
 | ||
| 
 | ||
| The console can appear in place of the terminal and allows you to display the output of a supervisor process in real time.
 | ||
| 
 | ||
| This means that if you type `print('cats like cheese')` in your application code and run it, you will see `cats like cheese` appear on the console! Pretty neat, right?
 | ||
| 
 | ||
| You can control the displaying of process logs to the console using the `console.rewriteContentWithProcessLogsOnDeploy` key in `config.ts`.
 | ||
| The value of `stdout` or `stderr` will cause the console to display the respective stream, while an empty string will disable any automatic output to the console altogether.
 | ||
| 
 | ||
| We recommend redirecting `stdout` and `stderr` to the same file and displaying the together.
 | ||
| 
 | ||
| The `console.showLiveLogs` key enables real time output from the standard stream you've selected.
 | ||
| 
 | ||
| ### IDE (webIde)
 | ||
| 
 | ||
| This component is a simple text editor based on ACE.
 | ||
| It always shows all files in a given folder and allows you to switch between them using the tabs on top.
 | ||
| The IDE automatically saves any changes made to the files (the interval is configurable).
 | ||
| 
 | ||
| It connects to an `IdeEventHandler` instance on the backend which handles the reading/writing of files and the selection of directories as well.
 | ||
| 
 | ||
| It is also capable of dynamically displaying any changes made to these files from the terminal or from another process (this means that you always see a live view of the files).
 | ||
| 
 | ||
| This component provides an optional 'Deploy' button, which can be configured to restart a process in supervisord.
 | ||
| You can enable this button by editig the `ide.showDeployButton` key of `config.ts`.
 | ||
| To configure which process the button should restart edit `ide.deployProcessName`.
 | ||
| 
 | ||
| ### Messages
 | ||
| 
 | ||
| This is a simple chat-like component you can use to instruct, help and guide your users.
 | ||
| It displays messages sent to the frontend with the key `message.`
 | ||
| 
 | ||
| This component can be used as a simple chatbot as well.
 | ||
| 
 | ||
| You can provide a list of messages to queue and they will be automatically displayed one after the other.
 | ||
| There is a wait time between each message so that the user can properly read them.
 | ||
| This wait time is calculated from the length of the last message, and can be configured using the `messages.messageQueueWPM` key in `config.ts`.
 | ||
| 
 | ||
| You can use the `MessageSender` class to send messages from the TFW server or event handlers written in Python.
 | ||
| 
 | ||
| ### Web – customisable component
 | ||
| 
 | ||
| In some of our layouts there is space allocated for a custom webservice or Angular component.
 | ||
| This allows you to embed your own website in the TFW frontend.
 | ||
| 
 | ||
| There are two ways to do this:
 | ||
| 
 | ||
| Should you prefer to avoid Angular you can run your own webserver on the backend and use our dashboard's `iframe`ing capabilities to include it.
 | ||
| To enable this feature you have to edit `src/app/config.ts` and to set `config.dashboard.iframeUrl` to the route your server is listening on.
 | ||
| 
 | ||
| Note that setting up a custom server is documented in the [test-tutorial-framework](https://github.com/avatao-content/test-tutorial-framework) repo.
 | ||
| 
 | ||
| Alternatively you can create your own Angular component(s) in `src/app/web`.
 | ||
| Just rewrite `WebComponent` as you please or even nest more components into it if needed.
 | ||
| Note that you must set `config.dashboard.iframeUrl` to an empty string(`''`) to enable the displaying of `WebComponent` (this also disables `iframe`ing).
 | ||
| 
 | ||
| ### Dashboard
 | ||
| 
 | ||
| The dashboard is the component that composes all others and organises them into layouts.
 | ||
| 
 | ||
| Edit `src/app/config.ts` to change the layout settings.
 | ||
| 
 | ||
| Set `config.dashboard.currentLayout` to the layout you want to be displayed by default.
 | ||
| 
 | ||
| You can specify the layouts you allow in `config.dashboard.enabledLayouts` (the user can switch between them using a sidebar).
 | ||
| This list must include the value of `currentLayout`.
 | ||
| 
 | ||
| Available layouts– with self explaining names:
 | ||
| - `terminal-ide-web`
 | ||
| - `terminal-ide-vertical`
 | ||
| - `terminal-ide-horizontal`
 | ||
| - `terminal-only`
 | ||
| - `terminal-web`
 | ||
| - `ide-web-vertical`
 | ||
| - `ide-only`
 | ||
| - `web-only`
 | ||
| 
 | ||
| 
 | ||
| ## API
 | ||
| 
 | ||
| Supported frontend APIs are documented here.
 | ||
| 
 | ||
| ### Dynamic configuration
 | ||
| 
 | ||
| Many configuration options are changeable dynamically, like so (these are stuff from `config.ts`):
 | ||
| ```
 | ||
| { 
 | ||
|     "key": ...component name...,
 | ||
|     "data":
 | ||
|     {
 | ||
|         "command": ...configuration key...,
 | ||
|         "value": ...
 | ||
|     }
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| ### Messages
 | ||
| 
 | ||
| To send a messages message you can use the following message:
 | ||
| ```
 | ||
| { 
 | ||
|     "key": "message",
 | ||
|     "data":
 | ||
|     {
 | ||
|         "originator": ...string...,
 | ||
|         "message": ...string...
 | ||
|     }
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| You can queue a list of messages like so:
 | ||
| ```
 | ||
| {
 | ||
|     "key": "queueMessages",
 | ||
|     "data":
 | ||
|     {
 | ||
|         "messages":
 | ||
|         [
 | ||
|             {
 | ||
|                 "originator": ...string...,
 | ||
|                 "message": ...string...
 | ||
|             },
 | ||
|             {
 | ||
|                 "originator": ...string...,
 | ||
|                 "message": ...string...
 | ||
|             },
 | ||
|             ...
 | ||
|         ]
 | ||
|     }
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| ### Dashboard
 | ||
| 
 | ||
| Changing layouts is possible using the following message (note that the layout you switch to must be enabled):
 | ||
| ```
 | ||
| { 
 | ||
|     "key": "dashboard",
 | ||
|     "data":
 | ||
|     {
 | ||
|         "command": "layout",
 | ||
|         "value": ...string...
 | ||
|     }
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| You can hide and show the messages component with the following message:
 | ||
| ```
 | ||
| { 
 | ||
|     "key": "dashboard",
 | ||
|     "data":
 | ||
|     {
 | ||
|         "command": "hideMessages",
 | ||
|         "value": ...boolean...
 | ||
|     }
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| To switch between the terminal and console use this message (where `value` is `terminal` or `console`:
 | ||
| ```
 | ||
| { 
 | ||
|     "key": "dashboard",
 | ||
|     "data":
 | ||
|     {
 | ||
|         "command": "terminalMenuItem",
 | ||
|         "value": ...string...
 | ||
|     }
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| ### Console
 | ||
| 
 | ||
| You can write to the console like so (this is only practical when `rewriteContentWithProcessLogsOnDeploy` equals an empty string):
 | ||
| ```
 | ||
| { 
 | ||
|     "key": "console",
 | ||
|     "data":
 | ||
|     {
 | ||
|         "command": "write",
 | ||
|         "content": ...string...
 | ||
|     }
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| Reading the contents is also possible:
 | ||
| ```
 | ||
| { 
 | ||
|     "key": "console",
 | ||
|     "data":
 | ||
|     {
 | ||
|         "command": "read"
 | ||
|     }
 | ||
| }
 | ||
| ```
 |