Setting up a Development Envrionment

This sections shows how to set up a development environment for Juxl. The setup allows you to develop Juxl and immediatly see the changes in a running JupyterLab instance. The setup process is composed into four steps:

  1. Setup Anaconda

  2. Setup Juxl

  3. Setup Juxl development environment

  4. Edit Juxl to see changes

Setup Anaconda

  1. Install Anaconda

  2. Create a new Anaconda environment

Install Anaconda

To install anaconda see: https://docs.anaconda.com/anaconda/install/index.html

To make sure anaconda is installed run:

root@device:~$ conda --help
usage: conda [-h] [-V] command ...

conda is a tool for managing and deploying applications, environments and packages.

Options:

positional arguments:
  command
    clean        Remove unused packages and caches.
    compare      Compare packages between conda environments.
    config       Modify configuration values in .condarc. This is modeled after the git config command. Writes to the user .condarc file (/home/yanik/.condarc) by default.
    create       Create a new conda environment from a list of specified packages.
    help         Displays a list of available conda commands and their help strings.
    info         Display information about current conda install.
    init         Initialize conda for shell interaction. [Experimental]
    install      Installs a list of packages into a specified conda environment.
    list         List linked packages in a conda environment.
    package      Low-level conda package utility. (EXPERIMENTAL)
    remove       Remove a list of packages from a specified conda environment.
    uninstall    Alias for conda remove.
    run          Run an executable in a conda environment. [Experimental]
    search       Search for packages and display associated information. The input is a MatchSpec, a query language for conda packages. See examples below.
    update       Updates conda packages to the latest compatible version.
    upgrade      Alias for conda update.

optional arguments:
  -h, --help     Show this help message and exit.
  -V, --version  Show the conda version number and exit.

conda commands available from other packages:
  env

Create a new Anaconda Environment:

The next step is setting up a Anaconda environment for Juxl.

We will name the environment juxl. We will also install jupyterlab, nodejs, jupyter-packaging. To create the envrionment run:

root@device:~$ conda create -n juxl --override-channels --strict-channel-priority -c conda-forge -c nodefaults jupyterlab=3.1.6 nodejs jupyter-packaging

For all further code we assume the juxl conda environment is activated. It can be activated by running:

root@device:~$ conda activate juxl
(juxl) root@device:~$

Setup Juxl

To setup Juxl, we need to execute the following steps:

  1. Clone Juxl

  2. Install Dependencies

  3. Build Juxl

  4. Test Juxl

  5. Locally install Juxl

each step is explained in the following sections:

Clone Juxl Repository

We use git to clone the Juxl repository in our home directory.

root@device:~$ git clone git@git.rwth-aachen.de:learntech-lufgi9/bama/juxl/juxl.git

Install Dependencies

Juxl has many npm dependencies that are needed for it to run and to be build. to install the dependencies, cd into the repository and run jlpm.

(juxl) root@device:~$ cd juxl
(juxl) root@device:~/juxl$ jlpm
yarn install v1.21.1
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 5.50s.

Build Juxl

Since Juxl is written in TypeScript, it needs to be compiled to JavaScript. To do so run jlpm build:

(juxl) root@device:~/juxl$ jlpm build
yarn run v1.21.1
$ lerna run build
lerna notice cli v4.0.0
lerna info versioning independent
lerna info Executing command in 7 packages: "jlpm run build"
lerna info run Ran npm script 'build' in '@juxl/performance' in 2.2s:
$ tsc
lerna info run Ran npm script 'build' in '@juxl/juxl' in 2.5s:
$ tsc
lerna info run Ran npm script 'build' in '@juxl/log-console' in 4.0s:
$ tsc
lerna info run Ran npm script 'build' in '@juxl/vocabulary' in 4.0s:
$ tsc
lerna info run Ran npm script 'build' in '@juxl/performance-extension' in 4.1s:
$ tsc
lerna info run Ran npm script 'build' in '@juxl/logging' in 4.2s:
$ tsc
lerna info run Ran npm script 'build' in '@juxl/juxl-extension' in 4.1s:
$ tsc
lerna success run Ran npm script 'build' in 7 packages in 14.8s:
lerna success - @juxl/juxl-extension
lerna success - @juxl/juxl
lerna success - @juxl/log-console
lerna success - @juxl/logging
lerna success - @juxl/performance-extension
lerna success - @juxl/performance
lerna success - @juxl/vocabulary
Done in 15.25s.

This script build all Juxl packages, namely @juxl/juxl-extension, @juxl/juxl, @juxl/log-console, @juxl/logging, @juxl/performance-extension, @juxl/performance, and @juxl/vocabulary.

Test Juxl

The Juxl Repository contains Unit-Test for Juxl. We can run the test by executing jlpm test

(juxl) root@device:~/juxl$ jlpm test
yarn run v1.21.1
$ jlpm test:all
$ lerna run test --concurrency 1 --stream
lerna notice cli v4.0.0
lerna info versioning independent
lerna info Executing command in 3 packages: "jlpm run test"
@juxl/juxl: $ jest --config test/test.config.js
@juxl/juxl: PASS test/tests/jlStatement.spec.ts (7.293 s)
@juxl/juxl: PASS test/tests/basicJuxl.spec.ts (7.406 s)
@juxl/juxl: PASS test/tests/xApiConnection/bufferedXApiConnection.spec.ts (7.474 s)
@juxl/juxl: PASS test/tests/mergeXApiContexts.spec.ts (7.44 s)
@juxl/juxl: PASS test/tests/lrsJuxl.spec.ts (7.444 s)
@juxl/juxl: PASS test/tests/countingJuxl.spec.ts (7.406 s)
@juxl/juxl: PASS test/tests/xApiConnection/xApiConnection.spec.ts (7.425 s)
@juxl/juxl: =============================== Coverage summary ===============================
@juxl/juxl: Statements   : 88.03% ( 103/117 )
@juxl/juxl: Branches     : 94.05% ( 79/84 )
@juxl/juxl: Functions    : 80.56% ( 29/36 )
@juxl/juxl: Lines        : 87.93% ( 102/116 )
@juxl/juxl: ================================================================================
@juxl/juxl: Test Suites: 7 passed, 7 total
@juxl/juxl: Tests:       24 passed, 24 total
@juxl/juxl: Snapshots:   0 total
@juxl/juxl: Time:        8.64 s
@juxl/juxl: Ran all test suites.
@juxl/juxl-extension: $ jest --config test/test.config.js
@juxl/juxl-extension: PASS test/tests/jest/jest.spec.ts (5.088 s)
@juxl/juxl-extension: PASS test/tests/jest/jest_coverage.spec.ts (5.769 s)
@juxl/juxl-extension: PASS test/tests/xAPI.spec.ts (6.254 s)
@juxl/juxl-extension: PASS test/tests/connectAbleJuxl.spec.ts (6.47 s)
@juxl/juxl-extension: PASS test/tests/agentSettings.spec.ts (6.494 s)
@juxl/juxl-extension: PASS test/tests/lrsSettings.spec.ts (6.544 s)
@juxl/juxl-extension: =============================== Coverage summary ===============================
@juxl/juxl-extension: Statements   : 20.87% ( 129/618 )
@juxl/juxl-extension: Branches     : 24% ( 48/200 )
@juxl/juxl-extension: Functions    : 20.44% ( 28/137 )
@juxl/juxl-extension: Lines        : 20.63% ( 125/606 )
@juxl/juxl-extension: ================================================================================
@juxl/juxl-extension: Test Suites: 6 passed, 6 total
@juxl/juxl-extension: Tests:       54 passed, 54 total
@juxl/juxl-extension: Snapshots:   0 total
@juxl/juxl-extension: Time:        19.427 s
@juxl/juxl-extension: Ran all test suites.
@juxl/performance-extension: $ jest --config test/test.config.js
@juxl/performance-extension: PASS test/tests/transformMatrix.spec.ts
@juxl/performance-extension:   transformMatrix
@juxl/performance-extension:      static matrix 1 (3 ms)
@juxl/performance-extension:      static string matrix
@juxl/performance-extension:      should throw on undefined matrix (4 ms)
@juxl/performance-extension: =============================== Coverage summary ===============================
@juxl/performance-extension: Statements   : 4.4% ( 14/318 )
@juxl/performance-extension: Branches     : 0% ( 0/28 )
@juxl/performance-extension: Functions    : 2.33% ( 2/86 )
@juxl/performance-extension: Lines        : 4.52% ( 14/310 )
@juxl/performance-extension: ================================================================================
@juxl/performance-extension: Test Suites: 1 passed, 1 total
@juxl/performance-extension: Tests:       3 passed, 3 total
@juxl/performance-extension: Snapshots:   0 total
@juxl/performance-extension: Time:        14.074 s
@juxl/performance-extension: Ran all test suites.
lerna success run Ran npm script 'test' in 3 packages in 47.2s:
lerna success - @juxl/juxl-extension
lerna success - @juxl/juxl
lerna success - @juxl/performance-extension
Done in 48.59s.

Locally Install a Package:

We can install each of the Juxl packages @juxl/juxl-extension, @juxl/juxl, @juxl/log-console, @juxl/logging, @juxl/performance-extension, @juxl/performance, and @juxl/vocabulary locally.

This sections how to install the @juxl/juxl-extension locally. To do so change the current diretory to the requested package and run jupyter labextension install ..

(juxl) root@device:~/juxl$ cd packages/juxl-extension
(juxl) root@device:~/juxl/packages/juxl-extension$ jupyter labextension install .
Building jupyterlab assets (development)

We can test if the package is installed sucessfully by listing the JupyterLab Extensions and looking for the @juxl/juxl-extension extension.

(juxl) root@device:~/juxl$ jupyter labextension list

jupyter labextension list
JupyterLab v3.1.6
Other labextensions (built into JupyterLab)
   app dir: /home/user/.conda/envs/juxl/share/jupyter/lab
        @juxl/juxl-extension v3.0.2 enabled OK*

   local extensions:
        @juxl/juxl-extension: /home/user/juxl/packages/juxl-extension

We see the @juxl/juxl-extension extension listed under local extensions.

Setup Juxl Development Envrionment

Finally we setup the development environment, that allows us to make changes to a package, which is then visible in a running JupyterLab instance. To do so, we need to automatically compile Juxl, if changes to the code are made and automatically compile JupyterLab if an extension changes. This section is split in the two parts:

  1. Setup automatic compilation of Juxl

  2. Setup automatic compilation of JupyterLab

Setup Automatic Compilation of Juxl

We can interactively compile a package with jlpm watch. This will watch for changes to the code and compile the code once changes are made.

Since the command will run indefinitely, it occupies the terminal. We later reference this terminal with #TERMINAL 1.

Caution

Do not forgett to activate the anaconda environment!

#TERMINAL 1
(juxl) root@device:~/juxl$ cd packages/juxl-extension
(juxl) root@device:~/juxl/packages/juxl-extension jlpm watch
yarn run v1.21.1
$ tsc -w
[11:04:07 AM] Starting compilation in watch mode...

[11:04:10 AM] Found 0 errors. Watching for file changes.

Setup Automatic Compilation of JupyterLab

We can run JupyterLab with the --watch flag, which makes JupyterLab watching the locally installed Extensions and compile itself once changes are made. This will occupie the terminal. We later reference this terminal with #TERMINAL 2.

#TERMINAL 2
(juxl) root@device:~$ jupyter lab --watch
[I 2021-12-10 11:09:46.883 ServerApp] jupyterlab | extension was successfully linked.
[I 2021-12-10 11:09:47.028 ServerApp] nbclassic | extension was successfully linked.
[I 2021-12-10 11:09:47.050 ServerApp] nbclassic | extension was successfully loaded.
[I 2021-12-10 11:09:47.051 LabApp] JupyterLab extension loaded from /home/user/.conda/envs/jl2/lib/python3.9/site-packages/jupyterlab
[I 2021-12-10 11:09:47.051 LabApp] JupyterLab application directory is /home/user/.conda/envs/jl2/share/jupyter/lab
[I 2021-12-10 11:09:47.051 LabApp] Starting JupyterLab watch mode...
[I 2021-12-10 11:09:51.010 LabApp] > node /home/user/.conda/envs/jl2/lib/python3.9/site-packages/jupyterlab/staging/yarn.js run watch
yarn run v1.21.1
warning ../../../../../../../package.json: No license field
$ webpack --watch

If changes are made to the installed package, they will be visible in JupyterLab after a few moments.

Edit Juxl to see changes

To get an better understanding of the process, we will edit the @juxl/juxl-extension package and see the changes to the running JupyterLab instance. To do so, we will:

  1. Edit the Extension

  2. See Changes in TERMINAL 1

  3. See Changes in TERMINAL 2

  4. See Changes to the JupyterLab Website

Edit the Extension

To edit the @juxl/juxl-extension extension, we will add a console log. I.e. we will add the line console.log("TEST") to the extension. This will log “TEST” to the JavaScript Console in our browser.

root@device:~/juxl/packages/juxl-extension echo 'console.log("TEST")' >> src/index.ts

See Changes in TERMINAL 1

You should see, that jlpm compiles the package: New entries: File change detected... are added.

# TERMINAL 1
root@device:~/juxl/packages/juxl-extension jlpm watch
yarn run v1.21.1
$ tsc -w
[11:08:51 AM] Starting compilation in watch mode...
[11:08:54 AM] Found 0 errors. Watching for file changes.
[11:12:51 AM] File change detected. Starting incremental compilation...
[11:12:52 AM] Found 0 errors. Watching for file changes.

See Changes in TERMINAL 2

Furthermore, you should see changes to TERMINAL 2. A new line :code:` webpack 5.50.0 compiled …` is added to the output.

#TERMINAL 2
root@device:~$ jupyter lab --watch
[I 2021-12-10 11:09:46.883 ServerApp] jupyterlab | extension was successfully linked.
[I 2021-12-10 11:09:47.028 ServerApp] nbclassic | extension was successfully linked.
[I 2021-12-10 11:09:47.050 ServerApp] nbclassic | extension was successfully loaded.
[I 2021-12-10 11:09:47.051 LabApp] JupyterLab extension loaded from /home/user/.conda/envs/jl2/lib/python3.9/site-packages/jupyterlab
[I 2021-12-10 11:09:47.051 LabApp] JupyterLab application directory is /home/user/.conda/envs/jl2/share/jupyter/lab
[I 2021-12-10 11:09:47.051 LabApp] Starting JupyterLab watch mode...
[I 2021-12-10 11:09:51.010 LabApp] > node /home/user/.conda/envs/jl2/lib/python3.9/site-packages/jupyterlab/staging/yarn.js run watch
yarn run v1.21.1
warning ../../../../../../../package.json: No license field
$ webpack --watch
webpack 5.50.0 compiled with 63 warnings in 1343 ms

See Changes to the JupyterLab Website

If we now reload the page and open the JavaScript Console, we see the logged string.

../_images/console_output.png

Caution

Do not forgett to refresh the Website after each change.