forked from enviPath/enviPy
Initial bayer app
This commit is contained in:
0
bayer/__init__.py
Normal file
0
bayer/__init__.py
Normal file
3
bayer/admin.py
Normal file
3
bayer/admin.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
6
bayer/apps.py
Normal file
6
bayer/apps.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class BayerConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'bayer'
|
||||||
35
bayer/migrations/0001_initial.py
Normal file
35
bayer/migrations/0001_initial.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Generated by Django 5.2.7 on 2026-03-06 10:51
|
||||||
|
|
||||||
|
import django.utils.timezone
|
||||||
|
import model_utils.fields
|
||||||
|
import uuid
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Package',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
|
||||||
|
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='UUID of this object')),
|
||||||
|
('name', models.TextField(default='no name', verbose_name='Name')),
|
||||||
|
('description', models.TextField(default='no description', verbose_name='Descriptions')),
|
||||||
|
('url', models.TextField(null=True, unique=True, verbose_name='URL')),
|
||||||
|
('kv', models.JSONField(blank=True, default=dict, null=True)),
|
||||||
|
('reviewed', models.BooleanField(default=False, verbose_name='Reviewstatus')),
|
||||||
|
('classification_level', models.IntegerField(choices=[(0, 'Internal'), (10, 'Restricted'), (20, 'Secret')], default=10)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'db_table': 'epdb_package',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
22
bayer/migrations/0002_initial.py
Normal file
22
bayer/migrations/0002_initial.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Generated by Django 5.2.7 on 2026-03-06 10:51
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('bayer', '0001_initial'),
|
||||||
|
('epdb', '0019_remove_scenario_additional_information_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='package',
|
||||||
|
name='license',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='epdb.license', verbose_name='License'),
|
||||||
|
),
|
||||||
|
]
|
||||||
0
bayer/migrations/__init__.py
Normal file
0
bayer/migrations/__init__.py
Normal file
95
bayer/models.py
Normal file
95
bayer/models.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
from django.conf import settings as s
|
||||||
|
from django.db import models
|
||||||
|
from django.db.models import QuerySet
|
||||||
|
|
||||||
|
from epdb.models import (
|
||||||
|
EnviPathModel,
|
||||||
|
ParallelRule,
|
||||||
|
SequentialRule,
|
||||||
|
SimpleAmbitRule,
|
||||||
|
SimpleRDKitRule,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Package(EnviPathModel):
|
||||||
|
reviewed = models.BooleanField(verbose_name="Reviewstatus", default=False)
|
||||||
|
license = models.ForeignKey(
|
||||||
|
"epdb.License", on_delete=models.SET_NULL, blank=True, null=True, verbose_name="License"
|
||||||
|
)
|
||||||
|
|
||||||
|
class Classification(models.IntegerChoices):
|
||||||
|
INTERNAL = 0, "Internal"
|
||||||
|
RESTRICTED = 10 , "Restricted"
|
||||||
|
SECRET = 20, "Secret"
|
||||||
|
|
||||||
|
classification_level = models.IntegerField(
|
||||||
|
choices=Classification,
|
||||||
|
default=Classification.RESTRICTED,
|
||||||
|
)
|
||||||
|
|
||||||
|
def delete(self, *args, **kwargs):
|
||||||
|
# explicitly handle related Rules
|
||||||
|
for r in self.rules.all():
|
||||||
|
r.delete()
|
||||||
|
super().delete(*args, **kwargs)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.name} (pk={self.pk})"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def compounds(self) -> QuerySet:
|
||||||
|
return self.compound_set.all()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rules(self) -> QuerySet:
|
||||||
|
return self.rule_set.all()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def reactions(self) -> QuerySet:
|
||||||
|
return self.reaction_set.all()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pathways(self) -> QuerySet:
|
||||||
|
return self.pathway_set.all()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def scenarios(self) -> QuerySet:
|
||||||
|
return self.scenario_set.all()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def models(self) -> QuerySet:
|
||||||
|
return self.epmodel_set.all()
|
||||||
|
|
||||||
|
def _url(self):
|
||||||
|
return "{}/package/{}".format(s.SERVER_URL, self.uuid)
|
||||||
|
|
||||||
|
def get_applicable_rules(self) -> List["Rule"]:
|
||||||
|
"""
|
||||||
|
Returns a ordered set of rules where the following applies:
|
||||||
|
1. All Composite will be added to result
|
||||||
|
2. All SimpleRules will be added if theres no CompositeRule present using the SimpleRule
|
||||||
|
Ordering is based on "url" field.
|
||||||
|
"""
|
||||||
|
rules = []
|
||||||
|
rule_qs = self.rules
|
||||||
|
|
||||||
|
reflected_simple_rules = set()
|
||||||
|
|
||||||
|
for r in rule_qs:
|
||||||
|
if isinstance(r, ParallelRule) or isinstance(r, SequentialRule):
|
||||||
|
rules.append(r)
|
||||||
|
for sr in r.simple_rules.all():
|
||||||
|
reflected_simple_rules.add(sr)
|
||||||
|
|
||||||
|
for r in rule_qs:
|
||||||
|
if isinstance(r, SimpleAmbitRule) or isinstance(r, SimpleRDKitRule):
|
||||||
|
if r not in reflected_simple_rules:
|
||||||
|
rules.append(r)
|
||||||
|
|
||||||
|
rules = sorted(rules, key=lambda x: x.url)
|
||||||
|
return rules
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
db_table = "epdb_package"
|
||||||
0
bayer/templates/actions/objects/compound.html
Normal file
0
bayer/templates/actions/objects/compound.html
Normal file
97
bayer/templates/objects/package.html
Normal file
97
bayer/templates/objects/package.html
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
{% extends "framework_modern.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% block action_modals %}
|
||||||
|
{% include "modals/objects/edit_package_modal.html" %}
|
||||||
|
{% include "modals/objects/edit_package_permissions_modal.html" %}
|
||||||
|
{% include "modals/objects/publish_package_modal.html" %}
|
||||||
|
{% include "modals/objects/set_license_modal.html" %}
|
||||||
|
{% include "modals/objects/export_package_modal.html" %}
|
||||||
|
{% include "modals/objects/generic_delete_modal.html" %}
|
||||||
|
{% endblock action_modals %}
|
||||||
|
|
||||||
|
<div class="space-y-2 p-4">
|
||||||
|
<!-- Header Section -->
|
||||||
|
<div class="card bg-base-100">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="card-title text-2xl">{{ package.name }} FROM APP</h2>
|
||||||
|
<div id="actionsButton" class="dropdown dropdown-e nd hidden">
|
||||||
|
<div tabindex="0" role="button" class="btn btn-ghost btn-sm">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-wrench"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
Actions
|
||||||
|
</div>
|
||||||
|
<ul
|
||||||
|
tabindex="-1"
|
||||||
|
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2"
|
||||||
|
>
|
||||||
|
{% block actions %}
|
||||||
|
{% include "actions/objects/package.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="mt-2">{{ package.description|safe }}</p>
|
||||||
|
<ul class="menu bg-base-200 rounded-box mt-4 w-full">
|
||||||
|
<li>
|
||||||
|
<a href="{{ package.url }}/pathway" class="hover:bg-base-300"
|
||||||
|
>Pathways ({{ package.pathways.count }})</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ package.url }}/rule" class="hover:bg-base-300"
|
||||||
|
>Rules ({{ package.rules.count }})</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ package.url }}/compound" class="hover:bg-base-300"
|
||||||
|
>Compounds ({{ package.compounds.count }})</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ package.url }}/reaction" class="hover:bg-base-300"
|
||||||
|
>Reactions ({{ package.reactions.count }})</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ package.url }}/model" class="hover:bg-base-300"
|
||||||
|
>Models ({{ package.models.count }})</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ package.url }}/scenario" class="hover:bg-base-300"
|
||||||
|
>Scenarios ({{ package.scenarios.count }})</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Show actions button if there are actions
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
const actionsButton = document.getElementById("actionsButton");
|
||||||
|
const actionsList = actionsButton?.querySelector("ul");
|
||||||
|
if (actionsList && actionsList.children.length > 0) {
|
||||||
|
actionsButton?.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock content %}
|
||||||
3
bayer/tests.py
Normal file
3
bayer/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
3
bayer/views.py
Normal file
3
bayer/views.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
||||||
Reference in New Issue
Block a user