diff --git a/README.md b/README.md index 3481157abf73562adf36db5ae3eb836009a7c064..7e5bf0ced2ed36396ee0d75aaabba9f79996b27c 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ A live version of the Interactive Atlas Viewer is available at [https://kg.human ### General information Interactive atlas viewer is built with [Angular (v6.0)](https://angular.io/), [Bootstrap (v4)](http://getbootstrap.com/), and [fontawesome icons](https://fontawesome.com/). Some other notable packages used are: [ng2-charts](https://valor-software.com/ng2-charts/) for charts visualisation, [ngx-bootstrap](https://valor-software.com/ngx-bootstrap/) for UI and [ngrx/store](https://github.com/ngrx/platform) for state management. +Releases newer than [v0.2.9](https://github.com/HumanBrainProject/interactive-viewer/tree/v0.2.9) also uses a nodejs backend, which uses [passportjs](http://www.passportjs.org/) for user authentication, [express](https://expressjs.com/) as a http framework. + ### Prerequisites - node > 6 @@ -19,27 +21,48 @@ Interactive atlas viewer is built with [Angular (v6.0)](https://angular.io/), [B To run a dev server, run: ``` -git clone https://github.com/HumanBrainProject/interactive-viewer -cd interactive-viewer -npm i -npm run dev-server +$ git clone https://github.com/HumanBrainProject/interactive-viewer +$ cd interactive-viewer +$ npm i +$ npm run dev ``` ### Develop Plugins -To develop plugins for the interactive viewer, run: +For releases newer than [v0.2.9](https://github.com/HumanBrainProject/interactive-viewer/tree/v0.2.9), Interactive Atlas Viewer attempts to fetch `GET {BACKEND_URL}/plugins` to retrieve a list of URLs. The interactive atlas viewer will then perform a `GET` request for each of the listed URLs, parsing them as [manifests](src/plugin_examples/README.md#Manifest%20JSON). + +The backend reads the environment variable `PLUGIN_URLS` and separate the string with `;` as a delimiter. In order to return a response akin to the following: + +```JSON +["http://localhost:3001/manifest.json","http://localhost:9001/manifest.json"] +``` + +Plugin developers may choose to do any of the following: + +_shell_ + +set env var every time + +```bash +$ PLUGIN_URLS=http://localhost:3001/manifest.json;http://localhost:9001/manifest.json npm run dev +``` + +_dotenv_ + +set a `.env` file in `./deploy/` once + +```bash +$ echo `PLUGIN_URLS=http://localhost:3001/manifest.json;http://localhost:9001/manifest.json` > ./deploy/.env ``` -git clone https://github.com/HumanBrainProject/interactive-viewer -cd interactive-viewer -npm i -npm run dev-plugin -/* or define your own endpoint that returns string of manifests */ -PLUGINDEV=http://mycustom.io/allPluginmanifest npm run dev-server +then, simple start the dev process with +```bash +$ npm run dev ``` -The contents inside the folder in `./src/plugin_examples` will be automatically fetched by the dev instance of the interactive-viewer on load. +Plugin developers can start their own webserver, use [interactive-viewer-plugin-template](https://github.com/HumanBrainProject/interactive-viewer-plugin-template), or (coming soon) provide link to a github repository. + [plugin readme](src/plugin_examples/README.md) @@ -48,19 +71,17 @@ The contents inside the folder in `./src/plugin_examples` will be automatically [plugin migration guide](src/plugin_examples/migrationGuide.md) -## Deployment +## Compilation `package.json` provide with two ways of building the interactive atlas viewer, `JIT` or `AOT` compilation. In general, `AOT` compilation produces a smaller package and has better performance. -## AOT compilation - -Define `BUNDLEDPLUGINS` as a comma separated environment variables to bundle the plugins. +### AOT compilation ``` -[BUNDLEDPLUGINS=pluginDir1[,pluginDir2...]] npm run build-aot +npm run build-aot ``` -## JIT Compilation +### JIT Compilation ``` npm run build @@ -69,6 +90,21 @@ npm run build npm run build-min ``` +### Docker + +The repository also provides a `Dockerfile`. Here are the environment variables used: + +_build time_ +- __BACKEND_URL__ : same as `HOSTNAME` during run time. Needed as root URL when fetching templates / datasets etc. If left empty, will fetch without hostname. + +_run time_ + +- __SESSION_SECRET__ : needed for session +- __HOSTNAME__ : needed for OIDC redirect +- __HBP_CLIENTID__ : neded for OIDC authentication +- __HBP_CLIENTSECRET__ : needed for OIDC authentication +- __PLUGIN_URLS__ : optional. Allows plugins to be populated +- __REFRESH_TOKEN__ : needed for access of public data ## Contributing @@ -80,4 +116,4 @@ Commit history prior to v0.2.0 is available in the [legacy-v0.2.0](https://githu ## License -MIT +TO BE DECIDED \ No newline at end of file diff --git a/package.json b/package.json index 2acb48676fed72ee9fa9639abe26b48488e7a0f4..ca4fd9bfed7c008c897935272ac7c59bbeb42c3b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "interactiveviewer", - "version": "1.0.0", + "version": "0.0.2", "description": "", "scripts": { "dev-server-export": "webpack-dev-server --config webpack.export.js", @@ -10,12 +10,11 @@ "build-aot": "PRODUCTION=true GIT_HASH=`git log --pretty=format:'%h' --invert-grep --grep=^.ignore -1` webpack --config webpack.aot.js", "build-min": "webpack --config webpack.prod.js", "build": "webpack --config webpack.dev.js", - "dev-plugin": "PLUGINDEV=http://localhost:10080/allPluginmanifests npm run dev-server & npm run plugin-server", "plugin-server": "node ./src/plugin_examples/server.js", "dev-server": "webpack-dev-server --config webpack.dev.js --mode development", + "dev": "npm run dev-server & (cd deploy; node server.js)", "dev-server-aot": "PRODUCTION=true GIT_HASH=`git log --pretty=format:'%h' --invert-grep --grep=^.ignore -1` webpack-dev-server --config webpack.aot.js", "dev-server-all-interfaces": "webpack-dev-server --config webpack.dev.js --mode development --hot --host 0.0.0.0", - "serve-plugins": "node src/plugin_examples/server.js", "test": "karma start spec/karma.conf.js", "e2e": "protractor e2e/protractor.conf" }, @@ -74,12 +73,12 @@ "webpack-cli": "^3.3.2", "webpack-closure-compiler": "^2.1.6", "webpack-dev-server": "^3.1.4", - "webpack-merge": "^4.1.2" - }, - "dependencies": { + "webpack-merge": "^4.1.2", "@angular/cdk": "^7.3.7", "@angular/material": "^7.3.7", "@angular/router": "^7.2.15", "zone.js": "^0.9.1" + }, + "dependencies": { } } diff --git a/src/plugin_examples/README.md b/src/plugin_examples/README.md index 1549c0963fcea559271259fa0fd121187394e066..2b1b126b3a0166eb2a416a5493705d5be63acd5e 100644 --- a/src/plugin_examples/README.md +++ b/src/plugin_examples/README.md @@ -1,5 +1,5 @@ -Plugin README -====== +# Plugin README + A plugin needs to contain three files. - Manifest JSON - template HTML @@ -9,8 +9,9 @@ A plugin needs to contain three files. These files need to be served by GET requests over HTTP with appropriate CORS header. If your application requires a backend, it is strongly recommended to host these three files with your backend. --- -Manifest JSON ------- + +## Manifest JSON + The manifest JSON file describes the metadata associated with the plugin. ```json @@ -34,8 +35,9 @@ The manifest JSON file describes the metadata associated with the plugin. - the `initState` object and `initStateUrl` will be available prior to the evaluation of `script.js`, and will populate the objects `interactiveViewer.pluginControl[MANIFEST.name].initState` and `interactiveViewer.pluginControl[MANIFEST.name].initStateUrl` respectively. --- -Template HTML ------- + +## Template HTML + The template HTML file describes the HTML view that will be rendered in the widget. @@ -74,14 +76,17 @@ The template HTML file describes the HTML view that will be rendered in the widg </div> </form> ``` + *NB* - *bootstrap 3.3.6* css is already included for templating. - keep in mind of the widget width restriction (400px) when crafting the template - whilst there are no vertical limits on the widget, contents can be rendered outside the viewport. Consider setting the *max-height* attribute. - your template and script will interact with each other likely via *element id*. As a result, it is highly recommended that unique id's are used. Please adhere to the convention: **AFFILIATION.AUTHOR.PACKAGENAME.ELEMENTID** + --- -Script JS ------- + +## Script JS + The script will always be appended **after** the rendering of the template. ```javascript diff --git a/src/plugin_examples/samplePlugin/manifest.json b/src/plugin_examples/samplePlugin/manifest.json deleted file mode 100644 index 765339e14a65bceeb5e8fea2a4056ebfa868b894..0000000000000000000000000000000000000000 --- a/src/plugin_examples/samplePlugin/manifest.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name":"fzj.xg.samplePlugin", - "displayName":"Sample Plugin Display Name (Optional)", - "templateURL":"http://localhost:10080/samplePlugin/template.html", - "scriptURL":"http://localhost:10080/samplePlugin/script.js", - "initState":{ - "hello": "world", - "foo": "bar" - }, - "initStateUrl":"http://localhost:10080/samplePlugin/optionalInitStateJson.json" -} \ No newline at end of file diff --git a/src/plugin_examples/samplePlugin/optionalInitStateJson.json b/src/plugin_examples/samplePlugin/optionalInitStateJson.json deleted file mode 100644 index 8b478475478e55bd6855b11061661c5ed524b5c9..0000000000000000000000000000000000000000 --- a/src/plugin_examples/samplePlugin/optionalInitStateJson.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "foo2": "bar2" -} \ No newline at end of file diff --git a/src/plugin_examples/samplePlugin/script.js b/src/plugin_examples/samplePlugin/script.js deleted file mode 100644 index 1dbd080572707585356a699dc4f76d7f944325aa..0000000000000000000000000000000000000000 --- a/src/plugin_examples/samplePlugin/script.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * use IIEF to avoid scope poisoning - */ -(() => { - const PLUGIN_NAME = 'fzj.xg.samplePlugin' - const initState = window.interactiveViewer.pluginControl[PLUGIN_NAME].initState - const initUrl = window.interactiveViewer.pluginControl[PLUGIN_NAME].initStateUrl - console.log(initState, initUrl) -})() \ No newline at end of file diff --git a/src/plugin_examples/samplePlugin/template.html b/src/plugin_examples/samplePlugin/template.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/plugin_examples/server.js b/src/plugin_examples/server.js deleted file mode 100644 index 355a0d40287f3748f6100ef6995e8583f3c2d920..0000000000000000000000000000000000000000 --- a/src/plugin_examples/server.js +++ /dev/null @@ -1,44 +0,0 @@ -const express = require('express') -const fs = require('fs') -const path = require('path') - -const app = express() - -const cors = (req, res, next)=>{ - res.setHeader('Access-Control-Allow-Origin','*') - next() -} - -app.get('/allPluginManifests', cors, (req, res) => { - try{ - res.status(200).send(JSON.stringify( - fs.readdirSync(__dirname) - .filter(file => fs.statSync(path.join(__dirname, file)).isDirectory()) - .filter(dir => fs.existsSync(path.join(__dirname, dir, 'manifest.json'))) - .map(dir => JSON.parse(fs.readFileSync(path.join(__dirname, dir, 'manifest.json'), 'utf-8'))) - )) - }catch(e){ - res.status(500).send(JSON.stringify(e)) - } -}) - -app.get('/test.json', cors, (req, res) => { - - console.log('test.json pinged') - res.status(200).send(JSON.stringify({ - "name": "fzj.xg.mime", - "displayName":"Mime", - "type": "plugin", - "templateURL": "http://localhost:10080/mime/template.html", - "scriptURL": "http://localhost:10080/mime/script.js", - "initState" : { - "test" : "value" - } - })) -}) - -app.use(cors,express.static(__dirname)) - -app.listen(10080, () => { - console.log(`listening on 10080, serving ${__dirname}`) -}) \ No newline at end of file