.. _juxl-setting_up_ad_development_envrionment: #################################### 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: #. Setup Anaconda #. Setup Juxl #. Setup Juxl development environment #. Edit Juxl to see changes Setup Anaconda ============== #. Install Anaconda #. 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: .. code-block:: bash 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 :code:`juxl`. We will also install :code:`jupyterlab`, :code:`nodejs`, :code:`jupyter-packaging`. To create the envrionment run: .. code-block:: bash 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 :code:`juxl` conda environment is activated. It can be activated by running: .. code-block:: bash root@device:~$ conda activate juxl (juxl) root@device:~$ Setup Juxl ========== To setup Juxl, we need to execute the following steps: #. Clone Juxl #. Install Dependencies #. Build Juxl #. Test Juxl #. Locally install Juxl each step is explained in the following sections: Clone Juxl Repository ^^^^^^^^^^^^^^^^^^^^^ We use :code:`git` to clone the Juxl repository in our home directory. .. code-block:: bash 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, :code:`cd` into the repository and run :code:`jlpm`. .. code-block:: bash (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 :code:`jlpm build`: .. code-block:: bash (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 :code:`@juxl/juxl-extension`, :code:`@juxl/juxl`, :code:`@juxl/log-console`, :code:`@juxl/logging`, :code:`@juxl/performance-extension`, :code:`@juxl/performance`, and :code:`@juxl/vocabulary`. Test Juxl ^^^^^^^^^ The Juxl Repository contains Unit-Test for Juxl. We can run the test by executing :code:`jlpm test` .. code-block:: bash (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 :code:`@juxl/juxl-extension`, :code:`@juxl/juxl`, :code:`@juxl/log-console`, :code:`@juxl/logging`, :code:`@juxl/performance-extension`, :code:`@juxl/performance`, and :code:`@juxl/vocabulary` locally. This sections how to install the :code:`@juxl/juxl-extension` locally. To do so change the current diretory to the requested package and run :code:`jupyter labextension install .`. .. code-block:: bash (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 :code:`@juxl/juxl-extension` extension. .. code-block:: bash (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 :code:`@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: #. Setup automatic compilation of Juxl #. Setup automatic compilation of JupyterLab Setup Automatic Compilation of Juxl ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ We can interactively compile a package with :code:`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 :code:`#TERMINAL 1`. .. caution:: Do not forgett to activate the anaconda environment! .. code-block:: bash #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 :code:`--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 :code:`#TERMINAL 2`. .. code-block:: bash #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 :code:`@juxl/juxl-extension` package and see the changes to the running JupyterLab instance. To do so, we will: #. Edit the Extension #. See Changes in TERMINAL 1 #. See Changes in TERMINAL 2 #. See Changes to the JupyterLab Website Edit the Extension ^^^^^^^^^^^^^^^^^^ To edit the :code:`@juxl/juxl-extension` extension, we will add a console log. I.e. we will add the line :code:`console.log("TEST")` to the extension. This will log "TEST" to the JavaScript Console in our browser. .. code-block:: bash 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: :code:`File change detected...` are added. .. code-block:: bash # 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 :code:`TERMINAL 2`. A new line :code:` webpack 5.50.0 compiled ...` is added to the output. .. code-block:: bash #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. .. image:: console_output.png :width: 1000% :align: center .. caution:: Do not forgett to refresh the Website after each change.