forked from enviPath/enviPy
Compare commits
14 Commits
fix/xss
...
enhancemen
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ec5e433ea | |||
| dddea79daf | |||
| cfd8d7440b | |||
| 6a5413b492 | |||
| 8282855975 | |||
| 09ddd46d69 | |||
| 9f0e396437 | |||
| 5dc4c822c4 | |||
| f1f7ce344c | |||
| 13af49488e | |||
| ac5d370b18 | |||
| ff51e48f90 | |||
| 8166df6f39 | |||
| 2980a75daa |
@ -1,116 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- develop
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
image: postgres:16
|
|
||||||
env:
|
|
||||||
POSTGRES_USER: ${{ vars.POSTGRES_USER }}
|
|
||||||
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
|
|
||||||
POSTGRES_DB: ${{ vars.POSTGRES_DB }}
|
|
||||||
ports:
|
|
||||||
- ${{ vars.POSTGRES_PORT}}:5432
|
|
||||||
options: >-
|
|
||||||
--health-cmd="pg_isready -U postgres"
|
|
||||||
--health-interval=10s
|
|
||||||
--health-timeout=5s
|
|
||||||
--health-retries=5
|
|
||||||
|
|
||||||
#redis:
|
|
||||||
# image: redis:7
|
|
||||||
# ports:
|
|
||||||
# - 6379:6379
|
|
||||||
# options: >-
|
|
||||||
# --health-cmd "redis-cli ping"
|
|
||||||
# --health-interval=10s
|
|
||||||
# --health-timeout=5s
|
|
||||||
# --health-retries=5
|
|
||||||
|
|
||||||
env:
|
|
||||||
RUNNER_TOOL_CACHE: /toolcache
|
|
||||||
EP_DATA_DIR: /opt/enviPy/
|
|
||||||
ALLOWED_HOSTS: 127.0.0.1,localhost
|
|
||||||
DEBUG: True
|
|
||||||
LOG_LEVEL: DEBUG
|
|
||||||
MODEL_BUILDING_ENABLED: True
|
|
||||||
APPLICABILITY_DOMAIN_ENABLED: True
|
|
||||||
ENVIFORMER_PRESENT: True
|
|
||||||
ENVIFORMER_DEVICE: cpu
|
|
||||||
FLAG_CELERY_PRESENT: False
|
|
||||||
PLUGINS_ENABLED: True
|
|
||||||
SERVER_URL: http://localhost:8000
|
|
||||||
ADMIN_APPROVAL_REQUIRED: True
|
|
||||||
REGISTRATION_MANDATORY: True
|
|
||||||
LOG_DIR: ''
|
|
||||||
# DB
|
|
||||||
POSTGRES_SERVICE_NAME: postgres
|
|
||||||
POSTGRES_DB: ${{ vars.POSTGRES_DB }}
|
|
||||||
POSTGRES_USER: ${{ vars.POSTGRES_USER }}
|
|
||||||
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
|
|
||||||
POSTGRES_PORT: 5432
|
|
||||||
# SENTRY
|
|
||||||
SENTRY_ENABLED: False
|
|
||||||
# MS ENTRA
|
|
||||||
MS_ENTRA_ENABLED: False
|
|
||||||
|
|
||||||
steps:
|
|
||||||
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install system tools via apt
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y postgresql-client redis-tools openjdk-11-jre-headless
|
|
||||||
|
|
||||||
- name: Setup ssh
|
|
||||||
run: |
|
|
||||||
echo "${{ secrets.ENVIPY_CI_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
|
|
||||||
chmod 600 ~/.ssh/id_ed25519
|
|
||||||
ssh-keyscan git.envipath.com >> ~/.ssh/known_hosts
|
|
||||||
eval $(ssh-agent -s)
|
|
||||||
ssh-add ~/.ssh/id_ed25519
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 10
|
|
||||||
|
|
||||||
- name: Use Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
cache: "pnpm"
|
|
||||||
|
|
||||||
- name: Install uv
|
|
||||||
uses: astral-sh/setup-uv@v6
|
|
||||||
with:
|
|
||||||
enable-cache: true
|
|
||||||
|
|
||||||
- name: Setup venv
|
|
||||||
run: |
|
|
||||||
uv sync --locked --all-extras --dev
|
|
||||||
|
|
||||||
- name: Wait for services
|
|
||||||
run: |
|
|
||||||
until pg_isready -h postgres -U postgres; do sleep 2; done
|
|
||||||
# until redis-cli -h redis ping; do sleep 2; done
|
|
||||||
|
|
||||||
- name: Run Django migrations
|
|
||||||
run: |
|
|
||||||
source .venv/bin/activate
|
|
||||||
python manage.py migrate --noinput
|
|
||||||
|
|
||||||
- name: Run Django tests
|
|
||||||
run: |
|
|
||||||
source .venv/bin/activate
|
|
||||||
python manage.py test tests --exclude-tag slow
|
|
||||||
@ -92,8 +92,6 @@ TEMPLATES = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
ALLOWED_HTML_TAGS = {'b', 'i', 'u', 'br', 'em', 'mark', 'p', 's', 'strong'}
|
|
||||||
|
|
||||||
WSGI_APPLICATION = "envipath.wsgi.application"
|
WSGI_APPLICATION = "envipath.wsgi.application"
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import json
|
|||||||
from typing import Union, List, Optional, Set, Dict, Any
|
from typing import Union, List, Optional, Set, Dict, Any
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
import nh3
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.conf import settings as s
|
from django.conf import settings as s
|
||||||
@ -186,12 +185,6 @@ class UserManager(object):
|
|||||||
def create_user(
|
def create_user(
|
||||||
username, email, password, set_setting=True, add_to_group=True, *args, **kwargs
|
username, email, password, set_setting=True, add_to_group=True, *args, **kwargs
|
||||||
):
|
):
|
||||||
# Clean for potential XSS
|
|
||||||
clean_username = nh3.clean(username).strip()
|
|
||||||
clean_email = nh3.clean(email).strip()
|
|
||||||
if clean_username != username or clean_email != email:
|
|
||||||
# This will be caught by the try in view.py/register
|
|
||||||
raise ValueError("Invalid username or password")
|
|
||||||
# avoid circular import :S
|
# avoid circular import :S
|
||||||
from .tasks import send_registration_mail
|
from .tasks import send_registration_mail
|
||||||
|
|
||||||
@ -269,9 +262,8 @@ class GroupManager(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def create_group(current_user, name, description):
|
def create_group(current_user, name, description):
|
||||||
g = Group()
|
g = Group()
|
||||||
# Clean for potential XSS
|
g.name = name
|
||||||
g.name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
g.description = description
|
||||||
g.description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
g.owner = current_user
|
g.owner = current_user
|
||||||
g.save()
|
g.save()
|
||||||
|
|
||||||
@ -526,13 +518,8 @@ class PackageManager(object):
|
|||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def create_package(current_user, name: str, description: str = None):
|
def create_package(current_user, name: str, description: str = None):
|
||||||
p = Package()
|
p = Package()
|
||||||
|
p.name = name
|
||||||
# Clean for potential XSS
|
p.description = description
|
||||||
p.name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
if description is not None and description.strip() != "":
|
|
||||||
p.description = nh3.clean(description.strip(), tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
p.save()
|
p.save()
|
||||||
|
|
||||||
up = UserPackagePermission()
|
up = UserPackagePermission()
|
||||||
@ -1107,29 +1094,28 @@ class SettingManager(object):
|
|||||||
model: EPModel = None,
|
model: EPModel = None,
|
||||||
model_threshold: float = None,
|
model_threshold: float = None,
|
||||||
):
|
):
|
||||||
new_s = Setting()
|
s = Setting()
|
||||||
# Clean for potential XSS
|
s.name = name
|
||||||
new_s.name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
s.description = description
|
||||||
new_s.description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
s.max_nodes = max_nodes
|
||||||
new_s.max_nodes = max_nodes
|
s.max_depth = max_depth
|
||||||
new_s.max_depth = max_depth
|
s.model = model
|
||||||
new_s.model = model
|
s.model_threshold = model_threshold
|
||||||
new_s.model_threshold = model_threshold
|
|
||||||
|
|
||||||
new_s.save()
|
s.save()
|
||||||
|
|
||||||
if rule_packages is not None:
|
if rule_packages is not None:
|
||||||
for r in rule_packages:
|
for r in rule_packages:
|
||||||
new_s.rule_packages.add(r)
|
s.rule_packages.add(r)
|
||||||
new_s.save()
|
s.save()
|
||||||
|
|
||||||
usp = UserSettingPermission()
|
usp = UserSettingPermission()
|
||||||
usp.user = user
|
usp.user = user
|
||||||
usp.setting = new_s
|
usp.setting = s
|
||||||
usp.permission = Permission.ALL[0]
|
usp.permission = Permission.ALL[0]
|
||||||
usp.save()
|
usp.save()
|
||||||
|
|
||||||
return new_s
|
return s
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_default_setting(user: User):
|
def get_default_setting(user: User):
|
||||||
@ -1556,9 +1542,7 @@ class SPathway(object):
|
|||||||
if sub.app_domain_assessment is None:
|
if sub.app_domain_assessment is None:
|
||||||
if self.prediction_setting.model:
|
if self.prediction_setting.model:
|
||||||
if self.prediction_setting.model.app_domain:
|
if self.prediction_setting.model.app_domain:
|
||||||
app_domain_assessment = self.prediction_setting.model.app_domain.assess(
|
app_domain_assessment = self.prediction_setting.model.app_domain.assess(sub.smiles)
|
||||||
sub.smiles
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.persist is not None:
|
if self.persist is not None:
|
||||||
n = self.snode_persist_lookup[sub]
|
n = self.snode_persist_lookup[sub]
|
||||||
@ -1590,9 +1574,7 @@ class SPathway(object):
|
|||||||
app_domain_assessment = None
|
app_domain_assessment = None
|
||||||
if self.prediction_setting.model:
|
if self.prediction_setting.model:
|
||||||
if self.prediction_setting.model.app_domain:
|
if self.prediction_setting.model.app_domain:
|
||||||
app_domain_assessment = (
|
app_domain_assessment = (self.prediction_setting.model.app_domain.assess(c))
|
||||||
self.prediction_setting.model.app_domain.assess(c)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.smiles_to_node[c] = SNode(
|
self.smiles_to_node[c] = SNode(
|
||||||
c, sub.depth + 1, app_domain_assessment
|
c, sub.depth + 1, app_domain_assessment
|
||||||
|
|||||||
191
epdb/models.py
191
epdb/models.py
@ -11,7 +11,6 @@ from typing import Union, List, Optional, Dict, Tuple, Set, Any
|
|||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
import math
|
import math
|
||||||
import joblib
|
import joblib
|
||||||
import nh3
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from django.conf import settings as s
|
from django.conf import settings as s
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
@ -29,14 +28,8 @@ from sklearn.metrics import precision_score, recall_score, jaccard_score
|
|||||||
from sklearn.model_selection import ShuffleSplit
|
from sklearn.model_selection import ShuffleSplit
|
||||||
|
|
||||||
from utilities.chem import FormatConverter, ProductSet, PredictionResult, IndigoUtils
|
from utilities.chem import FormatConverter, ProductSet, PredictionResult, IndigoUtils
|
||||||
from utilities.ml import (
|
from utilities.ml import RuleBasedDataset, ApplicabilityDomainPCA, EnsembleClassifierChain, RelativeReasoning, \
|
||||||
RuleBasedDataset,
|
EnviFormerDataset, Dataset
|
||||||
ApplicabilityDomainPCA,
|
|
||||||
EnsembleClassifierChain,
|
|
||||||
RelativeReasoning,
|
|
||||||
EnviFormerDataset,
|
|
||||||
Dataset,
|
|
||||||
)
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -810,16 +803,14 @@ class Compound(EnviPathModel, AliasMixin, ScenarioMixin, ChemicalIdentifierMixin
|
|||||||
c = Compound()
|
c = Compound()
|
||||||
c.package = package
|
c.package = package
|
||||||
|
|
||||||
if name is not None:
|
if name is None or name.strip() == "":
|
||||||
# Clean for potential XSS
|
|
||||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
if name is None or name == "":
|
|
||||||
name = f"Compound {Compound.objects.filter(package=package).count() + 1}"
|
name = f"Compound {Compound.objects.filter(package=package).count() + 1}"
|
||||||
|
|
||||||
c.name = name
|
c.name = name
|
||||||
|
|
||||||
# We have a default here only set the value if it carries some payload
|
# We have a default here only set the value if it carries some payload
|
||||||
if description is not None and description.strip() != "":
|
if description is not None and description.strip() != "":
|
||||||
c.description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
c.description = description.strip()
|
||||||
|
|
||||||
c.save()
|
c.save()
|
||||||
|
|
||||||
@ -991,11 +982,11 @@ class CompoundStructure(EnviPathModel, AliasMixin, ScenarioMixin, ChemicalIdenti
|
|||||||
raise ValueError("Unpersisted Compound! Persist compound first!")
|
raise ValueError("Unpersisted Compound! Persist compound first!")
|
||||||
|
|
||||||
cs = CompoundStructure()
|
cs = CompoundStructure()
|
||||||
# Clean for potential XSS
|
|
||||||
if name is not None:
|
if name is not None:
|
||||||
cs.name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
cs.name = name
|
||||||
|
|
||||||
if description is not None:
|
if description is not None:
|
||||||
cs.description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
cs.description = description
|
||||||
|
|
||||||
cs.smiles = smiles
|
cs.smiles = smiles
|
||||||
cs.compound = compound
|
cs.compound = compound
|
||||||
@ -1197,29 +1188,21 @@ class SimpleAmbitRule(SimpleRule):
|
|||||||
r = SimpleAmbitRule()
|
r = SimpleAmbitRule()
|
||||||
r.package = package
|
r.package = package
|
||||||
|
|
||||||
if name is not None:
|
if name is None or name.strip() == "":
|
||||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
if name is None or name == "":
|
|
||||||
name = f"Rule {Rule.objects.filter(package=package).count() + 1}"
|
name = f"Rule {Rule.objects.filter(package=package).count() + 1}"
|
||||||
|
|
||||||
r.name = name
|
r.name = name
|
||||||
|
|
||||||
if description is not None and description.strip() != "":
|
if description is not None and description.strip() != "":
|
||||||
r.description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
r.description = description
|
||||||
|
|
||||||
r.smirks = smirks
|
r.smirks = smirks
|
||||||
|
|
||||||
if reactant_filter_smarts is not None and reactant_filter_smarts.strip() != "":
|
if reactant_filter_smarts is not None and reactant_filter_smarts.strip() != "":
|
||||||
if not FormatConverter.is_valid_smarts(reactant_filter_smarts.strip()):
|
r.reactant_filter_smarts = reactant_filter_smarts
|
||||||
raise ValueError(f'Reactant Filter SMARTS "{reactant_filter_smarts}" is invalid!')
|
|
||||||
else:
|
|
||||||
r.reactant_filter_smarts = reactant_filter_smarts.strip()
|
|
||||||
|
|
||||||
if product_filter_smarts is not None and product_filter_smarts.strip() != "":
|
if product_filter_smarts is not None and product_filter_smarts.strip() != "":
|
||||||
if not FormatConverter.is_valid_smarts(product_filter_smarts.strip()):
|
r.product_filter_smarts = product_filter_smarts
|
||||||
raise ValueError(f'Product Filter SMARTS "{product_filter_smarts}" is invalid!')
|
|
||||||
else:
|
|
||||||
r.product_filter_smarts = product_filter_smarts.strip()
|
|
||||||
|
|
||||||
r.save()
|
r.save()
|
||||||
return r
|
return r
|
||||||
@ -1420,11 +1403,12 @@ class Reaction(EnviPathModel, AliasMixin, ScenarioMixin, ReactionIdentifierMixin
|
|||||||
|
|
||||||
r = Reaction()
|
r = Reaction()
|
||||||
r.package = package
|
r.package = package
|
||||||
# Clean for potential XSS
|
|
||||||
if name is not None and name.strip() != "":
|
if name is not None and name.strip() != "":
|
||||||
r.name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
r.name = name
|
||||||
|
|
||||||
if description is not None and name.strip() != "":
|
if description is not None and name.strip() != "":
|
||||||
r.description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
r.description = description
|
||||||
|
|
||||||
r.multi_step = multi_step
|
r.multi_step = multi_step
|
||||||
|
|
||||||
@ -1732,15 +1716,14 @@ class Pathway(EnviPathModel, AliasMixin, ScenarioMixin):
|
|||||||
):
|
):
|
||||||
pw = Pathway()
|
pw = Pathway()
|
||||||
pw.package = package
|
pw.package = package
|
||||||
if name is not None:
|
|
||||||
# Clean for potential XSS
|
if name is None or name.strip() == "":
|
||||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
if name is None or name == "":
|
|
||||||
name = f"Pathway {Pathway.objects.filter(package=package).count() + 1}"
|
name = f"Pathway {Pathway.objects.filter(package=package).count() + 1}"
|
||||||
|
|
||||||
pw.name = name
|
pw.name = name
|
||||||
|
|
||||||
if description is not None and description.strip() != "":
|
if description is not None and description.strip() != "":
|
||||||
pw.description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
pw.description = description
|
||||||
|
|
||||||
pw.save()
|
pw.save()
|
||||||
try:
|
try:
|
||||||
@ -2035,16 +2018,11 @@ class Edge(EnviPathModel, AliasMixin, ScenarioMixin):
|
|||||||
for node in end_nodes:
|
for node in end_nodes:
|
||||||
e.end_nodes.add(node)
|
e.end_nodes.add(node)
|
||||||
|
|
||||||
# Clean for potential XSS
|
if name is None:
|
||||||
# Cleaning technically not needed as it is also done in Reaction.create, including it here for consistency
|
|
||||||
if name is not None:
|
|
||||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
if name is None or name == "":
|
|
||||||
name = f"Reaction {pathway.package.reactions.count() + 1}"
|
name = f"Reaction {pathway.package.reactions.count() + 1}"
|
||||||
|
|
||||||
if description is None:
|
if description is None:
|
||||||
description = s.DEFAULT_VALUES["description"]
|
description = s.DEFAULT_VALUES["description"]
|
||||||
description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
r = Reaction.create(
|
r = Reaction.create(
|
||||||
pathway.package,
|
pathway.package,
|
||||||
@ -2366,9 +2344,7 @@ class PackageBasedModel(EPModel):
|
|||||||
eval_reactions = list(
|
eval_reactions = list(
|
||||||
Reaction.objects.filter(package__in=self.eval_packages.all()).distinct()
|
Reaction.objects.filter(package__in=self.eval_packages.all()).distinct()
|
||||||
)
|
)
|
||||||
ds = RuleBasedDataset.generate_dataset(
|
ds = RuleBasedDataset.generate_dataset(eval_reactions, self.applicable_rules, educts_only=True)
|
||||||
eval_reactions, self.applicable_rules, educts_only=True
|
|
||||||
)
|
|
||||||
if isinstance(self, RuleBasedRelativeReasoning):
|
if isinstance(self, RuleBasedRelativeReasoning):
|
||||||
X = ds.X(exclude_id_col=False, na_replacement=None).to_numpy()
|
X = ds.X(exclude_id_col=False, na_replacement=None).to_numpy()
|
||||||
y = ds.y(na_replacement=np.nan).to_numpy()
|
y = ds.y(na_replacement=np.nan).to_numpy()
|
||||||
@ -2566,15 +2542,14 @@ class RuleBasedRelativeReasoning(PackageBasedModel):
|
|||||||
):
|
):
|
||||||
rbrr = RuleBasedRelativeReasoning()
|
rbrr = RuleBasedRelativeReasoning()
|
||||||
rbrr.package = package
|
rbrr.package = package
|
||||||
if name is not None:
|
|
||||||
# Clean for potential XSS
|
if name is None or name.strip() == "":
|
||||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
if name is None or name == "":
|
|
||||||
name = f"RuleBasedRelativeReasoning {RuleBasedRelativeReasoning.objects.filter(package=package).count() + 1}"
|
name = f"RuleBasedRelativeReasoning {RuleBasedRelativeReasoning.objects.filter(package=package).count() + 1}"
|
||||||
|
|
||||||
rbrr.name = name
|
rbrr.name = name
|
||||||
|
|
||||||
if description is not None and description.strip() != "":
|
if description is not None and description.strip() != "":
|
||||||
rbrr.description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
rbrr.description = description
|
||||||
|
|
||||||
if threshold is None or (threshold <= 0 or 1 <= threshold):
|
if threshold is None or (threshold <= 0 or 1 <= threshold):
|
||||||
raise ValueError("Threshold must be a float between 0 and 1.")
|
raise ValueError("Threshold must be a float between 0 and 1.")
|
||||||
@ -2671,15 +2646,14 @@ class MLRelativeReasoning(PackageBasedModel):
|
|||||||
):
|
):
|
||||||
mlrr = MLRelativeReasoning()
|
mlrr = MLRelativeReasoning()
|
||||||
mlrr.package = package
|
mlrr.package = package
|
||||||
if name is not None:
|
|
||||||
# Clean for potential XSS
|
if name is None or name.strip() == "":
|
||||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
if name is None or name == "":
|
|
||||||
name = f"MLRelativeReasoning {MLRelativeReasoning.objects.filter(package=package).count() + 1}"
|
name = f"MLRelativeReasoning {MLRelativeReasoning.objects.filter(package=package).count() + 1}"
|
||||||
|
|
||||||
mlrr.name = name
|
mlrr.name = name
|
||||||
|
|
||||||
if description is not None and description.strip() != "":
|
if description is not None and description.strip() != "":
|
||||||
mlrr.description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
mlrr.description = description
|
||||||
|
|
||||||
if threshold is None or (threshold <= 0 or 1 <= threshold):
|
if threshold is None or (threshold <= 0 or 1 <= threshold):
|
||||||
raise ValueError("Threshold must be a float between 0 and 1.")
|
raise ValueError("Threshold must be a float between 0 and 1.")
|
||||||
@ -2833,9 +2807,7 @@ class ApplicabilityDomain(EnviPathModel):
|
|||||||
else:
|
else:
|
||||||
smiles.append(structures)
|
smiles.append(structures)
|
||||||
|
|
||||||
assessment_ds, assessment_prods = ds.classification_dataset(
|
assessment_ds, assessment_prods = ds.classification_dataset(structures, self.model.applicable_rules)
|
||||||
structures, self.model.applicable_rules
|
|
||||||
)
|
|
||||||
|
|
||||||
# qualified_neighbours_per_rule is a nested dictionary structured as:
|
# qualified_neighbours_per_rule is a nested dictionary structured as:
|
||||||
# {
|
# {
|
||||||
@ -2851,16 +2823,12 @@ class ApplicabilityDomain(EnviPathModel):
|
|||||||
qualified_neighbours_per_rule: Dict = {}
|
qualified_neighbours_per_rule: Dict = {}
|
||||||
|
|
||||||
import polars as pl
|
import polars as pl
|
||||||
|
|
||||||
# Select only the triggered columns
|
# Select only the triggered columns
|
||||||
for i, row in enumerate(assessment_ds[:, assessment_ds.triggered()].iter_rows(named=True)):
|
for i, row in enumerate(assessment_ds[:, assessment_ds.triggered()].iter_rows(named=True)):
|
||||||
# Find the rules the structure triggers. For each rule, filter the training dataset to rows that also
|
# Find the rules the structure triggers. For each rule, filter the training dataset to rows that also
|
||||||
# trigger that rule.
|
# trigger that rule.
|
||||||
train_trig = {
|
train_trig = {trig_uuid.split("_")[-1]: ds.filter(pl.col(trig_uuid).eq(1))
|
||||||
trig_uuid.split("_")[-1]: ds.filter(pl.col(trig_uuid).eq(1))
|
for trig_uuid, value in row.items() if value == 1}
|
||||||
for trig_uuid, value in row.items()
|
|
||||||
if value == 1
|
|
||||||
}
|
|
||||||
qualified_neighbours_per_rule[i] = train_trig
|
qualified_neighbours_per_rule[i] = train_trig
|
||||||
rule_to_i = {str(r.uuid): i for i, r in enumerate(self.model.applicable_rules)}
|
rule_to_i = {str(r.uuid): i for i, r in enumerate(self.model.applicable_rules)}
|
||||||
preds = self.model.combine_products_and_probs(
|
preds = self.model.combine_products_and_probs(
|
||||||
@ -2880,28 +2848,17 @@ class ApplicabilityDomain(EnviPathModel):
|
|||||||
# loop through rule indices together with the collected neighbours indices from train dataset
|
# loop through rule indices together with the collected neighbours indices from train dataset
|
||||||
for rule_uuid, train_instances in qualified_neighbours_per_rule[i].items():
|
for rule_uuid, train_instances in qualified_neighbours_per_rule[i].items():
|
||||||
# compute tanimoto distance for all neighbours and add to dataset
|
# compute tanimoto distance for all neighbours and add to dataset
|
||||||
dists = self._compute_distances(
|
dists = self._compute_distances(assessment_ds[i, assessment_ds.struct_features()].to_numpy()[0],
|
||||||
assessment_ds[i, assessment_ds.struct_features()].to_numpy()[0],
|
train_instances[:, train_instances.struct_features()].to_numpy())
|
||||||
train_instances[:, train_instances.struct_features()].to_numpy(),
|
|
||||||
)
|
|
||||||
train_instances = train_instances.with_columns(dist=pl.Series(dists))
|
train_instances = train_instances.with_columns(dist=pl.Series(dists))
|
||||||
|
|
||||||
# sort them in a descending way and take at most `self.num_neighbours`
|
# sort them in a descending way and take at most `self.num_neighbours`
|
||||||
# TODO: Should this be descending? If we want the most similar then we want values close to zero (ascending)
|
train_instances = train_instances.sort("dist", descending=True)[:self.num_neighbours]
|
||||||
train_instances = train_instances.sort("dist", descending=True)[
|
|
||||||
: self.num_neighbours
|
|
||||||
]
|
|
||||||
# compute average distance
|
# compute average distance
|
||||||
rule_reliabilities[rule_uuid] = (
|
rule_reliabilities[rule_uuid] = train_instances.select(pl.mean("dist")).fill_nan(0.0).item()
|
||||||
train_instances.select(pl.mean("dist")).fill_nan(0.0).item()
|
|
||||||
)
|
|
||||||
# for local_compatibility we'll need the datasets for the indices having the highest similarity
|
# for local_compatibility we'll need the datasets for the indices having the highest similarity
|
||||||
local_compatibilities[rule_uuid] = self._compute_compatibility(
|
local_compatibilities[rule_uuid] = self._compute_compatibility(rule_uuid, train_instances)
|
||||||
rule_uuid, train_instances
|
neighbours_per_rule[rule_uuid] = list(CompoundStructure.objects.filter(uuid__in=train_instances["structure_id"]))
|
||||||
)
|
|
||||||
neighbours_per_rule[rule_uuid] = list(
|
|
||||||
CompoundStructure.objects.filter(uuid__in=train_instances["structure_id"])
|
|
||||||
)
|
|
||||||
neighbor_probs_per_rule[rule_uuid] = train_instances[f"prob_{rule_uuid}"].to_list()
|
neighbor_probs_per_rule[rule_uuid] = train_instances[f"prob_{rule_uuid}"].to_list()
|
||||||
|
|
||||||
ad_res = {
|
ad_res = {
|
||||||
@ -2975,11 +2932,8 @@ class ApplicabilityDomain(EnviPathModel):
|
|||||||
def _compute_compatibility(self, rule_idx: int, neighbours: "RuleBasedDataset"):
|
def _compute_compatibility(self, rule_idx: int, neighbours: "RuleBasedDataset"):
|
||||||
accuracy = 0.0
|
accuracy = 0.0
|
||||||
import polars as pl
|
import polars as pl
|
||||||
|
obs_pred = neighbours.select(obs=pl.col(f"obs_{rule_idx}").cast(pl.Boolean),
|
||||||
obs_pred = neighbours.select(
|
pred=pl.col(f"prob_{rule_idx}") >= self.model.threshold)
|
||||||
obs=pl.col(f"obs_{rule_idx}").cast(pl.Boolean),
|
|
||||||
pred=pl.col(f"prob_{rule_idx}") >= self.model.threshold,
|
|
||||||
)
|
|
||||||
# Compute tp, tn, fp, fn using polars expressions
|
# Compute tp, tn, fp, fn using polars expressions
|
||||||
tp = obs_pred.filter((pl.col("obs")) & (pl.col("pred"))).height
|
tp = obs_pred.filter((pl.col("obs")) & (pl.col("pred"))).height
|
||||||
tn = obs_pred.filter((~pl.col("obs")) & (~pl.col("pred"))).height
|
tn = obs_pred.filter((~pl.col("obs")) & (~pl.col("pred"))).height
|
||||||
@ -3006,15 +2960,14 @@ class EnviFormer(PackageBasedModel):
|
|||||||
):
|
):
|
||||||
mod = EnviFormer()
|
mod = EnviFormer()
|
||||||
mod.package = package
|
mod.package = package
|
||||||
if name is not None:
|
|
||||||
# Clean for potential XSS
|
if name is None or name.strip() == "":
|
||||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
if name is None or name == "":
|
|
||||||
name = f"EnviFormer {EnviFormer.objects.filter(package=package).count() + 1}"
|
name = f"EnviFormer {EnviFormer.objects.filter(package=package).count() + 1}"
|
||||||
|
|
||||||
mod.name = name
|
mod.name = name
|
||||||
|
|
||||||
if description is not None and description.strip() != "":
|
if description is not None and description.strip() != "":
|
||||||
mod.description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
mod.description = description
|
||||||
|
|
||||||
if threshold is None or (threshold <= 0 or 1 <= threshold):
|
if threshold is None or (threshold <= 0 or 1 <= threshold):
|
||||||
raise ValueError("Threshold must be a float between 0 and 1.")
|
raise ValueError("Threshold must be a float between 0 and 1.")
|
||||||
@ -3149,7 +3102,7 @@ class EnviFormer(PackageBasedModel):
|
|||||||
pred_dict = {}
|
pred_dict = {}
|
||||||
for k, pred in enumerate(predictions):
|
for k, pred in enumerate(predictions):
|
||||||
pred_smiles, pred_proba = zip(*pred.items())
|
pred_smiles, pred_proba = zip(*pred.items())
|
||||||
reactant, _ = test_ds[k, "educts"], test_ds[k, "products"]
|
reactant, true_product = test_ds[k, "educts"], test_ds[k, "products"]
|
||||||
pred_dict.setdefault(reactant, {"predict": [], "scores": []})
|
pred_dict.setdefault(reactant, {"predict": [], "scores": []})
|
||||||
for smiles, proba in zip(pred_smiles, pred_proba):
|
for smiles, proba in zip(pred_smiles, pred_proba):
|
||||||
smiles = set(smiles.split("."))
|
smiles = set(smiles.split("."))
|
||||||
@ -3263,9 +3216,8 @@ class EnviFormer(PackageBasedModel):
|
|||||||
|
|
||||||
# If there are eval packages perform single generation evaluation on them instead of random splits
|
# If there are eval packages perform single generation evaluation on them instead of random splits
|
||||||
if self.eval_packages.count() > 0:
|
if self.eval_packages.count() > 0:
|
||||||
ds = EnviFormerDataset.generate_dataset(
|
ds = EnviFormerDataset.generate_dataset(Reaction.objects.filter(
|
||||||
Reaction.objects.filter(package__in=self.eval_packages.all()).distinct()
|
package__in=self.eval_packages.all()).distinct())
|
||||||
)
|
|
||||||
test_result = self.model.predict_batch(ds.X())
|
test_result = self.model.predict_batch(ds.X())
|
||||||
single_gen_result = evaluate_sg(ds, test_result, self.threshold)
|
single_gen_result = evaluate_sg(ds, test_result, self.threshold)
|
||||||
self.eval_results = self.compute_averages([single_gen_result])
|
self.eval_results = self.compute_averages([single_gen_result])
|
||||||
@ -3283,9 +3235,7 @@ class EnviFormer(PackageBasedModel):
|
|||||||
train = ds[train_index]
|
train = ds[train_index]
|
||||||
test = ds[test_index]
|
test = ds[test_index]
|
||||||
start = datetime.now()
|
start = datetime.now()
|
||||||
model = fine_tune(
|
model = fine_tune(train.X(), train.y(), s.MODEL_DIR, str(split_id), device=s.ENVIFORMER_DEVICE)
|
||||||
train.X(), train.y(), s.MODEL_DIR, str(split_id), device=s.ENVIFORMER_DEVICE
|
|
||||||
)
|
|
||||||
end = datetime.now()
|
end = datetime.now()
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"EnviFormer finetuning took {(end - start).total_seconds():.2f} seconds"
|
f"EnviFormer finetuning took {(end - start).total_seconds():.2f} seconds"
|
||||||
@ -3362,12 +3312,7 @@ class EnviFormer(PackageBasedModel):
|
|||||||
for pathway in train_pathways:
|
for pathway in train_pathways:
|
||||||
for reaction in pathway.edges:
|
for reaction in pathway.edges:
|
||||||
reaction = reaction.edge_label
|
reaction = reaction.edge_label
|
||||||
if any(
|
if any([educt in test_educts for educt in reaction_to_educts[str(reaction.uuid)]]):
|
||||||
[
|
|
||||||
educt in test_educts
|
|
||||||
for educt in reaction_to_educts[str(reaction.uuid)]
|
|
||||||
]
|
|
||||||
):
|
|
||||||
overlap += 1
|
overlap += 1
|
||||||
continue
|
continue
|
||||||
train_reactions.append(reaction)
|
train_reactions.append(reaction)
|
||||||
@ -3424,44 +3369,41 @@ class Scenario(EnviPathModel):
|
|||||||
scenario_type: str,
|
scenario_type: str,
|
||||||
additional_information: List["EnviPyModel"],
|
additional_information: List["EnviPyModel"],
|
||||||
):
|
):
|
||||||
new_s = Scenario()
|
s = Scenario()
|
||||||
new_s.package = package
|
s.package = package
|
||||||
if name is not None:
|
|
||||||
# Clean for potential XSS
|
if name is None or name.strip() == "":
|
||||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
if name is None or name == "":
|
|
||||||
name = f"Scenario {Scenario.objects.filter(package=package).count() + 1}"
|
name = f"Scenario {Scenario.objects.filter(package=package).count() + 1}"
|
||||||
new_s.name = name
|
|
||||||
|
s.name = name
|
||||||
|
|
||||||
if description is not None and description.strip() != "":
|
if description is not None and description.strip() != "":
|
||||||
new_s.description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
s.description = description
|
||||||
|
|
||||||
if scenario_date is not None and scenario_date.strip() != "":
|
if scenario_date is not None and scenario_date.strip() != "":
|
||||||
new_s.scenario_date = nh3.clean(scenario_date).strip()
|
s.scenario_date = scenario_date
|
||||||
|
|
||||||
if scenario_type is not None and scenario_type.strip() != "":
|
if scenario_type is not None and scenario_type.strip() != "":
|
||||||
new_s.scenario_type = scenario_type
|
s.scenario_type = scenario_type
|
||||||
|
|
||||||
add_inf = defaultdict(list)
|
add_inf = defaultdict(list)
|
||||||
|
|
||||||
for info in additional_information:
|
for info in additional_information:
|
||||||
cls_name = info.__class__.__name__
|
cls_name = info.__class__.__name__
|
||||||
# Clean for potential XSS hidden in the additional information fields.
|
ai_data = json.loads(info.model_dump_json())
|
||||||
ai_data = json.loads(nh3.clean(info.model_dump_json()).strip())
|
|
||||||
ai_data["uuid"] = f"{uuid4()}"
|
ai_data["uuid"] = f"{uuid4()}"
|
||||||
add_inf[cls_name].append(ai_data)
|
add_inf[cls_name].append(ai_data)
|
||||||
|
|
||||||
new_s.additional_information = add_inf
|
s.additional_information = add_inf
|
||||||
|
|
||||||
new_s.save()
|
s.save()
|
||||||
|
|
||||||
return new_s
|
return s
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def add_additional_information(self, data: "EnviPyModel"):
|
def add_additional_information(self, data: "EnviPyModel"):
|
||||||
cls_name = data.__class__.__name__
|
cls_name = data.__class__.__name__
|
||||||
# Clean for potential XSS hidden in the additional information fields.
|
ai_data = json.loads(data.model_dump_json())
|
||||||
ai_data = json.loads(nh3.clean(data.model_dump_json()).strip())
|
|
||||||
ai_data["uuid"] = f"{uuid4()}"
|
ai_data["uuid"] = f"{uuid4()}"
|
||||||
|
|
||||||
if cls_name not in self.additional_information:
|
if cls_name not in self.additional_information:
|
||||||
@ -3496,8 +3438,7 @@ class Scenario(EnviPathModel):
|
|||||||
new_ais = defaultdict(list)
|
new_ais = defaultdict(list)
|
||||||
for k, vals in data.items():
|
for k, vals in data.items():
|
||||||
for v in vals:
|
for v in vals:
|
||||||
# Clean for potential XSS hidden in the additional information fields.
|
ai_data = json.loads(v.model_dump_json())
|
||||||
ai_data = json.loads(nh3.clean(v.model_dump_json()).strip())
|
|
||||||
if hasattr(v, "uuid"):
|
if hasattr(v, "uuid"):
|
||||||
ai_data["uuid"] = str(v.uuid)
|
ai_data["uuid"] = str(v.uuid)
|
||||||
else:
|
else:
|
||||||
|
|||||||
115
epdb/views.py
115
epdb/views.py
@ -10,7 +10,6 @@ from django.urls import reverse
|
|||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from envipy_additional_information import NAME_MAPPING
|
from envipy_additional_information import NAME_MAPPING
|
||||||
from oauth2_provider.decorators import protected_resource
|
from oauth2_provider.decorators import protected_resource
|
||||||
import nh3
|
|
||||||
|
|
||||||
from utilities.chem import FormatConverter, IndigoUtils
|
from utilities.chem import FormatConverter, IndigoUtils
|
||||||
from utilities.decorators import package_permission_required
|
from utilities.decorators import package_permission_required
|
||||||
@ -86,10 +85,7 @@ def login(request):
|
|||||||
from django.contrib.auth import authenticate
|
from django.contrib.auth import authenticate
|
||||||
from django.contrib.auth import login
|
from django.contrib.auth import login
|
||||||
|
|
||||||
username = request.POST.get("username").strip()
|
username = request.POST.get("username")
|
||||||
if username != request.POST.get("username"):
|
|
||||||
context["message"] = "Login failed!"
|
|
||||||
return render(request, "static/login.html", context)
|
|
||||||
password = request.POST.get("password")
|
password = request.POST.get("password")
|
||||||
|
|
||||||
# Get email for username and check if the account is active
|
# Get email for username and check if the account is active
|
||||||
@ -674,8 +670,7 @@ def search(request):
|
|||||||
|
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
package_urls = request.GET.getlist("packages")
|
package_urls = request.GET.getlist("packages")
|
||||||
searchterm = request.GET.get("search").strip()
|
searchterm = request.GET.get("search")
|
||||||
|
|
||||||
mode = request.GET.get("mode")
|
mode = request.GET.get("mode")
|
||||||
|
|
||||||
# add HTTP_ACCEPT check to differentiate between index and ajax call
|
# add HTTP_ACCEPT check to differentiate between index and ajax call
|
||||||
@ -776,6 +771,7 @@ def package_models(request, package_uuid):
|
|||||||
|
|
||||||
elif request.method == "POST":
|
elif request.method == "POST":
|
||||||
log_post_params(request)
|
log_post_params(request)
|
||||||
|
|
||||||
name = request.POST.get("model-name")
|
name = request.POST.get("model-name")
|
||||||
description = request.POST.get("model-description")
|
description = request.POST.get("model-description")
|
||||||
|
|
||||||
@ -940,14 +936,8 @@ def package_model(request, package_uuid, model_uuid):
|
|||||||
else:
|
else:
|
||||||
return HttpResponseBadRequest()
|
return HttpResponseBadRequest()
|
||||||
else:
|
else:
|
||||||
# TODO: Move cleaning to property updater
|
name = request.POST.get("model-name", "").strip()
|
||||||
name = request.POST.get("model-name")
|
description = request.POST.get("model-description", "").strip()
|
||||||
if name is not None:
|
|
||||||
name = nh3.clean(name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
description = request.POST.get("model-description")
|
|
||||||
if description is not None:
|
|
||||||
description = nh3.clean(description, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
if any([name, description]):
|
if any([name, description]):
|
||||||
if name:
|
if name:
|
||||||
@ -1049,16 +1039,8 @@ def package(request, package_uuid):
|
|||||||
else:
|
else:
|
||||||
return HttpResponseBadRequest()
|
return HttpResponseBadRequest()
|
||||||
|
|
||||||
# TODO: Move cleaning to property updater
|
|
||||||
new_package_name = request.POST.get("package-name")
|
new_package_name = request.POST.get("package-name")
|
||||||
if new_package_name is not None:
|
|
||||||
new_package_name = nh3.clean(new_package_name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
new_package_description = request.POST.get("package-description")
|
new_package_description = request.POST.get("package-description")
|
||||||
if new_package_description is not None:
|
|
||||||
new_package_description = nh3.clean(
|
|
||||||
new_package_description, tags=s.ALLOWED_HTML_TAGS
|
|
||||||
).strip()
|
|
||||||
|
|
||||||
grantee_url = request.POST.get("grantee")
|
grantee_url = request.POST.get("grantee")
|
||||||
read = request.POST.get("read") == "on"
|
read = request.POST.get("read") == "on"
|
||||||
@ -1167,7 +1149,7 @@ def package_compounds(request, package_uuid):
|
|||||||
|
|
||||||
elif request.method == "POST":
|
elif request.method == "POST":
|
||||||
compound_name = request.POST.get("compound-name")
|
compound_name = request.POST.get("compound-name")
|
||||||
compound_smiles = request.POST.get("compound-smiles").strip()
|
compound_smiles = request.POST.get("compound-smiles")
|
||||||
compound_description = request.POST.get("compound-description")
|
compound_description = request.POST.get("compound-description")
|
||||||
|
|
||||||
c = Compound.create(current_package, compound_smiles, compound_name, compound_description)
|
c = Compound.create(current_package, compound_smiles, compound_name, compound_description)
|
||||||
@ -1220,16 +1202,8 @@ def package_compound(request, package_uuid, compound_uuid):
|
|||||||
|
|
||||||
return JsonResponse({"success": current_compound.url})
|
return JsonResponse({"success": current_compound.url})
|
||||||
|
|
||||||
# TODO: Move cleaning to property updater
|
new_compound_name = request.POST.get("compound-name", "").strip()
|
||||||
new_compound_name = request.POST.get("compound-name")
|
new_compound_description = request.POST.get("compound-description", "").strip()
|
||||||
if new_compound_name is not None:
|
|
||||||
new_compound_name = nh3.clean(new_compound_name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
new_compound_description = request.POST.get("compound-description")
|
|
||||||
if new_compound_description is not None:
|
|
||||||
new_compound_description = nh3.clean(
|
|
||||||
new_compound_description, tags=s.ALLOWED_HTML_TAGS
|
|
||||||
).strip()
|
|
||||||
|
|
||||||
if new_compound_name:
|
if new_compound_name:
|
||||||
current_compound.name = new_compound_name
|
current_compound.name = new_compound_name
|
||||||
@ -1294,7 +1268,7 @@ def package_compound_structures(request, package_uuid, compound_uuid):
|
|||||||
|
|
||||||
elif request.method == "POST":
|
elif request.method == "POST":
|
||||||
structure_name = request.POST.get("structure-name")
|
structure_name = request.POST.get("structure-name")
|
||||||
structure_smiles = request.POST.get("structure-smiles").strip()
|
structure_smiles = request.POST.get("structure-smiles")
|
||||||
structure_description = request.POST.get("structure-description")
|
structure_description = request.POST.get("structure-description")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -1365,16 +1339,8 @@ def package_compound_structure(request, package_uuid, compound_uuid, structure_u
|
|||||||
else:
|
else:
|
||||||
return HttpResponseBadRequest()
|
return HttpResponseBadRequest()
|
||||||
|
|
||||||
# TODO: Move cleaning to property updater
|
new_structure_name = request.POST.get("compound-structure-name", "").strip()
|
||||||
new_structure_name = request.POST.get("compound-structure-name")
|
new_structure_description = request.POST.get("compound-structure-description", "").strip()
|
||||||
if new_structure_name is not None:
|
|
||||||
new_structure_name = nh3.clean(new_structure_name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
new_structure_description = request.POST.get("compound-structure-description")
|
|
||||||
if new_structure_description is not None:
|
|
||||||
new_structure_description = nh3.clean(
|
|
||||||
new_structure_description, tags=s.ALLOWED_HTML_TAGS
|
|
||||||
).strip()
|
|
||||||
|
|
||||||
if new_structure_name:
|
if new_structure_name:
|
||||||
current_structure.name = new_structure_name
|
current_structure.name = new_structure_name
|
||||||
@ -1476,11 +1442,11 @@ def package_rules(request, package_uuid):
|
|||||||
|
|
||||||
# Obtain parameters as required by rule type
|
# Obtain parameters as required by rule type
|
||||||
if rule_type == "SimpleAmbitRule":
|
if rule_type == "SimpleAmbitRule":
|
||||||
params["smirks"] = request.POST.get("rule-smirks").strip()
|
params["smirks"] = request.POST.get("rule-smirks")
|
||||||
params["reactant_filter_smarts"] = request.POST.get("rule-reactant-smarts")
|
params["reactant_filter_smarts"] = request.POST.get("rule-reactant-smarts")
|
||||||
params["product_filter_smarts"] = request.POST.get("rule-product-smarts")
|
params["product_filter_smarts"] = request.POST.get("rule-product-smarts")
|
||||||
elif rule_type == "SimpleRDKitRule":
|
elif rule_type == "SimpleRDKitRule":
|
||||||
params["reaction_smarts"] = request.POST.get("rule-reaction-smarts").strip()
|
params["reaction_smarts"] = request.POST.get("rule-reaction-smarts")
|
||||||
elif rule_type == "ParallelRule":
|
elif rule_type == "ParallelRule":
|
||||||
pass
|
pass
|
||||||
elif rule_type == "SequentialRule":
|
elif rule_type == "SequentialRule":
|
||||||
@ -1581,14 +1547,8 @@ def package_rule(request, package_uuid, rule_uuid):
|
|||||||
|
|
||||||
return JsonResponse({"success": current_rule.url})
|
return JsonResponse({"success": current_rule.url})
|
||||||
|
|
||||||
# TODO: Move cleaning to property updater
|
rule_name = request.POST.get("rule-name", "").strip()
|
||||||
rule_name = request.POST.get("rule-name")
|
rule_description = request.POST.get("rule-description", "").strip()
|
||||||
if rule_name is not None:
|
|
||||||
rule_name = nh3.clean(rule_name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
rule_description = request.POST.get("rule-description")
|
|
||||||
if rule_description is not None:
|
|
||||||
rule_description = nh3.clean(rule_description, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
if rule_name:
|
if rule_name:
|
||||||
current_rule.name = rule_name
|
current_rule.name = rule_name
|
||||||
@ -1677,8 +1637,8 @@ def package_reactions(request, package_uuid):
|
|||||||
elif request.method == "POST":
|
elif request.method == "POST":
|
||||||
reaction_name = request.POST.get("reaction-name")
|
reaction_name = request.POST.get("reaction-name")
|
||||||
reaction_description = request.POST.get("reaction-description")
|
reaction_description = request.POST.get("reaction-description")
|
||||||
|
reactions_smirks = request.POST.get("reaction-smirks")
|
||||||
|
|
||||||
reactions_smirks = request.POST.get("reaction-smirks").strip()
|
|
||||||
educts = reactions_smirks.split(">>")[0].split(".")
|
educts = reactions_smirks.split(">>")[0].split(".")
|
||||||
products = reactions_smirks.split(">>")[1].split(".")
|
products = reactions_smirks.split(">>")[1].split(".")
|
||||||
|
|
||||||
@ -1739,16 +1699,8 @@ def package_reaction(request, package_uuid, reaction_uuid):
|
|||||||
|
|
||||||
return JsonResponse({"success": current_reaction.url})
|
return JsonResponse({"success": current_reaction.url})
|
||||||
|
|
||||||
# TODO: Move cleaning to property updater
|
new_reaction_name = request.POST.get("reaction-name", "").strip()
|
||||||
new_reaction_name = request.POST.get("reaction-name")
|
new_reaction_description = request.POST.get("reaction-description", "").strip()
|
||||||
if new_reaction_name is not None:
|
|
||||||
new_reaction_name = nh3.clean(new_reaction_name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
new_reaction_description = request.POST.get("reaction-description")
|
|
||||||
if new_reaction_description is not None:
|
|
||||||
new_reaction_description = nh3.clean(
|
|
||||||
new_reaction_description, tags=s.ALLOWED_HTML_TAGS
|
|
||||||
).strip()
|
|
||||||
|
|
||||||
if new_reaction_name:
|
if new_reaction_name:
|
||||||
current_reaction.name = new_reaction_name
|
current_reaction.name = new_reaction_name
|
||||||
@ -1825,9 +1777,8 @@ def package_pathways(request, package_uuid):
|
|||||||
|
|
||||||
name = request.POST.get("name")
|
name = request.POST.get("name")
|
||||||
description = request.POST.get("description")
|
description = request.POST.get("description")
|
||||||
|
|
||||||
smiles = request.POST.get("smiles", "").strip()
|
|
||||||
pw_mode = request.POST.get("predict", "predict").strip()
|
pw_mode = request.POST.get("predict", "predict").strip()
|
||||||
|
smiles = request.POST.get("smiles", "").strip()
|
||||||
|
|
||||||
if "smiles" in request.POST and smiles == "":
|
if "smiles" in request.POST and smiles == "":
|
||||||
return error(
|
return error(
|
||||||
@ -1836,6 +1787,8 @@ def package_pathways(request, package_uuid):
|
|||||||
"Pathway prediction failed due to missing or empty SMILES",
|
"Pathway prediction failed due to missing or empty SMILES",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
smiles = smiles.strip()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
stand_smiles = FormatConverter.standardize(smiles)
|
stand_smiles = FormatConverter.standardize(smiles)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -1994,14 +1947,8 @@ def package_pathway(request, package_uuid, pathway_uuid):
|
|||||||
|
|
||||||
return JsonResponse({"success": current_pathway.url})
|
return JsonResponse({"success": current_pathway.url})
|
||||||
|
|
||||||
# TODO: Move cleaning to property updater
|
|
||||||
pathway_name = request.POST.get("pathway-name")
|
pathway_name = request.POST.get("pathway-name")
|
||||||
if pathway_name is not None:
|
|
||||||
pathway_name = nh3.clean(pathway_name, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
pathway_description = request.POST.get("pathway-description")
|
pathway_description = request.POST.get("pathway-description")
|
||||||
if pathway_description is not None:
|
|
||||||
pathway_description = nh3.clean(pathway_description, tags=s.ALLOWED_HTML_TAGS).strip()
|
|
||||||
|
|
||||||
if any([pathway_name, pathway_description]):
|
if any([pathway_name, pathway_description]):
|
||||||
if pathway_name is not None and pathway_name.strip() != "":
|
if pathway_name is not None and pathway_name.strip() != "":
|
||||||
@ -2089,8 +2036,8 @@ def package_pathway_nodes(request, package_uuid, pathway_uuid):
|
|||||||
elif request.method == "POST":
|
elif request.method == "POST":
|
||||||
node_name = request.POST.get("node-name")
|
node_name = request.POST.get("node-name")
|
||||||
node_description = request.POST.get("node-description")
|
node_description = request.POST.get("node-description")
|
||||||
|
node_smiles = request.POST.get("node-smiles")
|
||||||
|
|
||||||
node_smiles = request.POST.get("node-smiles").strip()
|
|
||||||
current_pathway.add_node(node_smiles, name=node_name, description=node_description)
|
current_pathway.add_node(node_smiles, name=node_name, description=node_description)
|
||||||
|
|
||||||
return redirect(current_pathway.url)
|
return redirect(current_pathway.url)
|
||||||
@ -2252,9 +2199,9 @@ def package_pathway_edges(request, package_uuid, pathway_uuid):
|
|||||||
|
|
||||||
elif request.method == "POST":
|
elif request.method == "POST":
|
||||||
log_post_params(request)
|
log_post_params(request)
|
||||||
|
|
||||||
edge_name = request.POST.get("edge-name")
|
edge_name = request.POST.get("edge-name")
|
||||||
edge_description = request.POST.get("edge-description")
|
edge_description = request.POST.get("edge-description")
|
||||||
|
|
||||||
edge_substrates = request.POST.getlist("edge-substrates")
|
edge_substrates = request.POST.getlist("edge-substrates")
|
||||||
edge_products = request.POST.getlist("edge-products")
|
edge_products = request.POST.getlist("edge-products")
|
||||||
|
|
||||||
@ -2341,7 +2288,7 @@ def package_scenarios(request, package_uuid):
|
|||||||
"all", False
|
"all", False
|
||||||
):
|
):
|
||||||
scens = Scenario.objects.filter(package=current_package).order_by("name")
|
scens = Scenario.objects.filter(package=current_package).order_by("name")
|
||||||
res = [{"name": s_.name, "url": s_.url, "uuid": s_.uuid} for s_ in scens]
|
res = [{"name": s.name, "url": s.url, "uuid": s.uuid} for s in scens]
|
||||||
return JsonResponse(res, safe=False)
|
return JsonResponse(res, safe=False)
|
||||||
|
|
||||||
context = get_base_context(request)
|
context = get_base_context(request)
|
||||||
@ -2389,21 +2336,21 @@ def package_scenarios(request, package_uuid):
|
|||||||
"name": "soil",
|
"name": "soil",
|
||||||
"widgets": [
|
"widgets": [
|
||||||
HTMLGenerator.generate_html(ai, prefix=f"soil_{0}")
|
HTMLGenerator.generate_html(ai, prefix=f"soil_{0}")
|
||||||
for ai in [x for sv in SOIL_ADDITIONAL_INFORMATION.values() for x in sv]
|
for ai in [x for s in SOIL_ADDITIONAL_INFORMATION.values() for x in s]
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"Sludge Data": {
|
"Sludge Data": {
|
||||||
"name": "sludge",
|
"name": "sludge",
|
||||||
"widgets": [
|
"widgets": [
|
||||||
HTMLGenerator.generate_html(ai, prefix=f"sludge_{0}")
|
HTMLGenerator.generate_html(ai, prefix=f"sludge_{0}")
|
||||||
for ai in [x for sv in SLUDGE_ADDITIONAL_INFORMATION.values() for x in sv]
|
for ai in [x for s in SLUDGE_ADDITIONAL_INFORMATION.values() for x in s]
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"Water-Sediment System Data": {
|
"Water-Sediment System Data": {
|
||||||
"name": "sediment",
|
"name": "sediment",
|
||||||
"widgets": [
|
"widgets": [
|
||||||
HTMLGenerator.generate_html(ai, prefix=f"sediment_{0}")
|
HTMLGenerator.generate_html(ai, prefix=f"sediment_{0}")
|
||||||
for ai in [x for sv in SEDIMENT_ADDITIONAL_INFORMATION.values() for x in sv]
|
for ai in [x for s in SEDIMENT_ADDITIONAL_INFORMATION.values() for x in s]
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -2418,7 +2365,6 @@ def package_scenarios(request, package_uuid):
|
|||||||
|
|
||||||
scenario_name = request.POST.get("scenario-name")
|
scenario_name = request.POST.get("scenario-name")
|
||||||
scenario_description = request.POST.get("scenario-description")
|
scenario_description = request.POST.get("scenario-description")
|
||||||
|
|
||||||
scenario_date_year = request.POST.get("scenario-date-year")
|
scenario_date_year = request.POST.get("scenario-date-year")
|
||||||
scenario_date_month = request.POST.get("scenario-date-month")
|
scenario_date_month = request.POST.get("scenario-date-month")
|
||||||
scenario_date_day = request.POST.get("scenario-date-day")
|
scenario_date_day = request.POST.get("scenario-date-day")
|
||||||
@ -2432,9 +2378,9 @@ def package_scenarios(request, package_uuid):
|
|||||||
scenario_type = request.POST.get("scenario-type")
|
scenario_type = request.POST.get("scenario-type")
|
||||||
|
|
||||||
additional_information = HTMLGenerator.build_models(request.POST.dict())
|
additional_information = HTMLGenerator.build_models(request.POST.dict())
|
||||||
additional_information = [x for sv in additional_information.values() for x in sv]
|
additional_information = [x for s in additional_information.values() for x in s]
|
||||||
|
|
||||||
new_scen = Scenario.create(
|
s = Scenario.create(
|
||||||
current_package,
|
current_package,
|
||||||
name=scenario_name,
|
name=scenario_name,
|
||||||
description=scenario_description,
|
description=scenario_description,
|
||||||
@ -2443,7 +2389,7 @@ def package_scenarios(request, package_uuid):
|
|||||||
additional_information=additional_information,
|
additional_information=additional_information,
|
||||||
)
|
)
|
||||||
|
|
||||||
return redirect(new_scen.url)
|
return redirect(s.url)
|
||||||
else:
|
else:
|
||||||
return HttpResponseNotAllowed(
|
return HttpResponseNotAllowed(
|
||||||
[
|
[
|
||||||
@ -2743,7 +2689,6 @@ def settings(request):
|
|||||||
|
|
||||||
name = request.POST.get("prediction-setting-name")
|
name = request.POST.get("prediction-setting-name")
|
||||||
description = request.POST.get("prediction-setting-description")
|
description = request.POST.get("prediction-setting-description")
|
||||||
|
|
||||||
new_default = request.POST.get("prediction-setting-new-default", "off") == "on"
|
new_default = request.POST.get("prediction-setting-new-default", "off") == "on"
|
||||||
|
|
||||||
max_nodes = min(
|
max_nodes = min(
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
4
pnpm-lock.yaml
generated
4
pnpm-lock.yaml
generated
@ -1,4 +0,0 @@
|
|||||||
lockfileVersion: 6.0
|
|
||||||
specifiers: {}
|
|
||||||
dependencies: {}
|
|
||||||
packages: {}
|
|
||||||
@ -27,7 +27,6 @@ dependencies = [
|
|||||||
"scikit-learn>=1.6.1",
|
"scikit-learn>=1.6.1",
|
||||||
"sentry-sdk[django]>=2.32.0",
|
"sentry-sdk[django]>=2.32.0",
|
||||||
"setuptools>=80.8.0",
|
"setuptools>=80.8.0",
|
||||||
"nh3==0.3.2",
|
|
||||||
"polars==1.35.1",
|
"polars==1.35.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
{% extends "framework.html" %}
|
{% extends "framework.html" %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load envipytags %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="panel-group" id="reviewListAccordion">
|
<div class="panel-group" id="reviewListAccordion">
|
||||||
|
|||||||
@ -192,7 +192,7 @@
|
|||||||
<div class="panel-body list-group-item" id="ReviewedContent">
|
<div class="panel-body list-group-item" id="ReviewedContent">
|
||||||
{% if object_type == 'package' %}
|
{% if object_type == 'package' %}
|
||||||
{% for obj in reviewed_objects %}
|
{% for obj in reviewed_objects %}
|
||||||
<a class="list-group-item" href="{{ obj.url }}">{{ obj.name|safe }}
|
<a class="list-group-item" href="{{ obj.url }}">{{ obj.name }}
|
||||||
<span class="glyphicon glyphicon-star" aria-hidden="true"
|
<span class="glyphicon glyphicon-star" aria-hidden="true"
|
||||||
style="float:right" data-toggle="tooltip"
|
style="float:right" data-toggle="tooltip"
|
||||||
data-placement="top" title="" data-original-title="Reviewed">
|
data-placement="top" title="" data-original-title="Reviewed">
|
||||||
@ -201,7 +201,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% for obj in reviewed_objects|slice:":50" %}
|
{% for obj in reviewed_objects|slice:":50" %}
|
||||||
<a class="list-group-item" href="{{ obj.url }}">{{ obj.name|safe }}{# <i>({{ obj.package.name }})</i> #}
|
<a class="list-group-item" href="{{ obj.url }}">{{ obj.name }}{# <i>({{ obj.package.name }})</i> #}
|
||||||
<span class="glyphicon glyphicon-star" aria-hidden="true"
|
<span class="glyphicon glyphicon-star" aria-hidden="true"
|
||||||
style="float:right" data-toggle="tooltip"
|
style="float:right" data-toggle="tooltip"
|
||||||
data-placement="top" title="" data-original-title="Reviewed">
|
data-placement="top" title="" data-original-title="Reviewed">
|
||||||
@ -221,11 +221,11 @@
|
|||||||
<div class="panel-body list-group-item" id="UnreviewedContent">
|
<div class="panel-body list-group-item" id="UnreviewedContent">
|
||||||
{% if object_type == 'package' %}
|
{% if object_type == 'package' %}
|
||||||
{% for obj in unreviewed_objects %}
|
{% for obj in unreviewed_objects %}
|
||||||
<a class="list-group-item" href="{{ obj.url }}">{{ obj.name|safe }}</a>
|
<a class="list-group-item" href="{{ obj.url }}">{{ obj.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% for obj in unreviewed_objects|slice:":50" %}
|
{% for obj in unreviewed_objects|slice:":50" %}
|
||||||
<a class="list-group-item" href="{{ obj.url }}">{{ obj.name|safe }}</a>
|
<a class="list-group-item" href="{{ obj.url }}">{{ obj.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@ -236,9 +236,9 @@
|
|||||||
<ul class='list-group'>
|
<ul class='list-group'>
|
||||||
{% for obj in objects %}
|
{% for obj in objects %}
|
||||||
{% if object_type == 'user' %}
|
{% if object_type == 'user' %}
|
||||||
<a class="list-group-item" href="{{ obj.url }}">{{ obj.username|safe }}</a>
|
<a class="list-group-item" href="{{ obj.url }}">{{ obj.username }}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a class="list-group-item" href="{{ obj.url }}">{{ obj.name|safe }}</a>
|
<a class="list-group-item" href="{{ obj.url }}">{{ obj.name }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@ -26,12 +26,12 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<h4 class="panel-title">
|
<h4 class="panel-title">
|
||||||
<a id="{{ obj.id }}-link" data-toggle="collapse" data-parent="#migration-detail"
|
<a id="{{ obj.id }}-link" data-toggle="collapse" data-parent="#migration-detail"
|
||||||
href="#{{ obj.id }}">{{ obj.name|safe }}</a>
|
href="#{{ obj.id }}">{{ obj.name }}</a>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div id="{{ obj.id }}" class="panel-collapse collapse {% if not obj.status %}in{% endif %}">
|
<div id="{{ obj.id }}" class="panel-collapse collapse {% if not obj.status %}in{% endif %}">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
<a class="list-group-item" href="{{ obj.detail_url }}">{{ obj.name|safe }} Migration Detail Page</a>
|
<a class="list-group-item" href="{{ obj.detail_url }}">{{ obj.name }} Migration Detail Page</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<h4 class="panel-title">
|
<h4 class="panel-title">
|
||||||
<a id="{{ obj.id }}-link" data-toggle="collapse" data-parent="#migration-detail"
|
<a id="{{ obj.id }}-link" data-toggle="collapse" data-parent="#migration-detail"
|
||||||
href="#{{ obj.id }}">{{ obj.name|safe }}</a>
|
href="#{{ obj.id }}">{{ obj.name }}</a>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div id="{{ obj.id }}" class="panel-collapse collapse {% if not obj.status %}in{% endif %}">
|
<div id="{{ obj.id }}" class="panel-collapse collapse {% if not obj.status %}in{% endif %}">
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
<div class="modal fade" tabindex="-1" id="new_model_modal" role="dialog" aria-labelledby="new_model_modal"
|
<div class="modal fade" tabindex="-1" id="new_model_modal" role="dialog" aria-labelledby="new_model_modal"
|
||||||
aria-hidden="true">
|
aria-hidden="true">
|
||||||
<div class="modal-dialog modal-lg">
|
<div class="modal-dialog modal-lg">
|
||||||
@ -48,14 +47,14 @@
|
|||||||
<option disabled>Reviewed Packages</option>
|
<option disabled>Reviewed Packages</option>
|
||||||
{% for obj in meta.readable_packages %}
|
{% for obj in meta.readable_packages %}
|
||||||
{% if obj.reviewed %}
|
{% if obj.reviewed %}
|
||||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
<option value="{{ obj.url }}">{{ obj.name }}</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<option disabled>Unreviewed Packages</option>
|
<option disabled>Unreviewed Packages</option>
|
||||||
{% for obj in meta.readable_packages %}
|
{% for obj in meta.readable_packages %}
|
||||||
{% if not obj.reviewed %}
|
{% if not obj.reviewed %}
|
||||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
<option value="{{ obj.url }}">{{ obj.name }}</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
@ -69,14 +68,14 @@
|
|||||||
<option disabled>Reviewed Packages</option>
|
<option disabled>Reviewed Packages</option>
|
||||||
{% for obj in meta.readable_packages %}
|
{% for obj in meta.readable_packages %}
|
||||||
{% if obj.reviewed %}
|
{% if obj.reviewed %}
|
||||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
<option value="{{ obj.url }}">{{ obj.name }}</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<option disabled>Unreviewed Packages</option>
|
<option disabled>Unreviewed Packages</option>
|
||||||
{% for obj in meta.readable_packages %}
|
{% for obj in meta.readable_packages %}
|
||||||
{% if not obj.reviewed %}
|
{% if not obj.reviewed %}
|
||||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
<option value="{{ obj.url }}">{{ obj.name }}</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<div class="modal fade" tabindex="-1" id="new_pathway_modal" role="dialog" aria-labelledby="new_pathway_modal"
|
<div class="modal fade" tabindex="-1" id="new_pathway_modal" role="dialog" aria-labelledby="new_pathway_modal"
|
||||||
aria-hidden="true" style="overflow-y: auto;">
|
aria-hidden="true" style="overflow-y: auto;">
|
||||||
@ -112,7 +111,7 @@
|
|||||||
|
|
||||||
<select id="settingSelect" name="settingSelect" class="form-control">
|
<select id="settingSelect" name="settingSelect" class="form-control">
|
||||||
{% for setting in available_settings %}
|
{% for setting in available_settings %}
|
||||||
<option value="{{ setting.id }}">{{ setting.name|safe }}</option>
|
<option value="{{ setting.id }}">{{ setting.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
<p></p>
|
<p></p>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
<div id="new_prediction_setting_modal" class="modal" tabindex="-1">
|
<div id="new_prediction_setting_modal" class="modal" tabindex="-1">
|
||||||
@ -41,14 +40,14 @@
|
|||||||
<option disabled>Reviewed Packages</option>
|
<option disabled>Reviewed Packages</option>
|
||||||
{% for obj in meta.readable_packages %}
|
{% for obj in meta.readable_packages %}
|
||||||
{% if obj.reviewed %}
|
{% if obj.reviewed %}
|
||||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
<option value="{{ obj.url }}">{{ obj.name }}</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<option disabled>Unreviewed Packages</option>
|
<option disabled>Unreviewed Packages</option>
|
||||||
{% for obj in meta.readable_packages %}
|
{% for obj in meta.readable_packages %}
|
||||||
{% if not obj.reviewed %}
|
{% if not obj.reviewed %}
|
||||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
<option value="{{ obj.url }}">{{ obj.name }}</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
@ -58,7 +57,7 @@
|
|||||||
<select id="model-based-prediction-setting-model" name="model-based-prediction-setting-model" class="form-control" data-width='100%'>
|
<select id="model-based-prediction-setting-model" name="model-based-prediction-setting-model" class="form-control" data-width='100%'>
|
||||||
<option disabled selected>Select the model</option>
|
<option disabled selected>Select the model</option>
|
||||||
{% for m in models %}
|
{% for m in models %}
|
||||||
<option value="{{ m.url }}">{{ m.name|safe }}</option>
|
<option value="{{ m.url }}">{{ m.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
<label for="model-based-prediction-setting-threshold">Threshold</label>
|
<label for="model-based-prediction-setting-threshold">Threshold</label>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<div class="modal fade bs-modal-lg" id="add_pathway_edge_modal" tabindex="-1" aria-labelledby="add_pathway_edge_modal"
|
<div class="modal fade bs-modal-lg" id="add_pathway_edge_modal" tabindex="-1" aria-labelledby="add_pathway_edge_modal"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
@ -37,7 +36,7 @@
|
|||||||
<select id="add_pathway_edge_substrates" name="edge-substrates"
|
<select id="add_pathway_edge_substrates" name="edge-substrates"
|
||||||
data-actions-box='true' class="form-control" multiple data-width='100%'>
|
data-actions-box='true' class="form-control" multiple data-width='100%'>
|
||||||
{% for n in pathway.nodes %}
|
{% for n in pathway.nodes %}
|
||||||
<option data-smiles="{{ n.default_node_label.smiles }}" value="{{ n.url }}">{{ n.default_node_label.name|safe }}</option>
|
<option data-smiles="{{ n.default_node_label.smiles }}" value="{{ n.url }}">{{ n.default_node_label.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@ -48,7 +47,7 @@
|
|||||||
<select id="add_pathway_edge_products" name="edge-products"
|
<select id="add_pathway_edge_products" name="edge-products"
|
||||||
data-actions-box='true' class="form-control" multiple data-width='100%'>
|
data-actions-box='true' class="form-control" multiple data-width='100%'>
|
||||||
{% for n in pathway.nodes %}
|
{% for n in pathway.nodes %}
|
||||||
<option data-smiles="{{ n.default_node_label.smiles }}" value="{{ n.url }}">{{ n.default_node_label.name|safe }}</option>
|
<option data-smiles="{{ n.default_node_label.smiles }}" value="{{ n.url }}">{{ n.default_node_label.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Delete Edge -->
|
<!-- Delete Edge -->
|
||||||
<div id="delete_pathway_edge_modal" class="modal" tabindex="-1">
|
<div id="delete_pathway_edge_modal" class="modal" tabindex="-1">
|
||||||
@ -20,7 +19,7 @@
|
|||||||
data-actions-box='true' class="form-control" data-width='100%'>
|
data-actions-box='true' class="form-control" data-width='100%'>
|
||||||
<option value="" disabled selected>Select Reaction to delete</option>
|
<option value="" disabled selected>Select Reaction to delete</option>
|
||||||
{% for e in pathway.edges %}
|
{% for e in pathway.edges %}
|
||||||
<option value="{{ e.url }}">{{ e.edge_label.name|safe }}</option>
|
<option value="{{ e.url }}">{{ e.edge_label.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
<input type="hidden" id="hidden" name="hidden" value="delete"/>
|
<input type="hidden" id="hidden" name="hidden" value="delete"/>
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
<!-- Delete Node -->
|
<!-- Delete Node -->
|
||||||
<div id="delete_pathway_node_modal" class="modal" tabindex="-1">
|
<div id="delete_pathway_node_modal" class="modal" tabindex="-1">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
@ -20,7 +19,7 @@
|
|||||||
data-actions-box='true' class="form-control" data-width='100%'>
|
data-actions-box='true' class="form-control" data-width='100%'>
|
||||||
<option value="" disabled selected>Select Compound to delete</option>
|
<option value="" disabled selected>Select Compound to delete</option>
|
||||||
{% for n in pathway.nodes %}
|
{% for n in pathway.nodes %}
|
||||||
<option value="{{ n.url }}">{{ n.default_node_label.name|safe }}</option>
|
<option value="{{ n.url }}">{{ n.default_node_label.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
<input type="hidden" id="hidden" name="hidden" value="delete"/>
|
<input type="hidden" id="hidden" name="hidden" value="delete"/>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Edit Compound -->
|
<!-- Edit Compound -->
|
||||||
<div id="edit_compound_modal" class="modal" tabindex="-1">
|
<div id="edit_compound_modal" class="modal" tabindex="-1">
|
||||||
@ -16,12 +15,12 @@
|
|||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<p>
|
<p>
|
||||||
<label for="compound-name">Name</label>
|
<label for="compound-name">Name</label>
|
||||||
<input id="compound-name" class="form-control" name="compound-name" value="{{ compound.name|safe}}">
|
<input id="compound-name" class="form-control" name="compound-name" value="{{ compound.name}}">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label for="compound-description">Description</label>
|
<label for="compound-description">Description</label>
|
||||||
<input id="compound-description" type="text" class="form-control"
|
<input id="compound-description" type="text" class="form-control"
|
||||||
value="{{ compound.description|safe }}"
|
value="{{ compound.description }}"
|
||||||
name="compound-description">
|
name="compound-description">
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Edit Compound -->
|
<!-- Edit Compound -->
|
||||||
<div id="edit_compound_structure_modal" class="modal" tabindex="-1">
|
<div id="edit_compound_structure_modal" class="modal" tabindex="-1">
|
||||||
@ -16,12 +15,12 @@
|
|||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<p>
|
<p>
|
||||||
<label for="compound-structure-name">Name</label>
|
<label for="compound-structure-name">Name</label>
|
||||||
<input id="compound-structure-name" class="form-control" name="compound-structure-name" value="{{ compound_structure.name|safe }}">
|
<input id="compound-structure-name" class="form-control" name="compound-structure-name" value="{{ compound_structure.name }}">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label for="compound-structure-description">Description</label>
|
<label for="compound-structure-description">Description</label>
|
||||||
<input id="compound-structure-description" type="text" class="form-control"
|
<input id="compound-structure-description" type="text" class="form-control"
|
||||||
value="{{ compound_structure.description|safe }}" name="compound-structure-description">
|
value="{{ compound_structure.description }}" name="compound-structure-description">
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Edit Package Permission -->
|
<!-- Edit Package Permission -->
|
||||||
<div id="edit_group_member_modal" class="modal" tabindex="-1">
|
<div id="edit_group_member_modal" class="modal" tabindex="-1">
|
||||||
@ -40,7 +39,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
<option disabled>Groups</option>
|
<option disabled>Groups</option>
|
||||||
{% for g in groups %}
|
{% for g in groups %}
|
||||||
<option value="{{ g.url }}">{{ g.name|safe }}</option>
|
<option value="{{ g.url }}">{{ g.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
<input type="hidden" name="action" value="add">
|
<input type="hidden" name="action" value="add">
|
||||||
@ -82,7 +81,7 @@
|
|||||||
accept-charset="UTF-8" action="" data-remote="true" method="post">
|
accept-charset="UTF-8" action="" data-remote="true" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="col-xs-8">
|
<div class="col-xs-8">
|
||||||
{{ g.name|safe }}
|
{{ g.name }}
|
||||||
<input type="hidden" name="member" value="{{ g.url }}"/>
|
<input type="hidden" name="member" value="{{ g.url }}"/>
|
||||||
<input type="hidden" name="action" value="remove">
|
<input type="hidden" name="action" value="remove">
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Edit Model -->
|
<!-- Edit Model -->
|
||||||
<div id="edit_model_modal" class="modal" tabindex="-1">
|
<div id="edit_model_modal" class="modal" tabindex="-1">
|
||||||
@ -17,12 +16,12 @@
|
|||||||
<p>
|
<p>
|
||||||
<label for="model-name">Name</label>
|
<label for="model-name">Name</label>
|
||||||
<input id="model-name" type="text" class="form-control" name="model-name"
|
<input id="model-name" type="text" class="form-control" name="model-name"
|
||||||
value="{{ model.name|safe }}">
|
value="{{ model.name }}">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label for="model-description">Description</label>
|
<label for="model-description">Description</label>
|
||||||
<input id="model-description" type="text" class="form-control" name="model-description"
|
<input id="model-description" type="text" class="form-control" name="model-description"
|
||||||
value="{{ model.description|safe }}">
|
value="{{ model.description }}">
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Edit Node -->
|
<!-- Edit Node -->
|
||||||
<div id="edit_node_modal" class="modal" tabindex="-1">
|
<div id="edit_node_modal" class="modal" tabindex="-1">
|
||||||
@ -16,12 +15,12 @@
|
|||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<p>
|
<p>
|
||||||
<label for="node-name">Name</label>
|
<label for="node-name">Name</label>
|
||||||
<input id="node-name" class="form-control" name="node-name" value="{{ node.name|safe}}">
|
<input id="node-name" class="form-control" name="node-name" value="{{ node.name}}">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label for="node-description">Description</label>
|
<label for="node-description">Description</label>
|
||||||
<input id="node-description" type="text" class="form-control"
|
<input id="node-description" type="text" class="form-control"
|
||||||
value="{{ node.description|safe }}"
|
value="{{ node.description }}"
|
||||||
name="node-description">
|
name="node-description">
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Edit Package -->
|
<!-- Edit Package -->
|
||||||
<div id="edit_package_modal" class="modal" tabindex="-1">
|
<div id="edit_package_modal" class="modal" tabindex="-1">
|
||||||
@ -16,12 +15,12 @@
|
|||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<p>
|
<p>
|
||||||
<label for="package-name">Name</label>
|
<label for="package-name">Name</label>
|
||||||
<input id="package-name" class="form-control" name="package-name" value="{{ package.name|safe}}">
|
<input id="package-name" class="form-control" name="package-name" value="{{ package.name}}">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label for="package-description">Description</label>
|
<label for="package-description">Description</label>
|
||||||
<input id="package-description" type="text" class="form-control"
|
<input id="package-description" type="text" class="form-control"
|
||||||
value="{{ package.description|safe }}"
|
value="{{ package.description }}"
|
||||||
name="package-description">
|
name="package-description">
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Edit Package Permission -->
|
<!-- Edit Package Permission -->
|
||||||
<div id="edit_package_permissions_modal" class="modal" tabindex="-1">
|
<div id="edit_package_permissions_modal" class="modal" tabindex="-1">
|
||||||
@ -47,7 +46,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
<option disabled>Groups</option>
|
<option disabled>Groups</option>
|
||||||
{% for g in groups %}
|
{% for g in groups %}
|
||||||
<option value="{{ g.url }}">{{ g.name|safe }}</option>
|
<option value="{{ g.url }}">{{ g.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@ -101,7 +100,7 @@
|
|||||||
accept-charset="UTF-8" action="" data-remote="true" method="post">
|
accept-charset="UTF-8" action="" data-remote="true" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="col-xs-4">
|
<div class="col-xs-4">
|
||||||
{{ gp.group.name|safe }}
|
{{ gp.group.name }}
|
||||||
<input type="hidden" name="grantee" value="{{ gp.group.url }}"/>
|
<input type="hidden" name="grantee" value="{{ gp.group.url }}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-2">
|
<div class="col-xs-2">
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Edit Pathway -->
|
<!-- Edit Pathway -->
|
||||||
<div id="edit_pathway_modal" class="modal" tabindex="-1">
|
<div id="edit_pathway_modal" class="modal" tabindex="-1">
|
||||||
@ -16,12 +15,12 @@
|
|||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<p>
|
<p>
|
||||||
<label for="pathway-name">Name</label>
|
<label for="pathway-name">Name</label>
|
||||||
<input id="pathway-name" class="form-control" name="pathway-name" value="{{ pathway.name|safe }}">
|
<input id="pathway-name" class="form-control" name="pathway-name" value="{{ pathway.name }}">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label for="pathway-description">Description</label>
|
<label for="pathway-description">Description</label>
|
||||||
<textarea id="pathway-description" type="text" class="form-control" name="pathway-description"
|
<textarea id="pathway-description" type="text" class="form-control" name="pathway-description"
|
||||||
rows="10">{{ pathway.description|safe }}</textarea>
|
rows="10">{{ pathway.description }}</textarea>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -32,7 +32,7 @@
|
|||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<select id="model" name="model" class="form-control" data-width='100%'>
|
<select id="model" name="model" class="form-control" data-width='100%'>
|
||||||
{% for m in models %}
|
{% for m in models %}
|
||||||
<option value="{{ m.id }}" {% if user.prediction_settings.model.url == m.url %}selected{% endif %}>{{ m.name|safe }}</option>
|
<option value="{{ m.id }}" {% if user.prediction_settings.model.url == m.url %}selected{% endif %}>{{ m.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Edit Reaction -->
|
<!-- Edit Reaction -->
|
||||||
<div id="edit_reaction_modal" class="modal" tabindex="-1">
|
<div id="edit_reaction_modal" class="modal" tabindex="-1">
|
||||||
@ -15,12 +14,12 @@
|
|||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<p>
|
<p>
|
||||||
<label for="reaction-name">Name</label>
|
<label for="reaction-name">Name</label>
|
||||||
<input id="reaction-name" class="form-control" name="reaction-name" value="{{ reaction.name|safe }}">
|
<input id="reaction-name" class="form-control" name="reaction-name" value="{{ reaction.name }}">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label for="reaction-description">Description</label>
|
<label for="reaction-description">Description</label>
|
||||||
<input id="reaction-description" type="text" class="form-control"
|
<input id="reaction-description" type="text" class="form-control"
|
||||||
value="{{ reaction.description|safe }}" name="reaction-description">
|
value="{{ reaction.description }}" name="reaction-description">
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Edit Rule -->
|
<!-- Edit Rule -->
|
||||||
<div id="edit_rule_modal" class="modal" tabindex="-1">
|
<div id="edit_rule_modal" class="modal" tabindex="-1">
|
||||||
@ -15,12 +14,12 @@
|
|||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<p>
|
<p>
|
||||||
<label for="rule-name">Name</label>
|
<label for="rule-name">Name</label>
|
||||||
<input id="rule-name" class="form-control" name="rule-name" value="{{ rule.name|safe }}">
|
<input id="rule-name" class="form-control" name="rule-name" value="{{ rule.name }}">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label for="rule-description">Description</label>
|
<label for="rule-description">Description</label>
|
||||||
<input id="rule-description" type="text" class="form-control"
|
<input id="rule-description" type="text" class="form-control"
|
||||||
value="{{ rule.description|safe }}" name="rule-description">
|
value="{{ rule.description }}" name="rule-description">
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Edit User -->
|
<!-- Edit User -->
|
||||||
<div id="edit_user_modal" class="modal" tabindex="-1">
|
<div id="edit_user_modal" class="modal" tabindex="-1">
|
||||||
@ -19,7 +18,7 @@
|
|||||||
<select id="default-package" name="default-package" class="form-control" data-width='100%'>
|
<select id="default-package" name="default-package" class="form-control" data-width='100%'>
|
||||||
<option disabled>Select a Package</option>
|
<option disabled>Select a Package</option>
|
||||||
{% for p in meta.writeable_packages %}
|
{% for p in meta.writeable_packages %}
|
||||||
<option value="{{ p.url }}" {% if p.id == meta.user.default_package.id %}selected{% endif %}>{{ p.name|safe }}</option>
|
<option value="{{ p.url }}" {% if p.id == meta.user.default_package.id %}selected{% endif %}>{{ p.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</p>
|
</p>
|
||||||
@ -28,7 +27,7 @@
|
|||||||
<select id="default-group" name="default-group" class="form-control" data-width='100%'>
|
<select id="default-group" name="default-group" class="form-control" data-width='100%'>
|
||||||
<option disabled>Select a Group</option>
|
<option disabled>Select a Group</option>
|
||||||
{% for g in meta.available_groups %}
|
{% for g in meta.available_groups %}
|
||||||
<option value="{{ g.url }}" {% if g.id == meta.user.default_group.id %}selected{% endif %}>{{ g.name|safe }}</option>
|
<option value="{{ g.url }}" {% if g.id == meta.user.default_group.id %}selected{% endif %}>{{ g.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</p>
|
</p>
|
||||||
@ -37,7 +36,7 @@
|
|||||||
<select id="default-prediction-setting" name="default-prediction-setting" class="form-control" data-width='100%'>
|
<select id="default-prediction-setting" name="default-prediction-setting" class="form-control" data-width='100%'>
|
||||||
<option disabled>Select a Setting</option>
|
<option disabled>Select a Setting</option>
|
||||||
{% for s in meta.available_settings %}
|
{% for s in meta.available_settings %}
|
||||||
<option value="{{ s.url }}" {% if s.id == meta.user.default_setting.id %}selected{% endif %}>{{ s.name|safe }}</option>
|
<option value="{{ s.url }}" {% if s.id == meta.user.default_setting.id %}selected{% endif %}>{{ s.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
<div class="modal fade" tabindex="-1" id="evaluate_model_modal" role="dialog" aria-labelledby="evaluate_model_modal"
|
<div class="modal fade" tabindex="-1" id="evaluate_model_modal" role="dialog" aria-labelledby="evaluate_model_modal"
|
||||||
aria-hidden="true">
|
aria-hidden="true">
|
||||||
<div class="modal-dialog modal-lg">
|
<div class="modal-dialog modal-lg">
|
||||||
@ -25,14 +24,14 @@
|
|||||||
<option disabled>Reviewed Packages</option>
|
<option disabled>Reviewed Packages</option>
|
||||||
{% for obj in meta.readable_packages %}
|
{% for obj in meta.readable_packages %}
|
||||||
{% if obj.reviewed %}
|
{% if obj.reviewed %}
|
||||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
<option value="{{ obj.url }}">{{ obj.name }}</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<option disabled>Unreviewed Packages</option>
|
<option disabled>Unreviewed Packages</option>
|
||||||
{% for obj in meta.readable_packages %}
|
{% for obj in meta.readable_packages %}
|
||||||
{% if not obj.reviewed %}
|
{% if not obj.reviewed %}
|
||||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
<option value="{{ obj.url }}">{{ obj.name }}</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Copy Object -->
|
<!-- Copy Object -->
|
||||||
<div id="generic_copy_object_modal" class="modal" tabindex="-1">
|
<div id="generic_copy_object_modal" class="modal" tabindex="-1">
|
||||||
@ -19,7 +18,7 @@
|
|||||||
data-width='100%'>
|
data-width='100%'>
|
||||||
<option disabled selected>Select Target Package</option>
|
<option disabled selected>Select Target Package</option>
|
||||||
{% for p in meta.writeable_packages %}
|
{% for p in meta.writeable_packages %}
|
||||||
<option value="{{ p.url }}">{{ p.name|safe }}</option>`
|
<option value="{{ p.url }}">{{ p.name }}</option>`
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
<input type="hidden" name="hidden" value="copy">
|
<input type="hidden" name="hidden" value="copy">
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@ -56,7 +55,7 @@
|
|||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
<h4 class="modal-title">Set Aliases for {{ current_object.name|safe }}</h4>
|
<h4 class="modal-title">Set Aliases for {{ current_object.name }}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form id="set_aliases_modal_form" accept-charset="UTF-8" action="{{ current_object.url }}"
|
<form id="set_aliases_modal_form" accept-charset="UTF-8" action="{{ current_object.url }}"
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<!-- Delete Object -->
|
<!-- Delete Object -->
|
||||||
<div id="generic_set_external_reference_modal" class="modal" tabindex="-1">
|
<div id="generic_set_external_reference_modal" class="modal" tabindex="-1">
|
||||||
@ -24,7 +23,7 @@
|
|||||||
{% if entity == object_type %}
|
{% if entity == object_type %}
|
||||||
{% for db in databases %}
|
{% for db in databases %}
|
||||||
<option id="db-select-{{ db.database.pk }}" data-input-placeholder="{{ db.placeholder }}"
|
<option id="db-select-{{ db.database.pk }}" data-input-placeholder="{{ db.placeholder }}"
|
||||||
value="{{ db.database.id }}">{{ db.database.name|safe }}</option>`
|
value="{{ db.database.id }}">{{ db.database.name }}</option>`
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<div class="modal fade bs-modal-lg" id="set_scenario_modal" tabindex="-1" aria-labelledby="set_scenario_modal"
|
<div class="modal fade bs-modal-lg" id="set_scenario_modal" tabindex="-1" aria-labelledby="set_scenario_modal"
|
||||||
aria-modal="true" role="dialog">
|
aria-modal="true" role="dialog">
|
||||||
@ -8,7 +7,7 @@
|
|||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
<h4 class="modal-title">Set Scenarios for {{ current_object.name|safe }}</h4>
|
<h4 class="modal-title">Set Scenarios for {{ current_object.name }}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div id="loading_scenario_div" class="text-center"></div>
|
<div id="loading_scenario_div" class="text-center"></div>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
<div class="modal fade"
|
<div class="modal fade"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
id="manage_api_token_modal"
|
id="manage_api_token_modal"
|
||||||
@ -42,7 +41,7 @@
|
|||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="hidden" name="hidden" value="delete">
|
<input type="hidden" name="hidden" value="delete">
|
||||||
<input type="hidden" name="token-id" value="{{ t.pk }}">
|
<input type="hidden" name="token-id" value="{{ t.pk }}">
|
||||||
<input type="text" class="form-control" value="{{ t.name|safe }}" disabled>
|
<input type="text" class="form-control" value="{{ t.name }}" disabled>
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<button type="submit" class="btn btn-danger">Delete</button>
|
<button type="submit" class="btn btn-danger">Delete</button>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -56,7 +56,7 @@
|
|||||||
<option disabled>Select a Setting</option>
|
<option disabled>Select a Setting</option>
|
||||||
{% for s in meta.available_settings %}
|
{% for s in meta.available_settings %}
|
||||||
<option value="{{ s.url }}"{% if s.id == meta.user.default_setting.id %}selected{% endif %}>
|
<option value="{{ s.url }}"{% if s.id == meta.user.default_setting.id %}selected{% endif %}>
|
||||||
{{ s.name|safe }}{% if s.id == meta.user.default_setting.id %} <i>(User default)</i>{% endif %}
|
{{ s.name }}{% if s.id == meta.user.default_setting.id %} <i>(User default)</i>{% endif %}
|
||||||
</option>
|
</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
<div class="panel-group" id="rule-detail">
|
<div class="panel-group" id="rule-detail">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
||||||
{{ rule.name|safe }}
|
{{ rule.name }}
|
||||||
<div id="actionsButton"
|
<div id="actionsButton"
|
||||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||||
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
||||||
@ -60,7 +60,7 @@
|
|||||||
<div id="rule-reaction-patterns" class="panel-collapse collapse in">
|
<div id="rule-reaction-patterns" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for r in rule.srs %}
|
{% for r in rule.srs %}
|
||||||
<a class="list-group-item" href="{{ r.url }}">{{ r.name|safe }}</a>
|
<a class="list-group-item" href="{{ r.url }}">{{ r.name }}</a>
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<p>
|
<p>
|
||||||
{{r.as_svg|safe}}
|
{{r.as_svg|safe}}
|
||||||
@ -81,7 +81,7 @@
|
|||||||
<div id="rule-scenario" class="panel-collapse collapse in">
|
<div id="rule-scenario" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for s in rule.scenarios.all %}
|
{% for s in rule.scenarios.all %}
|
||||||
<a class="list-group-item" href="{{ s.url }}">{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a>
|
<a class="list-group-item" href="{{ s.url }}">{{ s.name }} <i>({{ s.package.name }})</i></a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
<div class="panel-group" id="compound-detail">
|
<div class="panel-group" id="compound-detail">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
||||||
{{ compound.name|safe }}
|
{{ compound.name }}
|
||||||
<div id="actionsButton"
|
<div id="actionsButton"
|
||||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||||
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
||||||
@ -64,7 +64,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="compound-desc" class="panel-collapse collapse in">
|
<div id="compound-desc" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{{ compound.description|safe }}
|
{{ compound.description }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -133,7 +133,7 @@
|
|||||||
<div id="compound-reaction" class="panel-collapse collapse in">
|
<div id="compound-reaction" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for r in compound.related_reactions %}
|
{% for r in compound.related_reactions %}
|
||||||
<a class="list-group-item" href="{{ r.url }}">{{ r.name|safe }} <i>({{ r.package.name|safe }})</i></a>
|
<a class="list-group-item" href="{{ r.url }}">{{ r.name }} <i>({{ r.package.name }})</i></a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -150,7 +150,7 @@
|
|||||||
<div id="compound-pathway" class="panel-collapse collapse in">
|
<div id="compound-pathway" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for r in compound.related_pathways %}
|
{% for r in compound.related_pathways %}
|
||||||
<a class="list-group-item" href="{{ r.url }}">{{ r.name|safe }} <i>({{ r.package.name|safe }})</i></a>
|
<a class="list-group-item" href="{{ r.url }}">{{ r.name }} <i>({{ r.package.name }})</i></a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -167,7 +167,7 @@
|
|||||||
<div id="compound-scenario" class="panel-collapse collapse in">
|
<div id="compound-scenario" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for s in compound.scenarios.all %}
|
{% for s in compound.scenarios.all %}
|
||||||
<a class="list-group-item" href="{{ s.url }}">{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a>
|
<a class="list-group-item" href="{{ s.url }}">{{ s.name }} <i>({{ s.package.name }})</i></a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
<div class="panel-group" id="compound-structure-detail">
|
<div class="panel-group" id="compound-structure-detail">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
||||||
{{ compound_structure.name|safe }}
|
{{ compound_structure.name }}
|
||||||
<div id="actionsButton"
|
<div id="actionsButton"
|
||||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||||
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
||||||
@ -28,7 +28,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<p> {{ compound_structure.description|safe }} </p>
|
<p> {{ compound_structure.description }} </p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Image -->
|
<!-- Image -->
|
||||||
@ -86,7 +86,7 @@
|
|||||||
<div id="compound-structure-scenario" class="panel-collapse collapse in">
|
<div id="compound-structure-scenario" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for s in compound_structure.scenarios.all %}
|
{% for s in compound_structure.scenarios.all %}
|
||||||
<a class="list-group-item" href="{{ s.url }}">{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a>
|
<a class="list-group-item" href="{{ s.url }}">{{ s.name }} <i>({{ s.package.name }})</i></a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
<div class="panel-group" id="edge-detail">
|
<div class="panel-group" id="edge-detail">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
||||||
{{ edge.edge_label.name|safe }}
|
{{ edge.edge_label.name }}
|
||||||
<div id="actionsButton"
|
<div id="actionsButton"
|
||||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||||
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
||||||
@ -36,7 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="edge-desc" class="panel-collapse collapse in">
|
<div id="edge-desc" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{{ edge.description|safe }}
|
{{ edge.description }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -82,12 +82,12 @@
|
|||||||
<div id="edge-description-smiles" class="panel-collapse collapse in">
|
<div id="edge-description-smiles" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for educt in edge.start_nodes.all %}
|
{% for educt in edge.start_nodes.all %}
|
||||||
<a class="btn btn-default" href="{{ educt.url }}">{{ educt.name|safe }}</a>
|
<a class="btn btn-default" href="{{ educt.url }}">{{ educt.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<span class="glyphicon glyphicon-arrow-right" style="margin-left:5em;margin-right:5em;"
|
<span class="glyphicon glyphicon-arrow-right" style="margin-left:5em;margin-right:5em;"
|
||||||
aria-hidden="true"></span>
|
aria-hidden="true"></span>
|
||||||
{% for product in edge.end_nodes.all %}
|
{% for product in edge.end_nodes.all %}
|
||||||
<a class="btn btn-default" href="{{ product.url }}">{{ product.name|safe }}</a>
|
<a class="btn btn-default" href="{{ product.url }}">{{ product.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -116,7 +116,7 @@
|
|||||||
<div id="edge-rules" class="panel-collapse collapse in">
|
<div id="edge-rules" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for r in edge.edge_label.rules.all %}
|
{% for r in edge.edge_label.rules.all %}
|
||||||
<a class="list-group-item" href="{{ r.url }}">{{ r.name|safe }}</a>
|
<a class="list-group-item" href="{{ r.url }}">{{ r.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -132,7 +132,7 @@
|
|||||||
<div id="edge-scenario" class="panel-collapse collapse in">
|
<div id="edge-scenario" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for s in edge.scenarios.all %}
|
{% for s in edge.scenarios.all %}
|
||||||
<a class="list-group-item" href="{{ s.url }}">{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a>
|
<a class="list-group-item" href="{{ s.url }}">{{ s.name }} <i>({{ s.package.name }})</i></a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
<div class="panel-group" id="package-detail">
|
<div class="panel-group" id="package-detail">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
||||||
{{ group.name|safe }}
|
{{ group.name }}
|
||||||
<div id="actionsButton"
|
<div id="actionsButton"
|
||||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||||
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
||||||
@ -26,7 +26,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<p> {{ group.description|safe }} </p>
|
<p> {{ group.description }} </p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -39,10 +39,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
{% for um in group.user_member.all %}
|
{% for um in group.user_member.all %}
|
||||||
<a class="list-group-item" href="{{ um.url }}">{{ um.username|safe }}</a>
|
<a class="list-group-item" href="{{ um.url }}">{{ um.username }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% for gm in group.group_member.all %}
|
{% for gm in group.group_member.all %}
|
||||||
<a class="list-group-item" href="{{ gm.url }}">{{ gm.name|safe }}</a>
|
<a class="list-group-item" href="{{ gm.url }}">{{ gm.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -56,7 +56,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
{% for p in packages %}
|
{% for p in packages %}
|
||||||
<a class="list-group-item" href="{{ p.url }}">{{ p.name|safe }}</a>
|
<a class="list-group-item" href="{{ p.url }}">{{ p.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
{% extends "framework.html" %}
|
{% extends "framework.html" %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load envipytags %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
{% block action_modals %}
|
{% block action_modals %}
|
||||||
@ -17,7 +18,7 @@
|
|||||||
<div class="panel-group" id="model-detail">
|
<div class="panel-group" id="model-detail">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
||||||
{{ model.name|safe }}
|
{{ model.name }}
|
||||||
<div id="actionsButton"
|
<div id="actionsButton"
|
||||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||||
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
||||||
@ -32,7 +33,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<p> {{ model.description|safe }} </p>
|
<p> {{ model.description }} </p>
|
||||||
</div>
|
</div>
|
||||||
{% if model|classname == 'MLRelativeReasoning' or model|classname == 'RuleBasedRelativeReasoning'%}
|
{% if model|classname == 'MLRelativeReasoning' or model|classname == 'RuleBasedRelativeReasoning'%}
|
||||||
<!-- Rule Packages -->
|
<!-- Rule Packages -->
|
||||||
@ -45,7 +46,7 @@
|
|||||||
<div id="rule-package" class="panel-collapse collapse in">
|
<div id="rule-package" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for p in model.rule_packages.all %}
|
{% for p in model.rule_packages.all %}
|
||||||
<a class="list-group-item" href="{{ p.url }}">{{ p.name|safe }}</a>
|
<a class="list-group-item" href="{{ p.url }}">{{ p.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -59,7 +60,7 @@
|
|||||||
<div id="reaction-package" class="panel-collapse collapse in">
|
<div id="reaction-package" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for p in model.data_packages.all %}
|
{% for p in model.data_packages.all %}
|
||||||
<a class="list-group-item" href="{{ p.url }}">{{ p.name|safe }}</a>
|
<a class="list-group-item" href="{{ p.url }}">{{ p.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -74,7 +75,7 @@
|
|||||||
<div id="eval-package" class="panel-collapse collapse in">
|
<div id="eval-package" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for p in model.eval_packages.all %}
|
{% for p in model.eval_packages.all %}
|
||||||
<a class="list-group-item" href="{{ p.url }}">{{ p.name|safe }}</a>
|
<a class="list-group-item" href="{{ p.url }}">{{ p.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
<div class="panel-group" id="node-detail">
|
<div class="panel-group" id="node-detail">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
||||||
{{ node.name|safe }}
|
{{ node.name }}
|
||||||
<div id="actionsButton"
|
<div id="actionsButton"
|
||||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||||
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
||||||
@ -39,7 +39,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="node-desc" class="panel-collapse collapse in">
|
<div id="node-desc" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{{ node.description|safe }}
|
{{ node.description }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -98,7 +98,7 @@
|
|||||||
<div id="node-scenario" class="panel-collapse collapse in">
|
<div id="node-scenario" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for s in node.scenarios.all %}
|
{% for s in node.scenarios.all %}
|
||||||
<a class="list-group-item" href="{{ s.url }}">{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a>
|
<a class="list-group-item" href="{{ s.url }}">{{ s.name }} <i>({{ s.package.name }})</i></a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
<div class="panel-group" id="package-detail">
|
<div class="panel-group" id="package-detail">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
||||||
{{ package.name|safe }}
|
{{ package.name }}
|
||||||
<div id="actionsButton"
|
<div id="actionsButton"
|
||||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||||
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
||||||
|
|||||||
@ -98,7 +98,7 @@
|
|||||||
<div class="panel-group" id="pwAccordion">
|
<div class="panel-group" id="pwAccordion">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
||||||
{{ pathway.name|safe }}
|
{{ pathway.name }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default panel-heading list-group-item" style="background-color:silver">
|
<div class="panel panel-default panel-heading list-group-item" style="background-color:silver">
|
||||||
@ -236,7 +236,7 @@
|
|||||||
<div id="pathway-scenario" class="panel-collapse collapse in">
|
<div id="pathway-scenario" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for s in pathway.scenarios.all %}
|
{% for s in pathway.scenarios.all %}
|
||||||
<a class="list-group-item" href="{{ s.url }}">{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a>
|
<a class="list-group-item" href="{{ s.url }}">{{ s.name }} <i>({{ s.package.name }})</i></a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -266,7 +266,7 @@
|
|||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<a href="{{ pathway.setting.model.url }}">
|
<a href="{{ pathway.setting.model.url }}">
|
||||||
{{ pathway.setting.model.name|safe }}
|
{{ pathway.setting.model.name }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</td>
|
</td>
|
||||||
@ -299,7 +299,7 @@
|
|||||||
{% for p in pathway.setting.rule_packages.all %}
|
{% for p in pathway.setting.rule_packages.all %}
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<a href="{{ p.url }}">
|
<a href="{{ p.url }}">
|
||||||
{{ p.name|safe }}
|
{{ p.name }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
<div class="panel-group" id="reaction-detail">
|
<div class="panel-group" id="reaction-detail">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
||||||
{{ reaction.name|safe }}
|
{{ reaction.name }}
|
||||||
<div id="actionsButton"
|
<div id="actionsButton"
|
||||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||||
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
||||||
@ -38,7 +38,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="reaction-desc" class="panel-collapse collapse in">
|
<div id="reaction-desc" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{{ reaction.description|safe }}
|
{{ reaction.description }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -84,12 +84,12 @@
|
|||||||
<div id="reaction-description-smiles" class="panel-collapse collapse in">
|
<div id="reaction-description-smiles" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for educt in reaction.educts.all %}
|
{% for educt in reaction.educts.all %}
|
||||||
<a class="btn btn-default" href="{{ educt.url }}">{{ educt.name|safe }}</a>
|
<a class="btn btn-default" href="{{ educt.url }}">{{ educt.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<span class="glyphicon glyphicon-arrow-right" style="margin-left:5em;margin-right:5em;"
|
<span class="glyphicon glyphicon-arrow-right" style="margin-left:5em;margin-right:5em;"
|
||||||
aria-hidden="true"></span>
|
aria-hidden="true"></span>
|
||||||
{% for product in reaction.products.all %}
|
{% for product in reaction.products.all %}
|
||||||
<a class="btn btn-default" href="{{ product.url }}">{{ product.name|safe }}</a>
|
<a class="btn btn-default" href="{{ product.url }}">{{ product.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -118,7 +118,7 @@
|
|||||||
<div id="reaction-rules" class="panel-collapse collapse in">
|
<div id="reaction-rules" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for r in reaction.rules.all %}
|
{% for r in reaction.rules.all %}
|
||||||
<a class="list-group-item" href="{{ r.url }}">{{ r.name|safe }}</a>
|
<a class="list-group-item" href="{{ r.url }}">{{ r.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -152,7 +152,7 @@
|
|||||||
<div id="reaction-pathway" class="panel-collapse collapse in">
|
<div id="reaction-pathway" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for r in reaction.related_pathways %}
|
{% for r in reaction.related_pathways %}
|
||||||
<a class="list-group-item" href="{{ r.url }}">{{ r.name|safe }}</a>
|
<a class="list-group-item" href="{{ r.url }}">{{ r.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -168,7 +168,7 @@
|
|||||||
<div id="reaction-scenario" class="panel-collapse collapse in">
|
<div id="reaction-scenario" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for s in reaction.scenarios.all %}
|
{% for s in reaction.scenarios.all %}
|
||||||
<a class="list-group-item" href="{{ s.url }}">{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a>
|
<a class="list-group-item" href="{{ s.url }}">{{ s.name }} <i>({{ s.package.name }})</i></a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
<div class="panel-group" id="scenario-detail">
|
<div class="panel-group" id="scenario-detail">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
||||||
{{ scenario.name|safe }}
|
{{ scenario.name }}
|
||||||
<div id="actionsButton"
|
<div id="actionsButton"
|
||||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||||
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
||||||
@ -30,7 +30,7 @@
|
|||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">Description</div>
|
<div class="panel-heading">Description</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
{{ scenario.description|safe }}
|
{{ scenario.description }}
|
||||||
<br>
|
<br>
|
||||||
{{ scenario.scenario_type }}
|
{{ scenario.scenario_type }}
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
<div class="panel-group" id="rule-detail">
|
<div class="panel-group" id="rule-detail">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
<div class="panel-heading" id="headingPanel" style="font-size:2rem;height: 46px">
|
||||||
{{ rule.name|safe }}
|
{{ rule.name }}
|
||||||
<div id="actionsButton"
|
<div id="actionsButton"
|
||||||
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
style="float: right;font-weight: normal;font-size: medium;position: relative; top: 50%; transform: translateY(-50%);z-index:100;display: none;"
|
||||||
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
|
||||||
@ -29,7 +29,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<p>
|
<p>
|
||||||
{{ rule.description|safe }}
|
{{ rule.description }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -145,7 +145,7 @@
|
|||||||
<div id="rule-composite-rule" class="panel-collapse collapse in">
|
<div id="rule-composite-rule" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for cr in rule.parallelrule_set.all %}
|
{% for cr in rule.parallelrule_set.all %}
|
||||||
<a class="list-group-item" href="{{ cr.url }}">{{ cr.name|safe }}</a>
|
<a class="list-group-item" href="{{ cr.url }}">{{ cr.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -162,7 +162,7 @@
|
|||||||
<div id="rule-scenario" class="panel-collapse collapse in">
|
<div id="rule-scenario" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for s in rule.scenarios.all %}
|
{% for s in rule.scenarios.all %}
|
||||||
<a class="list-group-item" href="{{ s.url }}">{{ s.name|safe }}</a>
|
<a class="list-group-item" href="{{ s.url }}">{{ s.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -179,7 +179,7 @@
|
|||||||
<div id="rule-reaction" class="panel-collapse collapse">
|
<div id="rule-reaction" class="panel-collapse collapse">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for r in rule.related_reactions %}
|
{% for r in rule.related_reactions %}
|
||||||
<a class="list-group-item" href="{{ r.url }}">{{ r.name|safe }}</a>
|
<a class="list-group-item" href="{{ r.url }}">{{ r.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -196,7 +196,7 @@
|
|||||||
<div id="rule-pathway" class="panel-collapse collapse">
|
<div id="rule-pathway" class="panel-collapse collapse">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for r in rule.related_pathways %}
|
{% for r in rule.related_pathways %}
|
||||||
<a class="list-group-item" href="{{ r.url }}">{{ r.name|safe }}</a>
|
<a class="list-group-item" href="{{ r.url }}">{{ r.name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -41,7 +41,7 @@
|
|||||||
<div id="default-package" class="panel-collapse collapse in">
|
<div id="default-package" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<a href="{{ user.default_package.url }}"> {{ user.default_package.name|safe }}</a>
|
<a href="{{ user.default_package.url }}"> {{ user.default_package.name }}</a>
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -58,7 +58,7 @@
|
|||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
{% for g in meta.available_groups %}
|
{% for g in meta.available_groups %}
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<a href="{{ g.url }}"> {{ g.name|safe }}</a>
|
<a href="{{ g.url }}"> {{ g.name }}</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
@ -90,7 +90,7 @@
|
|||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<a href="{{user.default_setting.model.url}}">
|
<a href="{{user.default_setting.model.url}}">
|
||||||
{{ user.default_setting.model.name|safe }}
|
{{ user.default_setting.model.name }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</td>
|
</td>
|
||||||
@ -123,7 +123,7 @@
|
|||||||
{% for p in user.default_setting.rule_packages.all %}
|
{% for p in user.default_setting.rule_packages.all %}
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<a href="{{p.url}}">
|
<a href="{{p.url}}">
|
||||||
{{ p.name|safe }}
|
{{ p.name }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p></p>
|
<p></p>
|
||||||
{{ pathway.name|safe }}
|
{{ pathway.name }}
|
||||||
<div id="viz">
|
<div id="viz">
|
||||||
<svg width="2000" height="2000"> <!-- Sehr großes SVG für Zoom -->
|
<svg width="2000" height="2000"> <!-- Sehr großes SVG für Zoom -->
|
||||||
<defs>
|
<defs>
|
||||||
|
|||||||
@ -11,13 +11,13 @@
|
|||||||
<option disabled>Reviewed Packages</option>
|
<option disabled>Reviewed Packages</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% for obj in reviewed_objects %}
|
{% for obj in reviewed_objects %}
|
||||||
<option value="{{ obj.url }}" selected>{{ obj.name|safe }}</option>
|
<option value="{{ obj.url }}" selected>{{ obj.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if unreviewed_objects %}
|
{% if unreviewed_objects %}
|
||||||
<option disabled>Unreviewed Packages</option>
|
<option disabled>Unreviewed Packages</option>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% for obj in unreviewed_objects %}
|
{% for obj in unreviewed_objects %}
|
||||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
<option value="{{ obj.url }}">{{ obj.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -29,7 +29,7 @@ class RuleTest(TestCase):
|
|||||||
self.assertEqual(r.name, "bt0022-2833")
|
self.assertEqual(r.name, "bt0022-2833")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
r.description,
|
r.description,
|
||||||
"Dihalomethyl derivative + Halomethyl derivative > 1-Halo-1-methylalcohol derivative + 1-Methylalcohol derivative",
|
"Dihalomethyl derivative + Halomethyl derivative > 1-Halo-1-methylalcohol derivative + 1-Methylalcohol derivative",
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_smirks_are_trimmed(self):
|
def test_smirks_are_trimmed(self):
|
||||||
|
|||||||
@ -255,30 +255,6 @@ class FormatConverter(object):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def is_valid_smarts(smarts: str) -> bool:
|
|
||||||
"""
|
|
||||||
Checks whether a given string is a valid SMARTS pattern.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
smarts : str
|
|
||||||
The SMARTS string to validate.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
bool
|
|
||||||
True if the SMARTS string is valid, False otherwise.
|
|
||||||
"""
|
|
||||||
if not isinstance(smarts, str) or not smarts.strip():
|
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
|
||||||
mol = Chem.MolFromSmarts(smarts)
|
|
||||||
return mol is not None
|
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def apply(
|
def apply(
|
||||||
smiles: str,
|
smiles: str,
|
||||||
|
|||||||
41
uv.lock
generated
41
uv.lock
generated
@ -571,7 +571,6 @@ dependencies = [
|
|||||||
{ name = "epam-indigo" },
|
{ name = "epam-indigo" },
|
||||||
{ name = "gunicorn" },
|
{ name = "gunicorn" },
|
||||||
{ name = "networkx" },
|
{ name = "networkx" },
|
||||||
{ name = "nh3" },
|
|
||||||
{ name = "polars" },
|
{ name = "polars" },
|
||||||
{ name = "psycopg2-binary" },
|
{ name = "psycopg2-binary" },
|
||||||
{ name = "python-dotenv" },
|
{ name = "python-dotenv" },
|
||||||
@ -614,7 +613,6 @@ requires-dist = [
|
|||||||
{ name = "gunicorn", specifier = ">=23.0.0" },
|
{ name = "gunicorn", specifier = ">=23.0.0" },
|
||||||
{ name = "msal", marker = "extra == 'ms-login'", specifier = ">=1.33.0" },
|
{ name = "msal", marker = "extra == 'ms-login'", specifier = ">=1.33.0" },
|
||||||
{ name = "networkx", specifier = ">=3.4.2" },
|
{ name = "networkx", specifier = ">=3.4.2" },
|
||||||
{ name = "nh3", specifier = "==0.3.2" },
|
|
||||||
{ name = "poethepoet", marker = "extra == 'dev'", specifier = ">=0.37.0" },
|
{ name = "poethepoet", marker = "extra == 'dev'", specifier = ">=0.37.0" },
|
||||||
{ name = "polars", specifier = "==1.35.1" },
|
{ name = "polars", specifier = "==1.35.1" },
|
||||||
{ name = "pre-commit", marker = "extra == 'dev'", specifier = ">=4.3.0" },
|
{ name = "pre-commit", marker = "extra == 'dev'", specifier = ">=4.3.0" },
|
||||||
@ -1149,39 +1147,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/eb/8d/776adee7bbf76365fdd7f2552710282c79a4ead5d2a46408c9043a2b70ba/networkx-3.5-py3-none-any.whl", hash = "sha256:0030d386a9a06dee3565298b4a734b68589749a544acbb6c412dc9e2489ec6ec", size = 2034406, upload-time = "2025-05-29T11:35:04.961Z" },
|
{ url = "https://files.pythonhosted.org/packages/eb/8d/776adee7bbf76365fdd7f2552710282c79a4ead5d2a46408c9043a2b70ba/networkx-3.5-py3-none-any.whl", hash = "sha256:0030d386a9a06dee3565298b4a734b68589749a544acbb6c412dc9e2489ec6ec", size = 2034406, upload-time = "2025-05-29T11:35:04.961Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nh3"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/ca/a5/34c26015d3a434409f4d2a1cd8821a06c05238703f49283ffeb937bef093/nh3-0.3.2.tar.gz", hash = "sha256:f394759a06df8b685a4ebfb1874fb67a9cbfd58c64fc5ed587a663c0e63ec376", size = 19288, upload-time = "2025-10-30T11:17:45.948Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/5b/01/a1eda067c0ba823e5e2bb033864ae4854549e49fb6f3407d2da949106bfb/nh3-0.3.2-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:d18957a90806d943d141cc5e4a0fefa1d77cf0d7a156878bf9a66eed52c9cc7d", size = 1419839, upload-time = "2025-10-30T11:17:09.956Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/30/57/07826ff65d59e7e9cc789ef1dc405f660cabd7458a1864ab58aefa17411b/nh3-0.3.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45c953e57028c31d473d6b648552d9cab1efe20a42ad139d78e11d8f42a36130", size = 791183, upload-time = "2025-10-30T11:17:11.99Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/af/2f/e8a86f861ad83f3bb5455f596d5c802e34fcdb8c53a489083a70fd301333/nh3-0.3.2-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c9850041b77a9147d6bbd6dbbf13eeec7009eb60b44e83f07fcb2910075bf9b", size = 829127, upload-time = "2025-10-30T11:17:13.192Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d8/97/77aef4daf0479754e8e90c7f8f48f3b7b8725a3b8c0df45f2258017a6895/nh3-0.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:403c11563e50b915d0efdb622866d1d9e4506bce590ef7da57789bf71dd148b5", size = 997131, upload-time = "2025-10-30T11:17:14.677Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/41/ee/fd8140e4df9d52143e89951dd0d797f5546004c6043285289fbbe3112293/nh3-0.3.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:0dca4365db62b2d71ff1620ee4f800c4729849906c5dd504ee1a7b2389558e31", size = 1068783, upload-time = "2025-10-30T11:17:15.861Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/87/64/bdd9631779e2d588b08391f7555828f352e7f6427889daf2fa424bfc90c9/nh3-0.3.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0fe7ee035dd7b2290715baf29cb27167dddd2ff70ea7d052c958dbd80d323c99", size = 994732, upload-time = "2025-10-30T11:17:17.155Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/79/66/90190033654f1f28ca98e3d76b8be1194505583f9426b0dcde782a3970a2/nh3-0.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a40202fd58e49129764f025bbaae77028e420f1d5b3c8e6f6fd3a6490d513868", size = 975997, upload-time = "2025-10-30T11:17:18.77Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/34/30/ebf8e2e8d71fdb5a5d5d8836207177aed1682df819cbde7f42f16898946c/nh3-0.3.2-cp314-cp314t-win32.whl", hash = "sha256:1f9ba555a797dbdcd844b89523f29cdc90973d8bd2e836ea6b962cf567cadd93", size = 583364, upload-time = "2025-10-30T11:17:20.286Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/94/ae/95c52b5a75da429f11ca8902c2128f64daafdc77758d370e4cc310ecda55/nh3-0.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:dce4248edc427c9b79261f3e6e2b3ecbdd9b88c267012168b4a7b3fc6fd41d13", size = 589982, upload-time = "2025-10-30T11:17:21.384Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b4/bd/c7d862a4381b95f2469704de32c0ad419def0f4a84b7a138a79532238114/nh3-0.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:019ecbd007536b67fdf76fab411b648fb64e2257ca3262ec80c3425c24028c80", size = 577126, upload-time = "2025-10-30T11:17:22.755Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b6/3e/f5a5cc2885c24be13e9b937441bd16a012ac34a657fe05e58927e8af8b7a/nh3-0.3.2-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7064ccf5ace75825bd7bf57859daaaf16ed28660c1c6b306b649a9eda4b54b1e", size = 1431980, upload-time = "2025-10-30T11:17:25.457Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/7f/f7/529a99324d7ef055de88b690858f4189379708abae92ace799365a797b7f/nh3-0.3.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8745454cdd28bbbc90861b80a0111a195b0e3961b9fa2e672be89eb199fa5d8", size = 820805, upload-time = "2025-10-30T11:17:26.98Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/3d/62/19b7c50ccd1fa7d0764822d2cea8f2a320f2fd77474c7a1805cb22cf69b0/nh3-0.3.2-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72d67c25a84579f4a432c065e8b4274e53b7cf1df8f792cf846abfe2c3090866", size = 803527, upload-time = "2025-10-30T11:17:28.284Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/4a/ca/f022273bab5440abff6302731a49410c5ef66b1a9502ba3fbb2df998d9ff/nh3-0.3.2-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:13398e676a14d6233f372c75f52d5ae74f98210172991f7a3142a736bd92b131", size = 1051674, upload-time = "2025-10-30T11:17:29.909Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fa/f7/5728e3b32a11daf5bd21cf71d91c463f74305938bc3eb9e0ac1ce141646e/nh3-0.3.2-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03d617e5c8aa7331bd2659c654e021caf9bba704b109e7b2b28b039a00949fe5", size = 1004737, upload-time = "2025-10-30T11:17:31.205Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/53/7f/f17e0dba0a99cee29e6cee6d4d52340ef9cb1f8a06946d3a01eb7ec2fb01/nh3-0.3.2-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2f55c4d2d5a207e74eefe4d828067bbb01300e06e2a7436142f915c5928de07", size = 911745, upload-time = "2025-10-30T11:17:32.945Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/42/0f/c76bf3dba22c73c38e9b1113b017cf163f7696f50e003404ec5ecdb1e8a6/nh3-0.3.2-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bb18403f02b655a1bbe4e3a4696c2ae1d6ae8f5991f7cacb684b1ae27e6c9f7", size = 797184, upload-time = "2025-10-30T11:17:34.226Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/08/a1/73d8250f888fb0ddf1b119b139c382f8903d8bb0c5bd1f64afc7e38dad1d/nh3-0.3.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6d66f41672eb4060cf87c037f760bdbc6847852ca9ef8e9c5a5da18f090abf87", size = 838556, upload-time = "2025-10-30T11:17:35.875Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d1/09/deb57f1fb656a7a5192497f4a287b0ade5a2ff6b5d5de4736d13ef6d2c1f/nh3-0.3.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f97f8b25cb2681d25e2338148159447e4d689aafdccfcf19e61ff7db3905768a", size = 1006695, upload-time = "2025-10-30T11:17:37.071Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b6/61/8f4d41c4ccdac30e4b1a4fa7be4b0f9914d8314a5058472f84c8e101a418/nh3-0.3.2-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:2ab70e8c6c7d2ce953d2a58102eefa90c2d0a5ed7aa40c7e29a487bc5e613131", size = 1075471, upload-time = "2025-10-30T11:17:38.225Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b0/c6/966aec0cb4705e69f6c3580422c239205d5d4d0e50fac380b21e87b6cf1b/nh3-0.3.2-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:1710f3901cd6440ca92494ba2eb6dc260f829fa8d9196b659fa10de825610ce0", size = 1002439, upload-time = "2025-10-30T11:17:39.553Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e2/c8/97a2d5f7a314cce2c5c49f30c6f161b7f3617960ade4bfc2fd1ee092cb20/nh3-0.3.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:91e9b001101fb4500a2aafe3e7c92928d85242d38bf5ac0aba0b7480da0a4cd6", size = 987439, upload-time = "2025-10-30T11:17:40.81Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/0d/95/2d6fc6461687d7a171f087995247dec33e8749a562bfadd85fb5dbf37a11/nh3-0.3.2-cp38-abi3-win32.whl", hash = "sha256:169db03df90da63286e0560ea0efa9b6f3b59844a9735514a1d47e6bb2c8c61b", size = 589826, upload-time = "2025-10-30T11:17:42.239Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/64/9a/1a1c154f10a575d20dd634e5697805e589bbdb7673a0ad00e8da90044ba7/nh3-0.3.2-cp38-abi3-win_amd64.whl", hash = "sha256:562da3dca7a17f9077593214a9781a94b8d76de4f158f8c895e62f09573945fe", size = 596406, upload-time = "2025-10-30T11:17:43.773Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9e/7e/a96255f63b7aef032cbee8fc4d6e37def72e3aaedc1f72759235e8f13cb1/nh3-0.3.2-cp38-abi3-win_arm64.whl", hash = "sha256:cf5964d54edd405e68583114a7cba929468bcd7db5e676ae38ee954de1cfc104", size = 584162, upload-time = "2025-10-30T11:17:44.96Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nodeenv"
|
name = "nodeenv"
|
||||||
version = "1.9.1"
|
version = "1.9.1"
|
||||||
@ -1889,11 +1854,11 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redis"
|
name = "redis"
|
||||||
version = "6.4.0"
|
version = "7.0.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/0d/d6/e8b92798a5bd67d659d51a18170e91c16ac3b59738d91894651ee255ed49/redis-6.4.0.tar.gz", hash = "sha256:b01bc7282b8444e28ec36b261df5375183bb47a07eb9c603f284e89cbc5ef010", size = 4647399, upload-time = "2025-08-07T08:10:11.441Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/57/8f/f125feec0b958e8d22c8f0b492b30b1991d9499a4315dfde466cf4289edc/redis-7.0.1.tar.gz", hash = "sha256:c949df947dca995dc68fdf5a7863950bf6df24f8d6022394585acc98e81624f1", size = 4755322, upload-time = "2025-10-27T14:34:00.33Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/e8/02/89e2ed7e85db6c93dfa9e8f691c5087df4e3551ab39081a4d7c6d1f90e05/redis-6.4.0-py3-none-any.whl", hash = "sha256:f0544fa9604264e9464cdf4814e7d4830f74b165d52f2a330a760a88dd248b7f", size = 279847, upload-time = "2025-08-07T08:10:09.84Z" },
|
{ url = "https://files.pythonhosted.org/packages/e9/97/9f22a33c475cda519f20aba6babb340fb2f2254a02fb947816960d1e669a/redis-7.0.1-py3-none-any.whl", hash = "sha256:4977af3c7d67f8f0eb8b6fec0dafc9605db9343142f634041fb0235f67c0588a", size = 339938, upload-time = "2025-10-27T14:33:58.553Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
Reference in New Issue
Block a user