Browse Source

Merge branch 'master' into saguaro-molstar

# Conflicts:
#	package-lock.json
#	package.json
bioinsilico 4 years ago
parent
commit
bd7ebaa038
5 changed files with 25 additions and 8 deletions
  1. 5 0
      CHANGELOG.md
  2. 1 1
      package-lock.json
  3. 1 1
      src/viewer/index.ts
  4. 4 2
      src/viewer/ui/exchanges.tsx
  5. 14 4
      src/viewer/ui/strucmotif.tsx

+ 5 - 0
CHANGELOG.md

@@ -2,6 +2,11 @@
 
 [Semantic Versioning](https://semver.org/)
 
+## [1.2.1] - 2021-02-18
+### Bug fixes
+- limit number of exchanges per position
+- hide State Tree panel
+
 ## [1.2.0] - 2021-02-16
 ### General
 -  structure alignment data visualization

+ 1 - 1
package-lock.json

@@ -1,6 +1,6 @@
 {
     "name": "@rcsb/rcsb-molstar",
-    "version": "1.2.0",
+    "version": "1.3.0-beta.saguaro.1",
     "lockfileVersion": 1,
     "requires": true,
     "dependencies": {

+ 1 - 1
src/viewer/index.ts

@@ -115,7 +115,7 @@ export class Viewer {
                     ...DefaultPluginSpec.layout && DefaultPluginSpec.layout.controls,
                     top: o.layoutShowSequence ? undefined : 'none',
                     bottom: o.layoutShowLog ? undefined : 'none',
-                    // left: 'none',
+                    left: 'none',
                     right: ControlsWrapper,
                 }
             },

+ 4 - 2
src/viewer/ui/exchanges.tsx

@@ -5,7 +5,7 @@
  */
 import * as React from 'react';
 import {Button} from 'molstar/lib/mol-plugin-ui/controls/common';
-import {Residue} from './strucmotif';
+import {MAX_EXCHANGES, Residue} from './strucmotif';
 
 export const DefaultExchanges = [
     ['ALA', 'Alanine'],
@@ -50,7 +50,9 @@ export class ExchangesControl extends React.Component<{ handler: Residue }> {
             {DefaultExchanges.map(e => {
                 const isSelected = this.props.handler.hasExchange(e[0]);
                 const className = isSelected ? 'msp-control-current' : '';
-                return <Button key={e[0]} title={e[1]} inline data-id={e[0]} onClick={this.onClickSwatch} style={{ padding: 0, fontSize: '13px' }} className={className}>
+                const isDisabled = this.props.handler.exchanges.size >= MAX_EXCHANGES && !isSelected;
+
+                return <Button key={e[0]} title={e[1]} inline data-id={e[0]} onClick={this.onClickSwatch} style={{ padding: 0, fontSize: '13px' }} className={className} disabled={isDisabled}>
                     {e[0] && isSelected ? <b>{e[0]}</b> : e[0]}
                 </Button>;
             })}

+ 14 - 4
src/viewer/ui/strucmotif.tsx

@@ -26,6 +26,7 @@ const ADVANCED_SEARCH_URL = 'https://rcsb.org/search?query=';
 const RETURN_TYPE = '&return_type=assembly';
 const MIN_MOTIF_SIZE = 3;
 const MAX_MOTIF_SIZE = 10;
+export const MAX_EXCHANGES = 4;
 
 /**
  * The top-level component that exposes the strucmotif search.
@@ -115,22 +116,27 @@ class SubmitControls extends PurePluginUIComponent<{}, { isBusy: boolean, residu
             // handle potential exchanges - can be empty if deselected by users
             const residueMapEntry = this.state.residueMap.get(l)!;
             if (residueMapEntry.exchanges?.size > 0) {
+                if (residueMapEntry.exchanges.size > MAX_EXCHANGES) {
+                    alert(`Maximum number of exchanges per position is ${MAX_EXCHANGES} - please remove some exchanges from residue ${residueId.label_asym_id}_${residueId.struct_oper_id}-${residueId.label_seq_id}`);
+                    return;
+                }
                 exchanges.push({ residue_id: residueId, allowed: Array.from(residueMapEntry.exchanges.values()) });
             }
         }
 
         if (pdbId.size > 1) {
-            this.plugin.log.warn('Motifs can only be extracted from a single model!');
+            alert('Motifs can only be extracted from a single model!');
             return;
         }
         if (residueIds.length > MAX_MOTIF_SIZE) {
-            this.plugin.log.warn(`Maximum motif size is ${MAX_MOTIF_SIZE} residues!`);
+            alert(`Maximum motif size is ${MAX_MOTIF_SIZE} residues!`);
             return;
         }
         if (residueIds.filter(v => v.label_seq_id === 0).length > 0) {
-            this.plugin.log.warn('Selections may only contain polymeric entities!');
+            alert('Selections may only contain polymeric entities!');
             return;
         }
+        // TODO warn if >15 A for better UX
 
         const query = {
             type: 'terminal',
@@ -272,7 +278,11 @@ export class Residue {
         if (this.hasExchange(val)) {
             this.exchanges.delete(val);
         } else {
-            this.exchanges.add(val);
+            if (this.exchanges.size < MAX_EXCHANGES) {
+                this.exchanges.add(val);
+            } else {
+                alert(`Maximum number of exchanges per position is ${MAX_EXCHANGES}`);
+            }
         }
         // this will update state of parent component
         this.parent.forceUpdate();