├── scriptedforms ├── .yarnrc ├── dev_utilities │ ├── __init__.py │ └── jupyterlab_extracts │ │ ├── __init__.py │ │ └── LICENSE ├── e2e │ ├── src │ │ ├── .gitignore │ │ ├── landing-page.md │ │ ├── variable-table.csv │ │ ├── section-start.md │ │ ├── variable-string.md │ │ ├── section-live.md │ │ ├── section-output.md │ │ ├── watchdog-manage.md │ │ ├── section-button.md │ │ ├── watchdog-template.md │ │ ├── protractor.conf.ts │ │ ├── utilities │ │ │ ├── send-token.ts │ │ │ └── before-and-after.ts │ │ ├── variable-table.py │ │ ├── landing-page.spec.ts │ │ ├── section-start.spec.ts │ │ ├── section-live.spec.ts │ │ ├── variable-table.md │ │ ├── section-output.spec.ts │ │ ├── variable-table.spec.ts │ │ ├── watchdog-test.spec.ts │ │ ├── section-button.spec.ts │ │ └── variable-string.spec.ts │ ├── tsconfig.e2e.json │ ├── tsconfig.json │ ├── package.json │ ├── run-test.py │ └── tslint.json ├── src │ ├── docs │ │ ├── landing-page │ │ │ ├── landing-page.component.html │ │ │ └── landing-page.component.ts │ │ ├── doc.component.ts │ │ ├── doc.component.html │ │ ├── doc.routing.ts │ │ ├── style.css │ │ ├── doc.module.ts │ │ └── developer-guide │ │ │ └── README.md │ ├── vendors │ │ ├── misc.ts │ │ ├── angular-styles.ts │ │ ├── jupyterlab-styles.ts │ │ ├── jupyterlab.ts │ │ ├── angular.ts │ │ ├── material.module.ts │ │ └── theme.scss │ ├── polyfills.ts │ ├── tsconfig.app.json │ ├── public-path.ts │ ├── tsconfig.spec.json │ ├── app │ │ ├── types │ │ │ ├── form-status.ts │ │ │ ├── variable-value.ts │ │ │ ├── section-component.ts │ │ │ └── variable-component.ts │ │ ├── interfaces │ │ │ ├── slider.ts │ │ │ ├── variable-store.ts │ │ │ └── pandas-table.ts │ │ ├── variables-module │ │ │ ├── variable-file.component.html │ │ │ ├── number-base.component.ts │ │ │ ├── conditional.component.ts │ │ │ ├── variable-parameter.component.ts │ │ │ ├── tick.component.ts │ │ │ ├── toggle.component.ts │ │ │ ├── number.component.ts │ │ │ ├── variable-file.component.ts │ │ │ ├── string.component.ts │ │ │ ├── variables.module.ts │ │ │ ├── dropdown.component.ts │ │ │ └── slider.component.ts │ │ ├── code-module │ │ │ └── code.module.ts │ │ ├── sections-module │ │ │ ├── start.component.ts │ │ │ ├── sections.module.ts │ │ │ ├── output.component.ts │ │ │ ├── section-file-change.component.ts │ │ │ ├── section-base.component.ts │ │ │ └── button.component.ts │ │ ├── form-builder-module │ │ │ ├── form-builder.module.ts │ │ │ └── session-start-code.ts │ │ ├── app.component.html │ │ ├── services │ │ │ ├── jupyter.service.ts │ │ │ ├── toolbar.service.ts │ │ │ ├── watchdog-code.ts │ │ │ ├── form.service.ts │ │ │ ├── initialisation.service.ts │ │ │ └── watchdog.service.ts │ │ ├── toolbar-module │ │ │ ├── toolbar.module.ts │ │ │ ├── toolbar-button.component.ts │ │ │ └── toolbar-base.component.ts │ │ ├── app-error-handler.ts │ │ ├── app.module.ts │ │ └── style.css │ ├── component-html.d.ts │ ├── docs.ts │ ├── app.ts │ ├── main.ts │ └── dev.ts ├── scripts │ ├── selenium.sh │ ├── pypi.sh │ ├── wait_for_selenium.sh │ ├── travis_script.sh │ ├── pip-freeze.sh │ └── travis_install.sh ├── __main__.py ├── scriptedforms.json ├── webpack.dev.js ├── _version.py ├── docs │ ├── docs-base.md │ ├── landing-page.md │ ├── docs.css │ └── create-your-own-angular-jupyterlab-extension.md ├── webpack.prod.js ├── tsconfig.json ├── __init__.py ├── webpack.config.js ├── index.html ├── _scriptedforms_handlers.py ├── scriptedforms.py ├── forms │ └── agree-to-license.md ├── tslint.json ├── angular.json └── package.json ├── deploy ├── docker │ ├── postgres │ │ └── Dockerfile │ ├── jupyterhub │ │ └── Dockerfile │ ├── nginx.conf │ ├── docker-compose.yml │ └── README.md ├── python-package │ ├── example │ │ ├── experimental │ │ │ ├── __init__.py │ │ │ ├── file-change.csv │ │ │ ├── two-columns.md │ │ │ └── file-change.md │ │ ├── code-template-split │ │ │ ├── __init__.py │ │ │ ├── functions.py │ │ │ ├── data.py │ │ │ └── template-only.md │ │ ├── __init__.py │ │ ├── __main__.py │ │ ├── example.py │ │ └── simple.md │ ├── MANIFEST.in │ ├── setup.py │ └── README.md └── windows-only │ └── portable-zip │ ├── .gitignore │ ├── scriptedforms.bat │ ├── package.json │ ├── README.md │ ├── my-forms │ ├── a-simple-form.md │ ├── landing-page.md │ └── a-slider.md │ └── build-instructions.md ├── images ├── detailed.png └── quick-start.png ├── MANIFEST.in ├── .vscode └── settings.json ├── .travis.yml ├── setup.py ├── .gitignore └── code-of-conduct.md /scriptedforms/.yarnrc: -------------------------------------------------------------------------------- 1 | network-timeout 600000 -------------------------------------------------------------------------------- /scriptedforms/dev_utilities/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /deploy/docker/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres -------------------------------------------------------------------------------- /scriptedforms/e2e/src/.gitignore: -------------------------------------------------------------------------------- 1 | watchdog-test.md -------------------------------------------------------------------------------- /scriptedforms/e2e/src/landing-page.md: -------------------------------------------------------------------------------- 1 | # A landing page -------------------------------------------------------------------------------- /deploy/python-package/example/experimental/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /deploy/docker/jupyterhub/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM jupyterhub/jupyterhub -------------------------------------------------------------------------------- /deploy/python-package/example/code-template-split/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scriptedforms/dev_utilities/jupyterlab_extracts/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /deploy/python-package/example/__init__.py: -------------------------------------------------------------------------------- 1 | from .__main__ import main -------------------------------------------------------------------------------- /deploy/windows-only/portable-zip/.gitignore: -------------------------------------------------------------------------------- 1 | python/ 2 | scriptedforms*.zip -------------------------------------------------------------------------------- /deploy/python-package/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE Apache-2.0 2 | include example/*.md 3 | -------------------------------------------------------------------------------- /images/detailed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBiggs/scriptedforms/HEAD/images/detailed.png -------------------------------------------------------------------------------- /images/quick-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonBiggs/scriptedforms/HEAD/images/quick-start.png -------------------------------------------------------------------------------- /scriptedforms/src/docs/landing-page/landing-page.component.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /scriptedforms/scripts/selenium.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")"/../e2e 3 | yarn selenium 4 | cd - 5 | -------------------------------------------------------------------------------- /deploy/python-package/example/__main__.py: -------------------------------------------------------------------------------- 1 | from .example import main 2 | 3 | if __name__ == '__main__': 4 | main() 5 | -------------------------------------------------------------------------------- /scriptedforms/__main__.py: -------------------------------------------------------------------------------- 1 | from .scriptedforms import main as _main 2 | 3 | if __name__ == '__main__': 4 | _main() 5 | -------------------------------------------------------------------------------- /scriptedforms/scripts/pypi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")"/../../ 3 | python setup.py sdist upload -r pypi 4 | cd - 5 | -------------------------------------------------------------------------------- /scriptedforms/src/vendors/misc.ts: -------------------------------------------------------------------------------- 1 | import '../public-path'; 2 | 3 | import 'json-stable-stringify'; 4 | import 'markdown-it'; 5 | import 'uuid'; 6 | -------------------------------------------------------------------------------- /scriptedforms/scriptedforms.json: -------------------------------------------------------------------------------- 1 | { 2 | "NotebookApp": { 3 | "nbserver_extensions": { 4 | "scriptedforms": true 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /deploy/windows-only/portable-zip/scriptedforms.bat: -------------------------------------------------------------------------------- 1 | start "%~dp0\python\python-3.5.4.amd64\python.exe" -m scriptedforms "%~dp0\my-forms\landing-page.md" 2 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/variable-table.csv: -------------------------------------------------------------------------------- 1 | index,1st,2nd,3rd,4th,5th,6th 2 | a,False,"""",12,apple,sally,1.2123 3 | b,True,,13,apple,philip,2.0 4 | c,True,,1,pear,green,3.0 -------------------------------------------------------------------------------- /scriptedforms/src/vendors/angular-styles.ts: -------------------------------------------------------------------------------- 1 | import 'style-loader!css-loader!sass-loader!./theme.scss'; 2 | import 'material-design-icons/iconfont/material-icons.css'; 3 | -------------------------------------------------------------------------------- /scriptedforms/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | import './public-path'; 2 | 3 | // Polyfills 4 | import 'core-js/es6/reflect'; 5 | import 'core-js/es7/reflect'; 6 | import 'zone.js/dist/zone'; 7 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | graft scriptedforms 2 | global-exclude *.py[co] yarn-error.log 3 | prune scriptedforms/node_modules 4 | prune scriptedforms/e2e/node_modules 5 | prune scriptedforms/e2e/build -------------------------------------------------------------------------------- /deploy/python-package/example/experimental/file-change.csv: -------------------------------------------------------------------------------- 1 | index,1st,2nd,3rd,4th,5th,6th 2 | a,False,"""",12,apple,sally,1.2123 3 | b,True,,13,apple,philip,2.0 4 | c,True,,1,pear,green,3.0 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.linting.enabled": true, 3 | "python.linting.pylintEnabled": false, 4 | "python.linting.flake8Enabled": true, 5 | "python.linting.mypyEnabled": false 6 | } 7 | -------------------------------------------------------------------------------- /scriptedforms/scripts/wait_for_selenium.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | printf 'Waiting for Selenium server to load\n' 4 | until $(curl --output /dev/null --silent --head --fail http://localhost:4444/wd/hub); do 5 | printf '.' 6 | sleep 1 7 | done 8 | printf '\n' -------------------------------------------------------------------------------- /scriptedforms/src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "baseUrl": "./", 6 | "module": "es2015" 7 | }, 8 | "exclude": [ 9 | "test.ts", 10 | "**/*.spec.ts" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /scriptedforms/src/public-path.ts: -------------------------------------------------------------------------------- 1 | declare var __webpack_public_path__: any; 2 | const CONFIG_DIV = document.getElementById('scriptedforms-config-data'); 3 | 4 | if (CONFIG_DIV) { 5 | const config = JSON.parse(CONFIG_DIV.textContent); 6 | __webpack_public_path__ = config.publicPath; 7 | } 8 | -------------------------------------------------------------------------------- /scriptedforms/e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": [ 9 | "jasmine", 10 | "jasminewd2", 11 | "node" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /deploy/python-package/example/code-template-split/functions.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from IPython.display import display, Markdown 3 | 4 | display(Markdown( 5 | 'Loaded functions.py at {}' 6 | .format(str(datetime.now())) 7 | )) 8 | 9 | 10 | def increment(a_table): 11 | a_table.loc['6MV', 'Meas1'] += 1 12 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/section-start.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ```python 6 | from IPython.display import display, Markdown 7 | ``` 8 | 9 | 10 | 11 | 12 | 13 | ```python 14 | display(Markdown('# Hello')) 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /scriptedforms/src/docs/doc.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | import * as htmlTemplate from 'html-loader!./doc.component.html'; 4 | const template = '' + htmlTemplate; 5 | 6 | @Component({ 7 | selector: 'doc-root', 8 | template: template 9 | }) 10 | export class DocComponent { 11 | constructor( 12 | ) {} 13 | } 14 | -------------------------------------------------------------------------------- /scriptedforms/e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitAny": true, 4 | "noEmitOnError": true, 5 | "noUnusedLocals": true, 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "target": "es5", 9 | "outDir": "./build", 10 | "lib": [ 11 | "es2017", 12 | "dom" 13 | ] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /scriptedforms/webpack.dev.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var webpackMerge = require('webpack-merge'); 3 | var baseConfig = require('./webpack.config.js'); 4 | 5 | module.exports = webpackMerge(baseConfig, { 6 | plugins: [ 7 | new webpack.DefinePlugin({ 8 | 'process.env.NODE_ENV': JSON.stringify('development') 9 | }) 10 | ] 11 | }); -------------------------------------------------------------------------------- /scriptedforms/src/vendors/jupyterlab-styles.ts: -------------------------------------------------------------------------------- 1 | import '@jupyterlab/rendermime/style/index.css'; 2 | import '@jupyterlab/notebook/style/index.css'; 3 | import '@jupyterlab/outputarea/style/index.css'; 4 | 5 | import '@jupyterlab/codemirror/style/index.css'; 6 | 7 | import '@jupyterlab/application/style/materialcolors.css'; 8 | import '@jupyterlab/theme-light-extension/static/index.css'; 9 | -------------------------------------------------------------------------------- /deploy/windows-only/portable-zip/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "update": "wine ./python/python-*/python.exe -m pip --no-cache-dir install --upgrade scriptedforms numpy pandas matplotlib", 4 | "test": "wine ./python/python-*/python.exe -m scriptedforms ./my-forms/a-slider.md", 5 | "zip": "zip -r scriptedforms-windows-portable.zip python/* my-forms/* scriptedforms.bat" 6 | } 7 | } -------------------------------------------------------------------------------- /scriptedforms/src/vendors/jupyterlab.ts: -------------------------------------------------------------------------------- 1 | import '../public-path'; 2 | 3 | import '@jupyterlab/codemirror'; 4 | import '@jupyterlab/docregistry'; 5 | import '@jupyterlab/outputarea'; 6 | import '@jupyterlab/rendermime'; 7 | import '@jupyterlab/services'; 8 | import '@jupyterlab/theme-light-extension'; 9 | import '@phosphor/signaling'; 10 | import '@phosphor/widgets'; 11 | 12 | import './jupyterlab-styles'; 13 | -------------------------------------------------------------------------------- /scriptedforms/scripts/travis_script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) Jupyter Development Team. 4 | # Distributed under the terms of the Modified BSD License. 5 | 6 | set -ex 7 | export DISPLAY=:99.0 8 | sh -e /etc/init.d/xvfb start || true 9 | 10 | export PATH="$MINICONDA_DIR/bin:$PATH" 11 | source activate test 12 | 13 | cd "$(dirname "$0")"/../e2e 14 | yarn 15 | yarn selenium & 16 | yarn e2e 17 | cd - 18 | -------------------------------------------------------------------------------- /scriptedforms/scripts/pip-freeze.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export PATH="~/.pyenv/bin:$PATH" 3 | eval "$(pyenv init -)" 4 | eval "$(pyenv virtualenv-init -)" 5 | 6 | yes | pyenv uninstall scriptedforms 7 | pyenv virtualenv 3.5.5 scriptedforms 8 | pyenv activate scriptedforms 9 | pip install --upgrade -e "$(dirname "$0")"/../../ 10 | yes | pip uninstall scriptedforms 11 | pip freeze > "$(dirname "$0")"/../../requirements.txt 12 | -------------------------------------------------------------------------------- /scriptedforms/_version.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | 4 | try: 5 | HERE = os.path.dirname(__file__) 6 | except NameError: 7 | HERE = 'scriptedforms' 8 | 9 | with open(os.path.join(HERE, 'package.json')) as file: 10 | data = json.load(file) 11 | 12 | version_info = data['version'].replace('.', ' ').replace('-', ' ').split(' ') 13 | __version__ = '.'.join(map(str, version_info[:3])) + ''.join(version_info[3:]) 14 | -------------------------------------------------------------------------------- /scriptedforms/src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "types": [ 8 | "jasmine", 9 | "node" 10 | ] 11 | }, 12 | "files": [ 13 | "test.ts", 14 | "polyfills.ts" 15 | ], 16 | "include": [ 17 | "**/*.spec.ts", 18 | "**/*.d.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/variable-string.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ```python 6 | foo = '' 7 | ``` 8 | 9 | 10 | 11 | 12 | 13 | foo 14 | foo 15 | 16 | ```python 17 | print(foo) 18 | ``` 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /scriptedforms/src/docs/doc.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

ScriptedForms

5 |
Navigation
6 |
links
7 |
go
8 |
here
9 |
10 | 11 |
12 | 13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /deploy/docker/nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 1024; 3 | } 4 | 5 | http { 6 | server { 7 | listen 80; 8 | server_name scriptedforms.com.au; 9 | charset utf-8; 10 | 11 | location / { 12 | proxy_pass http://jupyterhub:8000; 13 | proxy_set_header Host $host; 14 | proxy_set_header X-Real-IP $remote_addr; 15 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/section-live.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ```python 6 | from IPython.display import display, Markdown 7 | ``` 8 | 9 | 10 | 11 | 12 | 13 | ```python 14 | foo = 'bar' 15 | ``` 16 | 17 | 18 | 19 | 20 | 21 | foo 22 | 23 | ```python 24 | print('{}'.format(foo)) 25 | ``` 26 | 27 | -------------------------------------------------------------------------------- /deploy/docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.6" 2 | 3 | services: 4 | nginx: 5 | restart: always 6 | image: nginx 7 | ports: 8 | - "80:80" 9 | volumes: 10 | - ./nginx.conf:/etc/nginx/nginx.conf:ro 11 | links: 12 | - jupyterhub:jupyterhub 13 | command: [nginx-debug, '-g', 'daemon off;'] 14 | 15 | jupyterhub: 16 | restart: always 17 | build: ./jupyterhub 18 | links: 19 | - postgres:postgres 20 | 21 | postgres: 22 | restart: always 23 | build: ./postgres -------------------------------------------------------------------------------- /scriptedforms/src/docs/doc.routing.ts: -------------------------------------------------------------------------------- 1 | import { ModuleWithProviders } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { LandingPageComponent } from './landing-page/landing-page.component'; 5 | 6 | 7 | const appRoutes: Routes = [ 8 | { 9 | path: '', 10 | component: LandingPageComponent 11 | }, 12 | { 13 | path: '**', component: LandingPageComponent 14 | } 15 | ]; 16 | 17 | export const RoutingModule: ModuleWithProviders = RouterModule.forRoot(appRoutes); 18 | -------------------------------------------------------------------------------- /deploy/windows-only/portable-zip/README.md: -------------------------------------------------------------------------------- 1 | # Portable Windows Bundle 2 | 3 | Download `scriptedforms-windows-portable.zip` from the latest release: 4 | 5 | > 6 | 7 | Extract this zip file and run `scriptedforms.bat`. This will start a browser 8 | pointing to the form called `landing-page.md` within the `my-forms` directory. 9 | 10 | Edit the forms within the `my-forms` directory. Feel free to the rebundle up 11 | the zip and share the form bundle with your colleagues. -------------------------------------------------------------------------------- /scriptedforms/docs/docs-base.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

ScriptedForms

7 |
Navigation
8 |
links
9 |
go
10 |
here
11 |
12 | 13 | 14 |
15 | {% block content %}{% endblock %} 16 |
17 |
18 | 19 |
20 | -------------------------------------------------------------------------------- /scriptedforms/webpack.prod.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var webpackMerge = require('webpack-merge'); 3 | var baseConfig = require('./webpack.config.js'); 4 | 5 | module.exports = webpackMerge(baseConfig, { 6 | plugins: [ 7 | new webpack.NoEmitOnErrorsPlugin(), 8 | // new webpack.optimize.UglifyJsPlugin({ 9 | // mangle: { 10 | // keep_fnames: true 11 | // } 12 | // }), 13 | new webpack.DefinePlugin({ 14 | 'process.env.NODE_ENV': JSON.stringify('production') 15 | }) 16 | ] 17 | }); -------------------------------------------------------------------------------- /scriptedforms/src/vendors/angular.ts: -------------------------------------------------------------------------------- 1 | import '../public-path'; 2 | 3 | import '@angular/animations'; 4 | import '@angular/cdk'; 5 | import '@angular/common'; 6 | import '@angular/compiler'; 7 | import '@angular/core'; 8 | import '@angular/forms'; 9 | import '@angular/http'; 10 | import '@angular/material'; 11 | import '@angular/platform-browser'; 12 | import '@angular/platform-browser-dynamic'; 13 | 14 | import 'hammerjs'; 15 | import 'rxjs/BehaviorSubject'; 16 | import 'rxjs/Subscription'; 17 | import 'zone.js'; 18 | 19 | import './angular-styles'; 20 | -------------------------------------------------------------------------------- /deploy/python-package/example/code-template-split/data.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | 4 | from datetime import datetime 5 | from IPython.display import display, Markdown 6 | 7 | display(Markdown( 8 | 'Loaded data.py at {}' 9 | .format(str(datetime.now())) 10 | )) 11 | 12 | table = pd.DataFrame( 13 | columns=['Meas1', 'Meas2', 'Adjust'], 14 | index=['6MV', '10MV'], 15 | data=[[6, np.nan, False], [4, 5, False]]) 16 | 17 | input_types = { 18 | 'Meas1': 'number', 'Meas2': 'number', 'Adjust': 'toggle' 19 | } 20 | 21 | display(table) 22 | -------------------------------------------------------------------------------- /deploy/python-package/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name="example", 5 | version="0.1.0", 6 | author="Your Name", 7 | author_email="Your Email", 8 | description="Your short description", 9 | long_description="Your long description", 10 | packages=[ 11 | "example" 12 | ], 13 | entry_points={ 14 | 'console_scripts': [ 15 | 'example=example:main', 16 | ], 17 | }, 18 | license='AGPL-3.0+', 19 | install_requires=[ 20 | 'scriptedforms' 21 | ], 22 | include_package_data=True 23 | ) 24 | -------------------------------------------------------------------------------- /deploy/windows-only/portable-zip/my-forms/a-simple-form.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # A simple form 4 | 5 | ## Edit this form 6 | 7 | Open the plain text form file in a new window using the following link: 8 | 9 | > [Edit this form](../../edit/a-simple-form.md) 10 | 11 | With this window open, and the edit window open side by side you can see the 12 | effects of changes on the interface. 13 | 14 | ## Hello World 15 | 16 | 17 | 18 | your_name 19 | 20 | ```python 21 | print('Hello {}!'.format(your_name)) 22 | ``` 23 | 24 | -------------------------------------------------------------------------------- /scriptedforms/e2e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@simonbiggs/tests-e2e-scriptedforms", 3 | "version": "0.0.0", 4 | "private": true, 5 | "license": "AGPL-3.0+", 6 | "scripts": { 7 | "update": "webdriver-manager update", 8 | "selenium": "yarn update && webdriver-manager start", 9 | "e2e": "../scripts/wait_for_selenium.sh && tsc && python run-test.py" 10 | }, 11 | "dependencies": { 12 | "protractor": "^5.3.0" 13 | }, 14 | "devDependencies": { 15 | "@types/jasmine": "^2.8.6", 16 | "@types/jasminewd2": "^2.0.3", 17 | "rimraf": "~2.6.2", 18 | "typescript": "~2.6.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /scriptedforms/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "sourceMap": true, 5 | "declaration": true, 6 | "noImplicitAny": true, 7 | "noEmitOnError": true, 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "noUnusedLocals": true, 11 | "module": "commonjs", 12 | "moduleResolution": "node", 13 | "target": "es5", 14 | "outDir": "./jlab-build", 15 | "lib": [ 16 | "es2017", 17 | "dom" 18 | ], 19 | "typeRoots": [ 20 | "node_modules/@types" 21 | ] 22 | }, 23 | "include": ["src/*"] 24 | } 25 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/section-output.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ```python 6 | from IPython.display import display, Markdown 7 | ``` 8 | 9 | 10 | 11 | 12 | 13 | ```python 14 | foo = '' 15 | bar = 0 16 | ``` 17 | 18 | 19 | 20 | foo 21 | bar 22 | 23 | 24 | 25 | ```python 26 | bar += 1 27 | ``` 28 | 29 | 30 | 31 | 32 | 33 | ```python 34 | print('foo: {}, bar: {}'.format(foo, bar)) 35 | ``` 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /scriptedforms/docs/landing-page.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Live documentation 4 | 5 | There isn't any docs here yet. 6 | 7 | Watch this space. 8 | 9 | ## Available example forms 10 | 11 | 12 | 13 | ```python 14 | import urllib.parse 15 | from glob import glob 16 | from IPython.display import display, Markdown 17 | ``` 18 | 19 | 20 | 21 | 22 | 23 | ```python 24 | filepaths = glob('*.md') + glob('*/*.md') + glob('*/*/*.md') 25 | for filepath in filepaths: 26 | escaped_filepath = urllib.parse.quote(filepath) 27 | display(Markdown('[{}](../use/{})'.format(filepath, escaped_filepath))) 28 | ``` 29 | 30 | -------------------------------------------------------------------------------- /scriptedforms/src/app/types/form-status.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | export type FormStatus = 'initialising' | 'ready' | 'restarting'; 17 | -------------------------------------------------------------------------------- /scriptedforms/src/component-html.d.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | 5 | /* 6 | * # Create your own Angular JupyterLab extension (cont.) 7 | * 8 | * This is part of the guide available at 9 | * 10 | * 11 | * ## The custom html loader module 12 | * 13 | * Within [app.component.ts](./app/app.component.ts) the need for the special 14 | * importing of Angular HTML templates is described. 15 | * 16 | * So that Typescript allows that process this type definition is needed. 17 | */ 18 | 19 | 20 | declare module "html-loader!*.component.html" { 21 | const content: string; 22 | export = content; 23 | } 24 | -------------------------------------------------------------------------------- /scriptedforms/src/app/interfaces/slider.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | export interface Slider { 17 | min: number; 18 | max: number; 19 | step: number; 20 | value: number; 21 | } 22 | -------------------------------------------------------------------------------- /scriptedforms/__init__.py: -------------------------------------------------------------------------------- 1 | # Scripted Forms -- Making GUIs easy for everyone on your team. 2 | # Copyright (C) 2017 Simon Biggs 3 | 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | from .scriptedforms import ( # noqa F401 17 | load, main, 18 | load_jupyter_server_extension, _jupyter_server_extension_paths) 19 | 20 | from ._version import version_info, __version__ # noqa F401 -------------------------------------------------------------------------------- /scriptedforms/e2e/src/watchdog-manage.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ```python 6 | import os 7 | from IPython.display import display, Markdown 8 | 9 | template_filename = 'watchdog-template.md' 10 | test_filename = 'watchdog-test.md' 11 | 12 | with open(template_filename, 'r') as file: 13 | template_contents = file.read() 14 | ``` 15 | 16 | 17 | 18 | 19 | 20 | ```python 21 | display(Markdown('[{0}]({0})'.format(test_filename))) 22 | ``` 23 | 24 | 25 | 26 | 27 | 28 | ```python 29 | with open(test_filename, 'w') as file: 30 | file.write(template_contents) 31 | ``` 32 | 33 | 34 | 35 | 36 | 37 | ```python 38 | os.remove(test_filename) 39 | ``` 40 | 41 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/section-button.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ```python 6 | from IPython.display import display, Markdown 7 | ``` 8 | 9 | 10 | 11 | 12 | 13 | ```python 14 | button_enabled = False 15 | ``` 16 | 17 | 18 | 19 | 20 | 21 | 22 | ```python 23 | display(Markdown('# Hello')) 24 | ``` 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ```python 34 | button_enabled = False 35 | ``` 36 | 37 | 38 | 39 | 40 | 41 | 42 | ```python 43 | button_enabled = True 44 | ``` 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /scriptedforms/src/app/interfaces/variable-store.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { VariableValue } from '../types/variable-value'; 17 | 18 | export interface VariableStore { 19 | [key: string]: { 20 | defined: boolean, 21 | value?: VariableValue, 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /scriptedforms/src/app/types/variable-value.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { PandasTable } from '../interfaces/pandas-table'; 18 | import { Slider } from '../interfaces/slider'; 19 | 20 | export type VariableValue = boolean | string | number | PandasTable | Slider | string[] | number[]; 21 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/watchdog-template.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ```python 6 | from IPython.display import display, Markdown 7 | 8 | template_filename = 'watchdog-template.md' 9 | test_filename = 'watchdog-test.md' 10 | manage_filename = 'watchdog-manage.md' 11 | 12 | with open(template_filename, 'r') as file: 13 | template_contents = file.read() 14 | ``` 15 | 16 | 17 | 18 | 19 | 20 | ```python 21 | display(Markdown('[{0}]({0})'.format(manage_filename))) 22 | ``` 23 | 24 | 25 | 26 | 27 | 28 | to_be_prepended 29 | 30 | ```python 31 | new_template_contents = to_be_prepended + '\n\n' + template_contents 32 | 33 | with open(test_filename, 'w') as file: 34 | file.write(new_template_contents) 35 | ``` 36 | 37 | -------------------------------------------------------------------------------- /deploy/windows-only/portable-zip/my-forms/landing-page.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Scripted Forms Landing Page 4 | 5 | ## Edit this form 6 | 7 | Open the plain text form file in a new window using the following link: 8 | 9 | > [Edit this form](../../edit/landing-page.md) 10 | 11 | With this window open, and the edit window open side by side you can see the 12 | effects of changes on the interface. 13 | 14 | ## My forms 15 | 16 | Below is a link to all of the forms within this directory. This list will live 17 | update as you add more forms. 18 | 19 | 20 | 21 | ```python 22 | from glob import glob 23 | from IPython.display import display, Markdown 24 | ``` 25 | 26 | 27 | 28 | 29 | 30 | ```python 31 | filepaths = glob('*.md') + glob('*/*.md') + glob('*/*/*.md') 32 | for filepath in filepaths: 33 | display(Markdown('[./{0}]({0})'.format(filepath))) 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /scriptedforms/src/docs.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import './docs/style.css'; 17 | 18 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 19 | import { DocModule } from './docs/doc.module'; 20 | 21 | export function loadDocs() { 22 | platformBrowserDynamic().bootstrapModule(DocModule); 23 | } 24 | -------------------------------------------------------------------------------- /scriptedforms/src/app/interfaces/pandas-table.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | export interface PandasTable { 17 | schema: { 18 | fields: { 19 | name: string 20 | type: string 21 | }[] 22 | primaryKey: string | number 23 | pandas_version: string 24 | }; 25 | data: { [key: string]: string | number }[]; 26 | } 27 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/protractor.conf.ts: -------------------------------------------------------------------------------- 1 | import { Config } from 'protractor'; 2 | 3 | let config: Config = { 4 | framework: 'jasmine', 5 | params: { 6 | token: process.env.JUPYTER_TOKEN 7 | }, 8 | specs: [ 'utilities/send-token.js', process.env.PROTRACTOR_PATTERN ], 9 | noGlobals: false 10 | }; 11 | 12 | if (process.env.SAUCE_USERNAME) { 13 | config.capabilities = { 14 | 'sauceUser': process.env.SAUCE_USERNAME, 15 | 'sauceKey': process.env.SAUCE_ACCESS_KEY, 16 | 'browserName': process.env.BROWSER, 17 | 'name': `ScriptedForms`, 18 | 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER, 19 | 'build': process.env.TRAVIS_BUILD_NUMBER, 20 | 'platform': process.env.PLATFORM 21 | }; 22 | config.seleniumAddress = `http://${process.env.SAUCE_USERNAME}:${process.env.SAUCE_ACCESS_KEY}@localhost:4445/wd/hub` 23 | } else { 24 | config.capabilities = { 25 | browserName: 'chrome' 26 | } 27 | config.seleniumAddress = 'http://localhost:4444/wd/hub' 28 | } 29 | 30 | export { config }; 31 | -------------------------------------------------------------------------------- /deploy/python-package/example/example.py: -------------------------------------------------------------------------------- 1 | # Your Package Name -- Short description of your package. 2 | # Copyright (C) YEAR Your Name 3 | 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | import os 18 | import scriptedforms as sf 19 | 20 | 21 | def hello(name): 22 | print('Hello {}!'.format(name)) 23 | 24 | 25 | def main(): 26 | here = os.path.dirname(__file__) 27 | filepath = os.path.join(here, 'simple.md') 28 | sf.load(filepath) 29 | 30 | 31 | if __name__ == "__main__": 32 | main() 33 | -------------------------------------------------------------------------------- /scriptedforms/src/app/variables-module/variable-file.component.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /deploy/python-package/example/simple.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # An example 4 | 5 | 6 | 7 | ```python 8 | from glob import glob 9 | from IPython.display import display, Markdown 10 | 11 | # By using autoreload, any changes within the python package will update 12 | # automatically. This will slow the form down though, so only use it during 13 | # development. 14 | # http://ipython.readthedocs.io/en/stable/config/extensions/autoreload.html 15 | %load_ext autoreload 16 | %autoreload 1 17 | %aimport example 18 | 19 | # Normally you would just need to use the following: 20 | # import example 21 | ``` 22 | 23 | 24 | 25 | 26 | 27 | your_name 28 | 29 | ```python 30 | example.hello(your_name) 31 | ``` 32 | 33 | 34 | 35 | ## Links to all of the example files provided 36 | 37 | 38 | 39 | ```python 40 | filepaths = glob('*.md') + glob('**/*.md') 41 | for filepath in filepaths: 42 | display(Markdown('[./{0}]({0})'.format(filepath))) 43 | ``` 44 | 45 | -------------------------------------------------------------------------------- /scriptedforms/src/app/code-module/code.module.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | /* 17 | 18 | */ 19 | 20 | import { NgModule } from '@angular/core'; 21 | import { CommonModule } from '@angular/common'; 22 | 23 | import { CodeComponent } from './code.component'; 24 | 25 | 26 | @NgModule({ 27 | imports: [ 28 | CommonModule 29 | ], 30 | declarations: [ 31 | CodeComponent 32 | ], 33 | exports: [ 34 | CodeComponent, 35 | ] 36 | }) 37 | export class CodeModule { } 38 | -------------------------------------------------------------------------------- /scriptedforms/docs/docs.css: -------------------------------------------------------------------------------- 1 | .mat-sidenav { 2 | padding: 0px 40px; 3 | border-right: 1px solid #e0e0e0; 4 | background-color: #fafafa !important; 5 | } 6 | 7 | html { 8 | font-family: Roboto, "Helvetica Neue", sans-serif; 9 | } 10 | 11 | .content-frame { 12 | padding: 50px; 13 | line-height: 150%; 14 | } 15 | 16 | .fixed-toolbar { 17 | overflow: hidden; 18 | position: fixed; 19 | top: 0; 20 | left: 0; 21 | right: 0; 22 | z-index: 2; 23 | } 24 | 25 | .mat-sidenav-container { 26 | position: absolute !important; 27 | top: 0 !important; 28 | left: 0 !important; 29 | right: 0 !important; 30 | bottom: 0 !important; 31 | } 32 | 33 | a { 34 | word-wrap: break-word; 35 | } 36 | 37 | 38 | .primary-header-container { 39 | background: #009688; 40 | } 41 | 42 | .primary-header { 43 | padding: 50px; 44 | color: #fff; 45 | font-weight: 300; 46 | margin: 0; 47 | font-size: 35px; 48 | } 49 | 50 | .form { 51 | font-family: Roboto, "Helvetica Neue", sans-serif; 52 | } 53 | 54 | .mini-form { 55 | display: flex; 56 | flex-direction: column; 57 | } 58 | 59 | .mini-form .p-Widget { 60 | position: static !important; 61 | } 62 | -------------------------------------------------------------------------------- /scriptedforms/src/docs/style.css: -------------------------------------------------------------------------------- 1 | .mat-sidenav { 2 | padding: 0px 40px; 3 | border-right: 1px solid #e0e0e0; 4 | background-color: #fafafa !important; 5 | } 6 | 7 | html { 8 | font-family: Roboto, "Helvetica Neue", sans-serif; 9 | } 10 | 11 | .content-frame { 12 | padding: 50px; 13 | line-height: 150%; 14 | } 15 | 16 | .fixed-toolbar { 17 | overflow: hidden; 18 | position: fixed; 19 | top: 0; 20 | left: 0; 21 | right: 0; 22 | z-index: 2; 23 | } 24 | 25 | .mat-sidenav-container { 26 | position: absolute !important; 27 | top: 0 !important; 28 | left: 0 !important; 29 | right: 0 !important; 30 | bottom: 0 !important; 31 | } 32 | 33 | a { 34 | word-wrap: break-word; 35 | } 36 | 37 | 38 | .primary-header-container { 39 | background: #009688; 40 | } 41 | 42 | .primary-header { 43 | padding: 50px; 44 | color: #fff; 45 | font-weight: 300; 46 | margin: 0; 47 | font-size: 35px; 48 | } 49 | 50 | .form { 51 | font-family: Roboto, "Helvetica Neue", sans-serif; 52 | } 53 | 54 | .mini-form { 55 | display: flex; 56 | flex-direction: column; 57 | } 58 | 59 | .mini-form .p-Widget { 60 | position: static !important; 61 | } 62 | -------------------------------------------------------------------------------- /scriptedforms/src/app/variables-module/number-base.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { 18 | Component, AfterViewInit, Input 19 | } from '@angular/core'; 20 | 21 | import { VariableBaseComponent } from './variable-base.component'; 22 | 23 | @Component({ 24 | template: '' 25 | }) 26 | export class NumberBaseComponent extends VariableBaseComponent implements AfterViewInit { 27 | @Input() min?: number = null; 28 | @Input() max?: number = null; 29 | @Input() step?= 1; 30 | } 31 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '8' 4 | dist: trusty 5 | sudo: required 6 | services: 7 | - docker 8 | addons: 9 | chrome: stable 10 | sauce_connect: 11 | no_ssl_bump_domains: "127.0.0.1,localhost" 12 | cache: 13 | yarn: true 14 | directories: 15 | - $HOME/miniconda 16 | - $HOME/.cache/pip 17 | env: 18 | matrix: 19 | - BROWSER="chrome" PLATFORM="Windows 7" 20 | # - BROWSER="firefox" PLATFORM="Windows 7" 21 | # - BROWSER="edge" PLATFORM="Windows 10" 22 | # - BROWSER="safari" PLATFORM="OS X 10.9" 23 | # - BROWSER="chrome" PLATFORM="OS X 10.9" 24 | # - BROWSER="firefox" PLATFORM="Linux" 25 | # - BROWSER="chrome" PLATFORM="Linux" 26 | global: 27 | - MINICONDA_DIR="$HOME/miniconda" 28 | - GH_REF: github.com/SimonBiggs/scriptedforms.git 29 | # matrix: 30 | # allow_failures: 31 | # - env: BROWSER="firefox" PLATFORM="Windows 7" 32 | # - env: BROWSER="edge" PLATFORM="Windows 10" 33 | # - env: BROWSER="safari" PLATFORM="OS X 10.9" 34 | # - env: BROWSER="firefox" PLATFORM="Linux" 35 | install: 36 | - bash ./scriptedforms/scripts/travis_install.sh 37 | script: 38 | - bash ./scriptedforms/scripts/travis_script.sh -------------------------------------------------------------------------------- /scriptedforms/src/app/variables-module/conditional.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { VariableBaseComponent } from './variable-base.component'; 18 | 19 | import { Component, AfterViewInit } from '@angular/core'; 20 | 21 | @Component({ 22 | selector: 'variable-conditional', 23 | template: `` 24 | }) 25 | export class ConditionalComponent extends VariableBaseComponent 26 | implements AfterViewInit { } 27 | -------------------------------------------------------------------------------- /scriptedforms/src/app/sections-module/start.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { 18 | Component, Input 19 | } from '@angular/core'; 20 | 21 | import { SectionBaseComponent } from './section-base.component'; 22 | 23 | @Component({ 24 | selector: 'section-start', 25 | template: `
{{code}}
` 26 | }) 27 | export class StartComponent extends SectionBaseComponent { 28 | sectionType = 'start'; 29 | @Input() always?: string; 30 | } 31 | -------------------------------------------------------------------------------- /scriptedforms/src/app/form-builder-module/form-builder.module.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | /* 18 | The forms module. 19 | */ 20 | 21 | import { NgModule } from '@angular/core'; 22 | import { CommonModule } from '@angular/common'; 23 | 24 | import { FormBuilderComponent } from './form-builder.component'; 25 | 26 | @NgModule({ 27 | imports: [ 28 | CommonModule 29 | ], 30 | declarations: [ 31 | FormBuilderComponent 32 | ], 33 | exports: [ 34 | FormBuilderComponent 35 | ] 36 | }) 37 | export class FormBuilderModule { } 38 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/utilities/send-token.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { 18 | browser, element, by, ExpectedConditions 19 | } from 'protractor'; 20 | 21 | describe('send-token', () => { 22 | it('should send token to notebook server', () => { 23 | browser.waitForAngularEnabled(false) 24 | browser.get(`http://localhost:8989/tree?token=${browser.params.token}`); 25 | let notebooks = element(by.id('notebooks')) 26 | browser.wait(ExpectedConditions.presenceOf(notebooks)) 27 | expect(notebooks.isPresent()).toBe(true) 28 | }) 29 | }); -------------------------------------------------------------------------------- /scriptedforms/src/app/variables-module/variable-parameter.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { VariableBaseComponent } from './variable-base.component'; 18 | 19 | import { Component, AfterViewInit } from '@angular/core'; 20 | 21 | @Component({ 22 | selector: 'variable-parameter', 23 | template: `` 24 | }) 25 | export class VariableParameterComponent extends VariableBaseComponent 26 | implements AfterViewInit { 27 | variableValue: any; 28 | } 29 | -------------------------------------------------------------------------------- /scriptedforms/src/app/form-builder-module/session-start-code.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | export const sessionStartCode = ( 17 | `try: 18 | _VariableHandler 19 | _is_new_session = False 20 | except NameError: 21 | _is_new_session = True 22 | import json 23 | 24 | import numpy as np 25 | import pandas as pd 26 | import matplotlib.pyplot as plt 27 | %matplotlib inline 28 | 29 | from scriptedforms._utilities import ( 30 | _VariableHandler, _json_table_to_df, _watchdog_path_conversion) 31 | 32 | print(json.dumps(_is_new_session)) 33 | `); 34 | -------------------------------------------------------------------------------- /scriptedforms/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 17 | 18 |
19 |
20 | 21 | 24 | 25 |
26 | 27 |
28 |
29 | 30 |
-------------------------------------------------------------------------------- /scriptedforms/src/app/types/section-component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { StartComponent } from '../sections-module/start.component'; 17 | import { LiveComponent } from '../sections-module/live.component'; 18 | import { ButtonComponent } from '../sections-module/button.component'; 19 | import { OutputComponent } from '../sections-module/output.component'; 20 | import { SectionFileChangeComponent } from '../sections-module/section-file-change.component'; 21 | 22 | export type SectionComponent = StartComponent | LiveComponent | ButtonComponent | OutputComponent | SectionFileChangeComponent; 23 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/variable-table.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | import pandas as pd 4 | 5 | from IPython.display import display, Markdown 6 | 7 | display(Markdown( 8 | 'Loaded variable-table.py at {}' 9 | .format(str(datetime.now())) 10 | )) 11 | 12 | input_types_1 = { 13 | '1st': 'toggle', 14 | '3rd': 'number', 15 | '4th': 'dropdown', 16 | '5th': 'dropdown', 17 | '6th': 'readonly' 18 | } 19 | 20 | input_types_2 = { 21 | '1st': 'tick', 22 | '2nd': 'string', 23 | '3rd': 'readonly', 24 | '4th': 'readonly', 25 | '5th': 'readonly', 26 | '6th': 'readonly' 27 | } 28 | 29 | dropdown_items = { 30 | '4th': ['apple', 'orange', 'pear'], 31 | '5th': { 32 | 'a': ['sally', 'margaret', 'annita'], 33 | 'b': ['george', 'philip', 'simpson'], 34 | 'c': ['red', 'green', 'blue'] 35 | } 36 | } 37 | 38 | table = None 39 | table_other = None 40 | 41 | 42 | def load_table(): 43 | global table 44 | global table_other 45 | table = pd.read_csv('variable-table.csv', index_col=0) 46 | 47 | table_other = pd.DataFrame( 48 | data=[], columns=table.columns, index=table.index) 49 | display(Markdown( 50 | 'Loaded variable-table.csv at {}' 51 | .format(str(datetime.now())) 52 | )) 53 | -------------------------------------------------------------------------------- /scriptedforms/src/app/services/jupyter.service.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { Injectable } from '@angular/core'; 17 | 18 | import { 19 | ServiceManager, ContentsManager 20 | } from '@jupyterlab/services'; 21 | 22 | @Injectable() 23 | export class JupyterService { 24 | serviceManager: ServiceManager; 25 | contentsManager: ContentsManager; 26 | 27 | setServiceManager(serviceManager: ServiceManager) { 28 | this.serviceManager = serviceManager; 29 | } 30 | 31 | setContentsManager(contentsManager: ContentsManager) { 32 | this.contentsManager = contentsManager; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /deploy/python-package/example/experimental/two-columns.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | 18 | 19 | 20 | ```python 21 | table = pd.DataFrame(data=[[1,2,3],[4,5,6]], columns=['a', 'b', 'c']) 22 | 23 | def plot_xy(): 24 | plt.figure(figsize=(5,5)) 25 | plt.scatter(table.values[0], table.values[1]) 26 | plt.axis('equal') 27 | 28 | 29 | def plot_yx(): 30 | plt.figure(figsize=(5,5)) 31 | plt.scatter(table.values[1], table.values[0]) 32 | plt.axis('equal') 33 | ``` 34 | 35 | 36 | 37 | # Multi columns with CSS 38 | 39 | Need at least version `0.9.2-dev2` for this to work. 40 | 41 |
42 |
43 | ## Markdown won't work in here 44 |

You need to use html

45 | table 46 |
47 | 48 |
49 | 50 |
51 | 52 |
53 | 54 |
55 |
-------------------------------------------------------------------------------- /scriptedforms/e2e/src/landing-page.spec.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { 17 | browser, element, by, ExpectedConditions 18 | } from 'protractor'; 19 | 20 | import { before, after } from './utilities/before-and-after' 21 | 22 | const TEMPLATE_FILE = 'landing-page.md' 23 | 24 | describe(TEMPLATE_FILE, () => { 25 | beforeEach(before('http://localhost:8989/')); 26 | afterEach(after()) 27 | 28 | it('should have a heading', () => { 29 | let header = element(by.tagName('h1')) 30 | browser.wait(ExpectedConditions.presenceOf(header)) 31 | let text = header.getText() 32 | expect(text).toEqual('A landing page') 33 | }) 34 | }); -------------------------------------------------------------------------------- /scriptedforms/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var path = require('path'); 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 4 | 5 | module.exports = { 6 | entry: { 7 | 'polyfills': './src/polyfills.ts', 8 | 'angular': './src/vendors/angular.ts', 9 | 'jupyterlab': './src/vendors/jupyterlab.ts', 10 | 'misc': './src/vendors/misc.ts', 11 | 'scriptedforms': './src/main.ts' 12 | }, 13 | output: { 14 | path: __dirname + '/lib/', 15 | filename: '[name].js', 16 | chunkFilename: '[id].chunk.js' 17 | }, 18 | resolve: { 19 | extensions: ['.ts', '.js'] 20 | }, 21 | module: { 22 | rules: [ 23 | { 24 | test: /\.ts$/, 25 | loaders: [ 26 | { 27 | loader: 'awesome-typescript-loader', 28 | options: { configFileName: 'tsconfig.json' } 29 | }, 30 | 'angular2-template-loader' 31 | ] 32 | }, 33 | { test: /\.css$/, use: ['style-loader', 'css-loader'] }, 34 | { test: /\.(woff|woff2|ttf|eot)$/, use: 'file-loader' }, 35 | ] 36 | }, 37 | plugins: [ 38 | new webpack.optimize.CommonsChunkPlugin({ 39 | name: ['scriptedforms', 'misc', 'jupyterlab', 'angular', 'polyfills'] 40 | }), 41 | new ExtractTextPlugin('[name].css') 42 | ] 43 | }; 44 | -------------------------------------------------------------------------------- /scriptedforms/scripts/travis_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) Jupyter Development Team. 4 | # Distributed under the terms of the Modified BSD License. 5 | set -x 6 | 7 | # The miniconda directory may exist if it has been restored from cache 8 | if [ -d "$MINICONDA_DIR" ] && [ -e "$MINICONDA_DIR/bin/conda" ]; then 9 | echo "Miniconda install already present from cache: $MINICONDA_DIR" 10 | else # if it does not exist, we need to install miniconda 11 | rm -rf "$MINICONDA_DIR" # remove the directory in case we have an empty cached directory 12 | wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh; 13 | bash ~/miniconda.sh -b -p "$MINICONDA_DIR" 14 | chown -R "$USER" "$MINICONDA_DIR" 15 | hash -r 16 | fi 17 | 18 | export PATH="$MINICONDA_DIR/bin:$PATH" 19 | conda config --set always_yes yes --set changeps1 no 20 | conda update -q conda 21 | conda info -a # for debugging 22 | 23 | conda remove --name test --all || true 24 | conda create -n test -c notebook pytest 25 | source activate test 26 | 27 | # create jupyter base dir (needed for config retrieval) 28 | mkdir ~/.jupyter 29 | 30 | # Install and enable the server extension 31 | cd "$(dirname "$0")"/../ 32 | yarn 33 | yarn build 34 | cd - 35 | 36 | pip install .[test] 37 | 38 | jupyter serverextension enable --py scriptedforms -------------------------------------------------------------------------------- /scriptedforms/e2e/src/section-start.spec.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { 18 | browser, element, by, ExpectedConditions 19 | } from 'protractor'; 20 | 21 | import { beforeFromFile, after } from './utilities/before-and-after' 22 | 23 | const TEMPLATE_FILE = 'section-start.md' 24 | 25 | describe(TEMPLATE_FILE, () => { 26 | beforeEach(beforeFromFile(TEMPLATE_FILE)); 27 | afterEach(after()) 28 | 29 | it('should successfully run on start', () => { 30 | let elem = element(by.css('.check-me .jp-OutputArea-output')) 31 | browser.wait(ExpectedConditions.presenceOf(elem)) 32 | 33 | let text = element(by.tagName('h1')).getText() 34 | expect(text).toEqual('Hello') 35 | }) 36 | }); -------------------------------------------------------------------------------- /scriptedforms/src/app/variables-module/tick.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { VariableBaseComponent } from './variable-base.component'; 17 | 18 | import { 19 | Component, AfterViewInit 20 | } from '@angular/core'; 21 | 22 | @Component({ 23 | selector: 'variable-tick', 24 | template: ` 25 | 26 | 27 | 28 | 29 | 34 | {{labelValue}} 35 | `, 36 | }) 37 | export class TickComponent extends VariableBaseComponent implements AfterViewInit { } 38 | -------------------------------------------------------------------------------- /scriptedforms/src/docs/doc.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | 4 | import { APP_BASE_HREF } from '@angular/common'; 5 | 6 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 7 | import { MaterialModule } from '../vendors/material.module'; 8 | 9 | import { AppModule } from '../app/app.module'; 10 | import { RoutingModule } from './doc.routing'; 11 | 12 | import { DocComponent } from './doc.component'; 13 | import { LandingPageComponent } from './landing-page/landing-page.component'; 14 | 15 | const SF_CONFIG = document.getElementById('scriptedforms-config-data'); 16 | const JLAB_CONFIG = document.getElementById('jupyter-config-data'); 17 | 18 | let config: {baseUrl: string}; 19 | 20 | if (SF_CONFIG) { 21 | config = JSON.parse(SF_CONFIG.textContent); 22 | } else { 23 | config = JSON.parse(JLAB_CONFIG.textContent); 24 | } 25 | 26 | const baseUrl = config.baseUrl; 27 | 28 | @NgModule({ 29 | declarations: [ 30 | DocComponent, 31 | LandingPageComponent 32 | ], 33 | imports: [ 34 | BrowserModule, 35 | BrowserAnimationsModule, 36 | RoutingModule, 37 | MaterialModule, 38 | AppModule 39 | ], 40 | providers: [ 41 | { provide: APP_BASE_HREF, useValue: baseUrl } 42 | ], 43 | bootstrap: [DocComponent] 44 | }) 45 | export class DocModule { } 46 | -------------------------------------------------------------------------------- /scriptedforms/src/app/variables-module/toggle.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { VariableBaseComponent } from './variable-base.component'; 17 | 18 | import { 19 | Component, AfterViewInit 20 | } from '@angular/core'; 21 | 22 | @Component({ 23 | selector: 'variable-toggle', 24 | template: ` 25 | 26 | 27 | 28 | 29 | 34 | {{labelValue}} 35 | `, 36 | }) 37 | export class ToggleComponent extends VariableBaseComponent implements AfterViewInit { } 38 | -------------------------------------------------------------------------------- /scriptedforms/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 11 | 12 | 13 | 18 | 25 | 26 | 27 | 28 | 29 | 30 | {% if application_to_run == 'docs' %} 31 | 32 | {% endif %} 33 | 34 | 35 | -------------------------------------------------------------------------------- /scriptedforms/src/app/toolbar-module/toolbar.module.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | /* 17 | 18 | */ 19 | 20 | import { NgModule } from '@angular/core'; 21 | import { CommonModule } from '@angular/common'; 22 | 23 | import { 24 | MatButtonModule, MatIconModule 25 | } from '@angular/material'; 26 | 27 | import { ToolbarBaseComponent } from './toolbar-base.component'; 28 | import { ToolbarButtonComponent } from './toolbar-button.component'; 29 | 30 | 31 | 32 | @NgModule({ 33 | imports: [ 34 | CommonModule, 35 | MatButtonModule, 36 | MatIconModule 37 | ], 38 | declarations: [ 39 | ToolbarButtonComponent, 40 | ToolbarBaseComponent 41 | ], 42 | exports: [ 43 | ToolbarButtonComponent, 44 | ToolbarBaseComponent 45 | ] 46 | }) 47 | export class ToolbarModule { } 48 | -------------------------------------------------------------------------------- /deploy/python-package/example/code-template-split/template-only.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # A template with no nested code 4 | 5 | All code on this form is stored within a python file. 6 | 7 | 8 | 9 | ## Python files reload when changed 10 | 11 | By using `` any changes to the python files can be 12 | automatically updated. 13 | 14 | 15 | 16 | 17 | ## Varible data is loaded from within the data python file 18 | 19 | The variable `table` is defined within `data.py`, but it is able to be used 20 | here. 21 | 22 | data.table 23 | 24 | 25 | ## Cleaner easier to understand templates 26 | 27 | By using inline code within the sections the templates are more focused on 28 | what is visible on the screen. All programming logic can be delegated to the 29 | Python file. 30 | 31 | Conveniently this also plays nicer with linters. 32 | 33 | ## Debug 34 | 35 | This is displaying all of the variable values for debugging purposes. 36 | 37 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/section-live.spec.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { 18 | browser, element, by, ExpectedConditions 19 | } from 'protractor'; 20 | 21 | import { beforeFromFile, after, waitForSpinner } from './utilities/before-and-after' 22 | 23 | const TEMPLATE_FILE = 'section-live.md' 24 | 25 | describe(TEMPLATE_FILE, () => { 26 | beforeEach(beforeFromFile(TEMPLATE_FILE)); 27 | afterEach(after()) 28 | 29 | it('should run when variables are changed', () => { 30 | let outputContents = element(by.css('.check-me-running .jp-OutputArea-output pre')) 31 | browser.wait(ExpectedConditions.presenceOf(outputContents)) 32 | expect(outputContents.getText()).toEqual('bar') 33 | 34 | let fooString = element(by.css('.write-in-me textarea')) 35 | fooString.sendKeys(' boo') 36 | 37 | waitForSpinner() 38 | expect(outputContents.getText()).toEqual('bar boo') 39 | }) 40 | }); -------------------------------------------------------------------------------- /deploy/windows-only/portable-zip/my-forms/a-slider.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # A slider 4 | 5 | ## Edit this form 6 | 7 | Open the plain text form file in a new window using the following link: 8 | 9 | > [Edit this form](../../edit/a-slider.md) 10 | 11 | With this window open, and the edit window open side by side you can see the 12 | effects of changes on the interface. 13 | 14 | ## Example slider 15 | 16 | Using the slider and live sections combined with matplotlib plots you can 17 | produce utilities like the following: 18 | 19 | 20 | 21 | ```python 22 | plt.rc('font', size=15) 23 | 24 | t = np.linspace(-2*np.pi, 2*np.pi, 500) 25 | omega = np.ones(2) 26 | ``` 27 | 28 | 29 | 30 | 31 | 32 | Angular frequencies ($\omega$): 33 | 34 | omega[0] 35 | omega[1] 36 | 37 | ```python 38 | plt.figure(figsize=(5*1.618,5)) 39 | 40 | oscillation = np.sin(t[:, np.newaxis] * omega[np.newaxis, :]) 41 | summation = np.sum(oscillation, axis=1) 42 | 43 | plt.plot(t, oscillation) 44 | plt.plot(t, summation) 45 | 46 | plt.xlim([-2*np.pi, 2*np.pi]) 47 | plt.ylim([-2.8, 2.8]) 48 | plt.title('Two sin curves and their summation') 49 | plt.legend([ 50 | r'$\omega_0 = {0:0.1f}$'.format(omega[0]), 51 | r'$\omega_1 = {0:0.1f}$'.format(omega[1]), 52 | 'Summation'], loc='upper right') 53 | plt.xlabel('time (seconds)') 54 | plt.ylabel(r'$sin(\omega \times t)$'); 55 | ``` 56 | 57 | 58 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/variable-table.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Variable table 4 | 5 | 6 | 7 | 8 | 9 | ## Default table 10 | 11 | variable_table.table 12 | 13 | ## Editable pandas json types 14 | 15 | variable_table.table 16 | 17 | ## Each input type 18 | 19 | variable_table.table 20 | 21 | variable_table.table 22 | 23 | ## Dropdown input types with no dropdown items defined 24 | 25 | variable_table.table 26 | 27 | ## Nonsense parameter values 28 | 29 | variable_table.table 30 | 31 | ## Standalone Table 32 | 33 | variable_table.table_other -------------------------------------------------------------------------------- /scriptedforms/src/app/services/toolbar.service.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { 17 | Injectable, 18 | } from '@angular/core'; 19 | 20 | import { 21 | Widget 22 | } from '@phosphor/widgets'; 23 | 24 | import { 25 | Toolbar, 26 | } from '@jupyterlab/apputils'; 27 | import { PromiseDelegate } from '@phosphor/coreutils'; 28 | 29 | 30 | @Injectable() 31 | export class ToolbarService { 32 | toolbarReady = new PromiseDelegate(); 33 | toolbar: Toolbar; 34 | 35 | public setToolbar(toolbar: Toolbar) { 36 | this.toolbar = toolbar; 37 | this.toolbarReady.resolve(null); 38 | } 39 | 40 | public addSpacer() { 41 | this.toolbarReady.promise.then(() => { 42 | this.toolbar.addItem('spacer', Toolbar.createSpacerItem()); 43 | }); 44 | } 45 | 46 | public addItem(name: string, widget: Widget) { 47 | this.toolbarReady.promise.then(() => { 48 | this.toolbar.addItem(name, widget); 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /scriptedforms/dev_utilities/jupyterlab_extracts/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2015-2017, Project Jupyter Contributors 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /scriptedforms/src/app/types/variable-component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { TickComponent } from '../variables-module/tick.component'; 17 | import { ToggleComponent } from '../variables-module/toggle.component'; 18 | import { ConditionalComponent } from '../variables-module/conditional.component'; 19 | 20 | import { NumberComponent } from '../variables-module/number.component'; 21 | import { SliderComponent } from '../variables-module/slider.component'; 22 | import { VariableTableComponent } from '../variables-module/variable-table.component'; 23 | 24 | import { StringComponent } from '../variables-module/string.component'; 25 | import { DropdownComponent } from '../variables-module/dropdown.component'; 26 | 27 | import { VariableFileComponent } from '../variables-module/variable-file.component'; 28 | 29 | export type VariableComponent = ( 30 | NumberComponent | StringComponent | VariableTableComponent | TickComponent | 31 | ToggleComponent | SliderComponent | DropdownComponent | ConditionalComponent | VariableFileComponent); 32 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from glob import glob 3 | from setuptools import setup 4 | 5 | here = os.path.dirname(os.path.abspath(__file__)) 6 | name = 'scriptedforms' 7 | pjoin = os.path.join 8 | tar_path = pjoin(here, 'scriptedforms', '*.tgz') 9 | 10 | version_ns = {} 11 | with open(pjoin(here, name, '_version.py')) as file: 12 | code = file.read() 13 | exec(code, version_ns) 14 | 15 | version = version_ns['__version__'] 16 | 17 | 18 | def get_data_files(): 19 | """Get the data files for the package. 20 | """ 21 | return [ 22 | ('share/jupyter/lab/extensions', [ 23 | os.path.relpath(f, '.') for f in glob(tar_path) 24 | ]), 25 | ('etc/jupyter/jupyter_notebook_config.d', [ 26 | os.path.relpath( 27 | pjoin(here, 'scriptedforms', 'scriptedforms.json'), '.') 28 | ]) 29 | ] 30 | 31 | 32 | setup( 33 | name="scriptedforms", 34 | version=version, 35 | author="Simon Biggs", 36 | author_email="sbiggs@scriptedforms.com.au", 37 | description="ScriptedForms.", 38 | long_description=( 39 | "" 40 | ), 41 | keywords=[], 42 | packages=[ 43 | "scriptedforms" 44 | ], 45 | entry_points={ 46 | 'console_scripts': [ 47 | 'scriptedforms=scriptedforms:main', 48 | ], 49 | }, 50 | data_files=get_data_files(), 51 | license='AGPL-3.0+', 52 | python_requires='>=3.5', 53 | install_requires=[ 54 | 'notebook >= 5.5', 55 | 'numpy', 56 | 'pandas', 57 | 'watchdog', 58 | 'matplotlib', 59 | 'jupyterlab >= 0.32.0' 60 | ], 61 | classifiers=[], 62 | url="https://scriptedforms.com.au", 63 | include_package_data=True 64 | ) 65 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/utilities/before-and-after.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { 18 | browser, element, by, ExpectedConditions 19 | } from 'protractor'; 20 | 21 | export function waitForSpinner() { 22 | let spinner = element(by.css('.floating-spinner')) 23 | browser.wait(ExpectedConditions.stalenessOf(spinner)) 24 | } 25 | 26 | export function customGet(url: string) { 27 | browser.get(`${url}?telemetry=0`) 28 | } 29 | 30 | export function before(url: string) { 31 | return () => { 32 | browser.waitForAngularEnabled(false) 33 | customGet(url); 34 | browser.wait(ExpectedConditions.presenceOf( 35 | element(by.tagName('app-form')) 36 | )) 37 | waitForSpinner() 38 | } 39 | } 40 | 41 | export function makeUrlFromFile(templateFile: string) { 42 | return `http://localhost:8989/scriptedforms/use/${templateFile}` 43 | } 44 | 45 | export function beforeFromFile(templateFile: string) { 46 | return before(makeUrlFromFile(templateFile)) 47 | } 48 | 49 | export function after() { 50 | return () => { 51 | waitForSpinner() 52 | } 53 | } -------------------------------------------------------------------------------- /scriptedforms/src/app.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import './app/style.css'; 17 | 18 | const userStyle = document.createElement('style'); 19 | userStyle.id = 'scripted-forms-custom-user-style'; 20 | document.getElementsByTagName('head').item(0).appendChild(userStyle); 21 | 22 | import { Widget } from '@phosphor/widgets'; 23 | import { ServiceManager, ContentsManager } from '@jupyterlab/services'; 24 | import { ScriptedFormsWidget } from './app/widget'; 25 | import { AngularLoader } from './app/phosphor-angular-loader'; 26 | import { AppModule } from './app/app.module'; 27 | 28 | export function loadApp(): void { 29 | const serviceManager = new ServiceManager(); 30 | const contentsManager = new ContentsManager(); 31 | const angularLoader = new AngularLoader(AppModule); 32 | 33 | const formWidget = new ScriptedFormsWidget({ 34 | serviceManager, 35 | contentsManager, 36 | angularLoader 37 | }); 38 | 39 | // formWidget.content.initiliseScriptedForms(); 40 | window.onresize = () => { formWidget.update(); }; 41 | Widget.attach(formWidget, document.body); 42 | } -------------------------------------------------------------------------------- /scriptedforms/src/app/services/watchdog-code.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | export 17 | const startWatchdogSessionCode = ` 18 | try: 19 | observer 20 | raise AssertionError("observer shouldn't exist yet") 21 | except NameError: 22 | import os 23 | from watchdog.observers import Observer 24 | from watchdog.events import FileSystemEventHandler, FileModifiedEvent 25 | 26 | class MyHandler(FileSystemEventHandler): 27 | def on_modified(self, event): 28 | print('absolute: {}'.format(os.path.abspath(event.src_path))) 29 | try: 30 | print('relative: {}'.format(os.path.relpath(event.src_path))) 31 | finally: 32 | pass 33 | 34 | event_handler = MyHandler() 35 | observer = Observer() 36 | observer.start() 37 | `; 38 | 39 | export 40 | function addObserverPathCode(observerPath: string) { 41 | return ` 42 | next_path = os.path.dirname(os.path.abspath( 43 | os.path.expanduser(os.path.expandvars('${observerPath}')))) 44 | observer.schedule(event_handler, path=next_path)`; 45 | } 46 | -------------------------------------------------------------------------------- /scriptedforms/src/app/variables-module/number.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { NumberBaseComponent } from './number-base.component'; 18 | 19 | import { 20 | Component, AfterViewInit 21 | } from '@angular/core'; 22 | 23 | @Component({ 24 | selector: 'variable-number', 25 | template: ` 26 | 27 | 28 | 29 | 30 | 31 | {{labelValue}} 32 | 45 | `, 46 | styles: [ 47 | `.variableNumber { 48 | width: 200px; 49 | } 50 | `] 51 | }) 52 | export class NumberComponent extends NumberBaseComponent implements AfterViewInit { 53 | 54 | } 55 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/section-output.spec.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { 18 | browser, element, by, ExpectedConditions 19 | } from 'protractor'; 20 | 21 | import { beforeFromFile, after, waitForSpinner } from './utilities/before-and-after' 22 | 23 | const TEMPLATE_FILE = 'section-output.md' 24 | 25 | describe(TEMPLATE_FILE, () => { 26 | beforeEach(beforeFromFile(TEMPLATE_FILE)); 27 | afterEach(after()) 28 | 29 | it('should run when variables are changed', () => { 30 | let outputContents = element(by.css('.check-me-running .jp-OutputArea-output pre')) 31 | browser.wait(ExpectedConditions.presenceOf(outputContents)) 32 | expect(outputContents.getText()).toEqual('foo: , bar: 0') 33 | 34 | let fooString = element(by.css('.write-in-me textarea')) 35 | fooString.sendKeys('boo') 36 | 37 | waitForSpinner() 38 | expect(outputContents.getText()).toEqual('foo: boo, bar: 0') 39 | 40 | let adderButton = element(by.css('.click-me button')) 41 | adderButton.click() 42 | waitForSpinner() 43 | expect(outputContents.getText()).toEqual('foo: boo, bar: 1') 44 | }) 45 | }); -------------------------------------------------------------------------------- /deploy/python-package/example/experimental/file-change.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # An example of the file change section 4 | 5 | 6 | 7 | ```python 8 | from IPython.display import display 9 | filepath = 'file-change.csv' 10 | 11 | input_types = { 12 | '1st': 'toggle', 13 | '3rd': 'number', 14 | '4th': 'dropdown', 15 | '5th': 'dropdown', 16 | '6th': 'readonly' 17 | } 18 | 19 | dropdown_items = { 20 | '4th': ['apple', 'orange', 'pear'], 21 | '5th': { 22 | 'a': ['sally', 'margaret', 'annita'], 23 | 'b': ['george', 'philip', 'simpson'], 24 | 'c': ['red', 'green', 'blue'] 25 | } 26 | } 27 | ``` 28 | 29 | 30 | 31 | ## A Jupyter output display of the pandas dataframe from the csv file 32 | 33 | 34 | 35 | ```python 36 | from_csv = pd.read_csv(filepath, index_col=0) 37 | display(from_csv) 38 | ``` 39 | 40 | 41 | 42 | ## A default table 43 | 44 | 45 | 46 | from_csv 47 | 48 | ```python 49 | from_csv.to_csv(filepath) 50 | ``` 51 | 52 | 53 | 54 | ## A table that allows the json pandas types to be edited 55 | 56 | This is using the `typeEdit` property within the `` element. 57 | 58 | 59 | 60 | from_csv 61 | 62 | ```python 63 | from_csv.to_csv(filepath) 64 | ``` 65 | 66 | 67 | 68 | ## A table that forces input types 69 | 70 | This is using the `inputTypes` property within the `` element. 71 | 72 | 73 | 74 | from_csv 75 | 76 | ```python 77 | from_csv.to_csv(filepath) 78 | ``` 79 | 80 | 81 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/variable-table.spec.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { 18 | browser, 19 | element, by, 20 | ExpectedConditions, 21 | // ElementFinder, Key 22 | } from 'protractor'; 23 | 24 | import { beforeFromFile, after, waitForSpinner } from './utilities/before-and-after' 25 | 26 | const TEMPLATE_FILE = 'variable-table.md' 27 | 28 | var hasClass = function (element: any, cls: any) { 29 | return element.getAttribute('class').then(function (classes: any) { 30 | return classes.split(' ').indexOf(cls) !== -1; 31 | }); 32 | }; 33 | 34 | describe(TEMPLATE_FILE, () => { 35 | beforeEach(beforeFromFile(TEMPLATE_FILE)); 36 | afterEach(after()) 37 | 38 | it('first table test', () => { 39 | let defaultTableInput = element(by.css('.default mat-checkbox')) 40 | let typeEditTableInput = element(by.css('.type-edit mat-checkbox')) 41 | browser.wait(ExpectedConditions.presenceOf(defaultTableInput)) 42 | browser.wait(ExpectedConditions.presenceOf(typeEditTableInput)) 43 | 44 | expect(hasClass(typeEditTableInput, 'mat-checkbox-checked')).toBe(false); 45 | 46 | defaultTableInput.click() 47 | 48 | waitForSpinner() 49 | expect(hasClass(typeEditTableInput, 'mat-checkbox-checked')).toBe(true); 50 | }) 51 | }); 52 | 53 | 54 | -------------------------------------------------------------------------------- /scriptedforms/src/app/app-error-handler.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | /* 18 | Handler to print error messages at the top of the form. 19 | 20 | If the user makes an error within the form template at least the user will be 21 | presented with some form of error message. 22 | 23 | In the future the display of this message could integrate better with 24 | jupyterlab. 25 | */ 26 | 27 | import { ErrorHandler } from '@angular/core'; 28 | 29 | export class AppErrorHandler extends ErrorHandler { 30 | 31 | handleError(error: any) { 32 | // const errorbox = document.getElementsByClassName('errorbox'); 33 | // if (errorbox.length > 0) { 34 | // errorbox[0].innerHTML = `

Javascript Error:

35 | //

36 | // A Javascript error has occured. This could be due to an error within your 37 | // ScriptedForms template or an issue with ScriptedForms itself. 38 | //

39 | // '; 44 | // } 45 | 46 | // delegate to the default handler 47 | super.handleError(error); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /scriptedforms/src/main.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import './public-path'; 17 | 18 | const CONFIG_DIV = document.getElementById('scriptedforms-config-data'); 19 | if (CONFIG_DIV) { 20 | document.body.classList.add('fullscreen-body'); 21 | } 22 | 23 | import './polyfills'; 24 | 25 | import './vendors/jupyterlab'; 26 | import './vendors/angular'; 27 | import './vendors/misc'; 28 | 29 | import 'hammerjs'; 30 | 31 | import { enableProdMode } from '@angular/core'; 32 | 33 | import { 34 | plugin 35 | } from './jupyterlab-extension/jupyterlab-plugin'; 36 | 37 | import { loadApp } from './app'; 38 | import { loadDocs } from './docs'; 39 | import { loadDev } from './dev'; 40 | 41 | if (process.env.NODE_ENV === 'production') { 42 | console.log('Production Mode: Angular is in production mode.'); 43 | enableProdMode(); 44 | } 45 | 46 | function main() { 47 | const config = JSON.parse(CONFIG_DIV.textContent); 48 | 49 | if (config.applicationToRun === 'use') { 50 | loadApp(); 51 | } else if (config.applicationToRun === 'docs') { 52 | loadDocs(); 53 | } else { 54 | throw RangeError('Expected docs or use'); 55 | } 56 | } 57 | 58 | if (CONFIG_DIV) { 59 | if (process.env.NODE_ENV !== 'production') { 60 | console.log('Development Mode: ScriptedForms is watching for JavaScript changes.'); 61 | loadDev(); 62 | } 63 | window.onload = main; 64 | } 65 | 66 | export default plugin; 67 | -------------------------------------------------------------------------------- /scriptedforms/src/app/sections-module/sections.module.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | /* 17 | A module containing the form elements. 18 | */ 19 | 20 | import { NgModule } from '@angular/core'; 21 | import { CommonModule } from '@angular/common'; 22 | 23 | import { 24 | MatButtonModule, MatIconModule 25 | } from '@angular/material'; 26 | 27 | import { CodeModule } from '../code-module/code.module'; 28 | 29 | import { SectionBaseComponent } from './section-base.component'; 30 | 31 | import { StartComponent } from './start.component'; 32 | import { LiveComponent } from './live.component'; 33 | import { ButtonComponent } from './button.component'; 34 | import { OutputComponent } from './output.component'; 35 | import { SectionFileChangeComponent } from './section-file-change.component'; 36 | 37 | import { VariablesModule } from '../variables-module/variables.module'; 38 | 39 | @NgModule({ 40 | imports: [ 41 | CommonModule, 42 | MatButtonModule, 43 | MatIconModule, 44 | VariablesModule, 45 | CodeModule 46 | ], 47 | declarations: [ 48 | SectionBaseComponent, 49 | StartComponent, 50 | LiveComponent, 51 | ButtonComponent, 52 | OutputComponent, 53 | SectionFileChangeComponent 54 | ], 55 | exports: [ 56 | StartComponent, 57 | LiveComponent, 58 | ButtonComponent, 59 | OutputComponent, 60 | SectionFileChangeComponent 61 | ] 62 | }) 63 | export class SectionsModule { } 64 | -------------------------------------------------------------------------------- /scriptedforms/src/vendors/material.module.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | /* 17 | A module containing the form elements. 18 | */ 19 | 20 | import { NgModule } from '@angular/core'; 21 | 22 | import { 23 | MatInputModule, 24 | MatTableModule, 25 | MatCheckboxModule, 26 | MatSlideToggleModule, 27 | MatSliderModule, 28 | MatSelectModule, 29 | MatExpansionModule, 30 | MatButtonModule, 31 | MatIconModule, 32 | MatCardModule, 33 | MatProgressSpinnerModule, 34 | MatSidenavModule, 35 | MatToolbarModule, 36 | MatDividerModule 37 | } from '@angular/material'; 38 | 39 | @NgModule({ 40 | imports: [ 41 | MatButtonModule, 42 | MatIconModule, 43 | MatCardModule, 44 | MatInputModule, 45 | MatTableModule, 46 | MatCheckboxModule, 47 | MatSlideToggleModule, 48 | MatSliderModule, 49 | MatSelectModule, 50 | MatExpansionModule, 51 | MatProgressSpinnerModule, 52 | MatSidenavModule, 53 | MatToolbarModule, 54 | MatDividerModule 55 | ], 56 | exports: [ 57 | MatButtonModule, 58 | MatIconModule, 59 | MatCardModule, 60 | MatInputModule, 61 | MatTableModule, 62 | MatCheckboxModule, 63 | MatSlideToggleModule, 64 | MatSliderModule, 65 | MatSelectModule, 66 | MatExpansionModule, 67 | MatProgressSpinnerModule, 68 | MatSidenavModule, 69 | MatToolbarModule, 70 | MatDividerModule 71 | ] 72 | }) 73 | export class MaterialModule { } 74 | -------------------------------------------------------------------------------- /scriptedforms/src/app/sections-module/output.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { Subscription } from 'rxjs'; 18 | 19 | import { 20 | Component, OnDestroy, AfterViewInit 21 | } from '@angular/core'; 22 | 23 | import { SectionBaseComponent } from './section-base.component'; 24 | import { VariableService } from '../services/variable.service'; 25 | 26 | @Component({ 27 | selector: 'section-output', 28 | template: `
{{code}}
` 29 | }) 30 | export class OutputComponent extends SectionBaseComponent implements OnDestroy, AfterViewInit { 31 | sectionType = 'output'; 32 | variableSubscription: Subscription; 33 | hasFirstSubRun = false; 34 | 35 | constructor( 36 | private myVariableService: VariableService 37 | ) { super(); } 38 | 39 | subscribeToVariableChanges() { 40 | this.variableSubscription = this.myVariableService.variableChangedObservable 41 | .subscribe(value => { 42 | if (this.hasFirstSubRun) { 43 | if (value !== null) { 44 | this.runCode(); 45 | } 46 | } else { 47 | this.hasFirstSubRun = true; 48 | } 49 | }); 50 | } 51 | 52 | unsubscribe() { 53 | this.variableSubscription.unsubscribe(); 54 | } 55 | 56 | kernelReset() { 57 | this.unsubscribe(); 58 | } 59 | 60 | ngOnDestroy() { 61 | this.unsubscribe(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /scriptedforms/_scriptedforms_handlers.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | 5 | import os 6 | import re 7 | from glob import glob 8 | 9 | from notebook.base.handlers import IPythonHandler, FileFindHandler 10 | from notebook.utils import url_path_join as ujoin 11 | 12 | from jinja2 import FileSystemLoader 13 | 14 | from ._utilities import HERE 15 | LOADER = FileSystemLoader(HERE) 16 | 17 | 18 | def get_scriptedforms_handlers(base_url): 19 | lib_dir = os.path.join(HERE, 'lib') 20 | lib_files = glob(os.path.join(lib_dir, '*')) 21 | rel_paths = [os.path.relpath(item, lib_dir) for item in lib_files] 22 | 23 | lib_escaped = [re.escape(item) for item in rel_paths] 24 | lib_strings = '|'.join(lib_escaped) 25 | 26 | static_handler_regex = "/scriptedforms/static/({})".format(lib_strings) 27 | 28 | scriptedforms_handlers = [ 29 | ( 30 | ujoin(base_url, r'/scriptedforms/use/.*\.md'), 31 | ScriptedFormsHandler, 32 | {'application_to_run': 'use'} 33 | ), 34 | ( 35 | ujoin(base_url, static_handler_regex), 36 | FileFindHandler, 37 | {'path': lib_dir} 38 | ), 39 | ( 40 | ujoin(base_url, r'/scriptedforms/docs'), 41 | ScriptedFormsHandler, 42 | {'application_to_run': 'docs'} 43 | ), 44 | ( 45 | ujoin(base_url, r'/scriptedforms/docs/.*'), 46 | ScriptedFormsHandler, 47 | {'application_to_run': 'docs'} 48 | ) 49 | ] 50 | 51 | return scriptedforms_handlers 52 | 53 | 54 | class ScriptedFormsHandler(IPythonHandler): 55 | def initialize(self, application_to_run): 56 | self.application_to_run = application_to_run 57 | 58 | def get(self): 59 | return self.write(self.render_template( 60 | "index.html", 61 | base_url=self.base_url, 62 | application_to_run=self.application_to_run)) 63 | 64 | def get_template(self, name): 65 | return LOADER.load(self.settings['jinja2_env'], name) 66 | -------------------------------------------------------------------------------- /scriptedforms/src/app/variables-module/variable-file.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { VariableBaseComponent } from './variable-base.component'; 18 | 19 | import { Component, AfterViewInit, OnInit } from '@angular/core'; 20 | 21 | import * as htmlTemplate from 'html-loader!./variable-file.component.html'; 22 | const template = '' + htmlTemplate; 23 | 24 | @Component({ 25 | selector: 'variable-file', 26 | template: template 27 | }) 28 | export class VariableFileComponent extends VariableBaseComponent implements OnInit, AfterViewInit { 29 | variableValue: number[]; 30 | reader = new FileReader(); 31 | 32 | ngOnInit() { 33 | this.reader.onload = () => this.onFileLoaded(); 34 | } 35 | 36 | fileChanged(event: any) { 37 | const file = event.target.files[0]; 38 | this.reader.readAsArrayBuffer(file); 39 | } 40 | 41 | onFileLoaded() { 42 | const fileArray = new Int8Array(this.reader.result); 43 | // const encoded = String.fromCharCode.apply(null, fileArray); 44 | // const b64encoded = btoa(this.decoder.decode(fileArray)); 45 | this.variableValue = Array.from(fileArray); 46 | console.log(this.variableValue); 47 | this.variableChanged(); 48 | } 49 | 50 | pythonValueReference() { 51 | return `bytes(json.loads(r'${JSON.stringify(this.variableValue)}'))`; 52 | } 53 | 54 | pythonVariableEvaluate() { 55 | return `int.from_bytes(${this.variableName}, byteorder='little', signed=False)`; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /scriptedforms/src/app/variables-module/string.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { VariableBaseComponent } from './variable-base.component'; 17 | 18 | import { 19 | Component, AfterViewInit 20 | } from '@angular/core'; 21 | 22 | @Component({ 23 | selector: 'variable-string', 24 | template: ` 25 | 26 | 27 | 28 | 29 | {{labelValue}} 30 | 40 | `, 41 | styles: [ 42 | `.variableString { 43 | width: 100%; 44 | } 45 | `] 46 | }) 47 | export class StringComponent extends VariableBaseComponent implements AfterViewInit { 48 | variableValue: string; 49 | 50 | pythonValueReference() { 51 | const escapedString = this.variableValue 52 | .replace(/\\/g, '\\\\') 53 | .replace(/\"/g, '\\\"'); 54 | const valueReference = `"""${String(escapedString)}"""`; 55 | 56 | return valueReference; 57 | } 58 | 59 | // pythonValueReference() { 60 | // return `json.loads('${JSON.stringify(this.variableValue)}')` 61 | // } 62 | } 63 | -------------------------------------------------------------------------------- /scriptedforms/src/docs/landing-page/landing-page.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core'; 2 | 3 | import { Widget } from '@phosphor/widgets'; 4 | 5 | import { ServiceManager, ContentsManager } from '@jupyterlab/services'; 6 | import { ScriptedFormsWidget } from '../../app/widget'; 7 | import { AngularLoader } from '../../app/phosphor-angular-loader'; 8 | import { AppModule } from '../../app/app.module'; 9 | 10 | import * as htmlTemplate from 'html-loader!./landing-page.component.html'; 11 | const template = '' + htmlTemplate; 12 | 13 | const aTemplate = ` 14 | # Live documentation 15 | 16 | There isn't any docs here yet. 17 | 18 | Watch this space. 19 | 20 | ## Available example forms 21 | 22 | 23 | 24 | ~~~python 25 | import urllib.parse 26 | from glob import glob 27 | from IPython.display import display, Markdown 28 | ~~~ 29 | 30 | 31 | 32 | 33 | 34 | ~~~python 35 | filepaths = glob('*.md') + glob('*/*.md') + glob('*/*/*.md') 36 | for filepath in filepaths: 37 | escaped_filepath = urllib.parse.quote(filepath) 38 | display(Markdown('[{}](../use/{})'.format(filepath, escaped_filepath))) 39 | ~~~ 40 | 41 | 42 | `; 43 | 44 | 45 | @Component({ 46 | selector: 'app-landing-page', 47 | template: template 48 | }) 49 | export class LandingPageComponent implements AfterViewInit { 50 | @ViewChild('formWrapper') formWrapper: ElementRef; 51 | 52 | 53 | constructor( 54 | 55 | ) {} 56 | 57 | ngAfterViewInit() { 58 | const serviceManager = new ServiceManager(); 59 | const contentsManager = new ContentsManager(); 60 | const angularLoader = new AngularLoader(AppModule); 61 | 62 | const formWidget = new ScriptedFormsWidget({ 63 | serviceManager, 64 | contentsManager, 65 | angularLoader 66 | }); 67 | 68 | // formWidget.content.initiliseScriptedForms(); 69 | 70 | window.onresize = () => { formWidget.update(); }; 71 | Widget.attach(formWidget, this.formWrapper.nativeElement); 72 | 73 | formWidget.content.setTemplateToString('a_dummy_path', aTemplate); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /scriptedforms/e2e/run-test.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | 5 | import os 6 | from os.path import join as pjoin 7 | import sys 8 | import argparse 9 | 10 | from tornado.ioloop import IOLoop 11 | 12 | from scriptedforms.scriptedforms import ScriptedForms 13 | 14 | sys.path.append("..") 15 | from dev_utilities.jupyterlab_extracts.process import Process # noqa: E402 16 | 17 | HERE = os.path.realpath(os.path.dirname(__file__)) 18 | 19 | 20 | class ProtractorTestApp(ScriptedForms): 21 | notebook_dir = pjoin(HERE, 'src') 22 | open_browser = False 23 | default_url = '/scriptedforms/use/landing-page.md' 24 | port = 8989 25 | log_level = 30 26 | 27 | def get_command(self): 28 | """Get the command to run.""" 29 | cwd = HERE 30 | token = getattr(self, 'token', '') 31 | 32 | parser = argparse.ArgumentParser() 33 | parser.add_argument('--pattern', action='store') 34 | args, _ = parser.parse_known_args() 35 | pattern = args.pattern or '*.spec.js' 36 | 37 | env = os.environ.copy() 38 | env['JUPYTER_TOKEN'] = token 39 | env['PROTRACTOR_PATTERN'] = pattern 40 | protractor = os.path.abspath( 41 | pjoin(cwd, './node_modules/protractor/bin/protractor')) 42 | cmd = [protractor, 'build/protractor.conf.js'] + sys.argv[1:] 43 | return cmd, dict(env=env, cwd=cwd) 44 | 45 | def start(self): 46 | """Start the application. 47 | """ 48 | IOLoop.current().add_callback(self._run_command) 49 | ScriptedForms.start(self) 50 | 51 | def _run_command(self): 52 | command, kwargs = self.get_command() 53 | kwargs.setdefault('logger', self.log) 54 | future = Process(command, **kwargs).wait_async() 55 | IOLoop.current().add_future(future, self._process_finished) 56 | 57 | def _process_finished(self, future): 58 | try: 59 | IOLoop.current().stop() 60 | sys.exit(future.result()) 61 | except Exception as e: 62 | self.log.error(str(e)) 63 | sys.exit(1) 64 | 65 | 66 | def main(): 67 | app = ProtractorTestApp.instance() 68 | app.initialize([]) 69 | app.start() 70 | 71 | 72 | if __name__ == '__main__': 73 | main() 74 | -------------------------------------------------------------------------------- /deploy/docker/README.md: -------------------------------------------------------------------------------- 1 | # Advanced Docker Deploy of ScriptedForms 2 | 3 | This docker deploy is currently incomplete. It aims to be provide a full 4 | installation of ScriptedForms, served in a multi user format via JupyterHub 5 | behined nginx. 6 | 7 | It is planned that this docker build will become the focus for advanced use 8 | cases of ScriptedForms. The idea is it will provide the ability to save form 9 | results to the PostgreSQL database associating that data entered with the 10 | user login from JupyterHub. Data should then be trendable. Plan to also 11 | implement an easy to customise navigation panel. 12 | 13 | This docker installation will become the location where documentation and 14 | examples are written and provided to the user in an interactive format. This 15 | documentation + examples will also be the focus of the selenium tests. 16 | 17 | If you want to run this on a computer that has a public IP then you should 18 | (as in MUST) **secure it with ssl** by adding ssl options to the docker 19 | configuration for nginx. 20 | 21 | ## Usage 22 | 23 | ### Prep 24 | 25 | You will need docker and docker-compose: 26 | 27 | * [Docker](https://docs.docker.com/install/) 28 | * docker-compose -- `pip install docker-compose` 29 | 30 | For Linux you will need to set up docker to be able to managed as a non-root 31 | user: 32 | 33 | > 34 | 35 | ### Building 36 | 37 | Building is as simple as running the following in this directory 38 | 39 | ```bash 40 | docker-compose build 41 | ``` 42 | 43 | ### Running 44 | 45 | To start the server call the following in this directory: 46 | 47 | ```bash 48 | docker-compose up 49 | ``` 50 | 51 | To run as a daemon that will automatically boot when your computer turns on 52 | run the following: 53 | 54 | ```bash 55 | docker-compose up -d 56 | ``` 57 | 58 | You will be able to access the server by typing `localhost` within a browser. 59 | 60 | ### Shutdown the server 61 | 62 | To shutdown the server run: 63 | 64 | ```bash 65 | docker-compose stop 66 | ``` 67 | 68 | ### Delete all docker data 69 | 70 | If for some reason you need it, the following command will delete all docker 71 | data from all docker projects (WARNING, IRREVERSABLE): 72 | 73 | ```bash 74 | docker stop $(docker ps -a -q) && docker rm $(docker ps -a -q) && echo 'y' | docker volume prune 75 | ``` -------------------------------------------------------------------------------- /scriptedforms/src/app/services/form.service.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { Injectable } from '@angular/core'; 17 | import { BehaviorSubject } from 'rxjs'; 18 | 19 | import { IFormComponent } from '../form-builder-module/create-form-component-factory'; 20 | import { FormBuilderComponent } from '../form-builder-module/form-builder.component'; 21 | 22 | import { FormStatus } from '../types/form-status'; 23 | 24 | 25 | @Injectable() 26 | export class FormService { 27 | template: BehaviorSubject; 28 | component: IFormComponent; 29 | 30 | formBuilderComponent: FormBuilderComponent; 31 | initialising: FormStatus = 'initialising'; 32 | formStatus: BehaviorSubject = new BehaviorSubject(this.initialising); 33 | 34 | formInitialisation() { 35 | this.formStatus.next('initialising'); 36 | 37 | this.template = new BehaviorSubject(null); 38 | this.component = null; 39 | 40 | this.template.subscribe(template => { 41 | if (template !== null) { 42 | this.formBuilderComponent.buildForm(template).then(component => { 43 | this.component = component; 44 | component.formReady.promise.then(() => { 45 | this.formStatus.next('ready'); 46 | }); 47 | }); 48 | } 49 | }); 50 | } 51 | 52 | restartFormKernel() { 53 | this.formStatus.next('restarting'); 54 | const formReadyPromise = this.component.restartFormKernel(); 55 | formReadyPromise.then(() => { 56 | this.formStatus.next('ready'); 57 | }); 58 | return formReadyPromise; 59 | } 60 | 61 | setTemplate(template: string) { 62 | this.template.next(template); 63 | } 64 | 65 | getTemplate() { 66 | return this.template.getValue(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/watchdog-test.spec.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { 18 | browser, element, by, ExpectedConditions 19 | } from 'protractor'; 20 | 21 | import { 22 | beforeFromFile, after, waitForSpinner, makeUrlFromFile, customGet 23 | } from './utilities/before-and-after' 24 | 25 | describe('watchdog-test.md', () => { 26 | beforeEach(beforeFromFile('watchdog-manage.md')) 27 | afterEach(after()) 28 | 29 | it('should update file on changes', () => { 30 | let createButton = element(by.css('.create-watchdog-test button')) 31 | browser.wait(ExpectedConditions.elementToBeClickable(createButton)) 32 | createButton.click() 33 | 34 | waitForSpinner() 35 | customGet(makeUrlFromFile('watchdog-test.md')) 36 | waitForSpinner() 37 | 38 | let writeInMe = element(by.css('.write-in-me textarea')) 39 | browser.wait(ExpectedConditions.presenceOf(writeInMe)) 40 | waitForSpinner() 41 | const testTextHeading = "Prepended Heading!" 42 | writeInMe.sendKeys(`# ${testTextHeading}`) 43 | waitForSpinner() 44 | 45 | let prependButton = element(by.css('.prepend-string-contents button')) 46 | prependButton.click() 47 | 48 | let newHeader = element(by.tagName('h1')) 49 | browser.wait(ExpectedConditions.presenceOf(newHeader)) 50 | expect(newHeader.getText()).toEqual(testTextHeading) 51 | 52 | waitForSpinner() 53 | customGet(makeUrlFromFile('watchdog-manage.md')) 54 | waitForSpinner() 55 | 56 | let deleteButton = element(by.css('.delete-watchdog-test button')) 57 | browser.wait(ExpectedConditions.presenceOf(deleteButton)) 58 | browser.wait(ExpectedConditions.elementToBeClickable(deleteButton)) 59 | waitForSpinner() 60 | deleteButton.click() 61 | }) 62 | }); -------------------------------------------------------------------------------- /scriptedforms/src/vendors/theme.scss: -------------------------------------------------------------------------------- 1 | // The MIT License 2 | 3 | // Copyright (c) 2018 Google LLC. 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | /* 24 | A custom angular material design theme. 25 | */ 26 | 27 | @import "~@angular/material/theming"; 28 | 29 | // Include the common styles for Angular Material. We include this here so that you only 30 | // have to load a single css file for Angular Material in your app. 31 | // Be sure that you only ever include this mixin once! 32 | @include mat-core(); 33 | 34 | // Define the palettes for your theme using the Material Design palettes available in palette.scss 35 | // (imported above). For each palette, you can optionally specify a default, lighter, and darker 36 | // hue. 37 | $my-app-primary: mat-palette($mat-teal); 38 | $my-app-accent: mat-palette($mat-blue, A200, A100, A400); 39 | 40 | // The warn palette is optional (defaults to red). 41 | $my-app-warn: mat-palette($mat-red); 42 | 43 | // Create the theme object (a Sass map containing all of the palettes). 44 | $my-app-theme: mat-light-theme($my-app-primary, $my-app-accent, $my-app-warn); 45 | 46 | // Include theme styles for core and each component used in your app. 47 | // Alternatively, you can import and @include the theme mixins for each component 48 | // that you are using. 49 | @include angular-material-theme($my-app-theme); 50 | -------------------------------------------------------------------------------- /deploy/windows-only/portable-zip/build-instructions.md: -------------------------------------------------------------------------------- 1 | # Creating a portable bundle of ScriptedForms for Windows 2 | 3 | ## Overview 4 | 5 | To create a portable bundle of ScriptedForms and have it be able to run a wide range 6 | of forms all of Python needs to be included as well as any potential packages 7 | that might be imported by the forms themselves. Here is a set of instructions 8 | that creates a portable bundle of ScriptedForms that includes pandas, numpy and 9 | matplotlib. You will need to adjust these instructions if you need more 10 | packages. 11 | 12 | ## Tested bundle creation environment 13 | 14 | Counter-intuitively these instructions have been tested using a Linux Ubuntu 15 | distribution. You will need to make appropriate adjustments if you wish to 16 | create this bundle on another OS. 17 | 18 | ### Ubuntu 16.04 19 | 20 | Using [Ubuntu 16.04](http://releases.ubuntu.com/16.04.4/ubuntu-16.04.4-desktop-amd64.iso). 21 | 22 | ### Wine-Staging 23 | 24 | Wine staging is installed using the following method: 25 | 26 | 27 | 28 | wget -nc https://dl.winehq.org/wine-builds/Release.key 29 | sudo apt-key add Release.key 30 | sudo apt-add-repository https://dl.winehq.org/wine-builds/ubuntu/ 31 | 32 | sudo apt-get install --install-recommends winehq-staging wine-staging-compat 33 | 34 | ### Install WinPython 3.5.4.1Zero.exe 35 | 36 | 37 | 38 | Install to `./python` (relative to scriptedforms/portable-windows-bundle). 39 | 40 | ## Dependency handling 41 | 42 | ### Install dependencies 43 | 44 | wine ./python/python-*/python.exe -m pip --no-cache-dir install scriptedforms numpy pandas matplotlib 45 | 46 | ### Update the dependencies 47 | 48 | wine ./python/python-*/python.exe -m pip --no-cache-dir install --upgrade scriptedforms numpy pandas matplotlib 49 | 50 | ### Temporarily use dev-install of ScriptedForms 51 | 52 | wine ./python/python-*/python.exe -m pip --no-cache-dir install -e ../ 53 | 54 | ## Testing 55 | 56 | ### Testing that ScriptedForms works 57 | 58 | wine ./python/python-*/python.exe -m scriptedforms ./my-forms/landing-page.md 59 | 60 | ### Test the bat file 61 | 62 | This currently doesn't work on Linux, need to test on Windows 63 | 64 | wineconsole scriptedforms.bat 65 | 66 | ## Create the bundle 67 | 68 | zip -r scriptedforms.zip python/* my-forms/* scriptedforms.bat -------------------------------------------------------------------------------- /scriptedforms/e2e/src/section-button.spec.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { 18 | browser, element, by, ExpectedConditions 19 | } from 'protractor'; 20 | 21 | import { beforeFromFile, after, waitForSpinner } from './utilities/before-and-after' 22 | 23 | const TEMPLATE_FILE = 'section-button.md' 24 | 25 | describe(TEMPLATE_FILE, () => { 26 | beforeEach(beforeFromFile(TEMPLATE_FILE)); 27 | afterEach(after()) 28 | 29 | it('should run on click', () => { 30 | let runningButton = element(by.css('.check-my-running button')) 31 | browser.wait(ExpectedConditions.elementToBeClickable(runningButton)) 32 | 33 | let initialOutput = element.all(by.css('.check-my-running .jp-OutputArea-output')) 34 | expect(initialOutput.count()).toEqual(0) 35 | 36 | runningButton.click() 37 | let outputArea = element(by.css('.check-my-running .jp-OutputArea-output')) 38 | browser.wait(ExpectedConditions.presenceOf(outputArea)) 39 | 40 | let text = element(by.tagName('h1')).getText() 41 | expect(text).toEqual('Hello') 42 | }) 43 | 44 | it('should be able to be named', () => { 45 | let namedButtonLabel = element(by.css('.check-my-name button span')) 46 | expect(namedButtonLabel.getText()).toEqual('foo') 47 | }) 48 | 49 | it('should honour conditional', () => { 50 | let disableButton = element(by.css('.make-false button')) 51 | let enableButton = element(by.css('.make-true button')) 52 | 53 | browser.wait(ExpectedConditions.elementToBeClickable(disableButton)) 54 | browser.wait(ExpectedConditions.elementToBeClickable(enableButton)) 55 | 56 | let conditionalButton = element(by.css('.check-my-conditional button')) 57 | expect(conditionalButton.isEnabled()).toBe(false) 58 | 59 | enableButton.click() 60 | waitForSpinner() 61 | expect(conditionalButton.isEnabled()).toBe(true) 62 | 63 | disableButton.click() 64 | waitForSpinner() 65 | expect(conditionalButton.isEnabled()).toBe(false) 66 | }) 67 | }); -------------------------------------------------------------------------------- /scriptedforms/src/app/toolbar-module/toolbar-button.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | /* 17 | Creates the [button] section. 18 | 19 | A section that runs all code within it whenever the user presses the provided 20 | button. 21 | 22 | By calling the function `runCode` on this component all code components within 23 | this section will be iteratively run. The button is set to call the runCode 24 | function on click. 25 | */ 26 | 27 | import { BehaviorSubject, Subscription } from 'rxjs'; 28 | 29 | import { 30 | Component, Input, ElementRef, ViewChild 31 | } from '@angular/core'; 32 | 33 | export interface IOptions { 34 | click?: () => void; 35 | href?: string; 36 | icon?: string; 37 | disable?: BehaviorSubject; 38 | tooltip?: string; 39 | } 40 | 41 | @Component({ 42 | selector: 'toolbar-button', 43 | template: ` 44 | 49 | {{_options.icon}} 50 | 51 | 58 | 59 | 60 | ` 61 | }) 62 | export class ToolbarButtonComponent { 63 | _options: IOptions; 64 | @Input() set options(optionsInput: IOptions) { 65 | this._options = optionsInput; 66 | if (optionsInput.disable) { 67 | if (this.previousSubscription) { 68 | this.previousSubscription.unsubscribe(); 69 | } 70 | this.previousSubscription = optionsInput.disable.subscribe(disableInput => { 71 | this.isDisabled = disableInput; 72 | }); 73 | } 74 | } 75 | 76 | @ViewChild('button') button: ElementRef; 77 | 78 | previousSubscription: Subscription = null; 79 | isDisabled = false; 80 | 81 | constructor( 82 | public myElementRef: ElementRef 83 | ) { } 84 | } 85 | -------------------------------------------------------------------------------- /scriptedforms/src/app/variables-module/variables.module.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | /* 16 | A module containing the form elements. 17 | */ 18 | 19 | import { NgModule } from '@angular/core'; 20 | import { CommonModule } from '@angular/common'; 21 | import { FormsModule } from '@angular/forms'; 22 | 23 | import { 24 | MaterialModule 25 | } from '../../vendors/material.module'; 26 | 27 | import { VariableBaseComponent } from './variable-base.component'; 28 | import { NumberBaseComponent } from './number-base.component'; 29 | 30 | import { ToggleComponent } from './toggle.component'; 31 | import { TickComponent } from './tick.component'; 32 | import { ConditionalComponent } from './conditional.component'; 33 | 34 | import { NumberComponent } from './number.component'; 35 | import { SliderComponent } from './slider.component'; 36 | import { VariableTableComponent } from './variable-table.component'; 37 | 38 | import { StringComponent } from './string.component'; 39 | import { DropdownComponent } from './dropdown.component'; 40 | import { VariableParameterComponent } from './variable-parameter.component'; 41 | 42 | import { VariableFileComponent } from './variable-file.component'; 43 | 44 | 45 | @NgModule({ 46 | imports: [ 47 | CommonModule, 48 | MaterialModule, 49 | FormsModule 50 | ], 51 | declarations: [ 52 | VariableBaseComponent, 53 | NumberBaseComponent, 54 | ToggleComponent, 55 | TickComponent, 56 | ConditionalComponent, 57 | NumberComponent, 58 | SliderComponent, 59 | VariableTableComponent, 60 | StringComponent, 61 | DropdownComponent, 62 | VariableParameterComponent, 63 | VariableFileComponent 64 | ], 65 | exports: [ 66 | ToggleComponent, 67 | TickComponent, 68 | ConditionalComponent, 69 | NumberComponent, 70 | SliderComponent, 71 | VariableTableComponent, 72 | StringComponent, 73 | DropdownComponent, 74 | VariableParameterComponent, 75 | VariableFileComponent 76 | ] 77 | }) 78 | export class VariablesModule { } 79 | -------------------------------------------------------------------------------- /scriptedforms/scriptedforms.py: -------------------------------------------------------------------------------- 1 | # Scripted Forms -- Making GUIs easy for everyone on your team. 2 | # Copyright (C) 2017 Simon Biggs 3 | 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | import sys 18 | import os 19 | import argparse 20 | 21 | from notebook.notebookapp import NotebookApp 22 | 23 | from ._scriptedforms_handlers import get_scriptedforms_handlers 24 | 25 | 26 | def _jupyter_server_extension_paths(): 27 | return [{ 28 | "module": "scriptedforms" 29 | }] 30 | 31 | 32 | def load_jupyter_server_extension(notebook_app): 33 | web_app = notebook_app.web_app 34 | base_url = web_app.settings['base_url'] 35 | handlers = get_scriptedforms_handlers(base_url) 36 | 37 | web_app.add_handlers(".*$", handlers) 38 | 39 | 40 | class ScriptedForms(NotebookApp): 41 | """ScriptedForms.""" 42 | 43 | name = 'ScriptedForms' 44 | description = """ 45 | Scripted Forms 46 | 47 | Open a scriptedform based on a template file. 48 | """ 49 | 50 | def start(self): 51 | load_jupyter_server_extension(self) 52 | super(ScriptedForms, self).start() 53 | 54 | 55 | def load(filepath): 56 | absolute_path = os.path.abspath(filepath) 57 | if not os.path.exists(absolute_path): 58 | raise ValueError('File does not exist: {}'.format(absolute_path)) 59 | 60 | directory, filename = os.path.split(absolute_path) 61 | 62 | # workaround for Notebook app using sys.argv 63 | sys.argv = [sys.argv[0]] 64 | ScriptedForms.launch_instance( 65 | notebook_dir=directory, 66 | default_url='/scriptedforms/use/{}'.format(filename)) 67 | 68 | 69 | def open_docs(): 70 | sys.argv = [sys.argv[0]] 71 | ScriptedForms.launch_instance( 72 | default_url='/scriptedforms/docs') 73 | 74 | 75 | def main(): 76 | parser = argparse.ArgumentParser(description='ScriptedForms.') 77 | parser.add_argument( 78 | 'filepath', help='The file path of the form to open.', nargs='?', 79 | default=None) 80 | 81 | args = parser.parse_args() 82 | if args.filepath: 83 | load(args.filepath) 84 | else: 85 | open_docs() 86 | 87 | 88 | if __name__ == '__main__': 89 | main() 90 | -------------------------------------------------------------------------------- /scriptedforms/src/app/variables-module/dropdown.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { Component, AfterViewInit, Input, ViewChild } from '@angular/core'; 18 | 19 | import { VariableBaseComponent } from './variable-base.component'; 20 | import { VariableParameterComponent } from './variable-parameter.component'; 21 | 22 | @Component({ 23 | selector: 'variable-dropdown', 24 | template: ` 25 | 26 | 27 | 28 | {{items}} 29 | 30 | {{labelValue}} 31 | 39 | {{option}} 40 | 41 | `, 42 | styles: [ 43 | `.variableDropdown { 44 | width: 100%; 45 | } 46 | `] 47 | }) 48 | export class DropdownComponent extends VariableBaseComponent 49 | implements AfterViewInit { 50 | 51 | @Input() items: string; 52 | 53 | @ViewChild('optionsParameter') optionsParameter: VariableParameterComponent; 54 | 55 | parameterValues: { [s: string]: (string | number)[]; } = { 56 | optionsValue: [] 57 | } 58 | 59 | setVariableParameterMap() { 60 | this.variableParameterMap = [ 61 | [this.optionsParameter, 'optionsValue'], 62 | ] 63 | } 64 | 65 | pythonValueReference() { 66 | let valueReference: string; 67 | 68 | if (typeof this.variableValue === 'string') { 69 | const escapedString = String(this.variableValue) 70 | .replace(/\\/g, '\\\\') 71 | .replace(/\"/g, '\\\"'); 72 | valueReference = `"""${String(escapedString)}"""`; 73 | } else { 74 | valueReference = String(this.variableValue); 75 | } 76 | return valueReference; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /scriptedforms/src/app/sections-module/section-file-change.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { Subscription } from 'rxjs'; 18 | 19 | import { 20 | Component, OnDestroy, Input, AfterViewInit, 21 | ViewChild 22 | } from '@angular/core'; 23 | 24 | import { SectionBaseComponent } from './section-base.component'; 25 | import { VariableParameterComponent } from '../variables-module/variable-parameter.component'; 26 | 27 | import { WatchdogService } from '../services/watchdog.service'; 28 | 29 | @Component({ 30 | selector: 'section-filechange', 31 | template: ` 32 | _watchdog_path_conversion({{paths}}) 33 | {{code}}` 34 | }) 35 | export class SectionFileChangeComponent extends SectionBaseComponent implements OnDestroy, AfterViewInit { 36 | sectionType = 'filechange'; 37 | watchdogSubscription: Subscription; 38 | pathsConverted: string[]; 39 | 40 | @Input() paths: string; 41 | 42 | @ViewChild('variableParameterComponent') variableParameterComponent: VariableParameterComponent; 43 | 44 | constructor( 45 | private myWatchdogService: WatchdogService 46 | ) { super(); } 47 | 48 | updateFilepathObserver() { 49 | this.pathsConverted.forEach(value => { 50 | this.myWatchdogService.addFilepathObserver(value); 51 | }); 52 | } 53 | 54 | ngAfterViewInit() { 55 | super.ngAfterViewInit(); 56 | // this.updateFilepathObserver() 57 | 58 | this.variableParameterComponent.variableChange.asObservable().subscribe((value: string[]) => { 59 | this.pathsConverted = value; 60 | this.updateFilepathObserver(); 61 | }); 62 | 63 | this.watchdogSubscription = this.myWatchdogService.fileChanged.subscribe((value: string) => { 64 | if (this.pathsConverted) { 65 | if ( 66 | (this.pathsConverted.includes(value)) || 67 | (this.pathsConverted.includes(`./${value}`)) || 68 | (this.pathsConverted.includes(`.\\${value}`)) 69 | ) { 70 | this.runCode(); 71 | } 72 | } 73 | }); 74 | } 75 | 76 | ngOnDestroy() { 77 | this.watchdogSubscription.unsubscribe(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | 61 | build 62 | lib 63 | 64 | # Byte-compiled / optimized / DLL files 65 | __pycache__/ 66 | *.py[cod] 67 | *$py.class 68 | 69 | # C extensions 70 | *.so 71 | 72 | # Distribution / packaging 73 | .Python 74 | env/ 75 | build/ 76 | develop-eggs/ 77 | dist/ 78 | downloads/ 79 | eggs/ 80 | .eggs/ 81 | lib/ 82 | lib64/ 83 | parts/ 84 | sdist/ 85 | var/ 86 | wheels/ 87 | *.egg-info/ 88 | .installed.cfg 89 | *.egg 90 | 91 | # PyInstaller 92 | # Usually these files are written by a python script from a template 93 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 94 | *.manifest 95 | *.spec 96 | 97 | # Installer logs 98 | pip-log.txt 99 | pip-delete-this-directory.txt 100 | 101 | # Unit test / coverage reports 102 | htmlcov/ 103 | .tox/ 104 | .coverage 105 | .coverage.* 106 | .cache 107 | nosetests.xml 108 | coverage.xml 109 | *.cover 110 | .hypothesis/ 111 | 112 | # Translations 113 | *.mo 114 | *.pot 115 | 116 | # Django stuff: 117 | *.log 118 | local_settings.py 119 | 120 | # Flask stuff: 121 | instance/ 122 | .webassets-cache 123 | 124 | # Scrapy stuff: 125 | .scrapy 126 | 127 | # Sphinx documentation 128 | docs/_build/ 129 | 130 | # PyBuilder 131 | target/ 132 | 133 | # Jupyter Notebook 134 | .ipynb_checkpoints 135 | 136 | # pyenv 137 | .python-version 138 | 139 | # celery beat schedule file 140 | celerybeat-schedule 141 | 142 | # SageMath parsed files 143 | *.sage.py 144 | 145 | # dotenv 146 | .env 147 | 148 | # virtualenv 149 | .venv 150 | venv/ 151 | ENV/ 152 | 153 | # Spyder project settings 154 | .spyderproject 155 | .spyproject 156 | 157 | # Rope project settings 158 | .ropeproject 159 | 160 | # mkdocs documentation 161 | /site 162 | 163 | # mypy 164 | .mypy_cache/ 165 | 166 | scriptedforms/jlab-build 167 | -------------------------------------------------------------------------------- /scriptedforms/src/dev.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { 17 | PromiseDelegate 18 | } from '@phosphor/coreutils'; 19 | 20 | import { 21 | ServerConnection, Session, KernelMessage, ServiceManager 22 | } from '@jupyterlab/services'; 23 | 24 | 25 | export function loadDev(serviceManager = new ServiceManager()) { 26 | // const serviceManager = new ServiceManager(); 27 | runDevModeWatchdog(serviceManager); 28 | } 29 | 30 | const watchdogDevModeCode = ` 31 | import os 32 | from watchdog.observers import Observer 33 | from watchdog.events import FileSystemEventHandler, FileModifiedEvent 34 | 35 | import scriptedforms 36 | 37 | class MyHandler(FileSystemEventHandler): 38 | def on_modified(self, event): 39 | if type(event) == FileModifiedEvent: 40 | print(os.path.abspath(event.src_path)) 41 | 42 | event_handler = MyHandler() 43 | observer = Observer() 44 | observer.schedule( 45 | event_handler, 46 | path=os.path.join(os.path.dirname(scriptedforms.__file__), 'lib'), 47 | recursive=True) 48 | observer.start() 49 | `; 50 | 51 | function runDevModeWatchdog(serviceManager: ServiceManager) { 52 | const sessionReady = new PromiseDelegate(); 53 | 54 | const path = '_dev_watchdog_scriptedforms'; 55 | const settings = ServerConnection.makeSettings({}); 56 | const startNewOptions = { 57 | kernelName: 'python3', 58 | serverSettings: settings, 59 | path: path 60 | }; 61 | 62 | serviceManager.sessions.findByPath(path).then(model => { 63 | let session = Session.connectTo(model, settings) 64 | sessionReady.resolve(session); 65 | }).catch(() => { 66 | Session.startNew(startNewOptions).then(session => { 67 | session.kernel.requestExecute({ code: watchdogDevModeCode }); 68 | sessionReady.resolve(session); 69 | }); 70 | }); 71 | 72 | sessionReady.promise.then(session => { 73 | session.iopubMessage.connect((sender, msg) => { 74 | if (KernelMessage.isErrorMsg(msg)) { 75 | const errorMsg: KernelMessage.IErrorMsg = msg; 76 | console.error(errorMsg.content); 77 | } 78 | if (msg.content.text) { 79 | const content = String(msg.content.text).trim(); 80 | const files = content.split('\n'); 81 | console.log(files); 82 | location.reload(true); 83 | } 84 | }); 85 | }); 86 | } 87 | 88 | -------------------------------------------------------------------------------- /scriptedforms/src/app/services/initialisation.service.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { Injectable } from '@angular/core'; 17 | 18 | import { Widget } from '@phosphor/widgets'; 19 | 20 | import { ServiceManager, ContentsManager } from '@jupyterlab/services'; 21 | import { DocumentRegistry } from '@jupyterlab/docregistry'; 22 | 23 | import { 24 | Toolbar 25 | } from '@jupyterlab/apputils'; 26 | 27 | import { JupyterService } from './jupyter.service'; 28 | import { WatchdogService } from './watchdog.service'; 29 | import { FileService } from './file.service'; 30 | import { ToolbarService } from './toolbar.service'; 31 | 32 | export namespace IScriptedForms { 33 | export interface IOptions { 34 | serviceManager: ServiceManager; 35 | contentsManager: ContentsManager; 36 | node: HTMLElement; 37 | toolbar: Toolbar; 38 | context?: DocumentRegistry.Context; 39 | } 40 | } 41 | 42 | @Injectable() 43 | export class InitialisationService { 44 | 45 | constructor( 46 | private myJupyterService: JupyterService, 47 | private myFileService: FileService, 48 | private myWatchdogService: WatchdogService, 49 | private myToolbarService: ToolbarService 50 | ) { } 51 | 52 | public initiliseBaseScriptedForms(options: IScriptedForms.IOptions) { 53 | this.myJupyterService.setServiceManager(options.serviceManager); 54 | this.myJupyterService.setContentsManager(options.contentsManager); 55 | 56 | this.myFileService.setNode(options.node); 57 | this.myToolbarService.setToolbar(options.toolbar); 58 | this.myWatchdogService.startWatchdog(); 59 | } 60 | 61 | public initiliseScriptedForms(options: IScriptedForms.IOptions) { 62 | console.log('Initialising ScriptedForms'); 63 | this.initiliseBaseScriptedForms(options); 64 | 65 | if (!options.context) { 66 | console.log('No Widget Context. Assuming in standalone mode.'); 67 | this.myFileService.openUrl(window.location.href); 68 | } else { 69 | console.log('Widget context found. Assuming running as JupyterLab extension.'); 70 | this.myFileService.context = options.context; 71 | this.myFileService.openFile(options.context.path); 72 | } 73 | 74 | if (!options.context) { 75 | window.onpopstate = event => { 76 | this.myFileService.openUrl(window.location.href); 77 | }; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /scriptedforms/src/docs/developer-guide/README.md: -------------------------------------------------------------------------------- 1 | # [WIP] Contributor documentation 2 | 3 | ## Links for the technologies used 4 | 5 | * [Python](https://www.python.org/) 6 | * [Markdown](http://commonmark.org/help/) 7 | * [Typescript](https://www.typescriptlang.org/) 8 | * [JupyterLab packages](http://jupyterlab.readthedocs.io): 9 | * [@jupyterlab/services](https://github.com/jupyterlab/jupyterlab/tree/master/packages/services) 10 | * [@jupyterlab/outputarea](https://github.com/jupyterlab/jupyterlab/tree/master/packages/outputarea) 11 | * [Jupyter Notebook Server](http://jupyter-notebook.readthedocs.io) 12 | * [Tornado](http://www.tornadoweb.org) 13 | * [PhosphorJS](https://phosphorjs.github.io/) 14 | * [Angular](https://angular.io/) 15 | * [Angular Material](https://material.angular.io/) 16 | * [Webpack](https://webpack.js.org/) 17 | 18 | ## Setting up a development environment 19 | 20 | ### Required tools 21 | 22 | #### Yarn 23 | 24 | Yarn is a javascript package manager built by Facebook. A key benefit of yarn 25 | is its lock file `yarn.lock`. By using the lock file this means that everyone 26 | will install the same version of the depenedency packages. This simplifies 27 | set up on a new machine. 28 | 29 | Yarn can be downloaded and installed from 30 | 31 | #### Python 32 | 33 | Python 3.5 or greater is required. I personally use 34 | [pyenv](https://github.com/pyenv/pyenv) to manage my Python version. However 35 | to use this you either need to be running Linux or OSX, or optionally Windows 36 | 10 with the [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10). 37 | 38 | If you are on Windows I have found that the [Anaconda distribution of Python](https://www.anaconda.com/download) 39 | produces the least headaches. 40 | 41 | #### Git 42 | 43 | Git is a software version control system. It allows multiple users to 44 | collaborate on the code base. Each user can edit code on their own machine 45 | and then merge the results onto [the GitHub repository](https://github.com/SimonBiggs/scriptedforms). 46 | 47 | If you are on a Debian based Linux installing git is as simple as 48 | `sudo apt-get install git`. If you are on OSX a recommended way to get git is 49 | to [install homebrew](https://brew.sh/) and then run `brew install git`. 50 | 51 | If you are on Windows it is recommended to [install Chocolatey](https://chocolatey.org/) 52 | and then run `choco install git`. 53 | 54 | #### GitHub account 55 | 56 | GitHub is a website for the sharing of git based code repositories. You will 57 | need to create a GitHub account. 58 | 59 | ### Recommended tools 60 | 61 | #### Visual Studio Code 62 | 63 | [Visual Studio Code](https://code.visualstudio.com/) is a brilliant open source 64 | code editor by Microsoft. It is very useful for both Typescript and Python. 65 | 66 | #### Linters 67 | 68 | Flake8 is a linter for Python. Think of it as a spell check except for code. 69 | Combined with Visual Studio Code it helps run sanity checks on your code as 70 | you write it. -------------------------------------------------------------------------------- /scriptedforms/forms/agree-to-license.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Need to agree to Scripted Forms software license on first use 4 | 5 | This appears to be the first use of the Scripted Forms package on this 6 | computer. Please agree to the terms and conditions below before you can 7 | continue to use Scripted Forms. 8 | 9 | 24 | 25 | 26 | 27 | ```python 28 | import os 29 | from ipython_genutils.path import ensure_dir_exists 30 | from jupyter_core.paths import jupyter_data_dir 31 | 32 | from IPython.display import display, Markdown 33 | from scriptedforms._utilities import _print_agpl, _print_apache 34 | 35 | scripted_forms_data_directory = os.path.join( 36 | os.path.split(jupyter_data_dir())[0], 'scriptedforms') 37 | ensure_dir_exists(scripted_forms_data_directory) 38 | 39 | license_agreement_file = os.path.join( 40 | scripted_forms_data_directory, 41 | 'has-agreed-to-scriptedforms-license') 42 | 43 | i_agree_to_apache = False 44 | ``` 45 | 46 | 47 | 48 | ## Software license agreement 49 | 50 | Scripted Forms -- Making GUIs easy for everyone on your team. 51 | 52 | Copyright (C) 2017 Simon Biggs 53 | 54 | Licensed under the Apache License, Version 2.0 (the "License"); 55 | you may not use this file except in compliance with the License. 56 | You may obtain a copy of the License at 57 | 58 | > 59 | 60 | Unless required by applicable law or agreed to in writing, software 61 | distributed under the License is distributed on an "AS IS" BASIS, 62 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 63 | See the License for the specific language governing permissions and 64 | limitations under the License. 65 | 66 | 67 | 68 | Apache-2.0 69 | 70 | The Apache License, Version 2.0 71 | 72 | 73 | 74 | 75 | 76 | ```python 77 | _print_apache() 78 | ``` 79 | 80 | 81 | 82 | 83 | 84 | 85 | i_agree_to_apache 86 | 87 | 88 | 89 | 90 |



91 | 92 | 93 | 94 | ```python 95 | if i_agree_to_apache: 96 | with open(license_agreement_file, 'w') as file: 97 | file.write('') 98 | 99 | print('Record of agreement created at:\n {}'.format(license_agreement_file)) 100 | ``` 101 | 102 | -------------------------------------------------------------------------------- /scriptedforms/e2e/src/variable-string.spec.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { 18 | browser, element, by, ExpectedConditions, ElementFinder, Key 19 | } from 'protractor'; 20 | 21 | import { beforeFromFile, after, waitForSpinner } from './utilities/before-and-after' 22 | 23 | const TEMPLATE_FILE = 'variable-string.md' 24 | 25 | function writeInBothAndTest(text: string, sendKeysInto?: (elementFinder: ElementFinder) => void) { 26 | let firstString = element(by.css('.write-in-me-first textarea')) 27 | let secondString = element(by.css('.write-in-me-second textarea')) 28 | 29 | let resultContents = element(by.css('.see-my-result .jp-OutputArea-output pre')) 30 | browser.wait(ExpectedConditions.presenceOf(resultContents)) 31 | expect(resultContents.getText()).toEqual('') 32 | 33 | if (!sendKeysInto) { 34 | sendKeysInto = (elementFinder: ElementFinder) => { 35 | elementFinder.sendKeys(text) 36 | } 37 | } 38 | 39 | sendKeysInto(firstString) 40 | waitForSpinner() 41 | expect(secondString.getAttribute('value')).toEqual(text) 42 | 43 | browser.wait(ExpectedConditions.presenceOf(resultContents)) 44 | expect(resultContents.getText()).toEqual(text) 45 | 46 | sendKeysInto(secondString) 47 | waitForSpinner() 48 | expect(firstString.getAttribute('value')).toEqual(text + text) 49 | 50 | browser.wait(ExpectedConditions.presenceOf(resultContents)) 51 | expect(resultContents.getText()).toEqual(text + text) 52 | } 53 | 54 | describe(TEMPLATE_FILE, () => { 55 | beforeEach(beforeFromFile(TEMPLATE_FILE)); 56 | afterEach(after()) 57 | 58 | it('should handle backslash', () => { 59 | writeInBothAndTest('\\\\\\') 60 | }) 61 | 62 | it('should handle double quotes', () => { 63 | writeInBothAndTest('""""""') 64 | }) 65 | 66 | it('should handle single quotes', () => { 67 | writeInBothAndTest("''''''") 68 | }) 69 | 70 | it('should handle new lines', () => { 71 | let sendKeysInto = (elementFinder: ElementFinder) => { 72 | elementFinder.sendKeys( 73 | 'foo', Key.ENTER, 'bar', Key.ENTER, 'boo', Key.ENTER, 'hoo') 74 | } 75 | writeInBothAndTest('foo\nbar\nboo\nhoo', sendKeysInto) 76 | }) 77 | 78 | it('should handle quotes and backslashes together', () => { 79 | writeInBothAndTest("\\'\\\"\\\\") 80 | }) 81 | 82 | it('should handle fences', () => { 83 | writeInBothAndTest("``` ~~~ ``` ~~~") 84 | }) 85 | }); -------------------------------------------------------------------------------- /scriptedforms/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | /* 17 | The root app module. 18 | */ 19 | import { BrowserModule } from '@angular/platform-browser'; 20 | import { NgModule, ApplicationRef, ErrorHandler } from '@angular/core'; 21 | import { FormsModule } from '@angular/forms'; 22 | 23 | import { APP_BASE_HREF } from '@angular/common'; 24 | 25 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 26 | import { MaterialModule } from '../vendors/material.module'; 27 | 28 | import { AppErrorHandler } from './app-error-handler'; 29 | 30 | import { KernelService } from './services/kernel.service'; 31 | import { VariableService } from './services/variable.service'; 32 | import { FileService } from './services/file.service'; 33 | import { WatchdogService } from './services/watchdog.service'; 34 | import { FormService } from './services/form.service'; 35 | import { JupyterService } from './services/jupyter.service'; 36 | import { InitialisationService } from './services/initialisation.service'; 37 | import { ToolbarService } from './services/toolbar.service'; 38 | 39 | import { FormBuilderModule } from './form-builder-module/form-builder.module'; 40 | import { ToolbarModule } from './toolbar-module/toolbar.module'; 41 | 42 | import { ToolbarButtonComponent } from './toolbar-module/toolbar-button.component'; 43 | 44 | import { AppComponent } from './app.component'; 45 | 46 | const SF_CONFIG = document.getElementById('scriptedforms-config-data'); 47 | const JLAB_CONFIG = document.getElementById('jupyter-config-data'); 48 | 49 | let config: { baseUrl: string }; 50 | 51 | if (SF_CONFIG) { 52 | config = JSON.parse(SF_CONFIG.textContent); 53 | } else { 54 | config = JSON.parse(JLAB_CONFIG.textContent); 55 | } 56 | 57 | const baseUrl = config.baseUrl; 58 | 59 | 60 | @NgModule({ 61 | declarations: [ 62 | AppComponent 63 | ], 64 | imports: [ 65 | BrowserAnimationsModule, 66 | BrowserModule, 67 | FormsModule, 68 | MaterialModule, 69 | FormBuilderModule, 70 | ToolbarModule 71 | ], 72 | entryComponents: [AppComponent, ToolbarButtonComponent], 73 | providers: [ 74 | KernelService, 75 | VariableService, 76 | FileService, 77 | WatchdogService, 78 | FormService, 79 | JupyterService, 80 | InitialisationService, 81 | ToolbarService, 82 | { provide: ErrorHandler, useClass: AppErrorHandler }, 83 | { provide: APP_BASE_HREF, useValue: baseUrl } 84 | ], 85 | exports: [ 86 | AppComponent, 87 | ] 88 | }) 89 | export class AppModule { 90 | ngDoBootstrap(app: ApplicationRef) { } 91 | } 92 | -------------------------------------------------------------------------------- /scriptedforms/src/app/sections-module/section-base.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | 17 | import { 18 | Component, ContentChildren, QueryList, AfterViewInit, ViewChildren, Input 19 | } from '@angular/core'; 20 | import { PromiseDelegate } from '@phosphor/coreutils'; 21 | 22 | import { CodeComponent } from '../code-module/code.component'; 23 | 24 | 25 | @Component({ 26 | template: '' 27 | }) 28 | export class SectionBaseComponent implements AfterViewInit { 29 | @Input() onLoad?: string; 30 | @Input() code?: string; 31 | sectionId: number; 32 | sectionType: string; 33 | isFormReady = false; 34 | 35 | codeRunning = false; 36 | 37 | formReadyPromiseDelegate = new PromiseDelegate(); 38 | viewInitPromiseDelegate = new PromiseDelegate(); 39 | 40 | codeComponentsArray: CodeComponent[]; 41 | 42 | @ContentChildren(CodeComponent) contentCodeComponents: QueryList; 43 | @ViewChildren(CodeComponent) viewCodeComponents: QueryList; 44 | 45 | ngAfterViewInit() { 46 | this.viewInitPromiseDelegate.resolve(null); 47 | this.codeComponentsArray = this.contentCodeComponents.toArray().concat(this.viewCodeComponents.toArray()); 48 | } 49 | 50 | runCode(evenIfNotReady = false) { 51 | if (evenIfNotReady || this.formReady) { 52 | const runCodeComplete = new PromiseDelegate(); 53 | this.viewInitPromiseDelegate.promise 54 | .then(() => { 55 | this.codeRunning = true; 56 | this._runAllCodeComponents(runCodeComplete); 57 | runCodeComplete.promise.then(() => { 58 | this.codeRunning = false; 59 | }); 60 | }); 61 | return runCodeComplete.promise; 62 | } else { 63 | console.log(`did not run, form not ready: "${this.sectionType}"_${this.sectionId}`); 64 | return Promise.resolve(null); 65 | } 66 | 67 | } 68 | 69 | _runAllCodeComponents(runCodeComplete: PromiseDelegate) { 70 | const promiseList: Promise[] = []; 71 | this.codeComponentsArray.forEach((codeComponent, index) => { 72 | promiseList.push(codeComponent.runCode()); 73 | }); 74 | Promise.all(promiseList).then(() => { 75 | runCodeComplete.resolve(null); 76 | }); 77 | } 78 | 79 | formReady(isReady: boolean) { 80 | this.formReadyPromiseDelegate.resolve(null); 81 | this.isFormReady = isReady; 82 | } 83 | 84 | setId(id: number) { 85 | this.sectionId = id; 86 | this.codeComponentsArray.forEach((codeComponent, index) => { 87 | codeComponent.name = `"${this.sectionType}"_${this.sectionId}_${index}`; 88 | }); 89 | } 90 | 91 | kernelReset() { } 92 | } 93 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at mail@simonbiggs.net. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /scriptedforms/src/app/variables-module/slider.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { 17 | Component, AfterViewInit, Input, ViewChild 18 | } from '@angular/core'; 19 | 20 | import { VariableBaseComponent } from './variable-base.component'; 21 | import { VariableParameterComponent } from './variable-parameter.component'; 22 | // import { Slider } from '../interfaces/slider'; 23 | 24 | // import * as stringify from 'json-stable-stringify'; 25 | 26 | @Component({ 27 | selector: 'variable-slider', 28 | template: ` 29 | 30 | 31 | 32 | {{min}} 33 | {{max}} 34 | {{step}} 35 | {{labelValue}} 36 | 46 | 47 | 48 | `, 57 | styles: [ 58 | ` 59 | .container { 60 | display: flex; 61 | } 62 | 63 | .variableSlider { 64 | flex-grow: 1; 65 | } 66 | `] 67 | }) 68 | export class SliderComponent extends VariableBaseComponent implements AfterViewInit { 69 | @Input() min?: number | string; 70 | @Input() max?: number | string; 71 | @Input() step?: number | string; 72 | 73 | @ViewChild('minParameter') minParameter: VariableParameterComponent; 74 | @ViewChild('maxParameter') maxParameter: VariableParameterComponent; 75 | @ViewChild('stepParameter') stepParameter: VariableParameterComponent; 76 | 77 | parameterValues: { [s: string]: number; } = { 78 | minValue: 0, 79 | maxValue: 100, 80 | stepValue: 1 81 | } 82 | 83 | setVariableParameterMap() { 84 | this.variableParameterMap = [ 85 | [this.minParameter, 'minValue'], 86 | [this.maxParameter, 'maxValue'], 87 | [this.stepParameter, 'stepValue'], 88 | ] 89 | } 90 | 91 | updateValue(value: number) { 92 | this.variableValue = value; 93 | this.variableChanged(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /scriptedforms/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "arrow-return-shorthand": true, 7 | "callable-types": true, 8 | "class-name": true, 9 | "comment-format": [ 10 | true, 11 | "check-space" 12 | ], 13 | "curly": true, 14 | "deprecation": { 15 | "severity": "warn" 16 | }, 17 | "eofline": true, 18 | "forin": true, 19 | "import-blacklist": [ 20 | true, 21 | "rxjs/Rx" 22 | ], 23 | "import-spacing": true, 24 | "indent": [ 25 | true, 26 | "spaces" 27 | ], 28 | "interface-over-type-literal": true, 29 | "label-position": true, 30 | "max-line-length": [ 31 | true, 32 | 140 33 | ], 34 | "member-access": false, 35 | "member-ordering": [ 36 | true, 37 | { 38 | "order": [ 39 | "static-field", 40 | "instance-field", 41 | "static-method", 42 | "instance-method" 43 | ] 44 | } 45 | ], 46 | "no-arg": true, 47 | "no-bitwise": true, 48 | "no-console": [ 49 | true, 50 | "debug", 51 | "info", 52 | "time", 53 | "timeEnd", 54 | "trace" 55 | ], 56 | "no-construct": true, 57 | "no-debugger": true, 58 | "no-duplicate-super": true, 59 | "no-empty": false, 60 | "no-empty-interface": true, 61 | "no-eval": true, 62 | "no-inferrable-types": [ 63 | true, 64 | "ignore-params" 65 | ], 66 | "no-misused-new": true, 67 | "no-non-null-assertion": true, 68 | "no-shadowed-variable": true, 69 | "no-string-literal": false, 70 | "no-string-throw": true, 71 | "no-switch-case-fall-through": true, 72 | "no-trailing-whitespace": true, 73 | "no-unnecessary-initializer": true, 74 | "no-unused-expression": true, 75 | "no-use-before-declare": true, 76 | "no-var-keyword": true, 77 | "object-literal-sort-keys": false, 78 | "one-line": [ 79 | true, 80 | "check-open-brace", 81 | "check-catch", 82 | "check-else", 83 | "check-whitespace" 84 | ], 85 | "prefer-const": true, 86 | "quotemark": [ 87 | true, 88 | "single" 89 | ], 90 | "radix": true, 91 | "semicolon": [ 92 | true, 93 | "always" 94 | ], 95 | "triple-equals": [ 96 | true, 97 | "allow-null-check" 98 | ], 99 | "typedef-whitespace": [ 100 | true, 101 | { 102 | "call-signature": "nospace", 103 | "index-signature": "nospace", 104 | "parameter": "nospace", 105 | "property-declaration": "nospace", 106 | "variable-declaration": "nospace" 107 | } 108 | ], 109 | "unified-signatures": true, 110 | "variable-name": false, 111 | "whitespace": [ 112 | true, 113 | "check-branch", 114 | "check-decl", 115 | "check-operator", 116 | "check-separator", 117 | "check-type" 118 | ], 119 | "directive-selector": [ 120 | true, 121 | "attribute", 122 | "app", 123 | "camelCase" 124 | ], 125 | "no-output-on-prefix": true, 126 | "use-input-property-decorator": true, 127 | "use-output-property-decorator": true, 128 | "use-host-property-decorator": true, 129 | "no-input-rename": true, 130 | "no-output-rename": true, 131 | "use-life-cycle-interface": true, 132 | "use-pipe-transform-interface": true, 133 | "component-class-suffix": true, 134 | "directive-class-suffix": true 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /deploy/python-package/README.md: -------------------------------------------------------------------------------- 1 | # Scripted Forms Package Example 2 | 3 | Scipted Forms is designed to be used as a quick and easy GUI for python 4 | packages. Within this directory is an example package that creates a console 5 | script that then uses scriptedforms to boot up a GUI. 6 | 7 | ## Running the example 8 | 9 | To run this example you need to download this repository. One way to do that 10 | is by downloading the [repository zip file](https://github.com/SimonBiggs/scriptedforms/archive/master.zip). 11 | 12 | Once you have download and extracted the repository navigate to 13 | this `example` directory and then install this package by running the following within a terminal: 14 | 15 | ```bash 16 | pip install -e . 17 | ``` 18 | 19 | To then use the package, in any directory on your machine within a terminal run: 20 | 21 | ```bash 22 | python -m example 23 | ``` 24 | 25 | This will then boot up the scriptedforms GUI in your default browser. 26 | 27 | As an extra benefit, if you have either `simple.md` or `detailed.md` open in 28 | the browser while you edit and save the file scriptedforms will automatically 29 | reload. 30 | 31 | ## A possible method for creating your own package 32 | 33 | Firstly you need to change all instances of the package name "example" to your 34 | own package name. 35 | 36 | Here is a list of all of these instances within files: 37 | 38 | * [`setup.py`](./setup.py) lines [4](./setup.py#L4), [11](./setup.py#L11), and two instances on line [15](./setup.py#L15). 39 | * [`MANIFEST.in`](./MANIFEST.in#L1) 40 | * and [`your_package_name/__main__.py`](./example/__main__.py#L1) 41 | 42 | And then the `example` directory needs to be changed to your own package 43 | name as well as `example.py`. 44 | 45 | Then you need to create the functions you will be using within your GUI within 46 | `your_package_name.py`. Then within your markdown form file import your 47 | package and create your GUI. 48 | 49 | The [`detailed.md`](https://raw.githubusercontent.com/SimonBiggs/scriptedforms/master/example/example/detailed.md) 50 | file hopefully will be helpful as a starting place to build what ever you might 51 | need. 52 | 53 | Lastly, on [line 10 of `your_package_name/your_package_name.py`](https://github.com/SimonBiggs/scriptedforms/blob/master/example/example/example.py#L10) 54 | you will need to change the markdown filename to match the filename of your 55 | markdown file. 56 | 57 | ## A possible method for deploying on a user machine 58 | 59 | Lets say you have a really nifty script that does something great. But you want 60 | to make a non-technical frontend for others within your company to interface 61 | with your work. A workflow to get your brilliant tool on a client's machine 62 | might be the following. 63 | 64 | First drop your package on a network share. 65 | 66 | Then download and install the latest Python3 Anaconda distribution from the 67 | following link on the computer of the user who will need to use your software: 68 | 69 | > 70 | 71 | On the computer in question within the console navigate to your package on the 72 | shared drive making sure your console's working directory is at the top level 73 | of your package, where `setup.py` is located. Then install your package using 74 | the following command within the console: 75 | 76 | ```bash 77 | pip install . 78 | ``` 79 | 80 | Or if you want the user's installation to always match what exists on the 81 | network share then use the following: 82 | 83 | ```bash 84 | pip install -e . 85 | ``` 86 | 87 | Once it is installed create a `.bat` file which simply has within it: 88 | 89 | ```batch 90 | start python -m your_package_name 91 | ``` 92 | 93 | And then place that on the desktop, or where ever you expect the user will be 94 | clicking on it. 95 | -------------------------------------------------------------------------------- /scriptedforms/docs/create-your-own-angular-jupyterlab-extension.md: -------------------------------------------------------------------------------- 1 | # Create your own Angular JupyterLab extension 2 | 3 | ScriptedForms is built on top of [Angular](https://angular.io) and it is 4 | embedded within [PhosphorJS](http://phosphorjs.github.io/) so that it can be 5 | provided as a [JupyterLab extension](http://jupyterlab.readthedocs.io/en/stable/developer/xkcd_extension_tutorial.html). 6 | 7 | If you would like to use the above tools to create your own JupyterLab extension 8 | this document is for you. If you just want to make your own JupyterLab extension 9 | you should instead be reading the [xkcd extension tutorial](http://jupyterlab.readthedocs.io/en/stable/developer/xkcd_extension_tutorial.html). 10 | If you just want to use ScriptedForms head on over to . 11 | 12 | This guide assumes that you are comfortable using Angular, and you are 13 | comfortable creating a basic JupyterLab extension. 14 | 15 | ## Copying permissions 16 | 17 | ScriptedForms itself is licensed under the AGPLv3.0+ license with additional terms. 18 | However, so that you can make your own Angular JupyterLab extensions, and not 19 | have to use the AGPLv3.0+ yourself, the specific files required to achieve this 20 | in a bare bones fashion have been licensed either under the Apache 2.0+ or the 21 | BSD. The choice of which license the file is under depends on whether or not 22 | that file was derived from work done by the Jupyter team. 23 | 24 | ## Files specific to an Angular JupyterLab extension 25 | 26 | The source code for the Angular portion of ScriptedForms is all contained within 27 | [src](../src). The key files which are unique to the JupyterLab Angular 28 | combination are listed below. 29 | 30 | Key parts of this guide are actually contained as descriptive text within these 31 | listed files. This descriptive text is below the package imports and looks something like: 32 | 33 | ```typescript 34 | /* 35 | * # Create your own Angular JupyterLab extension (cont.) 36 | * 37 | * This is part of the guide available at 38 | * 39 | * 40 | * ... 41 | * 42 | */ 43 | ``` 44 | 45 | Please click through each of the links below to read what each of the required 46 | files do and why they are needed. 47 | 48 | * [phosphor-angular-loader.ts](../src/app/phosphor-angular-loader.ts) 49 | * [app.component.ts](../src/app/app.component.ts) 50 | * [component-html.d.ts](../src/component-html.d.ts) 51 | * [widget.ts](../src/app/widget.ts) 52 | * [jupyterlab-plugin.ts](../src/jupyterlab-extension/jupyterlab-plugin.ts) 53 | 54 | There are of course other files required. However they are not specific to this 55 | particular combination. 56 | 57 | If you believe more files from within ScriptedForms should be a part of this 58 | guide please either [create an issue](https://github.com/SimonBiggs/scriptedforms/issues/new) 59 | or a pull request to ScriptedForms. 60 | 61 | ## Providing your extension to JupyterLab 62 | 63 | To build ScriptedForms ready to be installed as a JupyterLab extension `tsc` is run 64 | and then html, css, and scss files are copied into the build directory. This command 65 | uses the [tsconfig.json](../tsconfig.json) file. 66 | 67 | This bundle of primarily css, html, and js is what is given to JupyterLab. 68 | 69 | To see the specific JupyterLab build process have a look at the [package.json](../package.json) 70 | file. In particular the "build:jlab" script. Also note how within "files" the "html" 71 | extension has been included. 72 | 73 | Importantly within the package.json file the `html-loader` is listed as a dependency 74 | not a `devDependency`. That way JupyterLab will install the `html-loader` package when it is 75 | building your extension. 76 | -------------------------------------------------------------------------------- /scriptedforms/e2e/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "arrow-return-shorthand": true, 7 | "callable-types": true, 8 | "class-name": true, 9 | "comment-format": [ 10 | true, 11 | "check-space" 12 | ], 13 | "curly": true, 14 | "deprecation": { 15 | "severity": "warn" 16 | }, 17 | "eofline": true, 18 | "forin": true, 19 | "import-blacklist": [ 20 | true, 21 | "rxjs", 22 | "rxjs/Rx" 23 | ], 24 | "import-spacing": true, 25 | "indent": [ 26 | true, 27 | "spaces" 28 | ], 29 | "interface-over-type-literal": true, 30 | "label-position": true, 31 | "max-line-length": [ 32 | true, 33 | 140 34 | ], 35 | "member-access": false, 36 | "member-ordering": [ 37 | true, 38 | { 39 | "order": [ 40 | "static-field", 41 | "instance-field", 42 | "static-method", 43 | "instance-method" 44 | ] 45 | } 46 | ], 47 | "no-arg": true, 48 | "no-bitwise": true, 49 | "no-console": [ 50 | true, 51 | "debug", 52 | "info", 53 | "time", 54 | "timeEnd", 55 | "trace" 56 | ], 57 | "no-construct": true, 58 | "no-debugger": true, 59 | "no-duplicate-super": true, 60 | "no-empty": false, 61 | "no-empty-interface": true, 62 | "no-eval": true, 63 | "no-inferrable-types": [ 64 | true, 65 | "ignore-params" 66 | ], 67 | "no-misused-new": true, 68 | "no-non-null-assertion": true, 69 | "no-shadowed-variable": true, 70 | "no-string-literal": false, 71 | "no-string-throw": true, 72 | "no-switch-case-fall-through": true, 73 | "no-trailing-whitespace": true, 74 | "no-unnecessary-initializer": true, 75 | "no-unused-expression": true, 76 | "no-use-before-declare": true, 77 | "no-var-keyword": true, 78 | "object-literal-sort-keys": false, 79 | "one-line": [ 80 | true, 81 | "check-open-brace", 82 | "check-catch", 83 | "check-else", 84 | "check-whitespace" 85 | ], 86 | "prefer-const": true, 87 | "quotemark": [ 88 | true, 89 | "single" 90 | ], 91 | "radix": true, 92 | "semicolon": [ 93 | true, 94 | "always" 95 | ], 96 | "triple-equals": [ 97 | true, 98 | "allow-null-check" 99 | ], 100 | "typedef-whitespace": [ 101 | true, 102 | { 103 | "call-signature": "nospace", 104 | "index-signature": "nospace", 105 | "parameter": "nospace", 106 | "property-declaration": "nospace", 107 | "variable-declaration": "nospace" 108 | } 109 | ], 110 | "typeof-compare": true, 111 | "unified-signatures": true, 112 | "variable-name": false, 113 | "whitespace": [ 114 | true, 115 | "check-branch", 116 | "check-decl", 117 | "check-operator", 118 | "check-separator", 119 | "check-type" 120 | ], 121 | "directive-selector": [ 122 | true, 123 | "attribute", 124 | "app", 125 | "camelCase" 126 | ], 127 | "component-selector": [ 128 | true, 129 | "element", 130 | "app", 131 | "kebab-case" 132 | ], 133 | "no-output-on-prefix": true, 134 | "use-input-property-decorator": true, 135 | "use-output-property-decorator": true, 136 | "use-host-property-decorator": true, 137 | "no-input-rename": true, 138 | "no-output-rename": true, 139 | "use-life-cycle-interface": true, 140 | "use-pipe-transform-interface": true, 141 | "component-class-suffix": true, 142 | "directive-class-suffix": true 143 | } 144 | } -------------------------------------------------------------------------------- /scriptedforms/src/app/sections-module/button.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | /* 17 | Creates the [button] section. 18 | 19 | A section that runs all code within it whenever the user presses the provided 20 | button. 21 | 22 | By calling the function `runCode` on this component all code components within 23 | this section will be iteratively run. The button is set to call the runCode 24 | function on click. 25 | */ 26 | 27 | import { 28 | Component, AfterViewInit, Input, ViewChild, ElementRef 29 | } from '@angular/core'; 30 | 31 | import { SectionBaseComponent } from './section-base.component'; 32 | import { ConditionalComponent } from '../variables-module/conditional.component'; 33 | 34 | @Component({ 35 | selector: 'section-button', 36 | template: `
37 |
38 | {{conditional}} 39 | 45 | 51 |
52 | 53 |
{{code}}
54 |
55 | ` 56 | }) 57 | export class ButtonComponent extends SectionBaseComponent implements AfterViewInit { 58 | sectionType = 'button'; 59 | @Input() inline?: string = null; 60 | @Input() conditional?: string; 61 | conditionalValue = true; 62 | 63 | @ViewChild('conditionalComponent') conditionalComponent: ConditionalComponent; 64 | 65 | @Input() value?: string; 66 | @Input() set name(nameInput: string) { 67 | this.value = nameInput; 68 | const element = this.myElementRef.nativeElement; 69 | const divElement = document.createElement('div'); 70 | divElement.innerHTML = ` 71 |
 72 | 
 73 |   The use of the "name" parameter has been deprecated. Please use the
 74 |   "value" parameter instead.
 75 | 
 76 |   Replace:
 77 | 
 78 |       <section-button name="${this.value}">
 79 | 
 80 |   With:
 81 | 
 82 |       <section-button value="${this.value}">
 83 | 
 84 | 
85 | `; 86 | divElement.classList.add('jp-RenderedText'); 87 | element.appendChild(divElement); 88 | } 89 | 90 | constructor( 91 | public myElementRef: ElementRef 92 | ) { super(); } 93 | 94 | ngAfterViewInit() { 95 | super.ngAfterViewInit(); 96 | 97 | if (this.conditional) { 98 | const value: any = this.conditionalComponent.variableValue; 99 | this.conditionalValue = value; 100 | 101 | this.conditionalComponent.variableChange.asObservable().subscribe((newValue: boolean) => { 102 | this.conditionalValue = newValue; 103 | }); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /scriptedforms/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "scriptedforms": { 7 | "root": "", 8 | "sourceRoot": "src", 9 | "projectType": "application", 10 | "architect": { 11 | "build": { 12 | "builder": "@angular-devkit/build-angular:browser", 13 | "options": { 14 | "outputPath": "lib", 15 | "index": "src/index.html", 16 | "main": "src/main.ts", 17 | "tsConfig": "src/tsconfig.app.json", 18 | "polyfills": "src/polyfills.ts", 19 | "assets": [ 20 | "src/assets", 21 | "src/favicon.ico" 22 | ], 23 | "styles": [ 24 | "src/styles.css" 25 | ], 26 | "scripts": [] 27 | }, 28 | "configurations": { 29 | "prod": { 30 | "fileReplacements": [ 31 | { 32 | "replace": "src/environments/environment.ts", 33 | "with": "src/environments/environment.prod.ts" 34 | } 35 | ] 36 | } 37 | } 38 | }, 39 | "serve": { 40 | "builder": "@angular-devkit/build-angular:dev-server", 41 | "options": { 42 | "browserTarget": "scriptedforms:build" 43 | }, 44 | "configurations": { 45 | "prod": { 46 | "browserTarget": "scriptedforms:build:prod" 47 | } 48 | } 49 | }, 50 | "extract-i18n": { 51 | "builder": "@angular-devkit/build-angular:extract-i18n", 52 | "options": { 53 | "browserTarget": "scriptedforms:build" 54 | } 55 | }, 56 | "test": { 57 | "builder": "@angular-devkit/build-angular:karma", 58 | "options": { 59 | "main": "src/test.ts", 60 | "karmaConfig": "./karma.conf.js", 61 | "polyfills": "src/polyfills.ts", 62 | "tsConfig": "src/tsconfig.spec.json", 63 | "scripts": [], 64 | "styles": [ 65 | "src/styles.css" 66 | ], 67 | "assets": [ 68 | "src/assets", 69 | "src/favicon.ico" 70 | ] 71 | } 72 | }, 73 | "lint": { 74 | "builder": "@angular-devkit/build-angular:tslint", 75 | "options": { 76 | "tsConfig": [ 77 | "src/tsconfig.app.json", 78 | "src/tsconfig.spec.json" 79 | ], 80 | "exclude": [ 81 | "**/node_modules/**" 82 | ] 83 | } 84 | } 85 | } 86 | }, 87 | "scriptedforms-e2e": { 88 | "root": "", 89 | "sourceRoot": "", 90 | "projectType": "application", 91 | "architect": { 92 | "e2e": { 93 | "builder": "@angular-devkit/build-angular:protractor", 94 | "options": { 95 | "protractorConfig": "./protractor.conf.js", 96 | "devServerTarget": "scriptedforms:serve" 97 | } 98 | }, 99 | "lint": { 100 | "builder": "@angular-devkit/build-angular:tslint", 101 | "options": { 102 | "tsConfig": [ 103 | "e2e/tsconfig.e2e.json" 104 | ], 105 | "exclude": [ 106 | "**/node_modules/**" 107 | ] 108 | } 109 | } 110 | } 111 | } 112 | }, 113 | "defaultProject": "scriptedforms", 114 | "schematics": { 115 | "@schematics/angular:component": { 116 | "prefix": "app", 117 | "styleext": "css" 118 | }, 119 | "@schematics/angular:directive": { 120 | "prefix": "app" 121 | } 122 | } 123 | } -------------------------------------------------------------------------------- /scriptedforms/src/app/toolbar-module/toolbar-base.component.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | /* 17 | Creates the [button] section. 18 | 19 | A section that runs all code within it whenever the user presses the provided 20 | button. 21 | 22 | By calling the function `runCode` on this component all code components within 23 | this section will be iteratively run. The button is set to call the runCode 24 | function on click. 25 | */ 26 | 27 | import { BehaviorSubject } from 'rxjs'; 28 | 29 | import { 30 | ComponentFactoryResolver, AfterViewInit, ComponentFactory, ViewChild, 31 | ViewContainerRef, ChangeDetectorRef 32 | } from '@angular/core'; 33 | 34 | import { 35 | Component, 36 | // Input 37 | } from '@angular/core'; 38 | 39 | import { 40 | // BoxLayout, 41 | Widget 42 | } from '@phosphor/widgets'; 43 | 44 | import { 45 | ToolbarButtonComponent, IOptions 46 | } from './toolbar-button.component'; 47 | 48 | import { 49 | ToolbarService 50 | } from '../services/toolbar.service'; 51 | 52 | import { FormService } from '../services/form.service'; 53 | 54 | @Component({ 55 | selector: 'toolbar-base', 56 | template: `` 57 | }) 58 | export class ToolbarBaseComponent implements AfterViewInit { 59 | restartingKernel: BehaviorSubject = new BehaviorSubject(false); 60 | 61 | @ViewChild('container', { read: ViewContainerRef }) 62 | container: ViewContainerRef; 63 | 64 | buttonFactory: ComponentFactory; 65 | 66 | constructor( 67 | private myComponentFactoryResolver: ComponentFactoryResolver, 68 | private myToolbarService: ToolbarService, 69 | private myFormService: FormService, 70 | private changeDetectorRef: ChangeDetectorRef 71 | ) { } 72 | 73 | ngAfterViewInit() { 74 | this.addButton({ 75 | icon: 'chrome_reader_mode', 76 | // href: '../docs', // Only change this link once the docs are ready 77 | href: 'https://scriptedforms.com.au', 78 | tooltip: 'ScriptedForms documentation, installation instructions, and source code.' 79 | }); 80 | this.addButton({ 81 | click: () => { window.print(); }, 82 | icon: 'print', 83 | tooltip: 'Print your ScriptedForm' 84 | }); 85 | this.addButton({ 86 | click: () => { this.restartKernel(); }, 87 | icon: 'refresh', 88 | disable: this.restartingKernel, 89 | tooltip: 'Restart the Jupyter Python Kernel. This will reset your inputs.' 90 | }); 91 | 92 | this.myToolbarService.addSpacer(); 93 | 94 | this.changeDetectorRef.detectChanges(); 95 | } 96 | 97 | addButton(options: IOptions) { 98 | this.buttonFactory = this.myComponentFactoryResolver.resolveComponentFactory(ToolbarButtonComponent); 99 | const button = this.container.createComponent(this.buttonFactory); 100 | 101 | button.instance.options = options; 102 | 103 | const widget = new Widget({ node: button.instance.myElementRef.nativeElement }); 104 | this.myToolbarService.addItem(options.icon, widget); 105 | } 106 | 107 | restartKernel() { 108 | this.restartingKernel.next(true); 109 | this.myFormService.restartFormKernel().then(() => { 110 | this.restartingKernel.next(false); 111 | }); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /scriptedforms/src/app/style.css: -------------------------------------------------------------------------------- 1 | /* Scripted Forms -- Making GUIs easy for everyone on your team. 2 | Copyright (C) 2017 Simon Biggs 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | */ 17 | 18 | .scripted-form-widget .form-container { 19 | font-family: Roboto, "Helvetica Neue", sans-serif; 20 | } 21 | 22 | .scripted-form-widget .no-ripple-height .mat-ripple { 23 | height: 0px; 24 | } 25 | 26 | .scripted-form-widget .jp-OutputArea-prompt { 27 | display: none; 28 | } 29 | 30 | .scripted-form-widget .float-right { 31 | float: right; 32 | } 33 | 34 | .scripted-form-widget img { 35 | display: block; 36 | margin-left: auto; 37 | margin-right: auto; 38 | } 39 | 40 | .hidden-iframe { 41 | width: 0; 42 | height: 0; 43 | border: 0; 44 | border: none; 45 | position: absolute; 46 | visibility: 0; 47 | } 48 | 49 | @media print { 50 | body, article { 51 | width: 100% !important; 52 | position: static !important; 53 | margin: 0 !important; 54 | padding: 0; 55 | max-width: 21cm !important; 56 | -webkit-print-color-adjust: exact; 57 | color-adjust: exact; 58 | } 59 | 60 | div, span { 61 | margin: 0 0 !important; 62 | max-width: 21cm !important; 63 | } 64 | 65 | /* .form-contents { 66 | width: 20cm !important; 67 | padding: 0 5mm !important; 68 | } */ 69 | 70 | .scripted-form-widget { 71 | width: 20cm !important; 72 | /* padding: 0 5mm !important; */ 73 | } 74 | 75 | .form-container { 76 | width: 20cm !important; 77 | height: 100% !important; 78 | } 79 | 80 | .margin { 81 | margin: 0 0 !important; 82 | } 83 | 84 | .hide-on-print { 85 | display: none !important; 86 | } 87 | 88 | .custom-toolbar { 89 | display: none !important; 90 | } 91 | 92 | .floating-spinner { 93 | display: none !important; 94 | } 95 | 96 | .p-Widget { 97 | position: static !important; 98 | } 99 | 100 | ul, img, .avoid-page-break { 101 | page-break-inside: avoid; 102 | } 103 | 104 | img { 105 | max-width: 450px !important; 106 | } 107 | 108 | @page { 109 | margin: 2cm; 110 | } 111 | } 112 | 113 | 114 | @media only screen { 115 | .fullscreen-body { 116 | display: flex; 117 | flex-direction: column; 118 | position: absolute; 119 | top: 0; 120 | left: 0; 121 | right: 0; 122 | bottom: 0; 123 | margin: 0; 124 | padding: 0; 125 | overflow: hidden; 126 | background: white; 127 | } 128 | 129 | .scripted-form-widget .margin { 130 | margin: 20px; 131 | } 132 | 133 | .scripted-form-widget .form-contents { 134 | max-width: 940px; 135 | margin: 0 auto; 136 | } 137 | 138 | .scripted-form-widget { 139 | flex: 1 1 auto; 140 | margin: 0; 141 | padding: 0; 142 | } 143 | 144 | .scripted-form-widget .form-container { 145 | overflow: auto; 146 | } 147 | 148 | .scripted-form-widget .output-container div .jp-RenderedText { 149 | padding-left: 0; 150 | } 151 | 152 | .scripted-form-widget .output-container div div .jp-OutputPrompt { 153 | padding: 0; 154 | flex: 0; 155 | border: 0; 156 | } 157 | 158 | .scripted-form-widget .floating-spinner { 159 | position: fixed; 160 | bottom: 20px; 161 | right: 40px; 162 | } 163 | 164 | .scripted-form-widget .footer-space { 165 | height: 300px; 166 | } 167 | 168 | .scripted-form-widget .custom-toolbar { 169 | min-height: 45px !important; 170 | } 171 | } -------------------------------------------------------------------------------- /scriptedforms/src/app/services/watchdog.service.ts: -------------------------------------------------------------------------------- 1 | // Scripted Forms -- Making GUIs easy for everyone on your team. 2 | // Copyright (C) 2017 Simon Biggs 3 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | 16 | import { BehaviorSubject } from 'rxjs'; 17 | 18 | import { Injectable } from '@angular/core'; 19 | 20 | import { 21 | PromiseDelegate 22 | } from '@phosphor/coreutils'; 23 | 24 | import { 25 | ServerConnection, Session, KernelMessage 26 | } from '@jupyterlab/services'; 27 | 28 | import { JupyterService } from './jupyter.service'; 29 | import { FileService } from './file.service'; 30 | 31 | import { 32 | startWatchdogSessionCode, addObserverPathCode 33 | } from './watchdog-code'; 34 | 35 | @Injectable() 36 | export class WatchdogService { 37 | // formFirstPassComplete = new PromiseDelegate(); 38 | everythingIdle = new PromiseDelegate(); 39 | session: Session.ISession; 40 | watchdogError: BehaviorSubject = new BehaviorSubject(null); 41 | fileChanged: BehaviorSubject = new BehaviorSubject(null); 42 | 43 | constructor( 44 | private myFileService: FileService, 45 | private myJupyterService: JupyterService, 46 | ) { } 47 | 48 | startWatchdog() { 49 | const path = '_watchdog_scriptedforms'; 50 | const settings = ServerConnection.makeSettings({}); 51 | const startNewOptions = { 52 | kernelName: 'python3', 53 | serverSettings: settings, 54 | path: path 55 | }; 56 | 57 | this.myJupyterService.serviceManager.sessions.findByPath(path).then(model => { 58 | let session = Session.connectTo(model, settings) 59 | this.watchdogFormUpdate(session); 60 | }).catch(() => { 61 | Session.startNew(startNewOptions).then(session => { 62 | session.kernel.requestExecute({ code: startWatchdogSessionCode }); 63 | this.watchdogFormUpdate(session); 64 | }); 65 | }); 66 | } 67 | 68 | watchdogFormUpdate(session: Session.ISession) { 69 | this.session = session; 70 | 71 | session.iopubMessage.connect((sender, msg) => { 72 | if (KernelMessage.isErrorMsg(msg)) { 73 | const errorMsg: KernelMessage.IErrorMsg = msg; 74 | console.error(errorMsg.content); 75 | this.watchdogError.next(msg); 76 | } 77 | if (msg.content.text) { 78 | const content = String(msg.content.text).trim(); 79 | const files = content.split('\n'); 80 | console.log(files); 81 | const path = this.myFileService.path.getValue(); 82 | const match = files.some(item => { 83 | return ( 84 | (item.startsWith('relative: ')) && 85 | ((item.replace('\\', '/') === `relative: ${path}`) || (item.includes('goutputstream')))); 86 | }); 87 | if (match) { 88 | this.myFileService.loadFileContents(path); 89 | } 90 | 91 | files.forEach(item => { 92 | const pathOnly = item.replace('absolute: ', '').replace('relative: ', ''); 93 | this.fileChanged.next(pathOnly); 94 | }); 95 | } 96 | }); 97 | this.myFileService.path.subscribe(value => { 98 | console.log(`File service path changed to: ${value}`); 99 | this.addFilepathObserver(value); 100 | }); 101 | } 102 | 103 | addFilepathObserver(filepath: string) { 104 | console.log(`Watchdog service: Adding ${filepath} to watch list`); 105 | this.session.kernel.requestExecute({ code: addObserverPathCode(filepath) }); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /scriptedforms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@simonbiggs/scriptedforms", 3 | "version": "0.10.1", 4 | "license": "AGPL-3.0+", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/SimonBiggs/scriptedforms.git" 8 | }, 9 | "keywords": [ 10 | "jupyter", 11 | "jupyterlab", 12 | "jupyterlab-extension" 13 | ], 14 | "main": "jlab-build/main.js", 15 | "types": "jlab-build/main.d.ts", 16 | "description": "Interactive forms.", 17 | "author": "Simon Biggs", 18 | "scripts": { 19 | "upgrade:jlab": "yarn upgrade --latest --tilde --scope @jupyterlab", 20 | "upgrade:angular": "yarn upgrade --latest --tilde --scope @angular", 21 | "upgrade:phosphor": "yarn upgrade --latest --tilde --scope @phosphor", 22 | "upgrade:types": "yarn upgrade --latest --tilde --scope @types", 23 | "upgrade:typescript": "yarn upgrade --latest --tilde typescript", 24 | "ng": "ng", 25 | "lint": "ng lint", 26 | "build": "rimraf lib && webpack --config webpack.dev.js", 27 | "build:prod": "rimraf lib && webpack --config webpack.prod.js", 28 | "build:jlab": "rimraf ./jlab-build && copyfiles -u 1 './src/**/*.{css,html,scss}' ./jlab-build && tsc && yarn package", 29 | "watch:jlab": "tsc -w", 30 | "package": "rimraf simonbiggs-scriptedforms*.tgz && yarn pack", 31 | "selenium": "./scripts/selenium.sh", 32 | "test": "yarn --cwd ./e2e e2e", 33 | "pip:install": "yarn pip:dev", 34 | "pip:dev": "pip install -e ../", 35 | "pip:uninstall": "pip uninstall -y scriptedforms", 36 | "pip:sys": "pip install ../", 37 | "pip:freeze": "./scripts/pip-freeze.sh", 38 | "pypi:prep": "yarn build:prod && yarn build:jlab && yarn pip:uninstall && yarn pip:sys && yarn test && yarn pip:dev", 39 | "pypi:upload": "./scripts/pypi.sh", 40 | "pypi:post": "yarn pip:uninstall && pip install --pre --no-cache scriptedforms && yarn test && yarn pip:dev", 41 | "bundle:update": "yarn --cwd ../portable-windows-bundle update", 42 | "bundle:test": "yarn --cwd ../portable-windows-bundle test", 43 | "bundle:zip": "yarn --cwd ../portable-windows-bundle zip", 44 | "watch": "webpack --config webpack.dev.js --watch" 45 | }, 46 | "files": [ 47 | "jlab-build/**/*.{d.ts,ts,eot,gif,html,css,jpg,js,js.map,json,png,svg,woff2,ttf,scss}" 48 | ], 49 | "dependencies": { 50 | "@angular/animations": "~6.1.4", 51 | "@angular/cdk": "~6.4.6", 52 | "@angular/common": "~6.1.4", 53 | "@angular/compiler": "~6.1.4", 54 | "@angular/core": "~6.1.4", 55 | "@angular/forms": "~6.1.4", 56 | "@angular/http": "~6.1.4", 57 | "@angular/material": "~6.4.6", 58 | "@angular/platform-browser": "~6.1.4", 59 | "@angular/platform-browser-dynamic": "~6.1.4", 60 | "@angular/router": "~6.1.4", 61 | "@jupyterlab/application": "~0.18.4", 62 | "@jupyterlab/apputils": "~0.18.4", 63 | "@jupyterlab/codemirror": "~0.18.4", 64 | "@jupyterlab/docmanager": "~0.18.4", 65 | "@jupyterlab/docregistry": "~0.18.4", 66 | "@jupyterlab/launcher": "~0.18.4", 67 | "@jupyterlab/notebook": "~0.18.4", 68 | "@jupyterlab/outputarea": "~0.18.4", 69 | "@jupyterlab/rendermime": "~0.18.4", 70 | "@jupyterlab/services": "~3.1.4", 71 | "@jupyterlab/theme-light-extension": "~0.18.4", 72 | "@phosphor/signaling": "~1.2.2", 73 | "@phosphor/widgets": "~1.6.0", 74 | "@types/codemirror": "~0.0.59", 75 | "@types/hammerjs": "^2.0.35", 76 | "@types/json-stable-stringify": "^1.0.32", 77 | "@types/markdown-it": "0.0.5", 78 | "@types/uuid": "^3.4.3", 79 | "core-js": "^2.5.4", 80 | "css-loader": "^0.28.11", 81 | "hammerjs": "^2.0.8", 82 | "html-loader": "^0.5.5", 83 | "json-stable-stringify": "^1.0.1", 84 | "markdown-it": "^8.4.0", 85 | "material-design-icons": "^3.0.1", 86 | "node-sass": "^4.8.3", 87 | "rxjs": "^6.2.0", 88 | "rxjs-compat": "^6.2.0", 89 | "sass-loader": "^7.0.1", 90 | "style-loader": "^0.21.0", 91 | "uuid": "^3.2.1", 92 | "zone.js": "^0.8.26" 93 | }, 94 | "devDependencies": { 95 | "@angular-devkit/build-angular": "~0.6.5", 96 | "@angular/cli": "6.1.5", 97 | "@angular/language-service": "6.1.4", 98 | "angular2-template-loader": "^0.6.2", 99 | "awesome-typescript-loader": "^3.4.1", 100 | "codelyzer": "^4.2.1", 101 | "copyfiles": "^2.0.0", 102 | "extract-text-webpack-plugin": "^3.0.2", 103 | "file-loader": "^1.1.7", 104 | "karma": "^2.0.0", 105 | "rimraf": "^2.6.1", 106 | "svg-inline-loader": "^0.8.0", 107 | "svg-url-loader": "^2.3.1", 108 | "tslint": "^5.9.1", 109 | "typescript": "~2.7.0", 110 | "webpack": "^3.10.0", 111 | "webpack-merge": "^4.1.1" 112 | }, 113 | "jupyterlab": { 114 | "extension": true 115 | } 116 | } 117 | --------------------------------------------------------------------------------